HD Packs: Improvements, new features, bug fixes
This commit is contained in:
parent
f1ba279de6
commit
e82371e2f8
67 changed files with 3407 additions and 883 deletions
|
@ -874,7 +874,7 @@ uint32_t BaseMapper::GetMemorySize(DebugMemoryType type)
|
|||
uint8_t BaseMapper::GetMemoryValue(DebugMemoryType memoryType, uint32_t address)
|
||||
{
|
||||
switch(memoryType) {
|
||||
case DebugMemoryType::ChrRom: return _chrRom[address];
|
||||
case DebugMemoryType::ChrRom: return _onlyChrRam ? _chrRam[address] : _chrRom[address];
|
||||
case DebugMemoryType::ChrRam: return _chrRam[address];
|
||||
case DebugMemoryType::SaveRam: return _saveRam[address];
|
||||
case DebugMemoryType::PrgRom: return _prgRom[address];
|
||||
|
@ -928,6 +928,9 @@ int32_t BaseMapper::ToAbsoluteChrAddress(uint16_t addr)
|
|||
if(chrAddr >= _chrRom && chrAddr < _chrRom + _chrRomSize) {
|
||||
return (uint32_t)(chrAddr - _chrRom);
|
||||
}
|
||||
if(chrAddr >= _chrRam && chrAddr < _chrRam + _chrRamSize) {
|
||||
return (uint32_t)(chrAddr - _chrRam);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -132,8 +132,6 @@ protected:
|
|||
|
||||
void RestoreOriginalPrgRam();
|
||||
void InitializeChrRam(int32_t chrRamSize = -1);
|
||||
bool HasChrRam();
|
||||
bool HasChrRom();
|
||||
|
||||
void AddRegisterRange(uint16_t startAddr, uint16_t endAddr, MemoryOperation operation = MemoryOperation::Any);
|
||||
void RemoveRegisterRange(uint16_t startAddr, uint16_t endAddr, MemoryOperation operation = MemoryOperation::Any);
|
||||
|
@ -196,6 +194,9 @@ public:
|
|||
static void InitializeRam(void* data, uint32_t length);
|
||||
|
||||
//Debugger Helper Functions
|
||||
bool HasChrRam();
|
||||
bool HasChrRom();
|
||||
|
||||
CartridgeState GetState();
|
||||
uint8_t* GetPrgRom();
|
||||
uint8_t* GetWorkRam();
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "stdafx.h"
|
||||
#include <cmath>
|
||||
#include "BaseRenderer.h"
|
||||
#include "Console.h"
|
||||
#include "EmulationSettings.h"
|
||||
#include "VideoDecoder.h"
|
||||
#include "PPU.h"
|
||||
|
|
|
@ -72,15 +72,10 @@ void BaseVideoFilter::TakeScreenshot(string filename, std::stringstream *stream)
|
|||
memcpy(frameBuffer, GetOutputBuffer(), _bufferSize);
|
||||
}
|
||||
|
||||
//ARGB -> ABGR
|
||||
for(uint32_t i = 0; i < _bufferSize / GetFrameInfo().BitsPerPixel; i++) {
|
||||
frameBuffer[i] = 0xFF000000 | (frameBuffer[i] & 0xFF00) | ((frameBuffer[i] & 0xFF0000) >> 16) | ((frameBuffer[i] & 0xFF) << 16);
|
||||
}
|
||||
|
||||
if(!filename.empty()) {
|
||||
PNGHelper::WritePNG(filename, (uint8_t*)frameBuffer, GetFrameInfo().Width, GetFrameInfo().Height);
|
||||
PNGHelper::WritePNG(filename, frameBuffer, GetFrameInfo().Width, GetFrameInfo().Height);
|
||||
} else {
|
||||
PNGHelper::WritePNG(*stream, (uint8_t*)frameBuffer, GetFrameInfo().Width, GetFrameInfo().Height);
|
||||
PNGHelper::WritePNG(*stream, frameBuffer, GetFrameInfo().Width, GetFrameInfo().Height);
|
||||
}
|
||||
|
||||
delete[] frameBuffer;
|
||||
|
|
215
Core/Console.cpp
215
Core/Console.cpp
|
@ -1,6 +1,7 @@
|
|||
#include "stdafx.h"
|
||||
#include <thread>
|
||||
#include "Console.h"
|
||||
#include "FileLoader.h"
|
||||
#include "CPU.h"
|
||||
#include "PPU.h"
|
||||
#include "APU.h"
|
||||
|
@ -14,9 +15,11 @@
|
|||
#include "MessageManager.h"
|
||||
#include "RomLoader.h"
|
||||
#include "EmulationSettings.h"
|
||||
#include "../Utilities/sha1.h"
|
||||
#include "../Utilities/Timer.h"
|
||||
#include "../Utilities/FolderUtilities.h"
|
||||
#include "../Utilities/PlatformUtilities.h"
|
||||
#include "HdBuilderPpu.h"
|
||||
#include "HdPpu.h"
|
||||
#include "NsfPpu.h"
|
||||
#include "SoundMixer.h"
|
||||
|
@ -25,6 +28,7 @@
|
|||
#include "MovieManager.h"
|
||||
#include "RewindManager.h"
|
||||
#include "SaveStateManager.h"
|
||||
#include "HdPackBuilder.h"
|
||||
|
||||
shared_ptr<Console> Console::Instance(new Console());
|
||||
|
||||
|
@ -62,73 +66,82 @@ bool Console::Initialize(string romFilename, stringstream *filestream, string pa
|
|||
//Save current game state before loading another one
|
||||
SaveStateManager::SaveRecentGame(_mapper->GetRomName(), _romFilepath, _patchFilename, _archiveFileIndex);
|
||||
}
|
||||
|
||||
shared_ptr<BaseMapper> mapper = MapperFactory::InitializeFromFile(romFilename, filestream, patchFilename, archiveFileIndex);
|
||||
|
||||
if(mapper) {
|
||||
if(_mapper) {
|
||||
//Send notification only if a game was already running and we successfully loaded the new one
|
||||
MessageManager::SendNotification(ConsoleNotificationType::GameStopped);
|
||||
}
|
||||
|
||||
_romFilepath = romFilename;
|
||||
_patchFilename = patchFilename;
|
||||
_archiveFileIndex = archiveFileIndex;
|
||||
|
||||
_autoSaveManager.reset(new AutoSaveManager());
|
||||
VideoDecoder::GetInstance()->StopThread();
|
||||
|
||||
_mapper = mapper;
|
||||
_memoryManager.reset(new MemoryManager(_mapper));
|
||||
_cpu.reset(new CPU(_memoryManager.get()));
|
||||
if(HdNesPack::HasHdPack(_romFilepath)) {
|
||||
_ppu.reset(new HdPpu(_mapper.get()));
|
||||
} else if(NsfMapper::GetInstance()) {
|
||||
//Disable most of the PPU for NSFs
|
||||
_ppu.reset(new NsfPpu(_mapper.get()));
|
||||
} else {
|
||||
_ppu.reset(new PPU(_mapper.get()));
|
||||
}
|
||||
_apu.reset(new APU(_memoryManager.get()));
|
||||
|
||||
_controlManager.reset(_mapper->GetGameSystem() == GameSystem::VsUniSystem ? new VsControlManager() : new ControlManager());
|
||||
_controlManager->UpdateControlDevices();
|
||||
|
||||
_memoryManager->RegisterIODevice(_ppu.get());
|
||||
_memoryManager->RegisterIODevice(_apu.get());
|
||||
_memoryManager->RegisterIODevice(_controlManager.get());
|
||||
_memoryManager->RegisterIODevice(_mapper.get());
|
||||
|
||||
_model = NesModel::Auto;
|
||||
UpdateNesModel(false);
|
||||
|
||||
_initialized = true;
|
||||
|
||||
if(_debugger) {
|
||||
auto lock = _debuggerLock.AcquireSafe();
|
||||
StopDebugger();
|
||||
GetDebugger();
|
||||
}
|
||||
|
||||
ResetComponents(false);
|
||||
|
||||
_rewindManager.reset(new RewindManager());
|
||||
|
||||
VideoDecoder::GetInstance()->StartThread();
|
||||
|
||||
FolderUtilities::AddKnownGameFolder(FolderUtilities::GetFolderName(romFilename));
|
||||
|
||||
string modelName = _model == NesModel::PAL ? "PAL" : (_model == NesModel::Dendy ? "Dendy" : "NTSC");
|
||||
string messageTitle = MessageManager::Localize("GameLoaded") + " (" + modelName + ")";
|
||||
MessageManager::DisplayMessage(messageTitle, FolderUtilities::GetFilename(_mapper->GetRomName(), false));
|
||||
if(EmulationSettings::GetOverclockRate() != 100) {
|
||||
MessageManager::DisplayMessage("ClockRate", std::to_string(EmulationSettings::GetOverclockRate()) + "%");
|
||||
vector<uint8_t> fileData;
|
||||
if(FileLoader::LoadFile(romFilename, filestream, archiveFileIndex, fileData)) {
|
||||
LoadHdPack(romFilename, fileData, patchFilename);
|
||||
if(!patchFilename.empty()) {
|
||||
FileLoader::ApplyPatch(patchFilename, fileData);
|
||||
}
|
||||
|
||||
shared_ptr<BaseMapper> mapper = MapperFactory::InitializeFromFile(romFilename, fileData);
|
||||
if(mapper) {
|
||||
if(_mapper) {
|
||||
//Send notification only if a game was already running and we successfully loaded the new one
|
||||
MessageManager::SendNotification(ConsoleNotificationType::GameStopped);
|
||||
}
|
||||
|
||||
_romFilepath = romFilename;
|
||||
_patchFilename = patchFilename;
|
||||
_archiveFileIndex = archiveFileIndex;
|
||||
|
||||
_autoSaveManager.reset(new AutoSaveManager());
|
||||
VideoDecoder::GetInstance()->StopThread();
|
||||
|
||||
_mapper = mapper;
|
||||
_memoryManager.reset(new MemoryManager(_mapper));
|
||||
_cpu.reset(new CPU(_memoryManager.get()));
|
||||
|
||||
if(_hdData) {
|
||||
_ppu.reset(new HdPpu(_mapper.get()));
|
||||
} else if(NsfMapper::GetInstance()) {
|
||||
//Disable most of the PPU for NSFs
|
||||
_ppu.reset(new NsfPpu(_mapper.get()));
|
||||
} else {
|
||||
_ppu.reset(new PPU(_mapper.get()));
|
||||
}
|
||||
|
||||
_apu.reset(new APU(_memoryManager.get()));
|
||||
|
||||
_controlManager.reset(_mapper->GetGameSystem() == GameSystem::VsUniSystem ? new VsControlManager() : new ControlManager());
|
||||
_controlManager->UpdateControlDevices();
|
||||
|
||||
_memoryManager->RegisterIODevice(_ppu.get());
|
||||
_memoryManager->RegisterIODevice(_apu.get());
|
||||
_memoryManager->RegisterIODevice(_controlManager.get());
|
||||
_memoryManager->RegisterIODevice(_mapper.get());
|
||||
|
||||
_model = NesModel::Auto;
|
||||
UpdateNesModel(false);
|
||||
|
||||
_initialized = true;
|
||||
|
||||
if(_debugger) {
|
||||
auto lock = _debuggerLock.AcquireSafe();
|
||||
StopDebugger();
|
||||
GetDebugger();
|
||||
}
|
||||
|
||||
ResetComponents(false);
|
||||
|
||||
_rewindManager.reset(new RewindManager());
|
||||
|
||||
VideoDecoder::GetInstance()->StartThread();
|
||||
|
||||
FolderUtilities::AddKnownGameFolder(FolderUtilities::GetFolderName(romFilename));
|
||||
|
||||
string modelName = _model == NesModel::PAL ? "PAL" : (_model == NesModel::Dendy ? "Dendy" : "NTSC");
|
||||
string messageTitle = MessageManager::Localize("GameLoaded") + " (" + modelName + ")";
|
||||
MessageManager::DisplayMessage(messageTitle, FolderUtilities::GetFilename(_mapper->GetRomName(), false));
|
||||
if(EmulationSettings::GetOverclockRate() != 100) {
|
||||
MessageManager::DisplayMessage("ClockRate", std::to_string(EmulationSettings::GetOverclockRate()) + "%");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
MessageManager::DisplayMessage("Error", "CouldNotLoadFile", FolderUtilities::GetFilename(romFilename, true));
|
||||
return false;
|
||||
}
|
||||
|
||||
MessageManager::DisplayMessage("Error", "CouldNotLoadFile", FolderUtilities::GetFilename(romFilename, true));
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Console::LoadROM(string filepath, stringstream *filestream, int32_t archiveFileIndex, string patchFilepath)
|
||||
|
@ -207,6 +220,15 @@ RomFormat Console::GetRomFormat()
|
|||
}
|
||||
}
|
||||
|
||||
bool Console::IsChrRam()
|
||||
{
|
||||
if(Instance->_mapper) {
|
||||
return Instance->_mapper->HasChrRam();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t Console::GetCrc32()
|
||||
{
|
||||
if(Instance->_mapper) {
|
||||
|
@ -264,8 +286,9 @@ void Console::ResetComponents(bool softReset)
|
|||
MovieManager::Stop();
|
||||
if(!softReset) {
|
||||
SoundMixer::StopRecording();
|
||||
_hdPackBuilder.reset();
|
||||
}
|
||||
|
||||
|
||||
_memoryManager->Reset(softReset);
|
||||
if(!EmulationSettings::CheckFlag(EmulationFlags::DisablePpuReset) || !softReset) {
|
||||
_ppu->Reset();
|
||||
|
@ -460,6 +483,9 @@ void Console::Run()
|
|||
_memoryManager.reset();
|
||||
_controlManager.reset();
|
||||
|
||||
_hdPackBuilder.reset();
|
||||
_hdData.reset();
|
||||
|
||||
_stopLock.Release();
|
||||
_runLock.Release();
|
||||
}
|
||||
|
@ -608,3 +634,62 @@ void Console::SetNextFrameOverclockStatus(bool disabled)
|
|||
{
|
||||
Instance->_disableOcNextFrame = disabled;
|
||||
}
|
||||
|
||||
HdPackData* Console::GetHdData()
|
||||
{
|
||||
return Instance->_hdData.get();
|
||||
}
|
||||
|
||||
void Console::LoadHdPack(string romFilename, vector<uint8_t> &fileData, string &patchFilename)
|
||||
{
|
||||
_hdData.reset();
|
||||
if(EmulationSettings::CheckFlag(EmulationFlags::UseHdPacks)) {
|
||||
string hdPackFolder = FolderUtilities::CombinePath(FolderUtilities::GetHdPackFolder(), FolderUtilities::GetFilename(romFilename, false));
|
||||
string hdPackDefinitionFile = FolderUtilities::CombinePath(hdPackFolder, "hires.txt");
|
||||
_hdData.reset(new HdPackData());
|
||||
if(!HdPackLoader::LoadHdNesPack(hdPackDefinitionFile, *_hdData.get())) {
|
||||
_hdData.reset();
|
||||
} else {
|
||||
string sha1hash = SHA1::GetHash(fileData);
|
||||
auto result = _hdData->PatchesByHash.find(sha1hash);
|
||||
if(result != _hdData->PatchesByHash.end()) {
|
||||
patchFilename = FolderUtilities::CombinePath(hdPackFolder, result->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Console::StartRecordingHdPack(string saveFolder, ScaleFilterType filterType, uint32_t scale, uint32_t flags, uint32_t chrRamBankSize)
|
||||
{
|
||||
Console::Pause();
|
||||
std::stringstream saveState;
|
||||
Instance->SaveState(saveState);
|
||||
|
||||
Instance->_hdPackBuilder.reset();
|
||||
Instance->_hdPackBuilder.reset(new HdPackBuilder(saveFolder, filterType, scale, flags, chrRamBankSize, !Instance->_mapper->HasChrRom()));
|
||||
|
||||
Instance->_memoryManager->UnregisterIODevice(Instance->_ppu.get());
|
||||
Instance->_ppu.reset();
|
||||
Instance->_ppu.reset(new HdBuilderPpu(Instance->_mapper.get(), Instance->_hdPackBuilder.get(), chrRamBankSize));
|
||||
Instance->_memoryManager->RegisterIODevice(Instance->_ppu.get());
|
||||
|
||||
Instance->LoadState(saveState);
|
||||
Console::Resume();
|
||||
}
|
||||
|
||||
void Console::StopRecordingHdPack()
|
||||
{
|
||||
Console::Pause();
|
||||
std::stringstream saveState;
|
||||
Instance->SaveState(saveState);
|
||||
|
||||
Instance->_memoryManager->UnregisterIODevice(Instance->_ppu.get());
|
||||
Instance->_ppu.reset();
|
||||
Instance->_ppu.reset(new PPU(Instance->_mapper.get()));
|
||||
Instance->_memoryManager->RegisterIODevice(Instance->_ppu.get());
|
||||
|
||||
Instance->_hdPackBuilder.reset();
|
||||
|
||||
Instance->LoadState(saveState);
|
||||
Console::Resume();
|
||||
}
|
|
@ -4,6 +4,7 @@
|
|||
#include <atomic>
|
||||
#include "../Utilities/SimpleLock.h"
|
||||
#include "RomData.h"
|
||||
#include "HdData.h"
|
||||
|
||||
class Debugger;
|
||||
class BaseMapper;
|
||||
|
@ -14,7 +15,9 @@ class PPU;
|
|||
class MemoryManager;
|
||||
class ControlManager;
|
||||
class AutoSaveManager;
|
||||
class HdPackBuilder;
|
||||
enum class NesModel;
|
||||
enum class ScaleFilterType;
|
||||
|
||||
class Console
|
||||
{
|
||||
|
@ -36,6 +39,9 @@ class Console
|
|||
|
||||
unique_ptr<AutoSaveManager> _autoSaveManager;
|
||||
|
||||
shared_ptr<HdPackBuilder> _hdPackBuilder;
|
||||
unique_ptr<HdPackData> _hdData;
|
||||
|
||||
NesModel _model;
|
||||
|
||||
string _romFilepath;
|
||||
|
@ -51,6 +57,8 @@ class Console
|
|||
|
||||
bool _initialized = false;
|
||||
|
||||
void LoadHdPack(string romFilename, vector<uint8_t> &fileData, string &patchFilename);
|
||||
|
||||
void ResetComponents(bool softReset);
|
||||
bool Initialize(string filename, stringstream *filestream = nullptr, string patchFilename = "", int32_t archiveFileIndex = -1);
|
||||
void UpdateNesModel(bool sendNotification);
|
||||
|
@ -85,6 +93,7 @@ class Console
|
|||
static bool LoadROM(string romName, string sha1Hash);
|
||||
static string GetROMPath();
|
||||
static string GetRomName();
|
||||
static bool IsChrRam();
|
||||
static RomFormat GetRomFormat();
|
||||
static uint32_t GetCrc32();
|
||||
static uint32_t GetPrgCrc32();
|
||||
|
@ -99,6 +108,11 @@ class Console
|
|||
|
||||
static bool IsDebuggerAttached();
|
||||
|
||||
static HdPackData* GetHdData();
|
||||
|
||||
static void StartRecordingHdPack(string saveFolder, ScaleFilterType filterType, uint32_t scale, uint32_t flags, uint32_t chrRamBankSize);
|
||||
static void StopRecordingHdPack();
|
||||
|
||||
static shared_ptr<Console> GetInstance();
|
||||
static void Release();
|
||||
};
|
||||
|
|
|
@ -413,6 +413,11 @@
|
|||
<ClInclude Include="AutomaticRomTest.h" />
|
||||
<ClInclude Include="BaseRenderer.h" />
|
||||
<ClInclude Include="FceuxMovie.h" />
|
||||
<ClInclude Include="FileLoader.h" />
|
||||
<ClInclude Include="HdBuilderPpu.h" />
|
||||
<ClInclude Include="HdData.h" />
|
||||
<ClInclude Include="HdPackBuilder.h" />
|
||||
<ClInclude Include="HdPackLoader.h" />
|
||||
<ClInclude Include="Mapper174.h" />
|
||||
<ClInclude Include="Rambo1_158.h" />
|
||||
<ClInclude Include="RecordedRomTest.h" />
|
||||
|
@ -774,6 +779,10 @@
|
|||
<ClCompile Include="AutomaticRomTest.cpp" />
|
||||
<ClCompile Include="BaseRenderer.cpp" />
|
||||
<ClCompile Include="FceuxMovie.cpp" />
|
||||
<ClCompile Include="FileLoader.cpp" />
|
||||
<ClCompile Include="HdNesPack.cpp" />
|
||||
<ClCompile Include="HdPackBuilder.cpp" />
|
||||
<ClCompile Include="HdPackLoader.cpp" />
|
||||
<ClCompile Include="RecordedRomTest.cpp" />
|
||||
<ClCompile Include="AutoSaveManager.cpp" />
|
||||
<ClCompile Include="AviRecorder.cpp" />
|
||||
|
|
|
@ -1180,6 +1180,21 @@
|
|||
<ClInclude Include="BaseRenderer.h">
|
||||
<Filter>VideoDecoder</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="HdPackBuilder.h">
|
||||
<Filter>VideoDecoder\HD</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="HdBuilderPpu.h">
|
||||
<Filter>VideoDecoder\HD</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="HdData.h">
|
||||
<Filter>VideoDecoder\HD</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="HdPackLoader.h">
|
||||
<Filter>VideoDecoder\HD</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="FileLoader.h">
|
||||
<Filter>Nes\RomLoader</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
|
@ -1404,5 +1419,17 @@
|
|||
<ClCompile Include="BaseRenderer.cpp">
|
||||
<Filter>VideoDecoder</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="HdPackBuilder.cpp">
|
||||
<Filter>VideoDecoder\HD</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="HdPackLoader.cpp">
|
||||
<Filter>VideoDecoder\HD</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="HdNesPack.cpp">
|
||||
<Filter>VideoDecoder\HD</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="FileLoader.cpp">
|
||||
<Filter>Misc</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -1,5 +1,6 @@
|
|||
#include "stdafx.h"
|
||||
#include <thread>
|
||||
#include "../Utilities/FolderUtilities.h"
|
||||
#include "MessageManager.h"
|
||||
#include "Debugger.h"
|
||||
#include "Console.h"
|
||||
|
|
|
@ -104,6 +104,17 @@ enum class RamPowerOnState
|
|||
Random = 2
|
||||
};
|
||||
|
||||
enum class ScaleFilterType
|
||||
{
|
||||
xBRZ = 0,
|
||||
HQX = 1,
|
||||
Scale2x = 2,
|
||||
_2xSai = 3,
|
||||
Super2xSai = 4,
|
||||
SuperEagle = 5,
|
||||
Prescale = 6,
|
||||
};
|
||||
|
||||
enum class VideoFilterType
|
||||
{
|
||||
None = 0,
|
||||
|
|
112
Core/FileLoader.cpp
Normal file
112
Core/FileLoader.cpp
Normal file
|
@ -0,0 +1,112 @@
|
|||
#include "stdafx.h"
|
||||
#include "FileLoader.h"
|
||||
#include "../Utilities/ZipReader.h"
|
||||
#include "../Utilities/SZReader.h"
|
||||
#include "../Utilities/BpsPatcher.h"
|
||||
#include "../Utilities/IpsPatcher.h"
|
||||
#include "../Utilities/UpsPatcher.h"
|
||||
#include "../Utilities/FolderUtilities.h"
|
||||
#include "MessageManager.h"
|
||||
|
||||
void FileLoader::ReadFile(istream &file, vector<uint8_t> &fileData)
|
||||
{
|
||||
file.seekg(0, ios::end);
|
||||
uint32_t fileSize = (uint32_t)file.tellg();
|
||||
file.seekg(0, ios::beg);
|
||||
|
||||
fileData = vector<uint8_t>(fileSize, 0);
|
||||
file.read((char*)fileData.data(), fileSize);
|
||||
}
|
||||
|
||||
bool FileLoader::LoadFromArchive(istream &zipFile, ArchiveReader &reader, int32_t archiveFileIndex, vector<uint8_t> &fileData)
|
||||
{
|
||||
ReadFile(zipFile, fileData);
|
||||
reader.LoadArchive(fileData.data(), fileData.size());
|
||||
|
||||
vector<string> fileList = reader.GetFileList({ ".nes", ".fds", ".nsf", ".nsfe", ".unf" });
|
||||
if(fileList.empty() || archiveFileIndex > (int32_t)fileList.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(archiveFileIndex == -1) {
|
||||
archiveFileIndex = 0;
|
||||
}
|
||||
reader.ExtractFile(fileList[archiveFileIndex], fileData);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FileLoader::LoadFile(string filename, istream *filestream, int32_t archiveFileIndex, vector<uint8_t> &fileData)
|
||||
{
|
||||
ifstream file;
|
||||
istream* input = nullptr;
|
||||
if(!filestream) {
|
||||
file.open(filename, ios::in | ios::binary);
|
||||
if(file) {
|
||||
input = &file;
|
||||
}
|
||||
} else {
|
||||
input = filestream;
|
||||
}
|
||||
|
||||
if(input) {
|
||||
char header[15];
|
||||
input->seekg(0, ios::beg);
|
||||
input->read(header, 15);
|
||||
input->seekg(0, ios::beg);
|
||||
if(memcmp(header, "PK", 2) == 0) {
|
||||
ZipReader reader;
|
||||
return LoadFromArchive(*input, reader, archiveFileIndex, fileData);
|
||||
} else if(memcmp(header, "7z", 2) == 0) {
|
||||
SZReader reader;
|
||||
return LoadFromArchive(*input, reader, archiveFileIndex, fileData);
|
||||
} else {
|
||||
if(archiveFileIndex > 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ReadFile(*input, fileData);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void FileLoader::ApplyPatch(string patchPath, vector<uint8_t> &fileData)
|
||||
{
|
||||
//Apply patch file
|
||||
MessageManager::DisplayMessage("Patch", "ApplyingPatch", FolderUtilities::GetFilename(patchPath, true));
|
||||
ifstream patchFile(patchPath, ios::binary | ios::in);
|
||||
if(patchFile.good()) {
|
||||
char buffer[5] = {};
|
||||
patchFile.read(buffer, 5);
|
||||
patchFile.close();
|
||||
if(memcmp(buffer, "PATCH", 5) == 0) {
|
||||
fileData = IpsPatcher::PatchBuffer(patchPath, fileData);
|
||||
} else if(memcmp(buffer, "UPS1", 4) == 0) {
|
||||
fileData = UpsPatcher::PatchBuffer(patchPath, fileData);
|
||||
} else if(memcmp(buffer, "BPS1", 4) == 0) {
|
||||
fileData = BpsPatcher::PatchBuffer(patchPath, fileData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vector<string> FileLoader::GetArchiveRomList(string filename)
|
||||
{
|
||||
ifstream in(filename, ios::in | ios::binary);
|
||||
if(in) {
|
||||
uint8_t header[2];
|
||||
in.read((char*)header, 2);
|
||||
in.close();
|
||||
|
||||
if(memcmp(header, "PK", 2) == 0) {
|
||||
ZipReader reader;
|
||||
reader.LoadArchive(filename);
|
||||
return reader.GetFileList({ ".nes", ".fds", ".nsf", ".nsfe", "*.unf" });
|
||||
} else if(memcmp(header, "7z", 2) == 0) {
|
||||
SZReader reader;
|
||||
reader.LoadArchive(filename);
|
||||
return reader.GetFileList({ ".nes", ".fds", ".nsf", ".nsfe", "*.unf" });
|
||||
}
|
||||
}
|
||||
return{};
|
||||
}
|
15
Core/FileLoader.h
Normal file
15
Core/FileLoader.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
#pragma once
|
||||
#include "stdafx.h"
|
||||
#include "../Utilities/ArchiveReader.h"
|
||||
|
||||
class FileLoader
|
||||
{
|
||||
private:
|
||||
static void ReadFile(istream &file, vector<uint8_t> &fileData);
|
||||
static bool LoadFromArchive(istream &zipFile, ArchiveReader& reader, int32_t archiveFileIndex, vector<uint8_t> &fileData);
|
||||
|
||||
public:
|
||||
static bool LoadFile(string filename, istream *filestream, int32_t archiveFileIndex, vector<uint8_t> &fileData);
|
||||
static void ApplyPatch(string patchPath, vector<uint8_t> &fileData);
|
||||
static vector<string> GetArchiveRomList(string filename);
|
||||
};
|
109
Core/HdBuilderPpu.h
Normal file
109
Core/HdBuilderPpu.h
Normal file
|
@ -0,0 +1,109 @@
|
|||
#pragma once
|
||||
#include "stdafx.h"
|
||||
#include "PPU.h"
|
||||
#include "HdNesPack.h"
|
||||
#include "VideoDecoder.h"
|
||||
#include "RewindManager.h"
|
||||
#include "HdPackBuilder.h"
|
||||
|
||||
class HdBuilderPpu : public PPU
|
||||
{
|
||||
private:
|
||||
HdPackBuilder* _hdPackBuilder;
|
||||
bool _isChrRam;
|
||||
bool _needChrHash = false;
|
||||
uint32_t _chrRamBankSize;
|
||||
uint32_t _chrRamIndexMask;
|
||||
vector<uint32_t> _bankHashes;
|
||||
|
||||
protected:
|
||||
void DrawPixel()
|
||||
{
|
||||
if(IsRenderingEnabled() || ((_state.VideoRamAddr & 0x3F00) != 0x3F00)) {
|
||||
_lastSprite = nullptr;
|
||||
uint32_t color = GetPixelColor();
|
||||
_currentOutputBuffer[(_scanline << 8) + _cycle - 1] = _paletteRAM[color & 0x03 ? color : 0];
|
||||
|
||||
if(_needChrHash) {
|
||||
uint16_t addr = 0;
|
||||
_bankHashes.clear();
|
||||
while(addr < 0x2000) {
|
||||
uint32_t hash = 0;
|
||||
for(uint16_t i = 0; i < _chrRamBankSize; i++) {
|
||||
hash += _mapper->DebugReadVRAM(i + addr);
|
||||
hash = (hash << 1) | (hash >> 31);
|
||||
}
|
||||
_bankHashes.push_back(hash);
|
||||
addr += _chrRamBankSize;
|
||||
}
|
||||
_needChrHash = false;
|
||||
}
|
||||
|
||||
HdPpuPixelInfo tileInfo;
|
||||
if(_lastSprite && _flags.SpritesEnabled) {
|
||||
if(_lastSprite->AbsoluteTileAddr >= 0) {
|
||||
tileInfo.Sprite.TileIndex = (_isChrRam ? (_lastSprite->TileAddr & _chrRamIndexMask) : _lastSprite->AbsoluteTileAddr) / 16;
|
||||
tileInfo.Sprite.PaletteColors = ReadPaletteRAM(_lastSprite->PaletteOffset + 3) | (ReadPaletteRAM(_lastSprite->PaletteOffset + 2) << 8) | (ReadPaletteRAM(_lastSprite->PaletteOffset + 1) << 16) | 0xFF000000;
|
||||
tileInfo.Sprite.IsChrRamTile = _isChrRam;
|
||||
for(int i = 0; i < 16; i++) {
|
||||
tileInfo.Sprite.TileData[i] = _mapper->GetMemoryValue(DebugMemoryType::ChrRom, _lastSprite->AbsoluteTileAddr / 16 * 16 + i);
|
||||
}
|
||||
|
||||
_hdPackBuilder->ProcessTile(_cycle - 1, _scanline, _lastSprite->AbsoluteTileAddr, tileInfo.Sprite, _mapper, false, _bankHashes[_lastSprite->TileAddr / _chrRamBankSize]);
|
||||
}
|
||||
}
|
||||
|
||||
if(_flags.BackgroundEnabled) {
|
||||
TileInfo* lastTile = &((_state.XScroll + ((_cycle - 1) & 0x07) < 8) ? _previousTile : _currentTile);
|
||||
if(lastTile->AbsoluteTileAddr >= 0) {
|
||||
tileInfo.Tile.TileIndex = (_isChrRam ? (lastTile->TileAddr & _chrRamIndexMask) : lastTile->AbsoluteTileAddr) / 16;
|
||||
tileInfo.Tile.PaletteColors = ReadPaletteRAM(lastTile->PaletteOffset + 3) | (ReadPaletteRAM(lastTile->PaletteOffset + 2) << 8) | (ReadPaletteRAM(lastTile->PaletteOffset + 1) << 16) | (ReadPaletteRAM(0) << 24);
|
||||
tileInfo.Tile.IsChrRamTile = _isChrRam;
|
||||
for(int i = 0; i < 16; i++) {
|
||||
tileInfo.Tile.TileData[i] = _mapper->GetMemoryValue(DebugMemoryType::ChrRom, lastTile->AbsoluteTileAddr / 16 * 16 + i);
|
||||
}
|
||||
|
||||
_hdPackBuilder->ProcessTile(_cycle - 1, _scanline, lastTile->AbsoluteTileAddr, tileInfo.Tile, _mapper, false, _bankHashes[lastTile->TileAddr / _chrRamBankSize]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//"If the current VRAM address points in the range $3F00-$3FFF during forced blanking, the color indicated by this palette location will be shown on screen instead of the backdrop color."
|
||||
_currentOutputBuffer[(_scanline << 8) + _cycle - 1] = _paletteRAM[_state.VideoRamAddr & 0x1F];
|
||||
}
|
||||
}
|
||||
|
||||
void WriteRAM(uint16_t addr, uint8_t value)
|
||||
{
|
||||
switch(GetRegisterID(addr)) {
|
||||
case PPURegisters::VideoMemoryData:
|
||||
if(_state.VideoRamAddr < 0x2000) {
|
||||
_needChrHash = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
PPU::WriteRAM(addr, value);
|
||||
}
|
||||
|
||||
void StreamState(bool saving)
|
||||
{
|
||||
PPU::StreamState(saving);
|
||||
if(!saving) {
|
||||
_needChrHash = true;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
HdBuilderPpu(BaseMapper* mapper, HdPackBuilder* hdPackBuilder, uint32_t chrRamBankSize) : PPU(mapper)
|
||||
{
|
||||
_hdPackBuilder = hdPackBuilder;
|
||||
_chrRamBankSize = chrRamBankSize;
|
||||
_chrRamIndexMask = chrRamBankSize - 1;
|
||||
_isChrRam = !_mapper->HasChrRom();
|
||||
_needChrHash = true;
|
||||
}
|
||||
|
||||
void SendFrame()
|
||||
{
|
||||
PPU::SendFrame();
|
||||
}
|
||||
};
|
364
Core/HdData.h
Normal file
364
Core/HdData.h
Normal file
|
@ -0,0 +1,364 @@
|
|||
#pragma once
|
||||
#include "stdafx.h"
|
||||
#include "PPU.h"
|
||||
#include "../Utilities/HexUtilities.h"
|
||||
|
||||
struct HdTileKey
|
||||
{
|
||||
static const uint32_t NoTile = -1;
|
||||
|
||||
uint32_t PaletteColors;
|
||||
uint8_t TileData[16];
|
||||
uint32_t TileIndex;
|
||||
bool IsChrRamTile = false;
|
||||
bool ForDefaultKey = false;
|
||||
|
||||
HdTileKey GetKey(bool defaultKey)
|
||||
{
|
||||
if(defaultKey) {
|
||||
HdTileKey copy = *this;
|
||||
copy.PaletteColors = 0xFFFFFFFF;
|
||||
return copy;
|
||||
} else {
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t GetHashCode() const
|
||||
{
|
||||
if(IsChrRamTile) {
|
||||
return CalculateHash((uint8_t*)&PaletteColors, 20);
|
||||
} else {
|
||||
uint64_t key = TileIndex | ((uint64_t)PaletteColors << 32);
|
||||
return CalculateHash((uint8_t*)&key, sizeof(key));
|
||||
}
|
||||
}
|
||||
|
||||
size_t operator() (const HdTileKey &tile) const {
|
||||
return tile.GetHashCode();
|
||||
}
|
||||
|
||||
bool operator==(const HdTileKey &other) const
|
||||
{
|
||||
if(IsChrRamTile) {
|
||||
return memcmp((uint8_t*)&PaletteColors, (uint8_t*)&other.PaletteColors, 20) == 0;
|
||||
} else {
|
||||
uint64_t key = TileIndex | ((uint64_t)PaletteColors << 32);
|
||||
uint64_t otherKey = other.TileIndex | ((uint64_t)other.PaletteColors << 32);
|
||||
return key == otherKey;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t CalculateHash(const uint8_t* key, size_t len) const
|
||||
{
|
||||
uint32_t result = 0;
|
||||
for(size_t i = 0; i < len; i += 4) {
|
||||
result += *((uint32_t*)key);
|
||||
result = (result << 2) | (result >> 30);
|
||||
key += 4;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool IsSpriteTile()
|
||||
{
|
||||
return (PaletteColors & 0xFF000000) == 0xFF000000;
|
||||
}
|
||||
};
|
||||
|
||||
namespace std {
|
||||
template <> struct hash<HdTileKey>
|
||||
{
|
||||
size_t operator()(const HdTileKey& x) const
|
||||
{
|
||||
return x.GetHashCode();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
struct HdPpuTileInfo : public HdTileKey
|
||||
{
|
||||
uint8_t OffsetX;
|
||||
uint8_t OffsetY;
|
||||
bool HorizontalMirroring;
|
||||
bool VerticalMirroring;
|
||||
bool BackgroundPriority;
|
||||
uint8_t BgColorIndex;
|
||||
uint8_t SpriteColorIndex;
|
||||
uint8_t BgColor;
|
||||
uint8_t SpriteColor;
|
||||
uint8_t NametableValue;
|
||||
};
|
||||
|
||||
struct HdPpuPixelInfo
|
||||
{
|
||||
HdPpuTileInfo Tile;
|
||||
HdPpuTileInfo Sprite;
|
||||
};
|
||||
|
||||
enum class HdPackConditionType
|
||||
{
|
||||
TileAtPosition,
|
||||
SpriteAtPosition,
|
||||
TileNearby,
|
||||
SpriteNearby,
|
||||
};
|
||||
|
||||
struct HdPackCondition
|
||||
{
|
||||
string Name;
|
||||
HdPackConditionType Type;
|
||||
int32_t TileX;
|
||||
int32_t TileY;
|
||||
uint32_t PaletteColors;
|
||||
int32_t TileIndex;
|
||||
uint8_t TileData[16];
|
||||
|
||||
bool CheckCondition(HdPpuPixelInfo *screenTiles, int x, int y)
|
||||
{
|
||||
switch(Type) {
|
||||
case HdPackConditionType::TileAtPosition:
|
||||
case HdPackConditionType::SpriteAtPosition: {
|
||||
int pixelIndex = (TileY << 8) + TileX;
|
||||
if(pixelIndex < 0 || pixelIndex > PPU::PixelCount) {
|
||||
return false;
|
||||
}
|
||||
|
||||
HdPpuTileInfo &tile = Type == HdPackConditionType::TileAtPosition ? screenTiles[pixelIndex].Tile : screenTiles[pixelIndex].Sprite;
|
||||
if(TileIndex >= 0) {
|
||||
return tile.PaletteColors == PaletteColors && tile.TileIndex == TileIndex;
|
||||
} else {
|
||||
return tile.PaletteColors == PaletteColors && memcmp(tile.TileData, TileData, sizeof(TileData)) == 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case HdPackConditionType::TileNearby:
|
||||
case HdPackConditionType::SpriteNearby: {
|
||||
int pixelIndex = ((y + TileY) << 8) + TileX + x;
|
||||
if(pixelIndex < 0 || pixelIndex > PPU::PixelCount) {
|
||||
return false;
|
||||
}
|
||||
|
||||
HdPpuTileInfo &tile = Type == HdPackConditionType::TileNearby ? screenTiles[pixelIndex].Tile : screenTiles[pixelIndex].Sprite;
|
||||
if(TileIndex >= 0) {
|
||||
return tile.TileIndex == TileIndex;
|
||||
} else {
|
||||
return memcmp(tile.TileData, TileData, sizeof(TileData)) == 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
string ToString()
|
||||
{
|
||||
stringstream out;
|
||||
out << "<condition>" << Name << ",";
|
||||
switch(Type) {
|
||||
case HdPackConditionType::TileAtPosition: out << "tileAtPosition"; break;
|
||||
case HdPackConditionType::SpriteAtPosition: out << "spriteAtPosition"; break;
|
||||
case HdPackConditionType::TileNearby: out << "tileNearby"; break;
|
||||
case HdPackConditionType::SpriteNearby: out << "spriteNearby"; break;
|
||||
}
|
||||
out << ",";
|
||||
out << TileX << ",";
|
||||
out << TileY << ",";
|
||||
if(TileIndex >= 0) {
|
||||
out << TileIndex << ",";
|
||||
} else {
|
||||
for(int i = 0; i < 16; i++) {
|
||||
out << HexUtilities::ToHex(TileData[i]);
|
||||
}
|
||||
}
|
||||
out << HexUtilities::ToHex(PaletteColors, true);
|
||||
|
||||
return out.str();
|
||||
}
|
||||
};
|
||||
|
||||
struct HdPackTileInfo : public HdTileKey
|
||||
{
|
||||
uint32_t X;
|
||||
uint32_t Y;
|
||||
uint32_t BitmapIndex;
|
||||
uint8_t Brightness;
|
||||
bool DefaultTile;
|
||||
bool Blank;
|
||||
vector<uint32_t> HdTileData;
|
||||
uint32_t ChrBankId;
|
||||
|
||||
vector<HdPackCondition*> Conditions;
|
||||
|
||||
bool MatchesCondition(HdPpuPixelInfo *screenTiles, int x, int y)
|
||||
{
|
||||
for(HdPackCondition* condition : Conditions) {
|
||||
if(!condition->CheckCondition(screenTiles, x, y)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
vector<uint32_t> ToRgb()
|
||||
{
|
||||
vector<uint32_t> rgbBuffer;
|
||||
uint32_t* palette = EmulationSettings::GetRgbPalette();
|
||||
for(uint8_t i = 0; i < 8; i++) {
|
||||
uint8_t lowByte = TileData[i];
|
||||
uint8_t highByte = TileData[i + 8];
|
||||
for(uint8_t j = 0; j < 8; j++) {
|
||||
uint8_t color = ((lowByte >> (7 - j)) & 0x01) | (((highByte >> (7 - j)) & 0x01) << 1);
|
||||
uint32_t rgbColor;
|
||||
if(IsSpriteTile()) {
|
||||
rgbColor = color == 0 ? 0x00FFFFFF : palette[(PaletteColors >> ((3 - color) * 8)) & 0x3F];
|
||||
} else {
|
||||
rgbColor = palette[(PaletteColors >> ((3 - color) * 8)) & 0x3F];
|
||||
}
|
||||
rgbBuffer.push_back(rgbColor);
|
||||
}
|
||||
}
|
||||
|
||||
return rgbBuffer;
|
||||
}
|
||||
|
||||
void UpdateBlankTileFlag()
|
||||
{
|
||||
for(size_t i = 0; i < HdTileData.size(); i++) {
|
||||
if(HdTileData[i] != HdTileData[0]) {
|
||||
Blank = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
Blank = true;
|
||||
}
|
||||
|
||||
string ToString(int pngIndex)
|
||||
{
|
||||
stringstream out;
|
||||
|
||||
if(Conditions.size() > 0) {
|
||||
out << "[";
|
||||
for(int i = 0; i < Conditions.size(); i++) {
|
||||
if(i > 0) {
|
||||
out << "&";
|
||||
}
|
||||
out << Conditions[i]->Name;
|
||||
}
|
||||
out << "]";
|
||||
}
|
||||
|
||||
if(IsChrRamTile) {
|
||||
out << "<tile>" << pngIndex << ",";
|
||||
|
||||
for(int i = 0; i < 16; i++) {
|
||||
out << HexUtilities::ToHex(TileData[i]);
|
||||
}
|
||||
out << "," <<
|
||||
HexUtilities::ToHex(PaletteColors, true) << "," <<
|
||||
X << "," <<
|
||||
Y << "," <<
|
||||
(double)Brightness / 255 << "," <<
|
||||
(DefaultTile ? "Y" : "N") << "," <<
|
||||
ChrBankId << "," <<
|
||||
TileIndex;
|
||||
} else {
|
||||
out << "<tile>" <<
|
||||
pngIndex << "," <<
|
||||
TileIndex << "," <<
|
||||
HexUtilities::ToHex(PaletteColors, true) << "," <<
|
||||
X << "," <<
|
||||
Y << "," <<
|
||||
(double)Brightness / 255 << "," <<
|
||||
(DefaultTile ? "Y" : "N");
|
||||
}
|
||||
|
||||
return out.str();
|
||||
}
|
||||
};
|
||||
|
||||
struct HdPackBitmapInfo
|
||||
{
|
||||
vector<uint8_t> PixelData;
|
||||
uint32_t Width;
|
||||
uint32_t Height;
|
||||
};
|
||||
|
||||
struct HdBackgroundFileData
|
||||
{
|
||||
string PngName;
|
||||
uint32_t Width;
|
||||
uint32_t Height;
|
||||
|
||||
vector<uint8_t> PixelData;
|
||||
};
|
||||
|
||||
struct HdBackgroundInfo
|
||||
{
|
||||
HdBackgroundFileData* Data;
|
||||
uint16_t Brightness;
|
||||
vector<HdPackCondition*> Conditions;
|
||||
|
||||
uint32_t* data()
|
||||
{
|
||||
return (uint32_t*)Data->PixelData.data();
|
||||
}
|
||||
|
||||
string ToString()
|
||||
{
|
||||
stringstream out;
|
||||
|
||||
if(Conditions.size() > 0) {
|
||||
out << "[";
|
||||
for(int i = 0; i < Conditions.size(); i++) {
|
||||
if(i > 0) {
|
||||
out << "&";
|
||||
}
|
||||
out << Conditions[i]->Name;
|
||||
}
|
||||
out << "]";
|
||||
}
|
||||
|
||||
out << Data->PngName << ",";
|
||||
out << (Brightness / 255.0);
|
||||
|
||||
return out.str();
|
||||
}
|
||||
};
|
||||
|
||||
struct HdPackData
|
||||
{
|
||||
vector<HdBackgroundInfo> Backgrounds;
|
||||
vector<unique_ptr<HdBackgroundFileData>> BackgroundFileData;
|
||||
vector<unique_ptr<HdPackTileInfo>> Tiles;
|
||||
vector<unique_ptr<HdPackCondition>> Conditions;
|
||||
std::unordered_map<HdTileKey, vector<HdPackTileInfo*>> TileByKey;
|
||||
std::unordered_map<string, string> PatchesByHash;
|
||||
vector<uint32_t> Palette;
|
||||
vector<uint32_t> PaletteBackup;
|
||||
uint32_t Scale = 1;
|
||||
uint32_t Version = 0;
|
||||
uint32_t OptionFlags = 0;
|
||||
|
||||
HdPackData()
|
||||
{
|
||||
}
|
||||
|
||||
HdPackData(const HdPackData&) = delete;
|
||||
HdPackData& operator=(const HdPackData&) = delete;
|
||||
|
||||
~HdPackData()
|
||||
{
|
||||
if(PaletteBackup.size() == 0x40) {
|
||||
EmulationSettings::SetRgbPalette(PaletteBackup.data());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
enum class HdPackOptions
|
||||
{
|
||||
None = 0,
|
||||
NoSpriteLimit = 1,
|
||||
};
|
229
Core/HdNesPack.cpp
Normal file
229
Core/HdNesPack.cpp
Normal file
|
@ -0,0 +1,229 @@
|
|||
#include "stdafx.h"
|
||||
#include <algorithm>
|
||||
#include <unordered_map>
|
||||
#include "HdNesPack.h"
|
||||
#include "Console.h"
|
||||
#include "MessageManager.h"
|
||||
#include "EmulationSettings.h"
|
||||
#include "HdPackLoader.h"
|
||||
#include "../Utilities/FolderUtilities.h"
|
||||
#include "../Utilities/PNGHelper.h"
|
||||
|
||||
HdNesPack::HdNesPack()
|
||||
{
|
||||
}
|
||||
|
||||
HdNesPack::~HdNesPack()
|
||||
{
|
||||
}
|
||||
|
||||
void HdNesPack::BlendColors(uint8_t output[4], uint8_t input[4])
|
||||
{
|
||||
uint8_t alpha = input[3] + 1;
|
||||
uint8_t invertedAlpha = 256 - input[3];
|
||||
output[0] = (uint8_t)((alpha * input[0] + invertedAlpha * output[0]) >> 8);
|
||||
output[1] = (uint8_t)((alpha * input[1] + invertedAlpha * output[1]) >> 8);
|
||||
output[2] = (uint8_t)((alpha * input[2] + invertedAlpha * output[2]) >> 8);
|
||||
output[3] = 0xFF;
|
||||
}
|
||||
|
||||
uint32_t HdNesPack::AdjustBrightness(uint8_t input[4], uint16_t brightness)
|
||||
{
|
||||
uint8_t output[4];
|
||||
output[0] = std::min(255, (brightness * input[0]) >> 8);
|
||||
output[1] = std::min(255, (brightness * input[1]) >> 8);
|
||||
output[2] = std::min(255, (brightness * input[2]) >> 8);
|
||||
output[3] = input[3];
|
||||
return *((uint32_t*)output);
|
||||
}
|
||||
|
||||
void HdNesPack::DrawTile(HdPpuTileInfo &tileInfo, HdPackTileInfo &hdPackTileInfo, uint32_t *outputBuffer, uint32_t screenWidth, bool drawBackground)
|
||||
{
|
||||
uint32_t scale = GetScale();
|
||||
uint32_t *bitmapData = hdPackTileInfo.HdTileData.data();
|
||||
uint32_t tileWidth = 8 * scale;
|
||||
uint8_t tileOffsetX = tileInfo.HorizontalMirroring ? 7 - tileInfo.OffsetX : tileInfo.OffsetX;
|
||||
uint32_t bitmapOffset = (tileInfo.OffsetY * scale) * tileWidth + tileOffsetX * scale;
|
||||
int32_t bitmapSmallInc = 1;
|
||||
int32_t bitmapLargeInc = tileWidth - scale;
|
||||
if(tileInfo.HorizontalMirroring) {
|
||||
bitmapOffset += scale - 1;
|
||||
bitmapSmallInc = -1;
|
||||
bitmapLargeInc = tileWidth + scale;
|
||||
}
|
||||
if(tileInfo.VerticalMirroring) {
|
||||
bitmapOffset += tileWidth * (scale - 1);
|
||||
bitmapLargeInc = (tileInfo.HorizontalMirroring ? (int32_t)scale : -(int32_t)scale) - (int32_t)tileWidth;
|
||||
}
|
||||
for(uint32_t y = 0; y < scale; y++) {
|
||||
for(uint32_t x = 0; x < scale; x++) {
|
||||
if(drawBackground) {
|
||||
*outputBuffer = EmulationSettings::GetRgbPalette()[tileInfo.BgColor];
|
||||
}
|
||||
if(!tileInfo.BackgroundPriority || tileInfo.BgColorIndex == 0) {
|
||||
uint32_t rgbValue = AdjustBrightness((uint8_t*)(bitmapData + bitmapOffset), hdPackTileInfo.Brightness);
|
||||
if((bitmapData[bitmapOffset] & 0xFF000000) == 0xFF000000) {
|
||||
*outputBuffer = rgbValue;
|
||||
} else if((bitmapData[bitmapOffset] & 0xFF000000) != 0) {
|
||||
BlendColors((uint8_t*)outputBuffer, (uint8_t*)&rgbValue);
|
||||
}
|
||||
}
|
||||
outputBuffer++;
|
||||
bitmapOffset += bitmapSmallInc;
|
||||
}
|
||||
bitmapOffset += bitmapLargeInc;
|
||||
outputBuffer += screenWidth - scale;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t HdNesPack::GetScale()
|
||||
{
|
||||
return Console::GetHdData()->Scale;
|
||||
}
|
||||
|
||||
void HdNesPack::OnBeforeApplyFilter(HdPpuPixelInfo *screenTiles)
|
||||
{
|
||||
HdPackData* hdData = Console::GetHdData();
|
||||
|
||||
if(hdData->OptionFlags & (int)HdPackOptions::NoSpriteLimit) {
|
||||
EmulationSettings::SetFlags(EmulationFlags::RemoveSpriteLimit | EmulationFlags::AdaptiveSpriteLimit);
|
||||
}
|
||||
|
||||
if(hdData->Palette.size() == 0x40) {
|
||||
EmulationSettings::SetRgbPalette(hdData->Palette.data());
|
||||
}
|
||||
|
||||
_backgroundIndex = -1;
|
||||
for(int i = 0; i < hdData->Backgrounds.size(); i++) {
|
||||
bool isMatch = true;
|
||||
for(HdPackCondition* condition : hdData->Backgrounds[i].Conditions) {
|
||||
if(!condition->CheckCondition(screenTiles, 0, 0)) {
|
||||
isMatch = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(isMatch) {
|
||||
_backgroundIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HdPackTileInfo * HdNesPack::GetMatchingTile(HdPpuPixelInfo *screenTiles, uint32_t x, uint32_t y, HdTileKey &key)
|
||||
{
|
||||
HdPackData *hdData = Console::GetHdData();
|
||||
std::unordered_map<HdTileKey, vector<HdPackTileInfo*>>::const_iterator hdTile;
|
||||
hdTile = hdData->TileByKey.find(key);
|
||||
if(hdTile == hdData->TileByKey.end()) {
|
||||
hdTile = hdData->TileByKey.find(key.GetKey(true));
|
||||
}
|
||||
|
||||
if(hdTile != hdData->TileByKey.end()) {
|
||||
for(HdPackTileInfo* tile : hdTile->second) {
|
||||
if(tile->MatchesCondition(screenTiles, x, y)) {
|
||||
return tile;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool HdNesPack::IsNextToSprite(HdPpuPixelInfo *screenTiles, uint32_t x, uint32_t y)
|
||||
{
|
||||
bool hasNonBackgroundSurrounding = false;
|
||||
auto processAdjacentTile = [&hasNonBackgroundSurrounding](HdPpuPixelInfo& pixelInfo) {
|
||||
if(pixelInfo.Sprite.TileIndex == HdPpuTileInfo::NoTile || pixelInfo.Sprite.SpriteColorIndex == 0 || pixelInfo.Sprite.SpriteColor != pixelInfo.Sprite.BgColor) {
|
||||
hasNonBackgroundSurrounding |= pixelInfo.Sprite.TileIndex != HdPpuTileInfo::NoTile && pixelInfo.Sprite.SpriteColorIndex != 0 || pixelInfo.Tile.BgColorIndex != 0;
|
||||
}
|
||||
};
|
||||
for(int i = -1; i <= 1; i++) {
|
||||
for(int j = -1; j <= 1; j++) {
|
||||
if(!hasNonBackgroundSurrounding) {
|
||||
processAdjacentTile(screenTiles[(i + y) * 256 + j + x]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return hasNonBackgroundSurrounding;
|
||||
}
|
||||
|
||||
uint32_t HdNesPack::GetCustomBackgroundPixel(int x, int y, int offsetX, int offsetY)
|
||||
{
|
||||
HdPackData *hdData = Console::GetHdData();
|
||||
return AdjustBrightness((uint8_t*)(hdData->Backgrounds[_backgroundIndex].data() + (y * hdData->Scale + offsetY) * 256 * hdData->Scale + x * hdData->Scale + offsetX), hdData->Backgrounds[_backgroundIndex].Brightness);
|
||||
}
|
||||
|
||||
void HdNesPack::GetPixels(HdPpuPixelInfo *screenTiles, uint32_t x, uint32_t y, HdPpuPixelInfo &pixelInfo, uint32_t sdPixel, uint32_t *outputBuffer, uint32_t screenWidth)
|
||||
{
|
||||
HdPackTileInfo *hdPackTileInfo = nullptr;
|
||||
HdPackTileInfo *hdPackSpriteInfo = nullptr;
|
||||
HdPackData *hdData = Console::GetHdData();
|
||||
|
||||
if(hdData->Version <= 2) {
|
||||
pixelInfo.Sprite.PaletteColors &= 0xFFFFFF;
|
||||
pixelInfo.Tile.PaletteColors &= 0xFFFFFF;
|
||||
}
|
||||
|
||||
bool hasTile = pixelInfo.Tile.TileIndex != HdPpuTileInfo::NoTile;
|
||||
bool hasSprite = pixelInfo.Sprite.TileIndex != HdPpuTileInfo::NoTile;
|
||||
|
||||
std::unordered_map<HdTileKey, HdPackTileInfo*>::const_iterator hdTile;
|
||||
if(hasTile) {
|
||||
hdPackTileInfo = GetMatchingTile(screenTiles, x, y, pixelInfo.Tile);
|
||||
}
|
||||
|
||||
if(hasSprite) {
|
||||
hdPackSpriteInfo = GetMatchingTile(screenTiles, x, y, pixelInfo.Sprite);
|
||||
}
|
||||
|
||||
bool needPixel = true;
|
||||
if(hdPackSpriteInfo && pixelInfo.Sprite.BackgroundPriority && pixelInfo.Tile.BgColorIndex == 0) {
|
||||
DrawTile(pixelInfo.Sprite, *hdPackSpriteInfo, outputBuffer, screenWidth, !hdPackTileInfo);
|
||||
needPixel = false;
|
||||
}
|
||||
|
||||
bool hasCustomBackground = _backgroundIndex >= 0 && y < hdData->Backgrounds[_backgroundIndex].Data->Height;
|
||||
bool hasNonBackgroundSurrounding = hasCustomBackground ? IsNextToSprite(screenTiles, x, y) : false;
|
||||
if(hasCustomBackground) {
|
||||
uint32_t *buffer = outputBuffer;
|
||||
for(uint32_t i = 0; i < hdData->Scale; i++) {
|
||||
for(uint32_t j = 0; j < hdData->Scale; j++) {
|
||||
*buffer = GetCustomBackgroundPixel(x, y, j, i);
|
||||
buffer++;
|
||||
}
|
||||
buffer += screenWidth - hdData->Scale;
|
||||
}
|
||||
}
|
||||
|
||||
if(hdPackTileInfo) {
|
||||
DrawTile(pixelInfo.Tile, *hdPackTileInfo, outputBuffer, screenWidth, true);
|
||||
needPixel = false;
|
||||
}
|
||||
|
||||
if(needPixel || (!hdPackSpriteInfo && hasSprite && pixelInfo.Sprite.SpriteColorIndex != 0 && (!pixelInfo.Sprite.BackgroundPriority || pixelInfo.Tile.BgColorIndex == 0))) {
|
||||
//Write the standard SD tile if no HD tile is present
|
||||
uint32_t *buffer = outputBuffer;
|
||||
|
||||
if(hasSprite && hdPackSpriteInfo) {
|
||||
sdPixel = EmulationSettings::GetRgbPalette()[pixelInfo.Sprite.BgColor];
|
||||
}
|
||||
|
||||
bool useCustomBackground = !hasNonBackgroundSurrounding && hasCustomBackground && (!hasSprite || pixelInfo.Sprite.SpriteColorIndex == 0 || pixelInfo.Sprite.SpriteColor == pixelInfo.Sprite.BgColor) && pixelInfo.Tile.BgColorIndex == 0;
|
||||
|
||||
for(uint32_t i = 0; i < hdData->Scale; i++) {
|
||||
for(uint32_t j = 0; j < hdData->Scale; j++) {
|
||||
if(useCustomBackground) {
|
||||
sdPixel = GetCustomBackgroundPixel(x, y, j, i);
|
||||
}
|
||||
*buffer = sdPixel;
|
||||
buffer++;
|
||||
}
|
||||
buffer += screenWidth - hdData->Scale;
|
||||
}
|
||||
}
|
||||
|
||||
if(hdPackSpriteInfo && (!pixelInfo.Sprite.BackgroundPriority || pixelInfo.Tile.BgColorIndex == 0)) {
|
||||
DrawTile(pixelInfo.Sprite, *hdPackSpriteInfo, outputBuffer, screenWidth, false);
|
||||
}
|
||||
}
|
283
Core/HdNesPack.h
283
Core/HdNesPack.h
|
@ -1,279 +1,26 @@
|
|||
#pragma once
|
||||
#include "stdafx.h"
|
||||
#include "HdData.h"
|
||||
|
||||
#include <unordered_map>
|
||||
#include "Console.h"
|
||||
#include "MessageManager.h"
|
||||
#include "EmulationSettings.h"
|
||||
#include "../Utilities/FolderUtilities.h"
|
||||
#include "../Utilities/PNGHelper.h"
|
||||
|
||||
struct HdPpuTileInfo
|
||||
{
|
||||
static const uint32_t NoTile = -1;
|
||||
uint32_t TileIndex;
|
||||
uint32_t PaletteColors;
|
||||
uint8_t OffsetX;
|
||||
uint8_t OffsetY;
|
||||
bool HorizontalMirroring;
|
||||
bool VerticalMirroring;
|
||||
bool BackgroundPriority;
|
||||
uint8_t BgColorIndex;
|
||||
uint8_t BgColor;
|
||||
|
||||
uint64_t GetKey(bool defaultKey)
|
||||
{
|
||||
if(defaultKey) {
|
||||
return (uint64_t)TileIndex | 0xFFFFFFFF00000000;
|
||||
} else {
|
||||
return (uint64_t)TileIndex | ((uint64_t)PaletteColors << 32);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct HdPpuPixelInfo
|
||||
{
|
||||
HdPpuTileInfo Tile;
|
||||
HdPpuTileInfo Sprite;
|
||||
};
|
||||
|
||||
struct HdPackTileInfo
|
||||
{
|
||||
uint32_t TileIndex;
|
||||
uint32_t BitmapIndex;
|
||||
uint32_t PaletteColors;
|
||||
uint32_t X;
|
||||
uint32_t Y;
|
||||
bool DefaultTile;
|
||||
|
||||
uint64_t GetKey(bool defaultKey)
|
||||
{
|
||||
if(defaultKey) {
|
||||
return (uint64_t)TileIndex | 0xFFFFFFFF00000000;
|
||||
} else {
|
||||
return (uint64_t)TileIndex | ((uint64_t)PaletteColors << 32);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct HdPackBitmapInfo
|
||||
{
|
||||
vector<uint8_t> PixelData;
|
||||
uint32_t Width;
|
||||
uint32_t Height;
|
||||
};
|
||||
|
||||
class HdNesPack : public INotificationListener
|
||||
class HdNesPack
|
||||
{
|
||||
private:
|
||||
vector<HdPackBitmapInfo> _hdNesBitmaps;
|
||||
vector<HdPackTileInfo> _hdNesTiles;
|
||||
std::unordered_map<uint64_t, HdPackTileInfo*> _tileInfoByKey;
|
||||
SimpleLock _loadLock;
|
||||
uint32_t _hdScale;
|
||||
int32_t _backgroundIndex = -1;
|
||||
|
||||
void LoadHdNesPack()
|
||||
{
|
||||
_loadLock.Acquire();
|
||||
void BlendColors(uint8_t output[4], uint8_t input[4]);
|
||||
uint32_t AdjustBrightness(uint8_t input[4], uint16_t brightness);
|
||||
void DrawTile(HdPpuTileInfo &tileInfo, HdPackTileInfo &hdPackTileInfo, uint32_t* outputBuffer, uint32_t screenWidth, bool drawBackground);
|
||||
|
||||
_hdNesBitmaps.clear();
|
||||
_hdNesTiles.clear();
|
||||
_tileInfoByKey.clear();
|
||||
|
||||
string hdPackFolder = FolderUtilities::CombinePath(FolderUtilities::GetHdPackFolder(), FolderUtilities::GetFilename(Console::GetRomName(), false));
|
||||
string hdPackDefinitionFile = FolderUtilities::CombinePath(hdPackFolder, "hires.txt");
|
||||
ifstream packDefinition(hdPackDefinitionFile, ios::in | ios::binary);
|
||||
while(packDefinition.good()) {
|
||||
string lineContent;
|
||||
std::getline(packDefinition, lineContent);
|
||||
lineContent = lineContent.substr(0, lineContent.length() - 1);
|
||||
|
||||
if(lineContent.substr(0, 7) == "<scale>") {
|
||||
lineContent = lineContent.substr(7);
|
||||
_hdScale = std::stoi(lineContent);
|
||||
} else if(lineContent.substr(0, 5) == "<img>") {
|
||||
lineContent = lineContent.substr(5);
|
||||
HdPackBitmapInfo bitmapInfo;
|
||||
string imageFile = FolderUtilities::CombinePath(hdPackFolder, lineContent);
|
||||
PNGHelper::ReadPNG(imageFile, bitmapInfo.PixelData, bitmapInfo.Width, bitmapInfo.Height);
|
||||
_hdNesBitmaps.push_back(bitmapInfo);
|
||||
} else if(lineContent.substr(0, 6) == "<tile>") {
|
||||
lineContent = lineContent.substr(6);
|
||||
vector<string> tokens = split(lineContent, ',');
|
||||
HdPackTileInfo tileInfo;
|
||||
tileInfo.TileIndex = std::stoi(tokens[0]);
|
||||
tileInfo.BitmapIndex = std::stoi(tokens[1]);
|
||||
tileInfo.PaletteColors = std::stoi(tokens[2]) | (std::stoi(tokens[3]) << 8) | (std::stoi(tokens[4]) << 16);
|
||||
tileInfo.X = std::stoi(tokens[5]);
|
||||
tileInfo.Y = std::stoi(tokens[6]);
|
||||
tileInfo.DefaultTile = (tokens[7] == "Y");
|
||||
_hdNesTiles.push_back(tileInfo);
|
||||
}
|
||||
}
|
||||
|
||||
for(HdPackTileInfo &tileInfo : _hdNesTiles) {
|
||||
_tileInfoByKey[tileInfo.GetKey(false)] = &tileInfo;
|
||||
if(tileInfo.DefaultTile) {
|
||||
_tileInfoByKey[tileInfo.GetKey(true)] = &tileInfo;
|
||||
}
|
||||
}
|
||||
|
||||
packDefinition.close();
|
||||
|
||||
_loadLock.Release();
|
||||
}
|
||||
|
||||
vector<string> split(const string &s, char delim)
|
||||
{
|
||||
vector<string> tokens;
|
||||
std::stringstream ss(s);
|
||||
std::string item;
|
||||
while(std::getline(ss, item, delim)) {
|
||||
tokens.push_back(item);
|
||||
}
|
||||
return tokens;
|
||||
}
|
||||
bool IsNextToSprite(HdPpuPixelInfo *screenTiles, uint32_t x, uint32_t y);
|
||||
uint32_t GetCustomBackgroundPixel(int x, int y, int offsetX, int offsetY);
|
||||
|
||||
public:
|
||||
HdNesPack()
|
||||
{
|
||||
_hdScale = 2;
|
||||
HdNesPack();
|
||||
~HdNesPack();
|
||||
|
||||
LoadHdNesPack();
|
||||
MessageManager::RegisterNotificationListener(this);
|
||||
}
|
||||
uint32_t GetScale();
|
||||
|
||||
~HdNesPack()
|
||||
{
|
||||
MessageManager::UnregisterNotificationListener(this);
|
||||
}
|
||||
|
||||
uint32_t GetScale()
|
||||
{
|
||||
return _hdScale;
|
||||
}
|
||||
|
||||
void BlendColors(uint8_t output[4], uint8_t input[4])
|
||||
{
|
||||
uint8_t alpha = input[3] + 1;
|
||||
uint8_t invertedAlpha = 256 - input[3];
|
||||
output[0] = (uint8_t)((alpha * input[0] + invertedAlpha * output[0]) >> 8);
|
||||
output[1] = (uint8_t)((alpha * input[1] + invertedAlpha * output[1]) >> 8);
|
||||
output[2] = (uint8_t)((alpha * input[2] + invertedAlpha * output[2]) >> 8);
|
||||
output[3] = 0xFF;
|
||||
}
|
||||
|
||||
void DrawTile(HdPpuTileInfo &tileInfo, HdPackTileInfo &hdPackTileInfo, uint32_t* outputBuffer, uint32_t screenWidth, bool drawBackground)
|
||||
{
|
||||
HdPackBitmapInfo &bitmapInfo = _hdNesBitmaps[hdPackTileInfo.BitmapIndex];
|
||||
uint32_t* bitmapData = (uint32_t*)&bitmapInfo.PixelData[0];
|
||||
uint8_t tileOffsetX = tileInfo.HorizontalMirroring ? 7 - tileInfo.OffsetX : tileInfo.OffsetX;
|
||||
uint32_t bitmapOffset = (hdPackTileInfo.Y + tileInfo.OffsetY * _hdScale) * bitmapInfo.Width + hdPackTileInfo.X + tileOffsetX * _hdScale;
|
||||
int32_t bitmapSmallInc = 1;
|
||||
int32_t bitmapLargeInc = bitmapInfo.Width - _hdScale;
|
||||
if(tileInfo.HorizontalMirroring) {
|
||||
bitmapOffset += _hdScale - 1;
|
||||
bitmapSmallInc = -1;
|
||||
bitmapLargeInc = bitmapInfo.Width + _hdScale;
|
||||
}
|
||||
if(tileInfo.VerticalMirroring) {
|
||||
bitmapOffset += bitmapInfo.Width * (_hdScale - 1);
|
||||
bitmapLargeInc = tileInfo.HorizontalMirroring ? -(int32_t)bitmapInfo.Width + (int32_t)_hdScale : -(int32_t)bitmapInfo.Width - (int32_t)_hdScale;
|
||||
}
|
||||
for(uint32_t y = 0; y < _hdScale; y++) {
|
||||
for(uint32_t x = 0; x < _hdScale; x++) {
|
||||
if(drawBackground) {
|
||||
*outputBuffer = EmulationSettings::GetRgbPalette()[tileInfo.BgColor];
|
||||
}
|
||||
if(!tileInfo.BackgroundPriority || tileInfo.BgColorIndex == 0) {
|
||||
if((bitmapData[bitmapOffset] & 0xFF000000) == 0xFF000000) {
|
||||
*outputBuffer = bitmapData[bitmapOffset];
|
||||
} else if((bitmapData[bitmapOffset] & 0xFF000000) != 0) {
|
||||
BlendColors((uint8_t*)outputBuffer, (uint8_t*)&bitmapData[bitmapOffset]);
|
||||
}
|
||||
}
|
||||
outputBuffer++;
|
||||
bitmapOffset += bitmapSmallInc;
|
||||
}
|
||||
bitmapOffset += bitmapLargeInc;
|
||||
outputBuffer += screenWidth - _hdScale;
|
||||
}
|
||||
}
|
||||
|
||||
void GetPixels(HdPpuPixelInfo &pixelInfo, uint32_t sdPixel, uint32_t *outputBuffer, uint32_t screenWidth)
|
||||
{
|
||||
_loadLock.Acquire();
|
||||
|
||||
HdPackTileInfo *hdPackTileInfo = nullptr;
|
||||
HdPackTileInfo *hdPackSpriteInfo = nullptr;
|
||||
|
||||
std::unordered_map<uint64_t, HdPackTileInfo*>::const_iterator hdTile;
|
||||
if(pixelInfo.Tile.TileIndex != HdPpuTileInfo::NoTile) {
|
||||
hdTile = _tileInfoByKey.find(pixelInfo.Tile.GetKey(false));
|
||||
if(hdTile != _tileInfoByKey.end()) {
|
||||
hdPackTileInfo = hdTile->second;
|
||||
} else {
|
||||
hdTile = _tileInfoByKey.find(pixelInfo.Tile.GetKey(true));
|
||||
if(hdTile != _tileInfoByKey.end()) {
|
||||
hdPackTileInfo = hdTile->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(pixelInfo.Sprite.TileIndex != HdPpuTileInfo::NoTile) {
|
||||
hdTile = _tileInfoByKey.find(pixelInfo.Sprite.GetKey(false));
|
||||
if(hdTile != _tileInfoByKey.end()) {
|
||||
hdPackSpriteInfo = hdTile->second;
|
||||
} else {
|
||||
hdTile = _tileInfoByKey.find(pixelInfo.Sprite.GetKey(true));
|
||||
if(hdTile != _tileInfoByKey.end()) {
|
||||
hdPackSpriteInfo = hdTile->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(hdPackSpriteInfo && pixelInfo.Sprite.BackgroundPriority) {
|
||||
DrawTile(pixelInfo.Sprite, *hdPackSpriteInfo, outputBuffer, screenWidth, !hdPackTileInfo);
|
||||
}
|
||||
|
||||
if(!hdPackTileInfo && !hdPackSpriteInfo) {
|
||||
//Write the standard SD tile if no HD tile is present
|
||||
uint32_t *buffer = outputBuffer;
|
||||
for(uint32_t y = 0; y < _hdScale; y++) {
|
||||
for(uint32_t x = 0; x < _hdScale; x++) {
|
||||
*buffer = sdPixel;
|
||||
buffer++;
|
||||
}
|
||||
buffer += screenWidth - _hdScale;
|
||||
}
|
||||
}
|
||||
|
||||
if(hdPackTileInfo) {
|
||||
DrawTile(pixelInfo.Tile, *hdPackTileInfo, outputBuffer, screenWidth, true);
|
||||
}
|
||||
|
||||
if(hdPackSpriteInfo && (!pixelInfo.Sprite.BackgroundPriority || pixelInfo.Tile.BgColorIndex == 0)) {
|
||||
DrawTile(pixelInfo.Sprite, *hdPackSpriteInfo, outputBuffer, screenWidth, !hdPackTileInfo);
|
||||
}
|
||||
|
||||
_loadLock.Release();
|
||||
}
|
||||
|
||||
void ProcessNotification(ConsoleNotificationType type, void* parameter) override
|
||||
{
|
||||
if(type == ConsoleNotificationType::GameLoaded) {
|
||||
LoadHdNesPack();
|
||||
}
|
||||
}
|
||||
|
||||
static bool HasHdPack(string romFilepath)
|
||||
{
|
||||
string hdPackFolder = FolderUtilities::CombinePath(FolderUtilities::GetHdPackFolder(), FolderUtilities::GetFilename(romFilepath, false));
|
||||
string hdPackDefinitionFile = FolderUtilities::CombinePath(hdPackFolder, "hires.txt");
|
||||
|
||||
if(ifstream(hdPackDefinitionFile)) {
|
||||
return EmulationSettings::CheckFlag(EmulationFlags::UseHdPacks);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
void OnBeforeApplyFilter(HdPpuPixelInfo *screenTiles);
|
||||
HdPackTileInfo* GetMatchingTile(HdPpuPixelInfo *screenTiles, uint32_t x, uint32_t y, HdTileKey& key);
|
||||
void GetPixels(HdPpuPixelInfo *screenTiles, uint32_t x, uint32_t y, HdPpuPixelInfo &pixelInfo, uint32_t sdPixel, uint32_t *outputBuffer, uint32_t screenWidth);
|
||||
};
|
||||
|
|
402
Core/HdPackBuilder.cpp
Normal file
402
Core/HdPackBuilder.cpp
Normal file
|
@ -0,0 +1,402 @@
|
|||
#include "stdafx.h"
|
||||
#include "HdPackBuilder.h"
|
||||
|
||||
HdPackBuilder* HdPackBuilder::_instance = nullptr;
|
||||
|
||||
enum HdPackRecordFlags
|
||||
{
|
||||
None = 0,
|
||||
UseLargeSprites = 1,
|
||||
SortByUsageFrequency = 2,
|
||||
GroupBlankTiles = 4,
|
||||
};
|
||||
|
||||
HdPackBuilder::HdPackBuilder(string saveFolder, ScaleFilterType filterType, uint32_t scale, uint32_t flags, uint32_t chrRamBankSize, bool isChrRam)
|
||||
{
|
||||
_saveFolder = saveFolder;
|
||||
_filterType = filterType;
|
||||
_chrRamBankSize = chrRamBankSize;
|
||||
_flags = flags;
|
||||
_isChrRam = isChrRam;
|
||||
|
||||
string existingPackDefinition = FolderUtilities::CombinePath(saveFolder, "hires.txt");
|
||||
if(ifstream(existingPackDefinition)) {
|
||||
HdPackLoader::LoadHdNesPack(existingPackDefinition, _hdData);
|
||||
for(unique_ptr<HdPackTileInfo> &tile : _hdData.Tiles) {
|
||||
//Mark the tiles in the first PNGs as higher usage (preserves order when adding new tiles to an existing set)
|
||||
AddTile(tile.get(), 0xFFFFFFFF - tile->BitmapIndex);
|
||||
}
|
||||
|
||||
if(_hdData.Scale != scale) {
|
||||
_filterType = ScaleFilterType::Prescale;
|
||||
}
|
||||
} else {
|
||||
_hdData.Scale = scale;
|
||||
}
|
||||
|
||||
_romName = FolderUtilities::GetFilename(Console::GetRomName(), false);
|
||||
_instance = this;
|
||||
}
|
||||
|
||||
HdPackBuilder::~HdPackBuilder()
|
||||
{
|
||||
SaveHdPack();
|
||||
if(_instance == this) {
|
||||
_instance = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void HdPackBuilder::AddTile(HdPackTileInfo *tile, uint32_t usageCount)
|
||||
{
|
||||
bool isTileBlank = (_flags & HdPackRecordFlags::GroupBlankTiles) ? tile->Blank : false;
|
||||
|
||||
int chrBankId = isTileBlank ? 0xFFFFFFFF : tile->ChrBankId;
|
||||
int palette = isTileBlank ? _blankTilePalette : tile->PaletteColors;
|
||||
|
||||
if(_tilesByChrBankByPalette.find(chrBankId) == _tilesByChrBankByPalette.end()) {
|
||||
_tilesByChrBankByPalette[chrBankId] = std::map<uint32_t, vector<HdPackTileInfo*>>();
|
||||
}
|
||||
|
||||
std::map<uint32_t, vector<HdPackTileInfo*>> &paletteMap = _tilesByChrBankByPalette[chrBankId];
|
||||
if(paletteMap.find(palette) == paletteMap.end()) {
|
||||
paletteMap[palette] = vector<HdPackTileInfo*>(256, nullptr);
|
||||
}
|
||||
|
||||
if(isTileBlank) {
|
||||
paletteMap[palette][_blankTileIndex] = tile;
|
||||
_blankTileIndex++;
|
||||
if(_blankTileIndex == _chrRamBankSize / 16) {
|
||||
_blankTileIndex = 0;
|
||||
_blankTilePalette++;
|
||||
}
|
||||
} else {
|
||||
paletteMap[palette][tile->TileIndex % 256] = tile;
|
||||
}
|
||||
|
||||
_tileUsageCount[tile->GetKey(false)] = usageCount;
|
||||
}
|
||||
|
||||
void HdPackBuilder::ProcessTile(int x, int y, uint16_t tileAddr, HdPpuTileInfo &tile, BaseMapper *mapper, bool isSprite, uint32_t chrBankHash)
|
||||
{
|
||||
auto result = _tileUsageCount.find(tile.GetKey(false));
|
||||
if(result == _tileUsageCount.end()) {
|
||||
//Check to see if a default tile matches
|
||||
result = _tileUsageCount.find(tile.GetKey(true));
|
||||
}
|
||||
|
||||
if(result == _tileUsageCount.end()) {
|
||||
//First time seeing this tile/palette combination, store it
|
||||
HdPackTileInfo* hdTile = new HdPackTileInfo();
|
||||
hdTile->PaletteColors = tile.PaletteColors;
|
||||
hdTile->TileIndex = tile.TileIndex;
|
||||
hdTile->DefaultTile = false;
|
||||
hdTile->IsChrRamTile = _isChrRam;
|
||||
hdTile->Brightness = 255;
|
||||
hdTile->ChrBankId = _isChrRam ? chrBankHash : (tileAddr / 16 / 256);
|
||||
|
||||
memcpy(hdTile->TileData, tile.TileData, 16);
|
||||
GenerateHdTile(hdTile);
|
||||
hdTile->UpdateBlankTileFlag();
|
||||
|
||||
_hdData.Tiles.push_back(unique_ptr<HdPackTileInfo>(hdTile));
|
||||
AddTile(hdTile, 1);
|
||||
} else {
|
||||
if(result->second < 0x7FFFFFFF) {
|
||||
//Increase usage count
|
||||
result->second++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HdPackBuilder::GenerateHdTile(HdPackTileInfo *tile)
|
||||
{
|
||||
uint32_t hdScale = _hdData.Scale;
|
||||
|
||||
vector<uint32_t> originalTile = tile->ToRgb();
|
||||
vector<uint32_t> hdTile(8 * 8 * hdScale*hdScale, 0);
|
||||
|
||||
switch(_filterType) {
|
||||
case ScaleFilterType::HQX:
|
||||
hqx(hdScale, originalTile.data(), hdTile.data(), 8, 8);
|
||||
break;
|
||||
|
||||
case ScaleFilterType::Prescale:
|
||||
hdTile.clear();
|
||||
for(uint8_t i = 0; i < 8 * hdScale; i++) {
|
||||
for(uint8_t j = 0; j < 8 * hdScale; j++) {
|
||||
hdTile.push_back(originalTile[i/hdScale*8+j/hdScale]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ScaleFilterType::Scale2x:
|
||||
scale(hdScale, hdTile.data(), 8 * sizeof(uint32_t) * hdScale, originalTile.data(), 8 * sizeof(uint32_t), 4, 8, 8);
|
||||
break;
|
||||
|
||||
case ScaleFilterType::_2xSai:
|
||||
twoxsai_generic_xrgb8888(8, 8, originalTile.data(), 8, hdTile.data(), 8 * hdScale);
|
||||
break;
|
||||
|
||||
case ScaleFilterType::Super2xSai:
|
||||
supertwoxsai_generic_xrgb8888(8, 8, originalTile.data(), 8, hdTile.data(), 8 * hdScale);
|
||||
break;
|
||||
|
||||
case ScaleFilterType::SuperEagle:
|
||||
supereagle_generic_xrgb8888(8, 8, originalTile.data(), 8, hdTile.data(), 8 * hdScale);
|
||||
break;
|
||||
|
||||
case ScaleFilterType::xBRZ:
|
||||
xbrz::scale(hdScale, originalTile.data(), hdTile.data(), 8, 8, xbrz::ColorFormat::ARGB);
|
||||
break;
|
||||
}
|
||||
|
||||
tile->HdTileData = hdTile;
|
||||
}
|
||||
|
||||
void HdPackBuilder::DrawTile(HdPackTileInfo *tile, int tileNumber, uint32_t *pngBuffer, int pageNumber, bool containsSpritesOnly)
|
||||
{
|
||||
if(containsSpritesOnly && (_flags & HdPackRecordFlags::UseLargeSprites)) {
|
||||
int row = tileNumber / 16;
|
||||
int column = tileNumber % 16;
|
||||
|
||||
int newColumn = column / 2 + ((row & 1) ? 8 : 0);
|
||||
int newRow = (row & 0xFE) + ((column & 1) ? 1 : 0);
|
||||
|
||||
tileNumber = newRow * 16 + newColumn;
|
||||
}
|
||||
|
||||
tileNumber += pageNumber * (256 / (0x1000 / _chrRamBankSize));
|
||||
|
||||
int tileDimension = 8 * _hdData.Scale;
|
||||
int x = tileNumber % 16 * tileDimension;
|
||||
int y = tileNumber / 16 * tileDimension;
|
||||
|
||||
tile->X = x;
|
||||
tile->Y = y;
|
||||
|
||||
int pngWidth = 128 * _hdData.Scale;
|
||||
int pngPos = y * pngWidth + x;
|
||||
int tilePos = 0;
|
||||
for(uint8_t i = 0; i < tileDimension; i++) {
|
||||
for(uint8_t j = 0; j < tileDimension; j++) {
|
||||
pngBuffer[pngPos] = tile->HdTileData[tilePos++];
|
||||
pngPos++;
|
||||
}
|
||||
pngPos += pngWidth - tileDimension;
|
||||
}
|
||||
}
|
||||
|
||||
void HdPackBuilder::SaveHdPack()
|
||||
{
|
||||
FolderUtilities::CreateFolder(_saveFolder);
|
||||
|
||||
stringstream pngRows;
|
||||
stringstream tileRows;
|
||||
stringstream ss;
|
||||
int pngIndex = 0;
|
||||
ss << "<ver>100" << std::endl;
|
||||
ss << "<scale>" << _hdData.Scale << std::endl;
|
||||
|
||||
int tileDimension = 8 * _hdData.Scale;
|
||||
int pngDimension = 16 * tileDimension;
|
||||
int pngBufferSize = pngDimension * pngDimension;
|
||||
uint32_t* pngBuffer = new uint32_t[pngBufferSize];
|
||||
|
||||
int maxPageNumber = 0x1000 / _chrRamBankSize;
|
||||
int pageNumber = 0;
|
||||
bool pngEmpty = true;
|
||||
int pngNumber = 0;
|
||||
|
||||
for(int i = 0; i < pngBufferSize; i++) {
|
||||
pngBuffer[i] = 0xFFFF00FF;
|
||||
}
|
||||
|
||||
auto savePng = [&tileRows, &pngRows, &ss, &pngBuffer, &pngDimension, &pngIndex, &pngBufferSize, &pngEmpty, &pngNumber, this](uint32_t chrBankId) {
|
||||
if(!pngEmpty) {
|
||||
string pngName;
|
||||
if(_isChrRam) {
|
||||
pngName = "Chr_" + std::to_string(pngNumber) + ".png";
|
||||
} else {
|
||||
pngName = "Chr_" + HexUtilities::ToHex(chrBankId) + "_" + std::to_string(pngNumber) + ".png";
|
||||
}
|
||||
|
||||
tileRows << std::endl << "#" << pngName << std::endl;
|
||||
tileRows << pngRows.str();
|
||||
pngRows = stringstream();
|
||||
|
||||
ss << "<img>" << pngName << std::endl;
|
||||
PNGHelper::WritePNG(FolderUtilities::CombinePath(_saveFolder, pngName), pngBuffer, pngDimension, pngDimension, 32);
|
||||
pngNumber++;
|
||||
pngIndex++;
|
||||
|
||||
for(int i = 0; i < pngBufferSize; i++) {
|
||||
pngBuffer[i] = 0xFFFF00FF;
|
||||
}
|
||||
pngEmpty = true;
|
||||
}
|
||||
};
|
||||
|
||||
for(std::pair<const uint32_t, std::map<uint32_t, vector<HdPackTileInfo*>>> &kvp : _tilesByChrBankByPalette) {
|
||||
/*if(true) { //flatten palette
|
||||
for(int i = 0; i < 256; i++) {
|
||||
auto readItt = kvp.second.begin();
|
||||
auto writeItt = kvp.second.begin();
|
||||
while(writeItt != kvp.second.end() && writeItt->second[i]) {
|
||||
readItt++;
|
||||
writeItt++;
|
||||
}
|
||||
for(; readItt != kvp.second.end() && writeItt != kvp.second.end(); readItt++) {
|
||||
if(writeItt->second[i] == nullptr && readItt->second[i] != nullptr) {
|
||||
writeItt->second[i] = readItt->second[i];
|
||||
readItt->second[i] = nullptr;
|
||||
while(writeItt != kvp.second.end() && writeItt->second[i]) {
|
||||
writeItt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
if(_flags & HdPackRecordFlags::SortByUsageFrequency) {
|
||||
for(int i = 0; i < 256; i++) {
|
||||
vector<std::pair<uint32_t, HdPackTileInfo*>> tiles;
|
||||
for(std::pair<const uint32_t, vector<HdPackTileInfo*>> &paletteMap : kvp.second) {
|
||||
if(paletteMap.second[i]) {
|
||||
tiles.push_back({ _tileUsageCount[paletteMap.second[i]->GetKey(false)], paletteMap.second[i] });
|
||||
}
|
||||
}
|
||||
std::sort(tiles.begin(), tiles.end(), [=](std::pair<uint32_t, HdPackTileInfo*> &a, std::pair<uint32_t, HdPackTileInfo*> &b) {
|
||||
return a.first > b.first;
|
||||
});
|
||||
|
||||
int j = 0;
|
||||
for(std::pair<const uint32_t, vector<HdPackTileInfo*>> &paletteMap : kvp.second) {
|
||||
if(j < tiles.size()) {
|
||||
paletteMap.second[i] = tiles[j].second;
|
||||
j++;
|
||||
} else {
|
||||
paletteMap.second[i] = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!_isChrRam) {
|
||||
pngNumber = 0;
|
||||
}
|
||||
|
||||
for(std::pair<const uint32_t, vector<HdPackTileInfo*>> &tileKvp : kvp.second) {
|
||||
bool pageEmpty = true;
|
||||
bool spritesOnly = true;
|
||||
for(HdPackTileInfo* tileInfo : tileKvp.second) {
|
||||
if(tileInfo && !tileInfo->IsSpriteTile()) {
|
||||
spritesOnly = false;
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < 256; i++) {
|
||||
HdPackTileInfo* tileInfo = tileKvp.second[i];
|
||||
if(tileInfo) {
|
||||
DrawTile(tileInfo, i, pngBuffer, pageNumber, spritesOnly);
|
||||
|
||||
pngRows << tileInfo->ToString(pngIndex) << std::endl;
|
||||
|
||||
pageEmpty = false;
|
||||
pngEmpty = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(!pageEmpty) {
|
||||
pageNumber++;
|
||||
|
||||
if(pageNumber == maxPageNumber) {
|
||||
savePng(kvp.first);
|
||||
pageNumber = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
savePng(-1);
|
||||
|
||||
for(unique_ptr<HdPackCondition> &condition : _hdData.Conditions) {
|
||||
ss << condition->ToString() << std::endl;
|
||||
}
|
||||
|
||||
for(HdBackgroundInfo &bgInfo : _hdData.Backgrounds) {
|
||||
ss << bgInfo.ToString() << std::endl;
|
||||
}
|
||||
|
||||
ss << tileRows.str();
|
||||
|
||||
ofstream hiresFile(FolderUtilities::CombinePath(_saveFolder, "hires.txt"), ios::out);
|
||||
hiresFile << ss.str();
|
||||
hiresFile.close();
|
||||
|
||||
delete[] pngBuffer;
|
||||
}
|
||||
|
||||
void HdPackBuilder::GetChrBankList(uint32_t *banks)
|
||||
{
|
||||
Console::Pause();
|
||||
for(std::pair<const uint32_t, std::map<uint32_t, vector<HdPackTileInfo*>>> &kvp : _instance->_tilesByChrBankByPalette) {
|
||||
*banks = kvp.first;
|
||||
banks++;
|
||||
}
|
||||
*banks = -1;
|
||||
Console::Resume();
|
||||
}
|
||||
|
||||
void HdPackBuilder::GetBankPreview(uint32_t bankNumber, uint32_t pageNumber, uint8_t *rgbBuffer)
|
||||
{
|
||||
Console::Pause();
|
||||
|
||||
for(uint32_t i = 0; i < 128 * 128 * _instance->_hdData.Scale*_instance->_hdData.Scale; i++) {
|
||||
((uint32_t*)rgbBuffer)[i] = 0xFFFF00FF;
|
||||
}
|
||||
|
||||
auto result = _instance->_tilesByChrBankByPalette.find(bankNumber);
|
||||
if(result != _instance->_tilesByChrBankByPalette.end()) {
|
||||
std::map<uint32_t, vector<HdPackTileInfo*>> bankData = result->second;
|
||||
|
||||
if(_instance->_flags & HdPackRecordFlags::SortByUsageFrequency) {
|
||||
for(int i = 0; i < 256; i++) {
|
||||
vector<std::pair<uint32_t, HdPackTileInfo*>> tiles;
|
||||
for(std::pair<const uint32_t, vector<HdPackTileInfo*>> &pageData : bankData) {
|
||||
if(pageData.second[i]) {
|
||||
tiles.push_back({ _instance->_tileUsageCount[pageData.second[i]->GetKey(false)], pageData.second[i] });
|
||||
}
|
||||
}
|
||||
|
||||
std::sort(tiles.begin(), tiles.end(), [=](std::pair<uint32_t, HdPackTileInfo*> &a, std::pair<uint32_t, HdPackTileInfo*> &b) {
|
||||
return a.first > b.first;
|
||||
});
|
||||
|
||||
int j = 0;
|
||||
for(std::pair<const uint32_t, vector<HdPackTileInfo*>> &pageData : bankData) {
|
||||
if(j < tiles.size()) {
|
||||
pageData.second[i] = tiles[j].second;
|
||||
j++;
|
||||
} else {
|
||||
pageData.second[i] = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool spritesOnly = true;
|
||||
for(HdPackTileInfo* tileInfo : (*bankData.begin()).second) {
|
||||
if(tileInfo && !tileInfo->IsSpriteTile()) {
|
||||
spritesOnly = false;
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < 256; i++) {
|
||||
HdPackTileInfo* tileInfo = (*bankData.begin()).second[i];
|
||||
if(tileInfo) {
|
||||
_instance->DrawTile(tileInfo, i, (uint32_t*)rgbBuffer, 0, spritesOnly);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Console::Resume();
|
||||
}
|
49
Core/HdPackBuilder.h
Normal file
49
Core/HdPackBuilder.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
#pragma once
|
||||
#include "stdafx.h"
|
||||
#include "../Utilities/xBRZ/xbrz.h"
|
||||
#include "../Utilities/HQX/hqx.h"
|
||||
#include "../Utilities/Scale2x/scalebit.h"
|
||||
#include "../Utilities/KreedSaiEagle/SaiEagle.h"
|
||||
#include "../Utilities/FolderUtilities.h"
|
||||
#include "../Utilities/PNGHelper.h"
|
||||
#include "../Utilities/HexUtilities.h"
|
||||
#include "Console.h"
|
||||
#include "HdPackLoader.h"
|
||||
#include "HdNesPack.h"
|
||||
#include "BaseMapper.h"
|
||||
#include "Types.h"
|
||||
#include <map>
|
||||
|
||||
class HdPackBuilder
|
||||
{
|
||||
private:
|
||||
static HdPackBuilder* _instance;
|
||||
|
||||
HdPackData _hdData;
|
||||
std::unordered_map<HdTileKey, uint32_t> _tileUsageCount;
|
||||
std::map<uint32_t, std::map<uint32_t, vector<HdPackTileInfo*>>> _tilesByChrBankByPalette;
|
||||
bool _isChrRam;
|
||||
uint32_t _chrRamBankSize;
|
||||
ScaleFilterType _filterType;
|
||||
string _saveFolder;
|
||||
string _romName;
|
||||
uint32_t _flags;
|
||||
|
||||
//Used to group blank tiles together
|
||||
int _blankTileIndex = 0;
|
||||
int _blankTilePalette = 0;
|
||||
|
||||
void AddTile(HdPackTileInfo *tile, uint32_t usageCount);
|
||||
void GenerateHdTile(HdPackTileInfo *tile);
|
||||
void DrawTile(HdPackTileInfo *tile, int tileIndex, uint32_t* pngBuffer, int pageNumber, bool containsSpritesOnly);
|
||||
|
||||
public:
|
||||
HdPackBuilder(string saveFolder, ScaleFilterType filterType, uint32_t scale, uint32_t flags, uint32_t chrRamBankSize, bool isChrRam);
|
||||
~HdPackBuilder();
|
||||
|
||||
void ProcessTile(int x, int y, uint16_t tileAddr, HdPpuTileInfo& tile, BaseMapper* mapper, bool isSprite, uint32_t chrBankHash);
|
||||
void SaveHdPack();
|
||||
|
||||
static void GetChrBankList(uint32_t *banks);
|
||||
static void GetBankPreview(uint32_t bankNumber, uint32_t pageNumber, uint8_t *rgbBuffer);
|
||||
};
|
337
Core/HdPackLoader.cpp
Normal file
337
Core/HdPackLoader.cpp
Normal file
|
@ -0,0 +1,337 @@
|
|||
#include "stdafx.h"
|
||||
#include <unordered_map>
|
||||
#include "../Utilities/FolderUtilities.h"
|
||||
#include "../Utilities/StringUtilities.h"
|
||||
#include "../Utilities/HexUtilities.h"
|
||||
#include "../Utilities/PNGHelper.h"
|
||||
#include "Console.h"
|
||||
#include "HdPackLoader.h"
|
||||
|
||||
HdPackLoader::HdPackLoader(string hdPackDefinitionFile, HdPackData *data)
|
||||
{
|
||||
_hdPackDefinitionFile = hdPackDefinitionFile;
|
||||
_hdPackFolder = FolderUtilities::GetFolderName(_hdPackDefinitionFile);
|
||||
_data = data;
|
||||
}
|
||||
|
||||
bool HdPackLoader::LoadHdNesPack(string hdPackDefinitionFile, HdPackData &outData)
|
||||
{
|
||||
//outData = HdPackData();
|
||||
|
||||
HdPackLoader loader(hdPackDefinitionFile, &outData);
|
||||
return loader.LoadPack();
|
||||
}
|
||||
|
||||
bool HdPackLoader::LoadPack()
|
||||
{
|
||||
try {
|
||||
ifstream packDefinition(_hdPackDefinitionFile, ios::in | ios::binary);
|
||||
if(!packDefinition.good()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
while(packDefinition.good()) {
|
||||
string lineContent;
|
||||
std::getline(packDefinition, lineContent);
|
||||
lineContent = lineContent.substr(0, lineContent.length() - 1);
|
||||
|
||||
vector<HdPackCondition*> conditions;
|
||||
if(lineContent.substr(0, 1) == "[") {
|
||||
size_t endOfCondition = lineContent.find_first_of(']', 1);
|
||||
conditions = ParseConditionString(lineContent.substr(1, endOfCondition - 1), _data->Conditions);
|
||||
lineContent = lineContent.substr(endOfCondition + 1);
|
||||
}
|
||||
|
||||
vector<string> tokens;
|
||||
if(lineContent.substr(0, 5) == "<ver>") {
|
||||
_data->Version = stoi(lineContent.substr(5));
|
||||
} else if(lineContent.substr(0, 7) == "<scale>") {
|
||||
lineContent = lineContent.substr(7);
|
||||
_data->Scale = std::stoi(lineContent);
|
||||
} else if(lineContent.substr(0, 5) == "<img>") {
|
||||
lineContent = lineContent.substr(5);
|
||||
HdPackBitmapInfo bitmapInfo;
|
||||
string imageFile = FolderUtilities::CombinePath(_hdPackFolder, lineContent);
|
||||
PNGHelper::ReadPNG(imageFile, bitmapInfo.PixelData, bitmapInfo.Width, bitmapInfo.Height);
|
||||
_hdNesBitmaps.push_back(bitmapInfo);
|
||||
} else if(lineContent.substr(0, 7) == "<patch>") {
|
||||
tokens = StringUtilities::Split(lineContent.substr(7), ',');
|
||||
ProcessPatchTag(tokens);
|
||||
} else if(lineContent.substr(0, 12) == "<background>") {
|
||||
tokens = StringUtilities::Split(lineContent.substr(12), ',');
|
||||
ProcessBackgroundTag(tokens, conditions);
|
||||
} else if(lineContent.substr(0, 11) == "<condition>") {
|
||||
tokens = StringUtilities::Split(lineContent.substr(11), ',');
|
||||
ProcessConditionTag(tokens);
|
||||
} else if(lineContent.substr(0, 6) == "<tile>") {
|
||||
tokens = StringUtilities::Split(lineContent.substr(6), ',');
|
||||
ProcessTileTag(tokens, conditions);
|
||||
} else if(lineContent.substr(0, 9) == "<options>") {
|
||||
tokens = StringUtilities::Split(lineContent.substr(9), ',');
|
||||
ProcessOptionTag(tokens);
|
||||
}
|
||||
}
|
||||
|
||||
LoadCustomPalette();
|
||||
InitializeHdPack();
|
||||
|
||||
packDefinition.close();
|
||||
return true;
|
||||
} catch(std::exception ex) {
|
||||
MessageManager::Log(string("[HDPack] Error loading HDPack: ") + ex.what());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void HdPackLoader::ProcessPatchTag(vector<string> &tokens)
|
||||
{
|
||||
if(tokens[1].size() != 40) {
|
||||
MessageManager::Log(string("[HDPack] Invalid SHA1 hash for patch (" + tokens[0] + "): " + tokens[1]));
|
||||
return;
|
||||
}
|
||||
if(!ifstream(FolderUtilities::CombinePath(_hdPackFolder, tokens[0]))) {
|
||||
MessageManager::Log(string("[HDPack] Patch file not found: " + tokens[1]));
|
||||
return;
|
||||
}
|
||||
|
||||
std::transform(tokens[1].begin(), tokens[1].end(), tokens[1].begin(), ::toupper);
|
||||
_data->PatchesByHash[tokens[1]] = tokens[0];
|
||||
}
|
||||
|
||||
void HdPackLoader::ProcessTileTag(vector<string> &tokens, vector<HdPackCondition*> conditions)
|
||||
{
|
||||
HdPackTileInfo *tileInfo = new HdPackTileInfo();
|
||||
int index = 0;
|
||||
if(_data->Version < 100) {
|
||||
tileInfo->TileIndex = std::stoi(tokens[index++]);
|
||||
tileInfo->BitmapIndex = std::stoi(tokens[index++]);
|
||||
tileInfo->PaletteColors = std::stoi(tokens[index + 2]) | (std::stoi(tokens[index + 1]) << 8) | (std::stoi(tokens[index]) << 16);
|
||||
index += 3;
|
||||
} else {
|
||||
tileInfo->BitmapIndex = std::stoi(tokens[index++]);
|
||||
string tileData = tokens[index++];
|
||||
if(tileData.size() >= 32) {
|
||||
//CHR RAM tile, read the tile data
|
||||
for(int i = 0; i < 16; i++) {
|
||||
tileInfo->TileData[i] = HexUtilities::FromHex(tileData.substr(i * 2, 2));
|
||||
}
|
||||
tileInfo->IsChrRamTile = true;
|
||||
} else {
|
||||
tileInfo->TileIndex = std::stoi(tokens[index++]);
|
||||
tileInfo->IsChrRamTile = false;
|
||||
}
|
||||
tileInfo->PaletteColors = HexUtilities::FromHex(tokens[index++]);
|
||||
}
|
||||
tileInfo->X = std::stoi(tokens[index++]);
|
||||
tileInfo->Y = std::stoi(tokens[index++]);
|
||||
tileInfo->Conditions = conditions;
|
||||
|
||||
if(_data->Version > 0) {
|
||||
tileInfo->Brightness = (uint8_t)(std::stof(tokens[index++]) * 255);
|
||||
} else {
|
||||
tileInfo->Brightness = 255;
|
||||
}
|
||||
tileInfo->DefaultTile = (tokens[index++] == "Y");
|
||||
|
||||
//For CHR ROM tiles, the ID is just the bank number in chr rom (4k banks)
|
||||
tileInfo->ChrBankId = tileInfo->TileIndex / 256;
|
||||
|
||||
if(_data->Version < 100) {
|
||||
if(tokens.size() >= 24) {
|
||||
//CHR RAM tile, read the tile data
|
||||
for(int i = 0; i < 16; i++) {
|
||||
tileInfo->TileData[i] = std::stoi(tokens[index++]);
|
||||
}
|
||||
tileInfo->IsChrRamTile = true;
|
||||
} else {
|
||||
tileInfo->IsChrRamTile = false;
|
||||
}
|
||||
} else {
|
||||
if(tileInfo->IsChrRamTile && tokens.size() > index) {
|
||||
tileInfo->ChrBankId = std::stoul(tokens[index++]);
|
||||
}
|
||||
if(tileInfo->IsChrRamTile && tokens.size() > index) {
|
||||
tileInfo->TileIndex = std::stoi(tokens[index++]);
|
||||
}
|
||||
}
|
||||
|
||||
if(tileInfo->BitmapIndex > _hdNesBitmaps.size()) {
|
||||
MessageManager::Log("[HDPack] Invalid bitmap index: " + std::to_string(tileInfo->BitmapIndex));
|
||||
return;
|
||||
}
|
||||
|
||||
HdPackBitmapInfo &bitmapInfo = _hdNesBitmaps[tileInfo->BitmapIndex];
|
||||
uint32_t bitmapOffset = tileInfo->Y * bitmapInfo.Width + tileInfo->X;
|
||||
uint32_t* pngData = (uint32_t*)bitmapInfo.PixelData.data();
|
||||
for(uint32_t y = 0; y < 8 * _data->Scale; y++) {
|
||||
for(uint32_t x = 0; x < 8 * _data->Scale; x++) {
|
||||
tileInfo->HdTileData.push_back(pngData[bitmapOffset]);
|
||||
bitmapOffset++;
|
||||
}
|
||||
bitmapOffset += bitmapInfo.Width - 8 * _data->Scale;
|
||||
}
|
||||
|
||||
tileInfo->UpdateBlankTileFlag();
|
||||
|
||||
_data->Tiles.push_back(unique_ptr<HdPackTileInfo>(tileInfo));
|
||||
}
|
||||
|
||||
void HdPackLoader::ProcessOptionTag(vector<string> &tokens)
|
||||
{
|
||||
for(string token : tokens) {
|
||||
if(token == "disableSpriteLimit") {
|
||||
_data->OptionFlags |= (int)HdPackOptions::NoSpriteLimit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HdPackLoader::ProcessConditionTag(vector<string> &tokens)
|
||||
{
|
||||
HdPackCondition *condition = new HdPackCondition();
|
||||
tokens[0].erase(tokens[0].find_last_not_of(" \n\r\t") + 1);
|
||||
condition->Name = tokens[0];
|
||||
|
||||
if(tokens[1] == "tileAtPosition") {
|
||||
condition->Type = HdPackConditionType::TileAtPosition;
|
||||
} else if(tokens[1] == "tileNearby") {
|
||||
condition->Type = HdPackConditionType::TileNearby;
|
||||
} else if(tokens[1] == "spriteAtPosition") {
|
||||
condition->Type = HdPackConditionType::SpriteAtPosition;
|
||||
} else if(tokens[1] == "spriteNearby") {
|
||||
condition->Type = HdPackConditionType::SpriteNearby;
|
||||
}
|
||||
|
||||
int index = 2;
|
||||
switch(condition->Type) {
|
||||
case HdPackConditionType::TileAtPosition:
|
||||
case HdPackConditionType::SpriteAtPosition:
|
||||
case HdPackConditionType::TileNearby:
|
||||
case HdPackConditionType::SpriteNearby:
|
||||
condition->TileX = std::stoi(tokens[index++]);
|
||||
condition->TileY = std::stoi(tokens[index++]);
|
||||
break;
|
||||
}
|
||||
|
||||
string tileData = tokens[index++];
|
||||
if(tileData.size() == 32) {
|
||||
//CHR RAM tile, read the tile data
|
||||
for(int i = 0; i < 16; i++) {
|
||||
condition->TileData[i] = HexUtilities::FromHex(tileData.substr(i * 2, 2));
|
||||
}
|
||||
condition->TileIndex = -1;
|
||||
} else {
|
||||
condition->TileIndex = std::stoi(tokens[index++]);
|
||||
}
|
||||
|
||||
condition->PaletteColors = HexUtilities::FromHex(tokens[index++]);
|
||||
|
||||
_data->Conditions.push_back(unique_ptr<HdPackCondition>(condition));
|
||||
}
|
||||
|
||||
void HdPackLoader::ProcessBackgroundTag(vector<string> &tokens, vector<HdPackCondition*> conditions)
|
||||
{
|
||||
HdBackgroundFileData* fileData = nullptr;
|
||||
for(unique_ptr<HdBackgroundFileData> &bgData : _data->BackgroundFileData) {
|
||||
if(bgData->PngName == tokens[0]) {
|
||||
fileData = bgData.get();
|
||||
}
|
||||
}
|
||||
|
||||
if(!fileData) {
|
||||
vector<uint8_t> pixelData;
|
||||
uint32_t width, height;
|
||||
string imageFile = FolderUtilities::CombinePath(_hdPackFolder, tokens[0]);
|
||||
if(PNGHelper::ReadPNG(imageFile, pixelData, width, height)) {
|
||||
_data->BackgroundFileData.push_back(unique_ptr<HdBackgroundFileData>(new HdBackgroundFileData()));
|
||||
fileData = _data->BackgroundFileData.back().get();
|
||||
fileData->PixelData = pixelData;
|
||||
fileData->Width = width;
|
||||
fileData->Height = height;
|
||||
fileData->PngName = tokens[0];
|
||||
}
|
||||
}
|
||||
|
||||
HdBackgroundInfo backgroundInfo;
|
||||
if(fileData) {
|
||||
backgroundInfo.Data = fileData;
|
||||
backgroundInfo.Brightness = (uint16_t)(std::stof(tokens[1]) * 255);
|
||||
backgroundInfo.Conditions = conditions;
|
||||
|
||||
for(HdPackCondition* condition : backgroundInfo.Conditions) {
|
||||
if(condition->Type == HdPackConditionType::SpriteNearby || condition->Type == HdPackConditionType::TileNearby) {
|
||||
MessageManager::Log("[HDPack] Invalid condition type for background: " + tokens[0]);
|
||||
}
|
||||
}
|
||||
|
||||
_data->Backgrounds.push_back(backgroundInfo);
|
||||
} else {
|
||||
MessageManager::Log("[HDPack] Error while loading background: " + tokens[0]);
|
||||
}
|
||||
}
|
||||
|
||||
vector<HdPackCondition*> HdPackLoader::ParseConditionString(string conditionString, vector<unique_ptr<HdPackCondition>> &conditions)
|
||||
{
|
||||
vector<string> conditionNames = StringUtilities::Split(conditionString, '&');
|
||||
|
||||
vector<HdPackCondition*> result;
|
||||
for(string conditionName : conditionNames) {
|
||||
conditionName.erase(conditionName.find_last_not_of(" \n\r\t") + 1);
|
||||
|
||||
bool found = false;
|
||||
for(unique_ptr<HdPackCondition> &condition : conditions) {
|
||||
if(conditionName == condition->Name) {
|
||||
result.push_back(condition.get());
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!found) {
|
||||
MessageManager::Log("[HDPack] Condition not found: " + conditionName);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void HdPackLoader::LoadCustomPalette()
|
||||
{
|
||||
string customPalettePath = FolderUtilities::CombinePath(_hdPackFolder, "palette.dat");
|
||||
ifstream file(customPalettePath, ios::binary);
|
||||
if(file.good()) {
|
||||
vector<uint32_t> paletteData;
|
||||
|
||||
uint8_t rgb[3];
|
||||
while(!file.eof()) {
|
||||
file.read((char*)rgb, 3);
|
||||
if(!file.eof()) {
|
||||
paletteData.push_back(0xFF000000 | (rgb[0] << 16) | (rgb[1] << 8) | rgb[2]);
|
||||
}
|
||||
}
|
||||
|
||||
if(paletteData.size() == 0x40) {
|
||||
_data->PaletteBackup = vector<uint32_t>(0x40, 0);
|
||||
EmulationSettings::GetRgbPalette(_data->PaletteBackup.data());
|
||||
_data->Palette = paletteData;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HdPackLoader::InitializeHdPack()
|
||||
{
|
||||
for(unique_ptr<HdPackTileInfo> &tileInfo : _data->Tiles) {
|
||||
auto tiles = _data->TileByKey.find(tileInfo->GetKey(false));
|
||||
if(tiles == _data->TileByKey.end()) {
|
||||
_data->TileByKey[tileInfo->GetKey(false)] = vector<HdPackTileInfo*>();
|
||||
}
|
||||
_data->TileByKey[tileInfo->GetKey(false)].push_back(tileInfo.get());
|
||||
|
||||
if(tileInfo->DefaultTile) {
|
||||
auto tiles = _data->TileByKey.find(tileInfo->GetKey(true));
|
||||
if(tiles == _data->TileByKey.end()) {
|
||||
_data->TileByKey[tileInfo->GetKey(false)] = vector<HdPackTileInfo*>();
|
||||
}
|
||||
_data->TileByKey[tileInfo->GetKey(true)].push_back(tileInfo.get());
|
||||
}
|
||||
}
|
||||
}
|
29
Core/HdPackLoader.h
Normal file
29
Core/HdPackLoader.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
#pragma once
|
||||
#include "stdafx.h"
|
||||
#include "HdData.h"
|
||||
|
||||
class HdPackLoader
|
||||
{
|
||||
public:
|
||||
static bool LoadHdNesPack(string hdPackDefinitionFile, HdPackData &data);
|
||||
|
||||
private:
|
||||
HdPackData* _data;
|
||||
string _hdPackDefinitionFile;
|
||||
string _hdPackFolder;
|
||||
vector<HdPackBitmapInfo> _hdNesBitmaps;
|
||||
|
||||
HdPackLoader(string hdPackDefinitionFile, HdPackData *data);
|
||||
|
||||
bool LoadPack();
|
||||
void InitializeHdPack();
|
||||
void LoadCustomPalette();
|
||||
|
||||
void ProcessPatchTag(vector<string> &tokens);
|
||||
void ProcessConditionTag(vector<string> &tokens);
|
||||
void ProcessTileTag(vector<string> &tokens, vector<HdPackCondition*> conditions);
|
||||
void ProcessBackgroundTag(vector<string> &tokens, vector<HdPackCondition*> conditions);
|
||||
void ProcessOptionTag(vector<string>& tokens);
|
||||
|
||||
vector<HdPackCondition*> ParseConditionString(string conditionString, vector<unique_ptr<HdPackCondition>> &conditions);
|
||||
};
|
49
Core/HdPpu.h
49
Core/HdPpu.h
|
@ -10,6 +10,7 @@ class HdPpu : public PPU
|
|||
private:
|
||||
HdPpuPixelInfo* _screenTileBuffers[2];
|
||||
HdPpuPixelInfo* _screenTiles;
|
||||
bool _isChrRam;
|
||||
|
||||
protected:
|
||||
void DrawPixel()
|
||||
|
@ -22,40 +23,69 @@ protected:
|
|||
uint32_t color = GetPixelColor();
|
||||
pixel = (_paletteRAM[color & 0x03 ? color : 0] & _paletteRamMask) | _intensifyColorBits;
|
||||
|
||||
TileInfo* lastTile = &((_state.XScroll + ((_cycle - 1) & 0x07) < 8) ? _previousTile : _currentTile);
|
||||
uint32_t backgroundColor = 0;
|
||||
if(_flags.BackgroundEnabled && _cycle > _minimumDrawBgCycle) {
|
||||
backgroundColor = (((_state.LowBitShift << _state.XScroll) & 0x8000) >> 15) | (((_state.HighBitShift << _state.XScroll) & 0x8000) >> 14);
|
||||
}
|
||||
|
||||
HdPpuPixelInfo &tileInfo = _screenTiles[bufferOffset];
|
||||
if(_lastSprite && _flags.SpritesEnabled) {
|
||||
tileInfo.Sprite.TileIndex = _mapper->ToAbsoluteChrAddress(_lastSprite->TileAddr) / 16;
|
||||
tileInfo.Sprite.PaletteColors = ReadPaletteRAM(_lastSprite->PaletteOffset + 1) | (ReadPaletteRAM(_lastSprite->PaletteOffset + 2) << 8) | (ReadPaletteRAM(_lastSprite->PaletteOffset + 3) << 16);
|
||||
tileInfo.Sprite.PaletteColors = ReadPaletteRAM(_lastSprite->PaletteOffset + 3) | (ReadPaletteRAM(_lastSprite->PaletteOffset + 2) << 8) | (ReadPaletteRAM(_lastSprite->PaletteOffset + 1) << 16);
|
||||
tileInfo.Sprite.OffsetY = _lastSprite->OffsetY;
|
||||
if(tileInfo.Sprite.OffsetY >= 8) {
|
||||
tileInfo.Sprite.OffsetY -= 8;
|
||||
}
|
||||
tileInfo.Sprite.IsChrRamTile = _isChrRam;
|
||||
if(_isChrRam) {
|
||||
for(int i = 0; i < 16; i++) {
|
||||
tileInfo.Sprite.TileData[i] = _mapper->GetMemoryValue(DebugMemoryType::ChrRom, _lastSprite->AbsoluteTileAddr / 16 * 16 + i);
|
||||
}
|
||||
}
|
||||
|
||||
tileInfo.Sprite.OffsetX = _cycle - _lastSprite->SpriteX - 1;
|
||||
tileInfo.Sprite.HorizontalMirroring = _lastSprite->HorizontalMirror;
|
||||
tileInfo.Sprite.VerticalMirroring = _lastSprite->VerticalMirror;
|
||||
tileInfo.Sprite.BackgroundPriority = _lastSprite->BackgroundPriority;
|
||||
|
||||
uint32_t backgroundColor = 0;
|
||||
if((_cycle > 8 || _flags.BackgroundMask) && _flags.BackgroundEnabled) {
|
||||
//BackgroundMask = false: Hide background in leftmost 8 pixels of screen
|
||||
backgroundColor = (((_state.LowBitShift << _state.XScroll) & 0x8000) >> 15) | (((_state.HighBitShift << _state.XScroll) & 0x8000) >> 14);
|
||||
int32_t shift = (int32_t)_cycle - _lastSprite->SpriteX - 1;
|
||||
if(_lastSprite->HorizontalMirror) {
|
||||
tileInfo.Sprite.SpriteColorIndex = ((_lastSprite->LowByte >> shift) & 0x01) | ((_lastSprite->HighByte >> shift) & 0x01) << 1;
|
||||
} else {
|
||||
tileInfo.Sprite.SpriteColorIndex = ((_lastSprite->LowByte << shift) & 0x80) >> 7 | ((_lastSprite->HighByte << shift) & 0x80) >> 6;
|
||||
}
|
||||
|
||||
if(tileInfo.Sprite.SpriteColorIndex == 0) {
|
||||
tileInfo.Sprite.SpriteColor = ReadPaletteRAM(0);
|
||||
} else {
|
||||
tileInfo.Sprite.SpriteColor = ReadPaletteRAM(_lastSprite->PaletteOffset + tileInfo.Sprite.SpriteColorIndex);
|
||||
}
|
||||
|
||||
tileInfo.Sprite.BgColorIndex = backgroundColor;
|
||||
if(backgroundColor == 0) {
|
||||
tileInfo.Sprite.BgColor = ReadPaletteRAM(0);
|
||||
} else {
|
||||
tileInfo.Sprite.BgColor = ReadPaletteRAM(_lastSprite->PaletteOffset + backgroundColor);
|
||||
tileInfo.Sprite.BgColor = ReadPaletteRAM(lastTile->PaletteOffset + backgroundColor);
|
||||
}
|
||||
} else {
|
||||
tileInfo.Sprite.TileIndex = HdPpuTileInfo::NoTile;
|
||||
}
|
||||
|
||||
if(_flags.BackgroundEnabled) {
|
||||
TileInfo* lastTile = &((_state.XScroll + ((_cycle - 1) & 0x07) < 8) ? _previousTile : _currentTile);
|
||||
if(_flags.BackgroundEnabled && _cycle > _minimumDrawBgCycle) {
|
||||
tileInfo.Tile.NametableValue = (lastTile->TileAddr / 16) & 0xFF;
|
||||
tileInfo.Tile.TileIndex = _mapper->ToAbsoluteChrAddress(lastTile->TileAddr) / 16;
|
||||
tileInfo.Tile.PaletteColors = ReadPaletteRAM(lastTile->PaletteOffset + 1) | (ReadPaletteRAM(lastTile->PaletteOffset + 2) << 8) | (ReadPaletteRAM(lastTile->PaletteOffset + 3) << 16);
|
||||
tileInfo.Tile.PaletteColors = ReadPaletteRAM(lastTile->PaletteOffset + 3) | (ReadPaletteRAM(lastTile->PaletteOffset + 2) << 8) | (ReadPaletteRAM(lastTile->PaletteOffset + 1) << 16) | (ReadPaletteRAM(0) << 24);
|
||||
tileInfo.Tile.OffsetY = lastTile->OffsetY;
|
||||
tileInfo.Tile.BackgroundPriority = false;
|
||||
tileInfo.Tile.IsChrRamTile = _isChrRam;
|
||||
if(_isChrRam) {
|
||||
for(int i = 0; i < 16; i++) {
|
||||
tileInfo.Tile.TileData[i] = _mapper->GetMemoryValue(DebugMemoryType::ChrRom, lastTile->AbsoluteTileAddr / 16 * 16 + i);
|
||||
}
|
||||
}
|
||||
|
||||
tileInfo.Tile.BgColorIndex = backgroundColor;
|
||||
tileInfo.Tile.OffsetX = (_state.XScroll + ((_cycle - 1) & 0x07)) & 0x07;
|
||||
tileInfo.Tile.HorizontalMirroring = false;
|
||||
tileInfo.Tile.VerticalMirroring = false;
|
||||
|
@ -77,6 +107,7 @@ public:
|
|||
_screenTileBuffers[0] = new HdPpuPixelInfo[256 * 240];
|
||||
_screenTileBuffers[1] = new HdPpuPixelInfo[256 * 240];
|
||||
_screenTiles = _screenTileBuffers[0];
|
||||
_isChrRam = !_mapper->HasChrRom();
|
||||
}
|
||||
|
||||
~HdPpu()
|
||||
|
|
|
@ -28,11 +28,14 @@ void HdVideoFilter::ApplyFilter(uint16_t *ppuOutputBuffer)
|
|||
uint32_t hdScale = _hdNesPack->GetScale();
|
||||
uint32_t screenWidth = overscan.GetScreenWidth() * hdScale;
|
||||
|
||||
_hdNesPack->OnBeforeApplyFilter(_hdScreenTiles);
|
||||
|
||||
for(uint32_t i = overscan.Top, iMax = 240 - overscan.Bottom; i < iMax; i++) {
|
||||
for(uint32_t j = overscan.Left, jMax = 256 - overscan.Right; j < jMax; j++) {
|
||||
uint32_t sdPixel = EmulationSettings::GetRgbPalette()[ppuOutputBuffer[i * 256 + j] & 0x3F]; //ProcessIntensifyBits(inputBuffer[i * 256 + j]);
|
||||
uint32_t bufferIndex = (i - overscan.Top) * screenWidth * hdScale + (j - overscan.Left) * hdScale;
|
||||
_hdNesPack->GetPixels(_hdScreenTiles[i * 256 + j], sdPixel, (uint32_t*)GetOutputBuffer() + bufferIndex, screenWidth);
|
||||
|
||||
_hdNesPack->GetPixels(_hdScreenTiles, j, i, _hdScreenTiles[i * 256 + j], sdPixel, (uint32_t*)GetOutputBuffer() + bufferIndex, screenWidth);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -564,11 +564,11 @@ BaseMapper* MapperFactory::GetMapperFromID(RomData &romData)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
shared_ptr<BaseMapper> MapperFactory::InitializeFromFile(string romFilename, stringstream *filestream, string patchFilename, int32_t archiveFileIndex)
|
||||
shared_ptr<BaseMapper> MapperFactory::InitializeFromFile(string romFilename, vector<uint8_t> &fileData)
|
||||
{
|
||||
RomLoader loader;
|
||||
|
||||
if(loader.LoadFile(romFilename, filestream, patchFilename, archiveFileIndex)) {
|
||||
if(loader.LoadFile(romFilename, fileData)) {
|
||||
RomData romData = loader.GetRomData();
|
||||
shared_ptr<BaseMapper> mapper(GetMapperFromID(romData));
|
||||
|
||||
|
|
|
@ -12,5 +12,5 @@ class MapperFactory
|
|||
static const uint16_t FdsMapperID = 65535;
|
||||
static const uint16_t NsfMapperID = 65534;
|
||||
|
||||
static shared_ptr<BaseMapper> InitializeFromFile(string romFilename, stringstream *filestream, string patchFilename, int32_t archiveFileIndex);
|
||||
static shared_ptr<BaseMapper> InitializeFromFile(string romFilename, vector<uint8_t> &fileData);
|
||||
};
|
||||
|
|
|
@ -239,23 +239,23 @@ void MemoryDumper::GetChrBank(int bankIndex, uint32_t* frameBuffer, uint8_t pale
|
|||
uint8_t chrBuffer[0x1000];
|
||||
bool chrIsDrawn[0x1000];
|
||||
bool tileUsed[0x4000];
|
||||
bool isChrRam = _mapper->GetMemorySize(DebugMemoryType::ChrRam) > 0;
|
||||
if(bankIndex == 0 || bankIndex == 1) {
|
||||
uint16_t baseAddr = bankIndex == 0 ? 0x0000 : 0x1000;
|
||||
for(int i = 0; i < 0x1000; i++) {
|
||||
chrBuffer[i] = _mapper->DebugReadVRAM(baseAddr + i);
|
||||
chrIsDrawn[i] = _codeDataLogger->IsDrawn(_mapper->ToAbsoluteChrAddress(baseAddr + i));
|
||||
chrIsDrawn[i] = isChrRam ? true : _codeDataLogger->IsDrawn(_mapper->ToAbsoluteChrAddress(baseAddr + i));
|
||||
}
|
||||
} else {
|
||||
int bank = bankIndex - 2;
|
||||
uint32_t baseAddr = bank * 0x1000;
|
||||
bool useChrRam = _mapper->GetMemorySize(DebugMemoryType::ChrRam) > 0;
|
||||
uint32_t chrSize = _mapper->GetMemorySize(useChrRam ? DebugMemoryType::ChrRam : DebugMemoryType::ChrRom);
|
||||
uint32_t chrSize = _mapper->GetMemorySize(isChrRam ? DebugMemoryType::ChrRam : DebugMemoryType::ChrRom);
|
||||
vector<uint8_t> chrData(chrSize, 0);
|
||||
_mapper->CopyMemory(useChrRam ? DebugMemoryType::ChrRam : DebugMemoryType::ChrRom, chrData.data());
|
||||
_mapper->CopyMemory(isChrRam ? DebugMemoryType::ChrRam : DebugMemoryType::ChrRom, chrData.data());
|
||||
|
||||
for(int i = 0; i < 0x1000; i++) {
|
||||
chrBuffer[i] = chrData[baseAddr + i];
|
||||
chrIsDrawn[i] = useChrRam ? true : _codeDataLogger->IsDrawn(baseAddr + i);
|
||||
chrIsDrawn[i] = isChrRam ? true : _codeDataLogger->IsDrawn(baseAddr + i);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -544,6 +544,7 @@ void PPU::LoadTileInfo()
|
|||
|
||||
case 3:
|
||||
_nextTile.LowByte = _mapper->ReadVRAM(_nextTile.TileAddr);
|
||||
_nextTile.AbsoluteTileAddr = _mapper->ToAbsoluteChrAddress(_nextTile.TileAddr);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
|
@ -590,6 +591,7 @@ void PPU::LoadSprite(uint8_t spriteY, uint8_t tileIndex, uint8_t attributes, uin
|
|||
info.HighByte = _mapper->ReadVRAM(tileAddr + 8);
|
||||
}
|
||||
info.TileAddr = tileAddr;
|
||||
info.AbsoluteTileAddr = _mapper->ToAbsoluteChrAddress(tileAddr);
|
||||
info.OffsetY = lineOffset;
|
||||
info.SpriteX = spriteX;
|
||||
|
||||
|
|
|
@ -1,154 +1,56 @@
|
|||
#include "stdafx.h"
|
||||
#include <algorithm>
|
||||
#include "../Utilities/FolderUtilities.h"
|
||||
#include "../Utilities/ArchiveReader.h"
|
||||
#include "../Utilities/CRC32.h"
|
||||
#include "../Utilities/sha1.h"
|
||||
#include "../Utilities/BpsPatcher.h"
|
||||
#include "../Utilities/IpsPatcher.h"
|
||||
#include "../Utilities/UpsPatcher.h"
|
||||
#include "../Utilities/ZipReader.h"
|
||||
#include "../Utilities/SZReader.h"
|
||||
#include "RomLoader.h"
|
||||
#include "FileLoader.h"
|
||||
#include "iNesLoader.h"
|
||||
#include "FdsLoader.h"
|
||||
#include "NsfLoader.h"
|
||||
#include "NsfeLoader.h"
|
||||
#include "UnifLoader.h"
|
||||
|
||||
vector<string> RomLoader::GetArchiveRomList(string filename)
|
||||
bool RomLoader::LoadFile(string filename, int32_t archiveFileIndex)
|
||||
{
|
||||
ifstream in(filename, ios::in | ios::binary);
|
||||
if(in) {
|
||||
uint8_t header[2];
|
||||
in.read((char*)header, 2);
|
||||
in.close();
|
||||
|
||||
if(memcmp(header, "PK", 2) == 0) {
|
||||
ZipReader reader;
|
||||
reader.LoadArchive(filename);
|
||||
return reader.GetFileList({ ".nes", ".fds", ".nsf", ".nsfe", "*.unf" });
|
||||
} else if(memcmp(header, "7z", 2) == 0) {
|
||||
SZReader reader;
|
||||
reader.LoadArchive(filename);
|
||||
return reader.GetFileList({ ".nes", ".fds", ".nsf", ".nsfe", "*.unf" });
|
||||
}
|
||||
}
|
||||
return{};
|
||||
}
|
||||
|
||||
bool RomLoader::LoadFromArchive(istream &zipFile, ArchiveReader& reader, int32_t archiveFileIndex)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
uint32_t fileSize;
|
||||
uint8_t* buffer = ReadFile(zipFile, fileSize);
|
||||
|
||||
reader.LoadArchive(buffer, fileSize);
|
||||
|
||||
vector<string> fileList = reader.GetFileList({ ".nes", ".fds", ".nsf", ".nsfe", ".unf" });
|
||||
int32_t currentIndex = 0;
|
||||
if(archiveFileIndex > (int32_t)fileList.size()) {
|
||||
vector<uint8_t> fileData;
|
||||
if(FileLoader::LoadFile(filename, nullptr, archiveFileIndex, fileData)) {
|
||||
return LoadFile(filename, fileData);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
for(string filename : fileList) {
|
||||
if(archiveFileIndex == -1 || archiveFileIndex == currentIndex) {
|
||||
uint8_t* fileBuffer = nullptr;
|
||||
size_t size = 0;
|
||||
reader.ExtractFile(filename, &fileBuffer, size);
|
||||
if(fileBuffer) {
|
||||
result = LoadFromMemory(fileBuffer, size, FolderUtilities::GetFilename(filename, true));
|
||||
delete[] fileBuffer;
|
||||
break;
|
||||
}
|
||||
}
|
||||
currentIndex++;
|
||||
}
|
||||
|
||||
delete[] buffer;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool RomLoader::LoadFromStream(istream &romFile, string romName)
|
||||
bool RomLoader::LoadFile(string filename, vector<uint8_t> &fileData)
|
||||
{
|
||||
uint32_t fileSize;
|
||||
uint8_t* buffer = ReadFile(romFile, fileSize);
|
||||
bool result = LoadFromMemory(buffer, fileSize, romName);
|
||||
delete[] buffer;
|
||||
_filename = filename;
|
||||
|
||||
return result;
|
||||
}
|
||||
string romName = FolderUtilities::GetFilename(filename, true);
|
||||
|
||||
uint32_t RomLoader::GetFileSize(istream &file)
|
||||
{
|
||||
file.seekg(0, ios::end);
|
||||
uint32_t fileSize = (uint32_t)file.tellg();
|
||||
file.seekg(0, ios::beg);
|
||||
|
||||
return fileSize;
|
||||
}
|
||||
|
||||
uint8_t* RomLoader::ReadFile(istream &file, uint32_t &fileSize)
|
||||
{
|
||||
fileSize = GetFileSize(file);
|
||||
|
||||
uint8_t* buffer = new uint8_t[fileSize];
|
||||
file.read((char*)buffer, fileSize);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void RomLoader::ApplyPatch(string patchPath, vector<uint8_t> &data)
|
||||
{
|
||||
//Apply patch file
|
||||
MessageManager::DisplayMessage("Patch", "ApplyingPatch", FolderUtilities::GetFilename(patchPath, true));
|
||||
ifstream patchFile(patchPath, ios::binary | ios::in);
|
||||
if(patchFile.good()) {
|
||||
char buffer[5] = {};
|
||||
patchFile.read(buffer, 5);
|
||||
patchFile.close();
|
||||
if(memcmp(buffer, "PATCH", 5) == 0) {
|
||||
data = IpsPatcher::PatchBuffer(patchPath, data);
|
||||
} else if(memcmp(buffer, "UPS1", 4) == 0) {
|
||||
data = UpsPatcher::PatchBuffer(patchPath, data);
|
||||
} else if(memcmp(buffer, "BPS1", 4) == 0) {
|
||||
data = BpsPatcher::PatchBuffer(patchPath, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool RomLoader::LoadFromMemory(uint8_t* buffer, size_t length, string romName)
|
||||
{
|
||||
vector<uint8_t> fileData(buffer, buffer + length);
|
||||
|
||||
if(!_patchFilename.empty()) {
|
||||
ApplyPatch(_patchFilename, fileData);
|
||||
}
|
||||
|
||||
uint32_t crc = CRC32::GetCRC(buffer, length);
|
||||
uint32_t crc = CRC32::GetCRC(fileData.data(), fileData.size());
|
||||
MessageManager::Log("");
|
||||
MessageManager::Log("Loading rom: " + romName);
|
||||
stringstream crcHex;
|
||||
crcHex << std::hex << std::uppercase << std::setfill('0') << std::setw(8) << crc;
|
||||
MessageManager::Log("File CRC32: 0x" + crcHex.str());
|
||||
|
||||
if(memcmp(buffer, "NES\x1a", 4) == 0) {
|
||||
if(memcmp(fileData.data(), "NES\x1a", 4) == 0) {
|
||||
iNesLoader loader;
|
||||
_romData = loader.LoadRom(fileData, nullptr);
|
||||
} else if(memcmp(buffer, "FDS\x1a", 4) == 0 || memcmp(buffer, "\x1*NINTENDO-HVC*", 15) == 0) {
|
||||
} else if(memcmp(fileData.data(), "FDS\x1a", 4) == 0 || memcmp(fileData.data(), "\x1*NINTENDO-HVC*", 15) == 0) {
|
||||
FdsLoader loader;
|
||||
_romData = loader.LoadRom(fileData, _filename);
|
||||
} else if(memcmp(buffer, "NESM\x1a", 5) == 0) {
|
||||
} else if(memcmp(fileData.data(), "NESM\x1a", 5) == 0) {
|
||||
NsfLoader loader;
|
||||
_romData = loader.LoadRom(fileData);
|
||||
} else if(memcmp(buffer, "NSFE", 4) == 0) {
|
||||
} else if(memcmp(fileData.data(), "NSFE", 4) == 0) {
|
||||
NsfeLoader loader;
|
||||
_romData = loader.LoadRom(fileData);
|
||||
} else if(memcmp(buffer, "UNIF", 4) == 0) {
|
||||
} else if(memcmp(fileData.data(), "UNIF", 4) == 0) {
|
||||
UnifLoader loader;
|
||||
_romData = loader.LoadRom(fileData);
|
||||
} else {
|
||||
NESHeader header = { };
|
||||
NESHeader header = {};
|
||||
if(GameDatabase::GetiNesHeader(crc, header)) {
|
||||
MessageManager::Log("[DB] Headerless ROM file found - using game database data.");
|
||||
iNesLoader loader;
|
||||
|
@ -170,7 +72,7 @@ bool RomLoader::LoadFromMemory(uint8_t* buffer, size_t length, string romName)
|
|||
string name = _romData.Filename;
|
||||
std::transform(name.begin(), name.end(), name.begin(), ::tolower);
|
||||
|
||||
if(name.find("(e)") != string::npos || name.find("(australia)") != string::npos || name.find("(europe)") != string::npos ||
|
||||
if(name.find("(e)") != string::npos || name.find("(australia)") != string::npos || name.find("(europe)") != string::npos ||
|
||||
name.find("(germany)") != string::npos || name.find("(spain)") != string::npos) {
|
||||
_romData.System = GameSystem::NesPal;
|
||||
} else if(name.find("(vs)") != string::npos) {
|
||||
|
@ -181,44 +83,6 @@ bool RomLoader::LoadFromMemory(uint8_t* buffer, size_t length, string romName)
|
|||
return !_romData.Error;
|
||||
}
|
||||
|
||||
bool RomLoader::LoadFile(string filename, istream *filestream, string patchFilename, int32_t archiveFileIndex)
|
||||
{
|
||||
_filename = filename;
|
||||
_patchFilename = patchFilename;
|
||||
|
||||
ifstream file;
|
||||
istream* input = nullptr;
|
||||
if(!filestream) {
|
||||
file.open(filename, ios::in | ios::binary);
|
||||
if(file) {
|
||||
input = &file;
|
||||
}
|
||||
} else {
|
||||
input = filestream;
|
||||
}
|
||||
|
||||
if(input) {
|
||||
char header[15];
|
||||
input->seekg(0, ios::beg);
|
||||
input->read(header, 15);
|
||||
input->seekg(0, ios::beg);
|
||||
if(memcmp(header, "PK", 2) == 0) {
|
||||
ZipReader reader;
|
||||
return LoadFromArchive(*input, reader, archiveFileIndex);
|
||||
} else if(memcmp(header, "7z", 2) == 0) {
|
||||
SZReader reader;
|
||||
return LoadFromArchive(*input, reader, archiveFileIndex);
|
||||
} else {
|
||||
if(archiveFileIndex > 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return LoadFromStream(*input, FolderUtilities::GetFilename(filename, true));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
RomData RomLoader::GetRomData()
|
||||
{
|
||||
return _romData;
|
||||
|
@ -226,13 +90,16 @@ RomData RomLoader::GetRomData()
|
|||
|
||||
int32_t RomLoader::FindMatchingRomInFile(string filename, HashInfo hashInfo)
|
||||
{
|
||||
RomLoader loader;
|
||||
int32_t fileIndex = 0;
|
||||
while(loader.LoadFile(filename, nullptr, "", fileIndex)) {
|
||||
if(hashInfo.Crc32Hash == loader._romData.Crc32 || hashInfo.Sha1Hash.compare(loader._romData.Sha1) == 0) {
|
||||
return fileIndex;
|
||||
vector<uint8_t> fileData;
|
||||
int fileIndex = 0;
|
||||
while(FileLoader::LoadFile(filename, nullptr, fileIndex, fileData)) {
|
||||
RomLoader loader;
|
||||
if(loader.LoadFile(filename, fileData)) {
|
||||
if(hashInfo.Crc32Hash == loader._romData.Crc32 || hashInfo.Sha1Hash.compare(loader._romData.Sha1) == 0) {
|
||||
return fileIndex;
|
||||
}
|
||||
fileIndex++;
|
||||
}
|
||||
fileIndex++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -8,20 +8,13 @@ class RomLoader
|
|||
private:
|
||||
RomData _romData;
|
||||
string _filename;
|
||||
string _patchFilename;
|
||||
|
||||
bool LoadFromArchive(istream &zipFile, ArchiveReader& reader, int32_t archiveFileIndex = -1);
|
||||
bool LoadFromStream(istream &romFile, string romName);
|
||||
uint32_t GetFileSize(istream &file);
|
||||
|
||||
uint8_t* ReadFile(istream &file, uint32_t &fileSize);
|
||||
bool LoadFromMemory(uint8_t* buffer, size_t length, string romName);
|
||||
static int32_t FindMatchingRomInFile(string filename, HashInfo hashInfo);
|
||||
void ApplyPatch(string patchPath, vector<uint8_t> &data);
|
||||
|
||||
public:
|
||||
bool LoadFile(string filename, istream *filestream = nullptr, string patchFilename = "", int32_t archiveFileIndex = -1);
|
||||
bool LoadFile(string filename, int32_t archiveFileIndex);
|
||||
bool LoadFile(string filename, vector<uint8_t> &fileData);
|
||||
|
||||
RomData GetRomData();
|
||||
static string FindMatchingRomInFolder(string folder, string romFilename, HashInfo hashInfo, bool useFastSearch, int32_t &archiveFileIndex);
|
||||
static vector<string> GetArchiveRomList(string filename);
|
||||
};
|
||||
|
|
|
@ -66,11 +66,7 @@ void ScaleFilter::ApplyFilter(uint16_t *ppuOutputBuffer)
|
|||
if(_scaleFilterType == ScaleFilterType::xBRZ) {
|
||||
xbrz::scale(_filterScale, _decodedPpuBuffer, outputBuffer, width, height, xbrz::ColorFormat::ARGB);
|
||||
} else if(_scaleFilterType == ScaleFilterType::HQX) {
|
||||
switch(_filterScale) {
|
||||
case 2: hq2x_32(_decodedPpuBuffer, outputBuffer, width, height); break;
|
||||
case 3: hq3x_32(_decodedPpuBuffer, outputBuffer, width, height); break;
|
||||
case 4: hq4x_32(_decodedPpuBuffer, outputBuffer, width, height); break;
|
||||
}
|
||||
hqx(_filterScale, _decodedPpuBuffer, outputBuffer, width, height);
|
||||
} else if(_scaleFilterType == ScaleFilterType::Scale2x) {
|
||||
scale(_filterScale, outputBuffer, width*sizeof(uint32_t)*_filterScale, _decodedPpuBuffer, width*sizeof(uint32_t), 4, width, height);
|
||||
} else if(_scaleFilterType == ScaleFilterType::_2xSai) {
|
||||
|
|
|
@ -3,17 +3,6 @@
|
|||
#include "stdafx.h"
|
||||
#include "DefaultVideoFilter.h"
|
||||
|
||||
enum class ScaleFilterType
|
||||
{
|
||||
xBRZ,
|
||||
HQX,
|
||||
Scale2x,
|
||||
_2xSai,
|
||||
Super2xSai,
|
||||
SuperEagle,
|
||||
Prescale,
|
||||
};
|
||||
|
||||
class ScaleFilter : public DefaultVideoFilter
|
||||
{
|
||||
private:
|
||||
|
|
|
@ -124,8 +124,9 @@ struct TileInfo
|
|||
uint8_t LowByte;
|
||||
uint8_t HighByte;
|
||||
uint32_t PaletteOffset;
|
||||
|
||||
uint16_t TileAddr; //used by HD ppu
|
||||
uint16_t TileAddr;
|
||||
|
||||
int32_t AbsoluteTileAddr; //used by HD ppu
|
||||
uint8_t OffsetY; //used by HD ppu
|
||||
};
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ RomData iNesLoader::LoadRom(vector<uint8_t>& romFile, NESHeader *preloadedHeader
|
|||
|
||||
NESHeader header;
|
||||
uint8_t* buffer = romFile.data();
|
||||
uint32_t dataSize = romFile.size();
|
||||
uint32_t dataSize = (uint32_t)romFile.size();
|
||||
if(preloadedHeader) {
|
||||
header = *preloadedHeader;
|
||||
header.SanitizeHeader(romFile.size() + sizeof(NESHeader));
|
||||
|
|
|
@ -268,6 +268,18 @@ namespace Mesen.GUI.Config
|
|||
}
|
||||
}
|
||||
|
||||
public static string HdPackFolder
|
||||
{
|
||||
get
|
||||
{
|
||||
string hdPackFolder = Path.Combine(ConfigManager.HomeFolder, "HdPacks");
|
||||
if(!Directory.Exists(hdPackFolder)) {
|
||||
Directory.CreateDirectory(hdPackFolder);
|
||||
}
|
||||
return hdPackFolder;
|
||||
}
|
||||
}
|
||||
|
||||
public static string ConfigFile
|
||||
{
|
||||
get
|
||||
|
|
49
GUI.NET/Debugger/Controls/ctrlChrViewer.Designer.cs
generated
49
GUI.NET/Debugger/Controls/ctrlChrViewer.Designer.cs
generated
|
@ -34,6 +34,7 @@
|
|||
this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel();
|
||||
this.lblPalette = new System.Windows.Forms.Label();
|
||||
this.cboPalette = new System.Windows.Forms.ComboBox();
|
||||
this.picPaletteTooltip = new System.Windows.Forms.PictureBox();
|
||||
this.chkLargeSprites = new System.Windows.Forms.CheckBox();
|
||||
this.flowLayoutPanel2 = new System.Windows.Forms.FlowLayoutPanel();
|
||||
this.lblChrSelection = new System.Windows.Forms.Label();
|
||||
|
@ -57,11 +58,13 @@
|
|||
this.picChrBank1 = new System.Windows.Forms.PictureBox();
|
||||
this.picChrBank2 = new System.Windows.Forms.PictureBox();
|
||||
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
|
||||
this.picPaletteTooltip = new System.Windows.Forms.PictureBox();
|
||||
this.ctxMenu = new System.Windows.Forms.ContextMenuStrip(this.components);
|
||||
this.mnuCopyHdPack = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.tableLayoutPanel3.SuspendLayout();
|
||||
this.grpDisplayOptions.SuspendLayout();
|
||||
this.tableLayoutPanel1.SuspendLayout();
|
||||
this.flowLayoutPanel1.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.picPaletteTooltip)).BeginInit();
|
||||
this.flowLayoutPanel2.SuspendLayout();
|
||||
this.flpHighlight.SuspendLayout();
|
||||
this.grpTileInfo.SuspendLayout();
|
||||
|
@ -73,7 +76,7 @@
|
|||
this.tableLayoutPanel2.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.picChrBank1)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.picChrBank2)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.picPaletteTooltip)).BeginInit();
|
||||
this.ctxMenu.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// tableLayoutPanel3
|
||||
|
@ -166,6 +169,18 @@
|
|||
this.cboPalette.TabIndex = 1;
|
||||
this.cboPalette.SelectedIndexChanged += new System.EventHandler(this.cboPalette_SelectedIndexChanged);
|
||||
//
|
||||
// picPaletteTooltip
|
||||
//
|
||||
this.picPaletteTooltip.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.picPaletteTooltip.Image = global::Mesen.GUI.Properties.Resources.Help;
|
||||
this.picPaletteTooltip.Location = new System.Drawing.Point(103, 7);
|
||||
this.picPaletteTooltip.Margin = new System.Windows.Forms.Padding(3, 4, 3, 3);
|
||||
this.picPaletteTooltip.Name = "picPaletteTooltip";
|
||||
this.picPaletteTooltip.Size = new System.Drawing.Size(14, 14);
|
||||
this.picPaletteTooltip.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
|
||||
this.picPaletteTooltip.TabIndex = 16;
|
||||
this.picPaletteTooltip.TabStop = false;
|
||||
//
|
||||
// chkLargeSprites
|
||||
//
|
||||
this.chkLargeSprites.AutoSize = true;
|
||||
|
@ -406,6 +421,7 @@
|
|||
// picChrBank1
|
||||
//
|
||||
this.picChrBank1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
|
||||
this.picChrBank1.ContextMenuStrip = this.ctxMenu;
|
||||
this.picChrBank1.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||
this.picChrBank1.Location = new System.Drawing.Point(1, 1);
|
||||
this.picChrBank1.Margin = new System.Windows.Forms.Padding(1);
|
||||
|
@ -420,6 +436,7 @@
|
|||
// picChrBank2
|
||||
//
|
||||
this.picChrBank2.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
|
||||
this.picChrBank2.ContextMenuStrip = this.ctxMenu;
|
||||
this.picChrBank2.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||
this.picChrBank2.Location = new System.Drawing.Point(1, 260);
|
||||
this.picChrBank2.Margin = new System.Windows.Forms.Padding(1);
|
||||
|
@ -437,17 +454,20 @@
|
|||
this.toolTip.InitialDelay = 10;
|
||||
this.toolTip.ReshowDelay = 10;
|
||||
//
|
||||
// picPaletteTooltip
|
||||
// ctxMenu
|
||||
//
|
||||
this.picPaletteTooltip.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.picPaletteTooltip.Image = global::Mesen.GUI.Properties.Resources.Help;
|
||||
this.picPaletteTooltip.Location = new System.Drawing.Point(103, 7);
|
||||
this.picPaletteTooltip.Margin = new System.Windows.Forms.Padding(3, 4, 3, 3);
|
||||
this.picPaletteTooltip.Name = "picPaletteTooltip";
|
||||
this.picPaletteTooltip.Size = new System.Drawing.Size(14, 14);
|
||||
this.picPaletteTooltip.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
|
||||
this.picPaletteTooltip.TabIndex = 16;
|
||||
this.picPaletteTooltip.TabStop = false;
|
||||
this.ctxMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.mnuCopyHdPack});
|
||||
this.ctxMenu.Name = "ctxMenu";
|
||||
this.ctxMenu.Size = new System.Drawing.Size(222, 48);
|
||||
this.ctxMenu.Opening += new System.ComponentModel.CancelEventHandler(this.ctxMenu_Opening);
|
||||
//
|
||||
// mnuCopyHdPack
|
||||
//
|
||||
this.mnuCopyHdPack.Name = "mnuCopyHdPack";
|
||||
this.mnuCopyHdPack.Size = new System.Drawing.Size(221, 22);
|
||||
this.mnuCopyHdPack.Text = "Copy Tile (HD Pack Format)";
|
||||
this.mnuCopyHdPack.Click += new System.EventHandler(this.mnuCopyHdPack_Click);
|
||||
//
|
||||
// ctrlChrViewer
|
||||
//
|
||||
|
@ -462,6 +482,7 @@
|
|||
this.tableLayoutPanel1.PerformLayout();
|
||||
this.flowLayoutPanel1.ResumeLayout(false);
|
||||
this.flowLayoutPanel1.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.picPaletteTooltip)).EndInit();
|
||||
this.flowLayoutPanel2.ResumeLayout(false);
|
||||
this.flowLayoutPanel2.PerformLayout();
|
||||
this.flpHighlight.ResumeLayout(false);
|
||||
|
@ -476,7 +497,7 @@
|
|||
this.tableLayoutPanel2.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)(this.picChrBank1)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.picChrBank2)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.picPaletteTooltip)).EndInit();
|
||||
this.ctxMenu.ResumeLayout(false);
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
@ -513,5 +534,7 @@
|
|||
private System.Windows.Forms.PictureBox picTileTooltip;
|
||||
private System.Windows.Forms.ToolTip toolTip;
|
||||
private System.Windows.Forms.PictureBox picPaletteTooltip;
|
||||
private System.Windows.Forms.ContextMenuStrip ctxMenu;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuCopyHdPack;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -415,5 +415,34 @@ namespace Mesen.GUI.Debugger.Controls
|
|||
_selectedColor = color;
|
||||
RefreshPalettePicker();
|
||||
}
|
||||
|
||||
string _copyData;
|
||||
private void mnuCopyHdPack_Click(object sender, EventArgs e)
|
||||
{
|
||||
Clipboard.SetText(_copyData);
|
||||
}
|
||||
|
||||
private void ctxMenu_Opening(object sender, CancelEventArgs e)
|
||||
{
|
||||
int baseAddress = _bottomBank ? 0x1000 : 0x0000;
|
||||
bool ppuMemory = this.cboChrSelection.SelectedIndex == 0;
|
||||
if(this.cboChrSelection.SelectedIndex > 1) {
|
||||
baseAddress += (this.cboChrSelection.SelectedIndex - 1) * 0x2000;
|
||||
}
|
||||
|
||||
int tileIndex = GetLargeSpriteIndex(_tileIndex);
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for(int i = 0; i < 16; i++) {
|
||||
sb.Append(InteropEmu.DebugGetMemoryValue(ppuMemory ? DebugMemoryType.PpuMemory : DebugMemoryType.ChrRom, (UInt32)(baseAddress + tileIndex * 16 + i)).ToString("X2"));
|
||||
}
|
||||
sb.Append(",");
|
||||
for(int i = 1; i < 4; i++) {
|
||||
sb.Append(InteropEmu.DebugGetMemoryValue(DebugMemoryType.PaletteMemory, (uint)(this._selectedPalette * 4 + i)).ToString("X2"));
|
||||
}
|
||||
|
||||
_copyData = sb.ToString();
|
||||
_copyData = _copyData.Substring(0, _copyData.Length - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -117,7 +117,10 @@
|
|||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<metadata name="toolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<metadata name="ctxMenu.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>17, 17</value>
|
||||
</metadata>
|
||||
<metadata name="toolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>116, 17</value>
|
||||
</metadata>
|
||||
</root>
|
|
@ -27,10 +27,14 @@
|
|||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.components = new System.ComponentModel.Container();
|
||||
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.picNametable = new System.Windows.Forms.PictureBox();
|
||||
this.grpTileInfo = new System.Windows.Forms.GroupBox();
|
||||
this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.txtPpuAddress = new System.Windows.Forms.TextBox();
|
||||
this.txtLocation = new System.Windows.Forms.TextBox();
|
||||
this.txtNametable = new System.Windows.Forms.TextBox();
|
||||
this.txtPaletteAddress = new System.Windows.Forms.TextBox();
|
||||
this.txtAttributeAddress = new System.Windows.Forms.TextBox();
|
||||
this.txtAttributeData = new System.Windows.Forms.TextBox();
|
||||
|
@ -43,22 +47,22 @@
|
|||
this.lblTile = new System.Windows.Forms.Label();
|
||||
this.txtTileIndex = new System.Windows.Forms.TextBox();
|
||||
this.picTile = new System.Windows.Forms.PictureBox();
|
||||
this.lblNametableIndex = new System.Windows.Forms.Label();
|
||||
this.lblLocation = new System.Windows.Forms.Label();
|
||||
this.lblPpuAddress = new System.Windows.Forms.Label();
|
||||
this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel();
|
||||
this.chkShowPpuScrollOverlay = new System.Windows.Forms.CheckBox();
|
||||
this.chkShowTileGrid = new System.Windows.Forms.CheckBox();
|
||||
this.chkShowAttributeGrid = new System.Windows.Forms.CheckBox();
|
||||
this.lblNametableIndex = new System.Windows.Forms.Label();
|
||||
this.lblLocation = new System.Windows.Forms.Label();
|
||||
this.txtNametable = new System.Windows.Forms.TextBox();
|
||||
this.txtLocation = new System.Windows.Forms.TextBox();
|
||||
this.lblPpuAddress = new System.Windows.Forms.Label();
|
||||
this.txtPpuAddress = new System.Windows.Forms.TextBox();
|
||||
this.ctxMenu = new System.Windows.Forms.ContextMenuStrip(this.components);
|
||||
this.mnuCopyHdPack = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.tableLayoutPanel1.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.picNametable)).BeginInit();
|
||||
this.grpTileInfo.SuspendLayout();
|
||||
this.tableLayoutPanel2.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.picTile)).BeginInit();
|
||||
this.flowLayoutPanel1.SuspendLayout();
|
||||
this.ctxMenu.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// tableLayoutPanel1
|
||||
|
@ -82,6 +86,7 @@
|
|||
// picNametable
|
||||
//
|
||||
this.picNametable.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
|
||||
this.picNametable.ContextMenuStrip = this.ctxMenu;
|
||||
this.picNametable.Location = new System.Drawing.Point(1, 1);
|
||||
this.picNametable.Margin = new System.Windows.Forms.Padding(1);
|
||||
this.picNametable.Name = "picNametable";
|
||||
|
@ -138,9 +143,33 @@
|
|||
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.tableLayoutPanel2.Size = new System.Drawing.Size(169, 282);
|
||||
this.tableLayoutPanel2.Size = new System.Drawing.Size(169, 311);
|
||||
this.tableLayoutPanel2.TabIndex = 0;
|
||||
//
|
||||
// txtPpuAddress
|
||||
//
|
||||
this.txtPpuAddress.Location = new System.Drawing.Point(84, 3);
|
||||
this.txtPpuAddress.Name = "txtPpuAddress";
|
||||
this.txtPpuAddress.ReadOnly = true;
|
||||
this.txtPpuAddress.Size = new System.Drawing.Size(42, 20);
|
||||
this.txtPpuAddress.TabIndex = 18;
|
||||
//
|
||||
// txtLocation
|
||||
//
|
||||
this.txtLocation.Location = new System.Drawing.Point(84, 55);
|
||||
this.txtLocation.Name = "txtLocation";
|
||||
this.txtLocation.ReadOnly = true;
|
||||
this.txtLocation.Size = new System.Drawing.Size(42, 20);
|
||||
this.txtLocation.TabIndex = 16;
|
||||
//
|
||||
// txtNametable
|
||||
//
|
||||
this.txtNametable.Location = new System.Drawing.Point(84, 29);
|
||||
this.txtNametable.Name = "txtNametable";
|
||||
this.txtNametable.ReadOnly = true;
|
||||
this.txtNametable.Size = new System.Drawing.Size(26, 20);
|
||||
this.txtNametable.TabIndex = 15;
|
||||
//
|
||||
// txtPaletteAddress
|
||||
//
|
||||
this.txtPaletteAddress.Location = new System.Drawing.Point(84, 185);
|
||||
|
@ -250,12 +279,42 @@
|
|||
this.picTile.TabIndex = 12;
|
||||
this.picTile.TabStop = false;
|
||||
//
|
||||
// lblNametableIndex
|
||||
//
|
||||
this.lblNametableIndex.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.lblNametableIndex.AutoSize = true;
|
||||
this.lblNametableIndex.Location = new System.Drawing.Point(3, 32);
|
||||
this.lblNametableIndex.Name = "lblNametableIndex";
|
||||
this.lblNametableIndex.Size = new System.Drawing.Size(61, 13);
|
||||
this.lblNametableIndex.TabIndex = 13;
|
||||
this.lblNametableIndex.Text = "Nametable:";
|
||||
//
|
||||
// lblLocation
|
||||
//
|
||||
this.lblLocation.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.lblLocation.AutoSize = true;
|
||||
this.lblLocation.Location = new System.Drawing.Point(3, 58);
|
||||
this.lblLocation.Name = "lblLocation";
|
||||
this.lblLocation.Size = new System.Drawing.Size(51, 13);
|
||||
this.lblLocation.TabIndex = 14;
|
||||
this.lblLocation.Text = "Location:";
|
||||
//
|
||||
// lblPpuAddress
|
||||
//
|
||||
this.lblPpuAddress.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.lblPpuAddress.AutoSize = true;
|
||||
this.lblPpuAddress.Location = new System.Drawing.Point(3, 6);
|
||||
this.lblPpuAddress.Name = "lblPpuAddress";
|
||||
this.lblPpuAddress.Size = new System.Drawing.Size(57, 13);
|
||||
this.lblPpuAddress.TabIndex = 17;
|
||||
this.lblPpuAddress.Text = "PPU Addr:";
|
||||
//
|
||||
// flowLayoutPanel1
|
||||
//
|
||||
this.flowLayoutPanel1.Controls.Add(this.chkShowPpuScrollOverlay);
|
||||
this.flowLayoutPanel1.Controls.Add(this.chkShowTileGrid);
|
||||
this.flowLayoutPanel1.Controls.Add(this.chkShowAttributeGrid);
|
||||
this.flowLayoutPanel1.Location = new System.Drawing.Point(516, 307);
|
||||
this.flowLayoutPanel1.Location = new System.Drawing.Point(516, 336);
|
||||
this.flowLayoutPanel1.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.flowLayoutPanel1.Name = "flowLayoutPanel1";
|
||||
this.flowLayoutPanel1.Size = new System.Drawing.Size(181, 100);
|
||||
|
@ -294,59 +353,20 @@
|
|||
this.chkShowAttributeGrid.UseVisualStyleBackColor = true;
|
||||
this.chkShowAttributeGrid.Click += new System.EventHandler(this.chkShowAttributeGrid_Click);
|
||||
//
|
||||
// lblNametableIndex
|
||||
// ctxMenu
|
||||
//
|
||||
this.lblNametableIndex.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.lblNametableIndex.AutoSize = true;
|
||||
this.lblNametableIndex.Location = new System.Drawing.Point(3, 32);
|
||||
this.lblNametableIndex.Name = "lblNametableIndex";
|
||||
this.lblNametableIndex.Size = new System.Drawing.Size(61, 13);
|
||||
this.lblNametableIndex.TabIndex = 13;
|
||||
this.lblNametableIndex.Text = "Nametable:";
|
||||
this.ctxMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.mnuCopyHdPack});
|
||||
this.ctxMenu.Name = "ctxMenu";
|
||||
this.ctxMenu.Size = new System.Drawing.Size(222, 48);
|
||||
this.ctxMenu.Opening += new System.ComponentModel.CancelEventHandler(this.ctxMenu_Opening);
|
||||
//
|
||||
// lblLocation
|
||||
// mnuCopyHdPack
|
||||
//
|
||||
this.lblLocation.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.lblLocation.AutoSize = true;
|
||||
this.lblLocation.Location = new System.Drawing.Point(3, 58);
|
||||
this.lblLocation.Name = "lblLocation";
|
||||
this.lblLocation.Size = new System.Drawing.Size(51, 13);
|
||||
this.lblLocation.TabIndex = 14;
|
||||
this.lblLocation.Text = "Location:";
|
||||
//
|
||||
// txtNametable
|
||||
//
|
||||
this.txtNametable.Location = new System.Drawing.Point(84, 29);
|
||||
this.txtNametable.Name = "txtNametable";
|
||||
this.txtNametable.ReadOnly = true;
|
||||
this.txtNametable.Size = new System.Drawing.Size(26, 20);
|
||||
this.txtNametable.TabIndex = 15;
|
||||
//
|
||||
// txtLocation
|
||||
//
|
||||
this.txtLocation.Location = new System.Drawing.Point(84, 55);
|
||||
this.txtLocation.Name = "txtLocation";
|
||||
this.txtLocation.ReadOnly = true;
|
||||
this.txtLocation.Size = new System.Drawing.Size(42, 20);
|
||||
this.txtLocation.TabIndex = 16;
|
||||
//
|
||||
// lblPpuAddress
|
||||
//
|
||||
this.lblPpuAddress.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.lblPpuAddress.AutoSize = true;
|
||||
this.lblPpuAddress.Location = new System.Drawing.Point(3, 6);
|
||||
this.lblPpuAddress.Name = "lblPpuAddress";
|
||||
this.lblPpuAddress.Size = new System.Drawing.Size(57, 13);
|
||||
this.lblPpuAddress.TabIndex = 17;
|
||||
this.lblPpuAddress.Text = "PPU Addr:";
|
||||
//
|
||||
// txtPpuAddress
|
||||
//
|
||||
this.txtPpuAddress.Location = new System.Drawing.Point(84, 3);
|
||||
this.txtPpuAddress.Name = "txtPpuAddress";
|
||||
this.txtPpuAddress.ReadOnly = true;
|
||||
this.txtPpuAddress.Size = new System.Drawing.Size(42, 20);
|
||||
this.txtPpuAddress.TabIndex = 18;
|
||||
this.mnuCopyHdPack.Name = "mnuCopyHdPack";
|
||||
this.mnuCopyHdPack.Size = new System.Drawing.Size(221, 22);
|
||||
this.mnuCopyHdPack.Text = "Copy Tile (HD Pack Format)";
|
||||
this.mnuCopyHdPack.Click += new System.EventHandler(this.mnuCopyHdPack_Click);
|
||||
//
|
||||
// ctrlNametableViewer
|
||||
//
|
||||
|
@ -363,6 +383,7 @@
|
|||
((System.ComponentModel.ISupportInitialize)(this.picTile)).EndInit();
|
||||
this.flowLayoutPanel1.ResumeLayout(false);
|
||||
this.flowLayoutPanel1.PerformLayout();
|
||||
this.ctxMenu.ResumeLayout(false);
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
@ -395,5 +416,7 @@
|
|||
private System.Windows.Forms.Label lblLocation;
|
||||
private System.Windows.Forms.TextBox txtPpuAddress;
|
||||
private System.Windows.Forms.Label lblPpuAddress;
|
||||
private System.Windows.Forms.ContextMenuStrip ctxMenu;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuCopyHdPack;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,9 @@ namespace Mesen.GUI.Debugger.Controls
|
|||
private Bitmap _gridOverlay;
|
||||
private Bitmap _nametableImage = new Bitmap(512, 480);
|
||||
private int _currentPpuAddress = -1;
|
||||
private int _tileX = 0;
|
||||
private int _tileY = 0;
|
||||
private int _nametableIndex = 0;
|
||||
|
||||
public ctrlNametableViewer()
|
||||
{
|
||||
|
@ -139,28 +142,28 @@ namespace Mesen.GUI.Debugger.Controls
|
|||
|
||||
private void picNametable_MouseMove(object sender, MouseEventArgs e)
|
||||
{
|
||||
int nametableIndex = 0;
|
||||
_nametableIndex = 0;
|
||||
if(e.X >= 256) {
|
||||
nametableIndex++;
|
||||
_nametableIndex++;
|
||||
}
|
||||
if(e.Y >= 240) {
|
||||
nametableIndex+=2;
|
||||
_nametableIndex+=2;
|
||||
}
|
||||
|
||||
int baseAddress = 0x2000 + nametableIndex * 0x400;
|
||||
int baseAddress = 0x2000 + _nametableIndex * 0x400;
|
||||
|
||||
int tileX = Math.Min(e.X / 8, 63);
|
||||
int tileY = Math.Min(e.Y / 8, 59);
|
||||
int shift = (tileX & 0x02) | ((tileY & 0x02) << 1);
|
||||
_tileX = Math.Min(e.X / 8, 63);
|
||||
_tileY = Math.Min(e.Y / 8, 59);
|
||||
int shift = (_tileX & 0x02) | ((_tileY & 0x02) << 1);
|
||||
|
||||
if(nametableIndex % 2 == 1) {
|
||||
tileX -= 32;
|
||||
if(_nametableIndex % 2 == 1) {
|
||||
_tileX -= 32;
|
||||
}
|
||||
if(nametableIndex >= 2) {
|
||||
tileY -= 30;
|
||||
if(_nametableIndex >= 2) {
|
||||
_tileY -= 30;
|
||||
}
|
||||
|
||||
int ppuAddress = (baseAddress + tileX + tileY * 32);
|
||||
int ppuAddress = (baseAddress + _tileX + _tileY * 32);
|
||||
if(_currentPpuAddress == ppuAddress) {
|
||||
return;
|
||||
}
|
||||
|
@ -170,14 +173,14 @@ namespace Mesen.GUI.Debugger.Controls
|
|||
InteropEmu.DebugGetState(ref state);
|
||||
int bgAddr = state.PPU.ControlFlags.BackgroundPatternAddr;
|
||||
|
||||
int tileIndex = _tileData[nametableIndex][tileY*32+tileX];
|
||||
int attributeData = _attributeData[nametableIndex][tileY*32+tileX];
|
||||
int attributeAddr = baseAddress + 960 + ((tileY & 0xFC) << 1) + (tileX >> 2);
|
||||
int tileIndex = _tileData[_nametableIndex][_tileY*32+_tileX];
|
||||
int attributeData = _attributeData[_nametableIndex][_tileY*32+_tileX];
|
||||
int attributeAddr = baseAddress + 960 + ((_tileY & 0xFC) << 1) + (_tileX >> 2);
|
||||
int paletteBaseAddr = ((attributeData >> shift) & 0x03) << 2;
|
||||
|
||||
this.txtPpuAddress.Text = _currentPpuAddress.ToString("X4");
|
||||
this.txtNametable.Text = nametableIndex.ToString();
|
||||
this.txtLocation.Text = tileX.ToString() + ", " + tileY.ToString();
|
||||
this.txtNametable.Text = _nametableIndex.ToString();
|
||||
this.txtLocation.Text = _tileX.ToString() + ", " + _tileY.ToString();
|
||||
this.txtTileIndex.Text = tileIndex.ToString("X2");
|
||||
this.txtTileAddress.Text = (bgAddr + tileIndex * 16).ToString("X4");
|
||||
this.txtAttributeData.Text = attributeData.ToString("X2");
|
||||
|
@ -221,5 +224,36 @@ namespace Mesen.GUI.Debugger.Controls
|
|||
this._gridOverlay = null;
|
||||
this.RefreshViewer();
|
||||
}
|
||||
|
||||
string _copyData;
|
||||
private void mnuCopyHdPack_Click(object sender, EventArgs e)
|
||||
{
|
||||
Clipboard.SetText(_copyData);
|
||||
}
|
||||
|
||||
private void ctxMenu_Opening(object sender, CancelEventArgs e)
|
||||
{
|
||||
int baseAddress = 0x2000 + _nametableIndex * 0x400;
|
||||
int tileIndex = _tileData[_nametableIndex][_tileY*32+_tileX];
|
||||
int attributeData = _attributeData[_nametableIndex][_tileY*32+_tileX];
|
||||
int shift = (_tileX & 0x02) | ((_tileY & 0x02) << 1);
|
||||
int paletteBaseAddr = ((attributeData >> shift) & 0x03) << 2;
|
||||
DebugState state = new DebugState();
|
||||
InteropEmu.DebugGetState(ref state);
|
||||
int bgAddr = state.PPU.ControlFlags.BackgroundPatternAddr;
|
||||
int tileAddr = bgAddr + tileIndex * 16;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for(int i = 0; i < 16; i++) {
|
||||
sb.Append(InteropEmu.DebugGetMemoryValue(DebugMemoryType.PpuMemory, (uint)(tileAddr + i)).ToString("X2"));
|
||||
}
|
||||
sb.Append(",");
|
||||
for(int i = 1; i < 4; i++) {
|
||||
sb.Append(InteropEmu.DebugGetMemoryValue(DebugMemoryType.PaletteMemory, (uint)(paletteBaseAddr + i)).ToString("X2"));
|
||||
}
|
||||
|
||||
_copyData = sb.ToString();
|
||||
_copyData = _copyData.Substring(0, _copyData.Length - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -117,4 +117,7 @@
|
|||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<metadata name="ctxMenu.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>17, 17</value>
|
||||
</metadata>
|
||||
</root>
|
127
GUI.NET/Debugger/Controls/ctrlSpriteViewer.Designer.cs
generated
127
GUI.NET/Debugger/Controls/ctrlSpriteViewer.Designer.cs
generated
|
@ -27,6 +27,7 @@
|
|||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.components = new System.ComponentModel.Container();
|
||||
this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.grpSpriteInfo = new System.Windows.Forms.GroupBox();
|
||||
this.tableLayoutPanel4 = new System.Windows.Forms.TableLayoutPanel();
|
||||
|
@ -36,9 +37,6 @@
|
|||
this.lblScreenPreview = new System.Windows.Forms.Label();
|
||||
this.lblTile = new System.Windows.Forms.Label();
|
||||
this.picTile = new System.Windows.Forms.PictureBox();
|
||||
this.chkVerticalMirroring = new System.Windows.Forms.CheckBox();
|
||||
this.chkHorizontalMirroring = new System.Windows.Forms.CheckBox();
|
||||
this.chkBackgroundPriority = new System.Windows.Forms.CheckBox();
|
||||
this.lblPosition = new System.Windows.Forms.Label();
|
||||
this.txtPosition = new System.Windows.Forms.TextBox();
|
||||
this.lblTileIndex = new System.Windows.Forms.Label();
|
||||
|
@ -47,15 +45,21 @@
|
|||
this.lblTileAddress = new System.Windows.Forms.Label();
|
||||
this.txtPaletteAddress = new System.Windows.Forms.TextBox();
|
||||
this.txtTileAddress = new System.Windows.Forms.TextBox();
|
||||
this.picSprites = new System.Windows.Forms.PictureBox();
|
||||
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.chkHorizontalMirroring = new System.Windows.Forms.CheckBox();
|
||||
this.chkVerticalMirroring = new System.Windows.Forms.CheckBox();
|
||||
this.chkBackgroundPriority = new System.Windows.Forms.CheckBox();
|
||||
this.picSprites = new System.Windows.Forms.PictureBox();
|
||||
this.ctxMenu = new System.Windows.Forms.ContextMenuStrip(this.components);
|
||||
this.mnuCopyHdPack = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.tableLayoutPanel3.SuspendLayout();
|
||||
this.grpSpriteInfo.SuspendLayout();
|
||||
this.tableLayoutPanel4.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.picPreview)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.picTile)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.picSprites)).BeginInit();
|
||||
this.tableLayoutPanel1.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.picSprites)).BeginInit();
|
||||
this.ctxMenu.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// tableLayoutPanel3
|
||||
|
@ -178,39 +182,6 @@
|
|||
this.picTile.TabIndex = 12;
|
||||
this.picTile.TabStop = false;
|
||||
//
|
||||
// chkVerticalMirroring
|
||||
//
|
||||
this.chkVerticalMirroring.AutoCheck = false;
|
||||
this.chkVerticalMirroring.AutoSize = true;
|
||||
this.chkVerticalMirroring.Location = new System.Drawing.Point(6, 29);
|
||||
this.chkVerticalMirroring.Name = "chkVerticalMirroring";
|
||||
this.chkVerticalMirroring.Size = new System.Drawing.Size(77, 17);
|
||||
this.chkVerticalMirroring.TabIndex = 14;
|
||||
this.chkVerticalMirroring.Text = "Vertical flip";
|
||||
this.chkVerticalMirroring.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// chkHorizontalMirroring
|
||||
//
|
||||
this.chkHorizontalMirroring.AutoCheck = false;
|
||||
this.chkHorizontalMirroring.AutoSize = true;
|
||||
this.chkHorizontalMirroring.Location = new System.Drawing.Point(6, 6);
|
||||
this.chkHorizontalMirroring.Name = "chkHorizontalMirroring";
|
||||
this.chkHorizontalMirroring.Size = new System.Drawing.Size(89, 17);
|
||||
this.chkHorizontalMirroring.TabIndex = 13;
|
||||
this.chkHorizontalMirroring.Text = "Horizontal flip";
|
||||
this.chkHorizontalMirroring.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// chkBackgroundPriority
|
||||
//
|
||||
this.chkBackgroundPriority.AutoCheck = false;
|
||||
this.chkBackgroundPriority.AutoSize = true;
|
||||
this.chkBackgroundPriority.Location = new System.Drawing.Point(6, 52);
|
||||
this.chkBackgroundPriority.Name = "chkBackgroundPriority";
|
||||
this.chkBackgroundPriority.Size = new System.Drawing.Size(118, 17);
|
||||
this.chkBackgroundPriority.TabIndex = 19;
|
||||
this.chkBackgroundPriority.Text = "Background Priority";
|
||||
this.chkBackgroundPriority.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// lblPosition
|
||||
//
|
||||
this.lblPosition.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
|
@ -283,18 +254,6 @@
|
|||
this.txtTileAddress.Size = new System.Drawing.Size(42, 20);
|
||||
this.txtTileAddress.TabIndex = 8;
|
||||
//
|
||||
// picSprites
|
||||
//
|
||||
this.picSprites.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
|
||||
this.picSprites.Location = new System.Drawing.Point(1, 1);
|
||||
this.picSprites.Margin = new System.Windows.Forms.Padding(1);
|
||||
this.picSprites.Name = "picSprites";
|
||||
this.picSprites.Size = new System.Drawing.Size(258, 514);
|
||||
this.picSprites.TabIndex = 0;
|
||||
this.picSprites.TabStop = false;
|
||||
this.picSprites.MouseLeave += new System.EventHandler(this.picSprites_MouseLeave);
|
||||
this.picSprites.MouseMove += new System.Windows.Forms.MouseEventHandler(this.picSprites_MouseMove);
|
||||
//
|
||||
// tableLayoutPanel1
|
||||
//
|
||||
this.tableLayoutPanel1.ColumnCount = 1;
|
||||
|
@ -304,7 +263,7 @@
|
|||
this.tableLayoutPanel1.Controls.Add(this.chkVerticalMirroring, 0, 1);
|
||||
this.tableLayoutPanel1.Controls.Add(this.chkBackgroundPriority, 0, 2);
|
||||
this.tableLayoutPanel1.Location = new System.Drawing.Point(206, 52);
|
||||
this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(0, 0, 0, 0);
|
||||
this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
|
||||
this.tableLayoutPanel1.Padding = new System.Windows.Forms.Padding(3);
|
||||
this.tableLayoutPanel1.RowCount = 3;
|
||||
|
@ -315,6 +274,67 @@
|
|||
this.tableLayoutPanel1.Size = new System.Drawing.Size(200, 82);
|
||||
this.tableLayoutPanel1.TabIndex = 24;
|
||||
//
|
||||
// chkHorizontalMirroring
|
||||
//
|
||||
this.chkHorizontalMirroring.AutoCheck = false;
|
||||
this.chkHorizontalMirroring.AutoSize = true;
|
||||
this.chkHorizontalMirroring.Location = new System.Drawing.Point(6, 6);
|
||||
this.chkHorizontalMirroring.Name = "chkHorizontalMirroring";
|
||||
this.chkHorizontalMirroring.Size = new System.Drawing.Size(89, 17);
|
||||
this.chkHorizontalMirroring.TabIndex = 13;
|
||||
this.chkHorizontalMirroring.Text = "Horizontal flip";
|
||||
this.chkHorizontalMirroring.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// chkVerticalMirroring
|
||||
//
|
||||
this.chkVerticalMirroring.AutoCheck = false;
|
||||
this.chkVerticalMirroring.AutoSize = true;
|
||||
this.chkVerticalMirroring.Location = new System.Drawing.Point(6, 29);
|
||||
this.chkVerticalMirroring.Name = "chkVerticalMirroring";
|
||||
this.chkVerticalMirroring.Size = new System.Drawing.Size(77, 17);
|
||||
this.chkVerticalMirroring.TabIndex = 14;
|
||||
this.chkVerticalMirroring.Text = "Vertical flip";
|
||||
this.chkVerticalMirroring.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// chkBackgroundPriority
|
||||
//
|
||||
this.chkBackgroundPriority.AutoCheck = false;
|
||||
this.chkBackgroundPriority.AutoSize = true;
|
||||
this.chkBackgroundPriority.Location = new System.Drawing.Point(6, 52);
|
||||
this.chkBackgroundPriority.Name = "chkBackgroundPriority";
|
||||
this.chkBackgroundPriority.Size = new System.Drawing.Size(118, 17);
|
||||
this.chkBackgroundPriority.TabIndex = 19;
|
||||
this.chkBackgroundPriority.Text = "Background Priority";
|
||||
this.chkBackgroundPriority.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// picSprites
|
||||
//
|
||||
this.picSprites.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
|
||||
this.picSprites.ContextMenuStrip = this.ctxMenu;
|
||||
this.picSprites.Location = new System.Drawing.Point(1, 1);
|
||||
this.picSprites.Margin = new System.Windows.Forms.Padding(1);
|
||||
this.picSprites.Name = "picSprites";
|
||||
this.picSprites.Size = new System.Drawing.Size(258, 514);
|
||||
this.picSprites.TabIndex = 0;
|
||||
this.picSprites.TabStop = false;
|
||||
this.picSprites.MouseLeave += new System.EventHandler(this.picSprites_MouseLeave);
|
||||
this.picSprites.MouseMove += new System.Windows.Forms.MouseEventHandler(this.picSprites_MouseMove);
|
||||
//
|
||||
// ctxMenu
|
||||
//
|
||||
this.ctxMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.mnuCopyHdPack});
|
||||
this.ctxMenu.Name = "ctxMenu";
|
||||
this.ctxMenu.Size = new System.Drawing.Size(222, 26);
|
||||
this.ctxMenu.Opening += new System.ComponentModel.CancelEventHandler(this.ctxMenu_Opening);
|
||||
//
|
||||
// mnuCopyHdPack
|
||||
//
|
||||
this.mnuCopyHdPack.Name = "mnuCopyHdPack";
|
||||
this.mnuCopyHdPack.Size = new System.Drawing.Size(221, 22);
|
||||
this.mnuCopyHdPack.Text = "Copy Tile (HD Pack Format)";
|
||||
this.mnuCopyHdPack.Click += new System.EventHandler(this.mnuCopyHdPack_Click);
|
||||
//
|
||||
// ctrlSpriteViewer
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
|
@ -328,9 +348,10 @@
|
|||
this.tableLayoutPanel4.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.picPreview)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.picTile)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.picSprites)).EndInit();
|
||||
this.tableLayoutPanel1.ResumeLayout(false);
|
||||
this.tableLayoutPanel1.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.picSprites)).EndInit();
|
||||
this.ctxMenu.ResumeLayout(false);
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
@ -359,5 +380,7 @@
|
|||
private System.Windows.Forms.Label lblSpriteIndex;
|
||||
private System.Windows.Forms.TextBox txtSpriteIndex;
|
||||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
|
||||
private System.Windows.Forms.ContextMenuStrip ctxMenu;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuCopyHdPack;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -173,5 +173,39 @@ namespace Mesen.GUI.Debugger.Controls
|
|||
this._selectedSprite = -1;
|
||||
this.CreateScreenPreview();
|
||||
}
|
||||
|
||||
string _copyData;
|
||||
private void mnuCopyHdPack_Click(object sender, EventArgs e)
|
||||
{
|
||||
Clipboard.SetText(_copyData);
|
||||
}
|
||||
|
||||
private void ctxMenu_Opening(object sender, CancelEventArgs e)
|
||||
{
|
||||
int ramAddr = _selectedSprite * 4;
|
||||
int spriteY = _spriteRam[ramAddr];
|
||||
int tileIndex = _spriteRam[ramAddr + 1];
|
||||
int palette = (_spriteRam[ramAddr + 2] & 0x03) + 4;
|
||||
int spriteX = _spriteRam[ramAddr + 3];
|
||||
|
||||
int tileAddr;
|
||||
if(_largeSprites) {
|
||||
tileAddr = ((tileIndex & 0x01) == 0x01 ? 0x1000 : 0x0000) + ((tileIndex & 0xFE) << 4);
|
||||
} else {
|
||||
tileAddr = _spritePatternAddr + (tileIndex << 4);
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for(int i = 0; i < 16; i++) {
|
||||
sb.Append(InteropEmu.DebugGetMemoryValue(DebugMemoryType.PpuMemory, (UInt32)(tileAddr + i)).ToString("X2"));
|
||||
}
|
||||
sb.Append(",");
|
||||
for(int i = 1; i < 4; i++) {
|
||||
sb.Append(InteropEmu.DebugGetMemoryValue(DebugMemoryType.PaletteMemory, (uint)(palette * 4 + i)).ToString("X2"));
|
||||
}
|
||||
|
||||
_copyData = sb.ToString();
|
||||
_copyData = _copyData.Substring(0, _copyData.Length - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -117,4 +117,7 @@
|
|||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<metadata name="ctxMenu.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>17, 17</value>
|
||||
</metadata>
|
||||
</root>
|
|
@ -61,11 +61,14 @@ namespace Mesen.GUI.Forms
|
|||
if(DialogResult == System.Windows.Forms.DialogResult.OK) {
|
||||
if(!ValidateInput()) {
|
||||
e.Cancel = true;
|
||||
} else {
|
||||
_validateTimer.Tick -= OnValidateInput;
|
||||
_validateTimer.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
if(!e.Cancel) {
|
||||
_validateTimer.Tick -= OnValidateInput;
|
||||
_validateTimer.Stop();
|
||||
}
|
||||
|
||||
base.OnFormClosing(e);
|
||||
}
|
||||
|
||||
|
|
|
@ -31,11 +31,8 @@ namespace Mesen.GUI.Forms
|
|||
this.Icon = menuItem.Image;
|
||||
}
|
||||
|
||||
if(owner != null) {
|
||||
CenterOnParent(owner);
|
||||
}
|
||||
|
||||
base.Show(owner);
|
||||
CenterOnParent(owner);
|
||||
base.Show();
|
||||
}
|
||||
|
||||
private void CenterOnParent(IWin32Window owner)
|
||||
|
|
398
GUI.NET/Forms/HdPackEditor/frmHdPackEditor.Designer.cs
generated
Normal file
398
GUI.NET/Forms/HdPackEditor/frmHdPackEditor.Designer.cs
generated
Normal file
|
@ -0,0 +1,398 @@
|
|||
namespace Mesen.GUI.Forms.HdPackEditor
|
||||
{
|
||||
partial class frmHdPackEditor
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if(disposing && (components != null)) {
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.components = new System.ComponentModel.Container();
|
||||
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.grpPreview = new System.Windows.Forms.GroupBox();
|
||||
this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.picBankPreview = new System.Windows.Forms.PictureBox();
|
||||
this.cboBank = new System.Windows.Forms.ComboBox();
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.groupBox1 = new System.Windows.Forms.GroupBox();
|
||||
this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.cboChrBankSize = new System.Windows.Forms.ComboBox();
|
||||
this.lblBankSize = new System.Windows.Forms.Label();
|
||||
this.lblScale = new System.Windows.Forms.Label();
|
||||
this.cboScale = new System.Windows.Forms.ComboBox();
|
||||
this.chkSortByFrequency = new System.Windows.Forms.CheckBox();
|
||||
this.chkLargeSprites = new System.Windows.Forms.CheckBox();
|
||||
this.chkGroupBlankTiles = new System.Windows.Forms.CheckBox();
|
||||
this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel();
|
||||
this.lblFolder = new System.Windows.Forms.Label();
|
||||
this.txtSaveFolder = new System.Windows.Forms.TextBox();
|
||||
this.btnSelectFolder = new System.Windows.Forms.Button();
|
||||
this.flowLayoutPanel2 = new System.Windows.Forms.FlowLayoutPanel();
|
||||
this.btnStartRecording = new System.Windows.Forms.Button();
|
||||
this.btnStopRecording = new System.Windows.Forms.Button();
|
||||
this.tmrRefresh = new System.Windows.Forms.Timer(this.components);
|
||||
this.tableLayoutPanel1.SuspendLayout();
|
||||
this.grpPreview.SuspendLayout();
|
||||
this.tableLayoutPanel3.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.picBankPreview)).BeginInit();
|
||||
this.groupBox1.SuspendLayout();
|
||||
this.tableLayoutPanel2.SuspendLayout();
|
||||
this.flowLayoutPanel1.SuspendLayout();
|
||||
this.flowLayoutPanel2.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// tableLayoutPanel1
|
||||
//
|
||||
this.tableLayoutPanel1.ColumnCount = 2;
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.tableLayoutPanel1.Controls.Add(this.grpPreview, 1, 1);
|
||||
this.tableLayoutPanel1.Controls.Add(this.groupBox1, 0, 1);
|
||||
this.tableLayoutPanel1.Controls.Add(this.flowLayoutPanel1, 0, 0);
|
||||
this.tableLayoutPanel1.Controls.Add(this.flowLayoutPanel2, 1, 2);
|
||||
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
|
||||
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
|
||||
this.tableLayoutPanel1.RowCount = 3;
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.tableLayoutPanel1.Size = new System.Drawing.Size(612, 376);
|
||||
this.tableLayoutPanel1.TabIndex = 0;
|
||||
//
|
||||
// grpPreview
|
||||
//
|
||||
this.grpPreview.Controls.Add(this.tableLayoutPanel3);
|
||||
this.grpPreview.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.grpPreview.Location = new System.Drawing.Point(340, 31);
|
||||
this.grpPreview.Name = "grpPreview";
|
||||
this.grpPreview.Size = new System.Drawing.Size(269, 310);
|
||||
this.grpPreview.TabIndex = 0;
|
||||
this.grpPreview.TabStop = false;
|
||||
this.grpPreview.Text = "CHR Bank Preview";
|
||||
//
|
||||
// tableLayoutPanel3
|
||||
//
|
||||
this.tableLayoutPanel3.ColumnCount = 2;
|
||||
this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.tableLayoutPanel3.Controls.Add(this.picBankPreview, 0, 1);
|
||||
this.tableLayoutPanel3.Controls.Add(this.cboBank, 1, 0);
|
||||
this.tableLayoutPanel3.Controls.Add(this.label1, 0, 0);
|
||||
this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.tableLayoutPanel3.Location = new System.Drawing.Point(3, 16);
|
||||
this.tableLayoutPanel3.Name = "tableLayoutPanel3";
|
||||
this.tableLayoutPanel3.RowCount = 2;
|
||||
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
|
||||
this.tableLayoutPanel3.Size = new System.Drawing.Size(263, 291);
|
||||
this.tableLayoutPanel3.TabIndex = 2;
|
||||
//
|
||||
// picBankPreview
|
||||
//
|
||||
this.tableLayoutPanel3.SetColumnSpan(this.picBankPreview, 2);
|
||||
this.picBankPreview.Location = new System.Drawing.Point(3, 30);
|
||||
this.picBankPreview.Name = "picBankPreview";
|
||||
this.picBankPreview.Size = new System.Drawing.Size(257, 258);
|
||||
this.picBankPreview.TabIndex = 0;
|
||||
this.picBankPreview.TabStop = false;
|
||||
//
|
||||
// cboBank
|
||||
//
|
||||
this.cboBank.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
this.cboBank.FormattingEnabled = true;
|
||||
this.cboBank.Location = new System.Drawing.Point(70, 3);
|
||||
this.cboBank.Name = "cboBank";
|
||||
this.cboBank.Size = new System.Drawing.Size(121, 21);
|
||||
this.cboBank.TabIndex = 1;
|
||||
//
|
||||
// label1
|
||||
//
|
||||
this.label1.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.label1.AutoSize = true;
|
||||
this.label1.Location = new System.Drawing.Point(3, 7);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(61, 13);
|
||||
this.label1.TabIndex = 3;
|
||||
this.label1.Text = "CHR Bank:";
|
||||
//
|
||||
// groupBox1
|
||||
//
|
||||
this.groupBox1.Controls.Add(this.tableLayoutPanel2);
|
||||
this.groupBox1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.groupBox1.Location = new System.Drawing.Point(3, 31);
|
||||
this.groupBox1.Name = "groupBox1";
|
||||
this.groupBox1.Size = new System.Drawing.Size(331, 310);
|
||||
this.groupBox1.TabIndex = 4;
|
||||
this.groupBox1.TabStop = false;
|
||||
this.groupBox1.Text = "Options";
|
||||
//
|
||||
// tableLayoutPanel2
|
||||
//
|
||||
this.tableLayoutPanel2.ColumnCount = 2;
|
||||
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.tableLayoutPanel2.Controls.Add(this.cboChrBankSize, 1, 1);
|
||||
this.tableLayoutPanel2.Controls.Add(this.lblBankSize, 0, 1);
|
||||
this.tableLayoutPanel2.Controls.Add(this.lblScale, 0, 0);
|
||||
this.tableLayoutPanel2.Controls.Add(this.cboScale, 1, 0);
|
||||
this.tableLayoutPanel2.Controls.Add(this.chkSortByFrequency, 0, 2);
|
||||
this.tableLayoutPanel2.Controls.Add(this.chkLargeSprites, 0, 4);
|
||||
this.tableLayoutPanel2.Controls.Add(this.chkGroupBlankTiles, 0, 3);
|
||||
this.tableLayoutPanel2.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.tableLayoutPanel2.Location = new System.Drawing.Point(3, 16);
|
||||
this.tableLayoutPanel2.Name = "tableLayoutPanel2";
|
||||
this.tableLayoutPanel2.RowCount = 5;
|
||||
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
|
||||
this.tableLayoutPanel2.Size = new System.Drawing.Size(325, 291);
|
||||
this.tableLayoutPanel2.TabIndex = 0;
|
||||
//
|
||||
// cboChrBankSize
|
||||
//
|
||||
this.cboChrBankSize.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
this.cboChrBankSize.FormattingEnabled = true;
|
||||
this.cboChrBankSize.Items.AddRange(new object[] {
|
||||
"1 KB",
|
||||
"2 KB",
|
||||
"4 KB"});
|
||||
this.cboChrBankSize.Location = new System.Drawing.Point(93, 30);
|
||||
this.cboChrBankSize.Name = "cboChrBankSize";
|
||||
this.cboChrBankSize.Size = new System.Drawing.Size(121, 21);
|
||||
this.cboChrBankSize.TabIndex = 10;
|
||||
//
|
||||
// lblBankSize
|
||||
//
|
||||
this.lblBankSize.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.lblBankSize.AutoSize = true;
|
||||
this.lblBankSize.Location = new System.Drawing.Point(3, 34);
|
||||
this.lblBankSize.Name = "lblBankSize";
|
||||
this.lblBankSize.Size = new System.Drawing.Size(84, 13);
|
||||
this.lblBankSize.TabIndex = 9;
|
||||
this.lblBankSize.Text = "CHR Bank Size:";
|
||||
//
|
||||
// lblScale
|
||||
//
|
||||
this.lblScale.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.lblScale.AutoSize = true;
|
||||
this.lblScale.Location = new System.Drawing.Point(3, 7);
|
||||
this.lblScale.Name = "lblScale";
|
||||
this.lblScale.Size = new System.Drawing.Size(64, 13);
|
||||
this.lblScale.TabIndex = 4;
|
||||
this.lblScale.Text = "Scale/Filter:";
|
||||
//
|
||||
// cboScale
|
||||
//
|
||||
this.cboScale.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
this.cboScale.FormattingEnabled = true;
|
||||
this.cboScale.Location = new System.Drawing.Point(93, 3);
|
||||
this.cboScale.Name = "cboScale";
|
||||
this.cboScale.Size = new System.Drawing.Size(121, 21);
|
||||
this.cboScale.TabIndex = 5;
|
||||
//
|
||||
// chkSortByFrequency
|
||||
//
|
||||
this.chkSortByFrequency.AutoSize = true;
|
||||
this.chkSortByFrequency.Checked = true;
|
||||
this.chkSortByFrequency.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
this.tableLayoutPanel2.SetColumnSpan(this.chkSortByFrequency, 2);
|
||||
this.chkSortByFrequency.Location = new System.Drawing.Point(3, 57);
|
||||
this.chkSortByFrequency.Name = "chkSortByFrequency";
|
||||
this.chkSortByFrequency.Size = new System.Drawing.Size(173, 17);
|
||||
this.chkSortByFrequency.TabIndex = 3;
|
||||
this.chkSortByFrequency.Text = "Sort pages by usage frequency";
|
||||
this.chkSortByFrequency.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// chkLargeSprites
|
||||
//
|
||||
this.chkLargeSprites.AutoSize = true;
|
||||
this.tableLayoutPanel2.SetColumnSpan(this.chkLargeSprites, 2);
|
||||
this.chkLargeSprites.Location = new System.Drawing.Point(3, 103);
|
||||
this.chkLargeSprites.Name = "chkLargeSprites";
|
||||
this.chkLargeSprites.Size = new System.Drawing.Size(163, 17);
|
||||
this.chkLargeSprites.TabIndex = 8;
|
||||
this.chkLargeSprites.Text = "Use 8x16 sprite display mode";
|
||||
this.chkLargeSprites.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// chkGroupBlankTiles
|
||||
//
|
||||
this.chkGroupBlankTiles.AutoSize = true;
|
||||
this.chkGroupBlankTiles.Checked = true;
|
||||
this.chkGroupBlankTiles.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
this.tableLayoutPanel2.SetColumnSpan(this.chkGroupBlankTiles, 2);
|
||||
this.chkGroupBlankTiles.Location = new System.Drawing.Point(3, 80);
|
||||
this.chkGroupBlankTiles.Name = "chkGroupBlankTiles";
|
||||
this.chkGroupBlankTiles.Size = new System.Drawing.Size(105, 17);
|
||||
this.chkGroupBlankTiles.TabIndex = 11;
|
||||
this.chkGroupBlankTiles.Text = "Group blank tiles";
|
||||
this.chkGroupBlankTiles.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// flowLayoutPanel1
|
||||
//
|
||||
this.tableLayoutPanel1.SetColumnSpan(this.flowLayoutPanel1, 2);
|
||||
this.flowLayoutPanel1.Controls.Add(this.lblFolder);
|
||||
this.flowLayoutPanel1.Controls.Add(this.txtSaveFolder);
|
||||
this.flowLayoutPanel1.Controls.Add(this.btnSelectFolder);
|
||||
this.flowLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.flowLayoutPanel1.Location = new System.Drawing.Point(0, 0);
|
||||
this.flowLayoutPanel1.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.flowLayoutPanel1.Name = "flowLayoutPanel1";
|
||||
this.flowLayoutPanel1.Size = new System.Drawing.Size(612, 28);
|
||||
this.flowLayoutPanel1.TabIndex = 5;
|
||||
//
|
||||
// lblFolder
|
||||
//
|
||||
this.lblFolder.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.lblFolder.AutoSize = true;
|
||||
this.lblFolder.Location = new System.Drawing.Point(3, 8);
|
||||
this.lblFolder.Name = "lblFolder";
|
||||
this.lblFolder.Size = new System.Drawing.Size(67, 13);
|
||||
this.lblFolder.TabIndex = 0;
|
||||
this.lblFolder.Text = "Save Folder:";
|
||||
//
|
||||
// txtSaveFolder
|
||||
//
|
||||
this.txtSaveFolder.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.txtSaveFolder.Location = new System.Drawing.Point(76, 4);
|
||||
this.txtSaveFolder.Name = "txtSaveFolder";
|
||||
this.txtSaveFolder.ReadOnly = true;
|
||||
this.txtSaveFolder.Size = new System.Drawing.Size(443, 20);
|
||||
this.txtSaveFolder.TabIndex = 1;
|
||||
this.txtSaveFolder.TabStop = false;
|
||||
//
|
||||
// btnSelectFolder
|
||||
//
|
||||
this.btnSelectFolder.AutoSize = true;
|
||||
this.btnSelectFolder.Location = new System.Drawing.Point(525, 3);
|
||||
this.btnSelectFolder.Name = "btnSelectFolder";
|
||||
this.btnSelectFolder.Size = new System.Drawing.Size(80, 23);
|
||||
this.btnSelectFolder.TabIndex = 8;
|
||||
this.btnSelectFolder.Text = "Select Folder";
|
||||
this.btnSelectFolder.UseVisualStyleBackColor = true;
|
||||
this.btnSelectFolder.Click += new System.EventHandler(this.btnSelectFolder_Click);
|
||||
//
|
||||
// flowLayoutPanel2
|
||||
//
|
||||
this.flowLayoutPanel2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.flowLayoutPanel2.Controls.Add(this.btnStartRecording);
|
||||
this.flowLayoutPanel2.Controls.Add(this.btnStopRecording);
|
||||
this.flowLayoutPanel2.FlowDirection = System.Windows.Forms.FlowDirection.RightToLeft;
|
||||
this.flowLayoutPanel2.Location = new System.Drawing.Point(348, 350);
|
||||
this.flowLayoutPanel2.Margin = new System.Windows.Forms.Padding(0, 0, 0, 0);
|
||||
this.flowLayoutPanel2.Name = "flowLayoutPanel2";
|
||||
this.flowLayoutPanel2.Size = new System.Drawing.Size(264, 26);
|
||||
this.flowLayoutPanel2.TabIndex = 7;
|
||||
//
|
||||
// btnStartRecording
|
||||
//
|
||||
this.btnStartRecording.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.btnStartRecording.AutoSize = true;
|
||||
this.btnStartRecording.Image = global::Mesen.GUI.Properties.Resources.Record;
|
||||
this.btnStartRecording.Location = new System.Drawing.Point(154, 3);
|
||||
this.btnStartRecording.Name = "btnStartRecording";
|
||||
this.btnStartRecording.Size = new System.Drawing.Size(107, 23);
|
||||
this.btnStartRecording.TabIndex = 6;
|
||||
this.btnStartRecording.Text = "Start Recording";
|
||||
this.btnStartRecording.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
|
||||
this.btnStartRecording.UseVisualStyleBackColor = true;
|
||||
this.btnStartRecording.Click += new System.EventHandler(this.btnStartRecording_Click);
|
||||
//
|
||||
// btnStopRecording
|
||||
//
|
||||
this.btnStopRecording.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.btnStopRecording.AutoSize = true;
|
||||
this.btnStopRecording.Image = global::Mesen.GUI.Properties.Resources.Stop;
|
||||
this.btnStopRecording.Location = new System.Drawing.Point(41, 3);
|
||||
this.btnStopRecording.Name = "btnStopRecording";
|
||||
this.btnStopRecording.Size = new System.Drawing.Size(107, 23);
|
||||
this.btnStopRecording.TabIndex = 7;
|
||||
this.btnStopRecording.Text = "Stop Recording";
|
||||
this.btnStopRecording.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
|
||||
this.btnStopRecording.UseVisualStyleBackColor = true;
|
||||
this.btnStopRecording.Visible = false;
|
||||
this.btnStopRecording.Click += new System.EventHandler(this.btnStopRecording_Click);
|
||||
//
|
||||
// tmrRefresh
|
||||
//
|
||||
this.tmrRefresh.Interval = 200;
|
||||
this.tmrRefresh.Tick += new System.EventHandler(this.tmrRefresh_Tick);
|
||||
//
|
||||
// frmHdPackEditor
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(612, 376);
|
||||
this.Controls.Add(this.tableLayoutPanel1);
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
|
||||
this.MaximizeBox = false;
|
||||
this.Name = "frmHdPackEditor";
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
||||
this.Text = "HD Pack Builder";
|
||||
this.tableLayoutPanel1.ResumeLayout(false);
|
||||
this.grpPreview.ResumeLayout(false);
|
||||
this.tableLayoutPanel3.ResumeLayout(false);
|
||||
this.tableLayoutPanel3.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.picBankPreview)).EndInit();
|
||||
this.groupBox1.ResumeLayout(false);
|
||||
this.tableLayoutPanel2.ResumeLayout(false);
|
||||
this.tableLayoutPanel2.PerformLayout();
|
||||
this.flowLayoutPanel1.ResumeLayout(false);
|
||||
this.flowLayoutPanel1.PerformLayout();
|
||||
this.flowLayoutPanel2.ResumeLayout(false);
|
||||
this.flowLayoutPanel2.PerformLayout();
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
|
||||
private System.Windows.Forms.GroupBox grpPreview;
|
||||
private System.Windows.Forms.PictureBox picBankPreview;
|
||||
private System.Windows.Forms.Timer tmrRefresh;
|
||||
private System.Windows.Forms.ComboBox cboBank;
|
||||
private System.Windows.Forms.CheckBox chkSortByFrequency;
|
||||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3;
|
||||
private System.Windows.Forms.Label label1;
|
||||
private System.Windows.Forms.GroupBox groupBox1;
|
||||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2;
|
||||
private System.Windows.Forms.Label lblScale;
|
||||
private System.Windows.Forms.ComboBox cboScale;
|
||||
private System.Windows.Forms.Button btnStartRecording;
|
||||
private System.Windows.Forms.CheckBox chkLargeSprites;
|
||||
private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1;
|
||||
private System.Windows.Forms.Label lblFolder;
|
||||
private System.Windows.Forms.TextBox txtSaveFolder;
|
||||
private System.Windows.Forms.Button btnSelectFolder;
|
||||
private System.Windows.Forms.ComboBox cboChrBankSize;
|
||||
private System.Windows.Forms.Label lblBankSize;
|
||||
private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel2;
|
||||
private System.Windows.Forms.Button btnStopRecording;
|
||||
private System.Windows.Forms.CheckBox chkGroupBlankTiles;
|
||||
}
|
||||
}
|
219
GUI.NET/Forms/HdPackEditor/frmHdPackEditor.cs
Normal file
219
GUI.NET/Forms/HdPackEditor/frmHdPackEditor.cs
Normal file
|
@ -0,0 +1,219 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using Mesen.GUI.Config;
|
||||
using Mesen.GUI.Controls;
|
||||
|
||||
namespace Mesen.GUI.Forms.HdPackEditor
|
||||
{
|
||||
public partial class frmHdPackEditor : BaseForm
|
||||
{
|
||||
private bool _isRecording = false;
|
||||
|
||||
public frmHdPackEditor()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
if(!InteropEmu.GetRomInfo().IsChrRam) {
|
||||
cboChrBankSize.Visible = false;
|
||||
lblBankSize.Visible = false;
|
||||
}
|
||||
|
||||
txtSaveFolder.Text = Path.Combine(ConfigManager.HdPackFolder, InteropEmu.GetRomInfo().GetRomName());
|
||||
picBankPreview.Image = new Bitmap(256, 256);
|
||||
|
||||
UpdateFilterDropdown();
|
||||
|
||||
cboChrBankSize.SelectedIndex = 2;
|
||||
|
||||
UpdateUI(false);
|
||||
}
|
||||
|
||||
protected override void OnFormClosing(FormClosingEventArgs e)
|
||||
{
|
||||
base.OnFormClosing(e);
|
||||
if(_isRecording) {
|
||||
StopRecording();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateFilterDropdown()
|
||||
{
|
||||
int scaleFilter = -1;
|
||||
string hdDefFile = Path.Combine(txtSaveFolder.Text, "hires.txt");
|
||||
if(File.Exists(hdDefFile)) {
|
||||
string fileContent = File.ReadAllText(hdDefFile);
|
||||
Match match = Regex.Match(fileContent, "<scale>(\\d*)");
|
||||
if(match.Success) {
|
||||
if(Int32.TryParse(match.Groups[1].ToString(), out int scale)) {
|
||||
scaleFilter = scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cboScale.Items.Clear();
|
||||
foreach(FilterInfo info in _filters) {
|
||||
if(scaleFilter == -1 || info.Scale == scaleFilter) {
|
||||
cboScale.Items.Add(info);
|
||||
}
|
||||
}
|
||||
cboScale.SelectedIndex = 0;
|
||||
}
|
||||
|
||||
private void tmrRefresh_Tick(object sender, EventArgs e)
|
||||
{
|
||||
UInt32[] bankList = InteropEmu.HdBuilderGetChrBankList();
|
||||
object selectedItem = cboBank.SelectedItem;
|
||||
if(bankList.Length != cboBank.Items.Count) {
|
||||
cboBank.Items.Clear();
|
||||
foreach(UInt32 bankNumber in bankList) {
|
||||
cboBank.Items.Add(bankNumber);
|
||||
}
|
||||
}
|
||||
cboBank.SelectedItem = selectedItem;
|
||||
if(cboBank.SelectedIndex < 0) {
|
||||
cboBank.SelectedIndex = 0;
|
||||
}
|
||||
|
||||
int scale = (int)((FilterInfo)cboScale.SelectedItem).Scale;
|
||||
|
||||
using(Graphics g = Graphics.FromImage(picBankPreview.Image)) {
|
||||
Byte[] rgbBuffer = InteropEmu.HdBuilderGetBankPreview((uint)cboBank.SelectedItem, scale, 0);
|
||||
GCHandle handle = GCHandle.Alloc(rgbBuffer, GCHandleType.Pinned);
|
||||
Bitmap source = new Bitmap(128*scale, 128*scale, 4*128*scale, System.Drawing.Imaging.PixelFormat.Format32bppArgb, handle.AddrOfPinnedObject());
|
||||
try {
|
||||
g.Clear(Color.Black);
|
||||
g.DrawImage(source, 0, 0, 256, 256);
|
||||
} finally {
|
||||
handle.Free();
|
||||
}
|
||||
}
|
||||
picBankPreview.Refresh();
|
||||
}
|
||||
|
||||
private void UpdateUI(bool isRecording)
|
||||
{
|
||||
btnStartRecording.Visible = !isRecording;
|
||||
btnStopRecording.Visible = isRecording;
|
||||
|
||||
cboBank.Enabled = isRecording;
|
||||
|
||||
chkLargeSprites.Enabled = !isRecording;
|
||||
chkSortByFrequency.Enabled = !isRecording;
|
||||
chkGroupBlankTiles.Enabled = !isRecording;
|
||||
|
||||
cboChrBankSize.Enabled = !isRecording;
|
||||
cboScale.Enabled = !isRecording;
|
||||
btnSelectFolder.Enabled = !isRecording;
|
||||
|
||||
_isRecording = isRecording;
|
||||
}
|
||||
|
||||
private void btnStartRecording_Click(object sender, EventArgs e)
|
||||
{
|
||||
StartRecording();
|
||||
}
|
||||
|
||||
private void btnStopRecording_Click(object sender, EventArgs e)
|
||||
{
|
||||
StopRecording();
|
||||
}
|
||||
|
||||
private void StartRecording()
|
||||
{
|
||||
HdPackRecordFlags flags = HdPackRecordFlags.None;
|
||||
if(chkLargeSprites.Checked) {
|
||||
flags |= HdPackRecordFlags.UseLargeSprites;
|
||||
}
|
||||
if(chkSortByFrequency.Checked) {
|
||||
flags |= HdPackRecordFlags.SortByUsageFrequency;
|
||||
}
|
||||
if(chkGroupBlankTiles.Checked) {
|
||||
flags |= HdPackRecordFlags.GroupBlankTiles;
|
||||
}
|
||||
|
||||
InteropEmu.HdBuilderStartRecording(txtSaveFolder.Text, ((FilterInfo)cboScale.SelectedItem).FilterType, ((FilterInfo)cboScale.SelectedItem).Scale, flags, (UInt32)Math.Pow(2, cboChrBankSize.SelectedIndex) * 0x400);
|
||||
tmrRefresh.Start();
|
||||
|
||||
UpdateUI(true);
|
||||
}
|
||||
|
||||
private void StopRecording()
|
||||
{
|
||||
tmrRefresh.Stop();
|
||||
InteropEmu.HdBuilderStopRecording();
|
||||
|
||||
UpdateFilterDropdown();
|
||||
|
||||
UpdateUI(false);
|
||||
}
|
||||
|
||||
private void btnSelectFolder_Click(object sender, EventArgs e)
|
||||
{
|
||||
using(FolderBrowserDialog fbd = new FolderBrowserDialog()) {
|
||||
fbd.SelectedPath = ConfigManager.HdPackFolder;
|
||||
if(fbd.ShowDialog() == DialogResult.OK) {
|
||||
txtSaveFolder.Text = Path.Combine(fbd.SelectedPath, InteropEmu.GetRomInfo().GetRomName());
|
||||
UpdateFilterDropdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
|
||||
{
|
||||
if(keyData == Keys.Escape) {
|
||||
this.Close();
|
||||
}
|
||||
return base.ProcessCmdKey(ref msg, keyData);
|
||||
}
|
||||
|
||||
private class FilterInfo
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public ScaleFilterType FilterType { get; set; }
|
||||
public UInt32 Scale { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Name;
|
||||
}
|
||||
}
|
||||
|
||||
private FilterInfo[] _filters = {
|
||||
new FilterInfo() { Name = "None (1x)", FilterType = ScaleFilterType.Prescale, Scale = 1 },
|
||||
new FilterInfo() { Name = ResourceHelper.GetEnumText(VideoFilterType.Prescale2x), FilterType = ScaleFilterType.Prescale, Scale = 2 },
|
||||
new FilterInfo() { Name = ResourceHelper.GetEnumText(VideoFilterType.Prescale3x), FilterType = ScaleFilterType.Prescale, Scale = 3 },
|
||||
new FilterInfo() { Name = ResourceHelper.GetEnumText(VideoFilterType.Prescale4x), FilterType = ScaleFilterType.Prescale, Scale = 4 },
|
||||
new FilterInfo() { Name = ResourceHelper.GetEnumText(VideoFilterType.Prescale6x), FilterType = ScaleFilterType.Prescale, Scale = 6 },
|
||||
new FilterInfo() { Name = ResourceHelper.GetEnumText(VideoFilterType.Prescale8x), FilterType = ScaleFilterType.Prescale, Scale = 8 },
|
||||
new FilterInfo() { Name = ResourceHelper.GetEnumText(VideoFilterType.Prescale10x), FilterType = ScaleFilterType.Prescale, Scale = 10 },
|
||||
|
||||
new FilterInfo() { Name = ResourceHelper.GetEnumText(VideoFilterType.HQ2x), FilterType = ScaleFilterType.HQX, Scale = 2 },
|
||||
new FilterInfo() { Name = ResourceHelper.GetEnumText(VideoFilterType.HQ3x), FilterType = ScaleFilterType.HQX, Scale = 3 },
|
||||
new FilterInfo() { Name = ResourceHelper.GetEnumText(VideoFilterType.HQ4x), FilterType = ScaleFilterType.HQX, Scale = 4 },
|
||||
|
||||
new FilterInfo() { Name = ResourceHelper.GetEnumText(VideoFilterType.Scale2x), FilterType = ScaleFilterType.Scale2x, Scale = 2 },
|
||||
new FilterInfo() { Name = ResourceHelper.GetEnumText(VideoFilterType.Scale3x), FilterType = ScaleFilterType.Scale2x, Scale = 3 },
|
||||
new FilterInfo() { Name = ResourceHelper.GetEnumText(VideoFilterType.Scale4x), FilterType = ScaleFilterType.Scale2x, Scale = 4 },
|
||||
|
||||
new FilterInfo() { Name = ResourceHelper.GetEnumText(VideoFilterType.Super2xSai), FilterType = ScaleFilterType.Super2xSai, Scale = 2 },
|
||||
new FilterInfo() { Name = ResourceHelper.GetEnumText(VideoFilterType.SuperEagle), FilterType = ScaleFilterType.SuperEagle, Scale = 2 },
|
||||
new FilterInfo() { Name = ResourceHelper.GetEnumText(VideoFilterType._2xSai), FilterType = ScaleFilterType._2xSai, Scale = 2 },
|
||||
|
||||
new FilterInfo() { Name = ResourceHelper.GetEnumText(VideoFilterType.xBRZ2x), FilterType = ScaleFilterType.xBRZ, Scale = 2 },
|
||||
new FilterInfo() { Name = ResourceHelper.GetEnumText(VideoFilterType.xBRZ3x), FilterType = ScaleFilterType.xBRZ, Scale = 3 },
|
||||
new FilterInfo() { Name = ResourceHelper.GetEnumText(VideoFilterType.xBRZ4x), FilterType = ScaleFilterType.xBRZ, Scale = 4 },
|
||||
new FilterInfo() { Name = ResourceHelper.GetEnumText(VideoFilterType.xBRZ5x), FilterType = ScaleFilterType.xBRZ, Scale = 5 },
|
||||
new FilterInfo() { Name = ResourceHelper.GetEnumText(VideoFilterType.xBRZ6x), FilterType = ScaleFilterType.xBRZ, Scale = 6 },
|
||||
};
|
||||
}
|
||||
}
|
126
GUI.NET/Forms/HdPackEditor/frmHdPackEditor.resx
Normal file
126
GUI.NET/Forms/HdPackEditor/frmHdPackEditor.resx
Normal file
|
@ -0,0 +1,126 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<metadata name="toolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>17, 17</value>
|
||||
</metadata>
|
||||
<metadata name="tmrRefresh.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>107, 17</value>
|
||||
</metadata>
|
||||
</root>
|
33
GUI.NET/Forms/frmMain.Designer.cs
generated
33
GUI.NET/Forms/frmMain.Designer.cs
generated
|
@ -176,6 +176,7 @@ namespace Mesen.GUI.Forms
|
|||
this.mnuRunAutomaticTest = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuDebugger = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuLogWindow = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuHdPackEditor = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.mnuRandomGame = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuTakeScreenshot = new System.Windows.Forms.ToolStripMenuItem();
|
||||
|
@ -533,7 +534,7 @@ namespace Mesen.GUI.Forms
|
|||
this.mnuShowFPS});
|
||||
this.mnuEmulationSpeed.Image = global::Mesen.GUI.Properties.Resources.Speed;
|
||||
this.mnuEmulationSpeed.Name = "mnuEmulationSpeed";
|
||||
this.mnuEmulationSpeed.Size = new System.Drawing.Size(135, 22);
|
||||
this.mnuEmulationSpeed.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuEmulationSpeed.Text = "Speed";
|
||||
this.mnuEmulationSpeed.DropDownOpening += new System.EventHandler(this.mnuEmulationSpeed_DropDownOpening);
|
||||
//
|
||||
|
@ -635,7 +636,7 @@ namespace Mesen.GUI.Forms
|
|||
this.mnuFullscreen});
|
||||
this.mnuVideoScale.Image = global::Mesen.GUI.Properties.Resources.Fullscreen;
|
||||
this.mnuVideoScale.Name = "mnuVideoScale";
|
||||
this.mnuVideoScale.Size = new System.Drawing.Size(135, 22);
|
||||
this.mnuVideoScale.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuVideoScale.Text = "Video Size";
|
||||
//
|
||||
// mnuScale1x
|
||||
|
@ -751,7 +752,7 @@ namespace Mesen.GUI.Forms
|
|||
this.mnuBilinearInterpolation});
|
||||
this.mnuVideoFilter.Image = global::Mesen.GUI.Properties.Resources.VideoFilter;
|
||||
this.mnuVideoFilter.Name = "mnuVideoFilter";
|
||||
this.mnuVideoFilter.Size = new System.Drawing.Size(135, 22);
|
||||
this.mnuVideoFilter.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuVideoFilter.Text = "Video Filter";
|
||||
//
|
||||
// mnuNoneFilter
|
||||
|
@ -981,7 +982,7 @@ namespace Mesen.GUI.Forms
|
|||
this.mnuRegionDendy});
|
||||
this.mnuRegion.Image = global::Mesen.GUI.Properties.Resources.Globe;
|
||||
this.mnuRegion.Name = "mnuRegion";
|
||||
this.mnuRegion.Size = new System.Drawing.Size(135, 22);
|
||||
this.mnuRegion.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuRegion.Text = "Region";
|
||||
//
|
||||
// mnuRegionAuto
|
||||
|
@ -1015,13 +1016,13 @@ namespace Mesen.GUI.Forms
|
|||
// toolStripMenuItem10
|
||||
//
|
||||
this.toolStripMenuItem10.Name = "toolStripMenuItem10";
|
||||
this.toolStripMenuItem10.Size = new System.Drawing.Size(132, 6);
|
||||
this.toolStripMenuItem10.Size = new System.Drawing.Size(149, 6);
|
||||
//
|
||||
// mnuAudioConfig
|
||||
//
|
||||
this.mnuAudioConfig.Image = global::Mesen.GUI.Properties.Resources.Audio;
|
||||
this.mnuAudioConfig.Name = "mnuAudioConfig";
|
||||
this.mnuAudioConfig.Size = new System.Drawing.Size(135, 22);
|
||||
this.mnuAudioConfig.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuAudioConfig.Text = "Audio";
|
||||
this.mnuAudioConfig.Click += new System.EventHandler(this.mnuAudioConfig_Click);
|
||||
//
|
||||
|
@ -1029,7 +1030,7 @@ namespace Mesen.GUI.Forms
|
|||
//
|
||||
this.mnuInput.Image = global::Mesen.GUI.Properties.Resources.Controller;
|
||||
this.mnuInput.Name = "mnuInput";
|
||||
this.mnuInput.Size = new System.Drawing.Size(135, 22);
|
||||
this.mnuInput.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuInput.Text = "Input";
|
||||
this.mnuInput.Click += new System.EventHandler(this.mnuInput_Click);
|
||||
//
|
||||
|
@ -1037,7 +1038,7 @@ namespace Mesen.GUI.Forms
|
|||
//
|
||||
this.mnuVideoConfig.Image = global::Mesen.GUI.Properties.Resources.Video;
|
||||
this.mnuVideoConfig.Name = "mnuVideoConfig";
|
||||
this.mnuVideoConfig.Size = new System.Drawing.Size(135, 22);
|
||||
this.mnuVideoConfig.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuVideoConfig.Text = "Video";
|
||||
this.mnuVideoConfig.Click += new System.EventHandler(this.mnuVideoConfig_Click);
|
||||
//
|
||||
|
@ -1045,20 +1046,20 @@ namespace Mesen.GUI.Forms
|
|||
//
|
||||
this.mnuEmulationConfig.Image = global::Mesen.GUI.Properties.Resources.DipSwitches;
|
||||
this.mnuEmulationConfig.Name = "mnuEmulationConfig";
|
||||
this.mnuEmulationConfig.Size = new System.Drawing.Size(135, 22);
|
||||
this.mnuEmulationConfig.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuEmulationConfig.Text = "Emulation";
|
||||
this.mnuEmulationConfig.Click += new System.EventHandler(this.mnuEmulationConfig_Click);
|
||||
//
|
||||
// toolStripMenuItem11
|
||||
//
|
||||
this.toolStripMenuItem11.Name = "toolStripMenuItem11";
|
||||
this.toolStripMenuItem11.Size = new System.Drawing.Size(132, 6);
|
||||
this.toolStripMenuItem11.Size = new System.Drawing.Size(149, 6);
|
||||
//
|
||||
// mnuPreferences
|
||||
//
|
||||
this.mnuPreferences.Image = global::Mesen.GUI.Properties.Resources.Cog;
|
||||
this.mnuPreferences.Name = "mnuPreferences";
|
||||
this.mnuPreferences.Size = new System.Drawing.Size(135, 22);
|
||||
this.mnuPreferences.Size = new System.Drawing.Size(152, 22);
|
||||
this.mnuPreferences.Text = "Preferences";
|
||||
this.mnuPreferences.Click += new System.EventHandler(this.mnuPreferences_Click);
|
||||
//
|
||||
|
@ -1075,6 +1076,7 @@ namespace Mesen.GUI.Forms
|
|||
this.mnuTests,
|
||||
this.mnuDebugger,
|
||||
this.mnuLogWindow,
|
||||
this.mnuHdPackEditor,
|
||||
this.toolStripMenuItem1,
|
||||
this.mnuRandomGame,
|
||||
this.mnuTakeScreenshot});
|
||||
|
@ -1410,6 +1412,14 @@ namespace Mesen.GUI.Forms
|
|||
this.mnuLogWindow.Text = "Log Window";
|
||||
this.mnuLogWindow.Click += new System.EventHandler(this.mnuLogWindow_Click);
|
||||
//
|
||||
// mnuHdPackEditor
|
||||
//
|
||||
this.mnuHdPackEditor.Image = global::Mesen.GUI.Properties.Resources.HdPack;
|
||||
this.mnuHdPackEditor.Name = "mnuHdPackEditor";
|
||||
this.mnuHdPackEditor.Size = new System.Drawing.Size(231, 22);
|
||||
this.mnuHdPackEditor.Text = "HD Pack Builder";
|
||||
this.mnuHdPackEditor.Click += new System.EventHandler(this.mnuHdPackEditor_Click);
|
||||
//
|
||||
// toolStripMenuItem1
|
||||
//
|
||||
this.toolStripMenuItem1.Name = "toolStripMenuItem1";
|
||||
|
@ -1671,6 +1681,7 @@ namespace Mesen.GUI.Forms
|
|||
private Controls.ctrlRecentGames ctrlRecentGames;
|
||||
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem24;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuPowerOff;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuHdPackEditor;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ using Mesen.GUI.Config;
|
|||
using Mesen.GUI.Debugger;
|
||||
using Mesen.GUI.Forms.Cheats;
|
||||
using Mesen.GUI.Forms.Config;
|
||||
using Mesen.GUI.Forms.HdPackEditor;
|
||||
using Mesen.GUI.Forms.NetPlay;
|
||||
using Mesen.GUI.GoogleDriveIntegration;
|
||||
|
||||
|
@ -28,6 +29,7 @@ namespace Mesen.GUI.Forms
|
|||
private frmDebugger _debugger;
|
||||
private frmLogWindow _logWindow;
|
||||
private frmCheatList _cheatListWindow;
|
||||
private frmHdPackEditor _hdPackEditorWindow;
|
||||
private string _currentRomPath = null;
|
||||
private int _currentRomArchiveIndex = -1;
|
||||
private string _currentGame = null;
|
||||
|
@ -497,6 +499,9 @@ namespace Mesen.GUI.Forms
|
|||
this._currentGame = null;
|
||||
CheatInfo.ClearCheats();
|
||||
this.BeginInvoke((MethodInvoker)(() => {
|
||||
if(_hdPackEditorWindow != null) {
|
||||
_hdPackEditorWindow.Close();
|
||||
}
|
||||
ctrlRecentGames.Initialize();
|
||||
}));
|
||||
break;
|
||||
|
@ -544,13 +549,14 @@ namespace Mesen.GUI.Forms
|
|||
|
||||
private void mnuOpen_Click(object sender, EventArgs e)
|
||||
{
|
||||
OpenFileDialog ofd = new OpenFileDialog();
|
||||
ofd.SetFilter(ResourceHelper.GetMessage("FilterRomIps"));
|
||||
if(ConfigManager.Config.RecentFiles.Count > 0) {
|
||||
ofd.InitialDirectory = Path.GetDirectoryName(ConfigManager.Config.RecentFiles[0].Path);
|
||||
}
|
||||
if(ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
|
||||
LoadFile(ofd.FileName);
|
||||
using(OpenFileDialog ofd = new OpenFileDialog()) {
|
||||
ofd.SetFilter(ResourceHelper.GetMessage("FilterRomIps"));
|
||||
if(ConfigManager.Config.RecentFiles.Count > 0) {
|
||||
ofd.InitialDirectory = Path.GetDirectoryName(ConfigManager.Config.RecentFiles[0].Path);
|
||||
}
|
||||
if(ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
|
||||
LoadFile(ofd.FileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -585,15 +591,16 @@ namespace Mesen.GUI.Forms
|
|||
{
|
||||
if(_emuThread == null) {
|
||||
if(MesenMsgBox.Show("SelectRomIps", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.OK) {
|
||||
OpenFileDialog ofd = new OpenFileDialog();
|
||||
ofd.SetFilter(ResourceHelper.GetMessage("FilterRom"));
|
||||
if(ConfigManager.Config.RecentFiles.Count > 0) {
|
||||
ofd.InitialDirectory = Path.GetDirectoryName(ConfigManager.Config.RecentFiles[0].Path);
|
||||
}
|
||||
using(OpenFileDialog ofd = new OpenFileDialog()) {
|
||||
ofd.SetFilter(ResourceHelper.GetMessage("FilterRom"));
|
||||
if(ConfigManager.Config.RecentFiles.Count > 0) {
|
||||
ofd.InitialDirectory = Path.GetDirectoryName(ConfigManager.Config.RecentFiles[0].Path);
|
||||
}
|
||||
|
||||
if(ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
|
||||
LoadROM(ofd.FileName, true, -1, patchFile);
|
||||
}
|
||||
if(ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
|
||||
LoadROM(ofd.FileName, true, -1, patchFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if(MesenMsgBox.Show("PatchAndReset", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.OK) {
|
||||
LoadROM(_currentRomPath, true, _currentRomArchiveIndex, patchFile);
|
||||
|
@ -763,6 +770,7 @@ namespace Mesen.GUI.Forms
|
|||
mnuTestRecordFrom.Enabled = (mnuTestRecordStart.Enabled || mnuTestRecordNow.Enabled || mnuTestRecordMovie.Enabled || mnuTestRecordTest.Enabled);
|
||||
|
||||
mnuDebugger.Enabled = !netPlay && _emuThread != null;
|
||||
mnuHdPackEditor.Enabled = !netPlay && _emuThread != null;
|
||||
|
||||
mnuTakeScreenshot.Enabled = _emuThread != null && !InteropEmu.IsNsf();
|
||||
mnuNetPlay.Enabled = !InteropEmu.IsNsf();
|
||||
|
@ -988,9 +996,10 @@ namespace Mesen.GUI.Forms
|
|||
if(InteropEmu.IsServerRunning()) {
|
||||
Task.Run(() => InteropEmu.StopServer());
|
||||
} else {
|
||||
frmServerConfig frm = new frmServerConfig();
|
||||
if(frm.ShowDialog(sender) == System.Windows.Forms.DialogResult.OK) {
|
||||
InteropEmu.StartServer(ConfigManager.Config.ServerInfo.Port, ConfigManager.Config.Profile.PlayerName);
|
||||
using(frmServerConfig frm = new frmServerConfig()) {
|
||||
if(frm.ShowDialog(sender) == System.Windows.Forms.DialogResult.OK) {
|
||||
InteropEmu.StartServer(ConfigManager.Config.ServerInfo.Port, ConfigManager.Config.Profile.PlayerName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1000,18 +1009,21 @@ namespace Mesen.GUI.Forms
|
|||
if(InteropEmu.IsConnected()) {
|
||||
Task.Run(() => InteropEmu.Disconnect());
|
||||
} else {
|
||||
frmClientConfig frm = new frmClientConfig();
|
||||
if(frm.ShowDialog(sender) == System.Windows.Forms.DialogResult.OK) {
|
||||
Task.Run(() => {
|
||||
InteropEmu.Connect(ConfigManager.Config.ClientConnectionInfo.Host, ConfigManager.Config.ClientConnectionInfo.Port, ConfigManager.Config.Profile.PlayerName, ConfigManager.Config.ClientConnectionInfo.Spectator);
|
||||
});
|
||||
using(frmClientConfig frm = new frmClientConfig()) {
|
||||
if(frm.ShowDialog(sender) == System.Windows.Forms.DialogResult.OK) {
|
||||
Task.Run(() => {
|
||||
InteropEmu.Connect(ConfigManager.Config.ClientConnectionInfo.Host, ConfigManager.Config.ClientConnectionInfo.Port, ConfigManager.Config.Profile.PlayerName, ConfigManager.Config.ClientConnectionInfo.Spectator);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void mnuProfile_Click(object sender, EventArgs e)
|
||||
{
|
||||
new frmPlayerProfile().ShowDialog(sender);
|
||||
using(frmPlayerProfile frm = new frmPlayerProfile()) {
|
||||
frm.ShowDialog(sender);
|
||||
}
|
||||
}
|
||||
|
||||
private void mnuExit_Click(object sender, EventArgs e)
|
||||
|
@ -1021,7 +1033,9 @@ namespace Mesen.GUI.Forms
|
|||
|
||||
private void mnuVideoConfig_Click(object sender, EventArgs e)
|
||||
{
|
||||
new frmVideoConfig().ShowDialog(sender);
|
||||
using(frmVideoConfig frm = new frmVideoConfig()) {
|
||||
frm.ShowDialog(sender);
|
||||
}
|
||||
UpdateVideoSettings();
|
||||
}
|
||||
|
||||
|
@ -1057,22 +1071,24 @@ namespace Mesen.GUI.Forms
|
|||
|
||||
private void RecordMovie(bool resetEmu)
|
||||
{
|
||||
SaveFileDialog sfd = new SaveFileDialog();
|
||||
sfd.SetFilter(ResourceHelper.GetMessage("FilterMovie"));
|
||||
sfd.InitialDirectory = ConfigManager.MovieFolder;
|
||||
sfd.FileName = InteropEmu.GetRomInfo().GetRomName() + ".mmo";
|
||||
if(sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
|
||||
InteropEmu.MovieRecord(sfd.FileName, resetEmu);
|
||||
using(SaveFileDialog sfd = new SaveFileDialog()) {
|
||||
sfd.SetFilter(ResourceHelper.GetMessage("FilterMovie"));
|
||||
sfd.InitialDirectory = ConfigManager.MovieFolder;
|
||||
sfd.FileName = InteropEmu.GetRomInfo().GetRomName() + ".mmo";
|
||||
if(sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
|
||||
InteropEmu.MovieRecord(sfd.FileName, resetEmu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void mnuPlayMovie_Click(object sender, EventArgs e)
|
||||
{
|
||||
OpenFileDialog ofd = new OpenFileDialog();
|
||||
ofd.SetFilter(ResourceHelper.GetMessage("FilterMovie"));
|
||||
ofd.InitialDirectory = ConfigManager.MovieFolder;
|
||||
if(ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
|
||||
InteropEmu.MoviePlay(ofd.FileName);
|
||||
using(OpenFileDialog ofd = new OpenFileDialog()) {
|
||||
ofd.SetFilter(ResourceHelper.GetMessage("FilterMovie"));
|
||||
ofd.InitialDirectory = ConfigManager.MovieFolder;
|
||||
if(ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
|
||||
InteropEmu.MoviePlay(ofd.FileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1093,12 +1109,13 @@ namespace Mesen.GUI.Forms
|
|||
|
||||
private void mnuWaveRecord_Click(object sender, EventArgs e)
|
||||
{
|
||||
SaveFileDialog sfd = new SaveFileDialog();
|
||||
sfd.SetFilter(ResourceHelper.GetMessage("FilterWave"));
|
||||
sfd.InitialDirectory = ConfigManager.WaveFolder;
|
||||
sfd.FileName = InteropEmu.GetRomInfo().GetRomName() + ".wav";
|
||||
if(sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
|
||||
InteropEmu.WaveRecord(sfd.FileName);
|
||||
using(SaveFileDialog sfd = new SaveFileDialog()) {
|
||||
sfd.SetFilter(ResourceHelper.GetMessage("FilterWave"));
|
||||
sfd.InitialDirectory = ConfigManager.WaveFolder;
|
||||
sfd.FileName = InteropEmu.GetRomInfo().GetRomName() + ".wav";
|
||||
if(sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
|
||||
InteropEmu.WaveRecord(sfd.FileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1123,51 +1140,52 @@ namespace Mesen.GUI.Forms
|
|||
|
||||
private void mnuTestRun_Click(object sender, EventArgs e)
|
||||
{
|
||||
OpenFileDialog ofd = new OpenFileDialog();
|
||||
ofd.SetFilter(ResourceHelper.GetMessage("FilterTest"));
|
||||
ofd.InitialDirectory = ConfigManager.TestFolder;
|
||||
ofd.Multiselect = true;
|
||||
if(ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
|
||||
List<string> passedTests = new List<string>();
|
||||
List<string> failedTests = new List<string>();
|
||||
List<int> failedFrameCount = new List<int>();
|
||||
using(OpenFileDialog ofd = new OpenFileDialog()) {
|
||||
ofd.SetFilter(ResourceHelper.GetMessage("FilterTest"));
|
||||
ofd.InitialDirectory = ConfigManager.TestFolder;
|
||||
ofd.Multiselect = true;
|
||||
if(ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
|
||||
List<string> passedTests = new List<string>();
|
||||
List<string> failedTests = new List<string>();
|
||||
List<int> failedFrameCount = new List<int>();
|
||||
|
||||
this.menuStrip.Enabled = false;
|
||||
this.menuStrip.Enabled = false;
|
||||
|
||||
Task.Run(() => {
|
||||
foreach(string filename in ofd.FileNames) {
|
||||
int result = InteropEmu.RunRecordedTest(filename);
|
||||
Task.Run(() => {
|
||||
foreach(string filename in ofd.FileNames) {
|
||||
int result = InteropEmu.RunRecordedTest(filename);
|
||||
|
||||
if(result == 0) {
|
||||
passedTests.Add(Path.GetFileNameWithoutExtension(filename));
|
||||
} else {
|
||||
failedTests.Add(Path.GetFileNameWithoutExtension(filename));
|
||||
failedFrameCount.Add(result);
|
||||
if(result == 0) {
|
||||
passedTests.Add(Path.GetFileNameWithoutExtension(filename));
|
||||
} else {
|
||||
failedTests.Add(Path.GetFileNameWithoutExtension(filename));
|
||||
failedFrameCount.Add(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.BeginInvoke((MethodInvoker)(() => {
|
||||
if(failedTests.Count == 0) {
|
||||
MessageBox.Show("All tests passed.", "", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
} else {
|
||||
StringBuilder message = new StringBuilder();
|
||||
if(passedTests.Count > 0) {
|
||||
message.AppendLine("Passed tests:");
|
||||
foreach(string test in passedTests) {
|
||||
message.AppendLine(" -" + test);
|
||||
this.BeginInvoke((MethodInvoker)(() => {
|
||||
if(failedTests.Count == 0) {
|
||||
MessageBox.Show("All tests passed.", "", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
} else {
|
||||
StringBuilder message = new StringBuilder();
|
||||
if(passedTests.Count > 0) {
|
||||
message.AppendLine("Passed tests:");
|
||||
foreach(string test in passedTests) {
|
||||
message.AppendLine(" -" + test);
|
||||
}
|
||||
message.AppendLine("");
|
||||
}
|
||||
message.AppendLine("");
|
||||
message.AppendLine("Failed tests:");
|
||||
for(int i = 0, len = failedTests.Count; i < len; i++) {
|
||||
message.AppendLine(" -" + failedTests[i] + " (" + failedFrameCount[i] + ")");
|
||||
}
|
||||
MessageBox.Show(message.ToString(), "", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
message.AppendLine("Failed tests:");
|
||||
for(int i = 0, len = failedTests.Count; i < len; i++) {
|
||||
message.AppendLine(" -" + failedTests[i] + " (" + failedFrameCount[i] + ")");
|
||||
}
|
||||
MessageBox.Show(message.ToString(), "", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
|
||||
this.menuStrip.Enabled = true;
|
||||
}));
|
||||
});
|
||||
this.menuStrip.Enabled = true;
|
||||
}));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1183,44 +1201,47 @@ namespace Mesen.GUI.Forms
|
|||
|
||||
private void RecordTest(bool resetEmu)
|
||||
{
|
||||
SaveFileDialog sfd = new SaveFileDialog();
|
||||
sfd.SetFilter(ResourceHelper.GetMessage("FilterTest"));
|
||||
sfd.InitialDirectory = ConfigManager.TestFolder;
|
||||
sfd.FileName = InteropEmu.GetRomInfo().GetRomName() + ".mtp";
|
||||
if(sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
|
||||
InteropEmu.RomTestRecord(sfd.FileName, resetEmu);
|
||||
using(SaveFileDialog sfd = new SaveFileDialog()) {
|
||||
sfd.SetFilter(ResourceHelper.GetMessage("FilterTest"));
|
||||
sfd.InitialDirectory = ConfigManager.TestFolder;
|
||||
sfd.FileName = InteropEmu.GetRomInfo().GetRomName() + ".mtp";
|
||||
if(sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
|
||||
InteropEmu.RomTestRecord(sfd.FileName, resetEmu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void mnuTestRecordMovie_Click(object sender, EventArgs e)
|
||||
{
|
||||
OpenFileDialog ofd = new OpenFileDialog();
|
||||
ofd.SetFilter(ResourceHelper.GetMessage("FilterMovie"));
|
||||
ofd.InitialDirectory = ConfigManager.MovieFolder;
|
||||
if(ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
|
||||
SaveFileDialog sfd = new SaveFileDialog();
|
||||
sfd.SetFilter(ResourceHelper.GetMessage("FilterTest"));
|
||||
sfd.InitialDirectory = ConfigManager.TestFolder;
|
||||
sfd.FileName = Path.GetFileNameWithoutExtension(ofd.FileName) + ".mtp";
|
||||
if(sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
|
||||
InteropEmu.RomTestRecordFromMovie(sfd.FileName, ofd.FileName);
|
||||
using(OpenFileDialog ofd = new OpenFileDialog()) {
|
||||
ofd.SetFilter(ResourceHelper.GetMessage("FilterMovie"));
|
||||
ofd.InitialDirectory = ConfigManager.MovieFolder;
|
||||
if(ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
|
||||
SaveFileDialog sfd = new SaveFileDialog();
|
||||
sfd.SetFilter(ResourceHelper.GetMessage("FilterTest"));
|
||||
sfd.InitialDirectory = ConfigManager.TestFolder;
|
||||
sfd.FileName = Path.GetFileNameWithoutExtension(ofd.FileName) + ".mtp";
|
||||
if(sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
|
||||
InteropEmu.RomTestRecordFromMovie(sfd.FileName, ofd.FileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void mnuTestRecordTest_Click(object sender, EventArgs e)
|
||||
{
|
||||
OpenFileDialog ofd = new OpenFileDialog();
|
||||
ofd.SetFilter(ResourceHelper.GetMessage("FilterTest"));
|
||||
ofd.InitialDirectory = ConfigManager.TestFolder;
|
||||
using(OpenFileDialog ofd = new OpenFileDialog()) {
|
||||
ofd.SetFilter(ResourceHelper.GetMessage("FilterTest"));
|
||||
ofd.InitialDirectory = ConfigManager.TestFolder;
|
||||
|
||||
if(ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
|
||||
SaveFileDialog sfd = new SaveFileDialog();
|
||||
sfd.SetFilter(ResourceHelper.GetMessage("FilterTest"));
|
||||
sfd.InitialDirectory = ConfigManager.TestFolder;
|
||||
sfd.FileName = Path.GetFileNameWithoutExtension(ofd.FileName) + ".mtp";
|
||||
if(sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
|
||||
InteropEmu.RomTestRecordFromTest(sfd.FileName, ofd.FileName);
|
||||
if(ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
|
||||
SaveFileDialog sfd = new SaveFileDialog();
|
||||
sfd.SetFilter(ResourceHelper.GetMessage("FilterTest"));
|
||||
sfd.InitialDirectory = ConfigManager.TestFolder;
|
||||
sfd.FileName = Path.GetFileNameWithoutExtension(ofd.FileName) + ".mtp";
|
||||
if(sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
|
||||
InteropEmu.RomTestRecordFromTest(sfd.FileName, ofd.FileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1248,30 +1269,36 @@ namespace Mesen.GUI.Forms
|
|||
|
||||
private void mnuInput_Click(object sender, EventArgs e)
|
||||
{
|
||||
new frmInputConfig().ShowDialog(sender);
|
||||
using(frmInputConfig frm = new frmInputConfig()) {
|
||||
frm.ShowDialog(sender);
|
||||
}
|
||||
}
|
||||
|
||||
private void mnuAudioConfig_Click(object sender, EventArgs e)
|
||||
{
|
||||
new frmAudioConfig().ShowDialog(sender);
|
||||
using(frmAudioConfig frm = new frmAudioConfig()) {
|
||||
frm.ShowDialog(sender);
|
||||
}
|
||||
this.ctrlNsfPlayer.UpdateVolume();
|
||||
}
|
||||
|
||||
private void mnuPreferences_Click(object sender, EventArgs e)
|
||||
{
|
||||
if(new frmPreferences().ShowDialog(sender) == DialogResult.OK) {
|
||||
ResourceHelper.LoadResources(ConfigManager.Config.PreferenceInfo.DisplayLanguage);
|
||||
ResourceHelper.UpdateEmuLanguage();
|
||||
ResourceHelper.ApplyResources(this);
|
||||
UpdateMenus();
|
||||
InitializeFdsDiskMenu();
|
||||
InitializeNsfMode(true);
|
||||
ctrlRecentGames.UpdateGameInfo();
|
||||
} else {
|
||||
UpdateVideoSettings();
|
||||
UpdateMenus();
|
||||
UpdateRecentFiles();
|
||||
UpdateViewerSize();
|
||||
using(frmPreferences frm = new frmPreferences()) {
|
||||
if(frm.ShowDialog(sender) == DialogResult.OK) {
|
||||
ResourceHelper.LoadResources(ConfigManager.Config.PreferenceInfo.DisplayLanguage);
|
||||
ResourceHelper.UpdateEmuLanguage();
|
||||
ResourceHelper.ApplyResources(this);
|
||||
UpdateMenus();
|
||||
InitializeFdsDiskMenu();
|
||||
InitializeNsfMode(true);
|
||||
ctrlRecentGames.UpdateGameInfo();
|
||||
} else {
|
||||
UpdateVideoSettings();
|
||||
UpdateMenus();
|
||||
UpdateRecentFiles();
|
||||
UpdateViewerSize();
|
||||
}
|
||||
}
|
||||
ResizeRecentGames(sender, e);
|
||||
}
|
||||
|
@ -1565,15 +1592,16 @@ namespace Mesen.GUI.Forms
|
|||
private void SelectFdsBiosPrompt()
|
||||
{
|
||||
if(MesenMsgBox.Show("FdsBiosNotFound", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.OK) {
|
||||
OpenFileDialog ofd = new OpenFileDialog();
|
||||
ofd.SetFilter(ResourceHelper.GetMessage("FilterAll"));
|
||||
if(ofd.ShowDialog() == DialogResult.OK) {
|
||||
string hash = MD5Helper.GetMD5Hash(ofd.FileName).ToLowerInvariant();
|
||||
if(hash == "ca30b50f880eb660a320674ed365ef7a" || hash == "c1a9e9415a6adde3c8563c622d4c9fce") {
|
||||
File.Copy(ofd.FileName, Path.Combine(ConfigManager.HomeFolder, "FdsBios.bin"));
|
||||
LoadROM(_currentRomPath, ConfigManager.Config.PreferenceInfo.AutoLoadIpsPatches);
|
||||
} else {
|
||||
MesenMsgBox.Show("InvalidFdsBios", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
using(OpenFileDialog ofd = new OpenFileDialog()) {
|
||||
ofd.SetFilter(ResourceHelper.GetMessage("FilterAll"));
|
||||
if(ofd.ShowDialog() == DialogResult.OK) {
|
||||
string hash = MD5Helper.GetMD5Hash(ofd.FileName).ToLowerInvariant();
|
||||
if(hash == "ca30b50f880eb660a320674ed365ef7a" || hash == "c1a9e9415a6adde3c8563c622d4c9fce") {
|
||||
File.Copy(ofd.FileName, Path.Combine(ConfigManager.HomeFolder, "FdsBios.bin"));
|
||||
LoadROM(_currentRomPath, ConfigManager.Config.PreferenceInfo.AutoLoadIpsPatches);
|
||||
} else {
|
||||
MesenMsgBox.Show("InvalidFdsBios", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1668,7 +1696,9 @@ namespace Mesen.GUI.Forms
|
|||
|
||||
private void mnuAbout_Click(object sender, EventArgs e)
|
||||
{
|
||||
new frmAbout().ShowDialog();
|
||||
using(frmAbout frm = new frmAbout()) {
|
||||
frm.ShowDialog();
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckForUpdates(bool displayResult)
|
||||
|
@ -1688,9 +1718,10 @@ namespace Mesen.GUI.Forms
|
|||
|
||||
if(latestVersion > currentVersion) {
|
||||
this.BeginInvoke((MethodInvoker)(() => {
|
||||
frmUpdatePrompt frmUpdate = new frmUpdatePrompt(currentVersion, latestVersion, changeLog, fileHash, donateText);
|
||||
if(frmUpdate.ShowDialog(null, this) == DialogResult.OK) {
|
||||
Application.Exit();
|
||||
using(frmUpdatePrompt frmUpdate = new frmUpdatePrompt(currentVersion, latestVersion, changeLog, fileHash, donateText)) {
|
||||
if(frmUpdate.ShowDialog(null, this) == DialogResult.OK) {
|
||||
Application.Exit();
|
||||
}
|
||||
}
|
||||
}));
|
||||
} else if(displayResult) {
|
||||
|
@ -1740,8 +1771,10 @@ namespace Mesen.GUI.Forms
|
|||
private void ShowVsGameConfig()
|
||||
{
|
||||
VsConfigInfo configInfo = VsConfigInfo.GetCurrentGameConfig(true);
|
||||
if(new frmVsGameConfig(configInfo).ShowDialog(null, this) == DialogResult.OK) {
|
||||
VsConfigInfo.ApplyConfig();
|
||||
using(frmVsGameConfig frm = new frmVsGameConfig(configInfo)) {
|
||||
if(frm.ShowDialog(null, this) == DialogResult.OK) {
|
||||
VsConfigInfo.ApplyConfig();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1761,10 +1794,7 @@ namespace Mesen.GUI.Forms
|
|||
{
|
||||
if(_logWindow == null) {
|
||||
_logWindow = new frmLogWindow();
|
||||
_logWindow.StartPosition = FormStartPosition.Manual;
|
||||
_logWindow.Left = this.Left + (this.Width - _logWindow.Width) / 2;
|
||||
_logWindow.Top = this.Top + (this.Height - _logWindow.Height) / 2;
|
||||
_logWindow.Show(sender, null);
|
||||
_logWindow.Show(sender, this);
|
||||
_logWindow.FormClosed += (object a, FormClosedEventArgs b) => {
|
||||
_logWindow = null;
|
||||
};
|
||||
|
@ -1775,7 +1805,9 @@ namespace Mesen.GUI.Forms
|
|||
|
||||
private void mnuEmulationConfig_Click(object sender, EventArgs e)
|
||||
{
|
||||
new frmEmulationConfig().ShowDialog(sender);
|
||||
using(frmEmulationConfig frm = new frmEmulationConfig()) {
|
||||
frm.ShowDialog(sender);
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeNsfMode(bool updateTextOnly = false, bool gameLoaded = false)
|
||||
|
@ -1852,5 +1884,18 @@ namespace Mesen.GUI.Forms
|
|||
{
|
||||
CursorManager.OnMouseLeave();
|
||||
}
|
||||
|
||||
private void mnuHdPackEditor_Click(object sender, EventArgs e)
|
||||
{
|
||||
if(_hdPackEditorWindow == null) {
|
||||
_hdPackEditorWindow = new frmHdPackEditor();
|
||||
_hdPackEditorWindow.Show(sender, this);
|
||||
_hdPackEditorWindow.FormClosed += (object a, FormClosedEventArgs b) => {
|
||||
_hdPackEditorWindow = null;
|
||||
};
|
||||
} else {
|
||||
_hdPackEditorWindow.Focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -643,6 +643,12 @@
|
|||
<Compile Include="Forms\frmUpdatePrompt.Designer.cs">
|
||||
<DependentUpon>frmUpdatePrompt.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Forms\HdPackEditor\frmHdPackEditor.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Forms\HdPackEditor\frmHdPackEditor.Designer.cs">
|
||||
<DependentUpon>frmHdPackEditor.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Forms\MesenMsgBox.cs" />
|
||||
<Compile Include="Forms\NetPlay\frmClientConfig.cs">
|
||||
<SubType>Form</SubType>
|
||||
|
@ -679,6 +685,7 @@
|
|||
<Compile Include="ResourceManager.cs" />
|
||||
<Compile Include="RuntimeChecker.cs" />
|
||||
<Compile Include="SingleInstance.cs" />
|
||||
<None Include="Resources\HdPack.png" />
|
||||
<None Include="Resources\VideoFilter.png" />
|
||||
<None Include="Resources\map.png" />
|
||||
<None Include="Resources\PowerCycle.png" />
|
||||
|
@ -871,6 +878,9 @@
|
|||
<EmbeddedResource Include="Forms\frmUpdatePrompt.resx">
|
||||
<DependentUpon>frmUpdatePrompt.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Forms\HdPackEditor\frmHdPackEditor.resx">
|
||||
<DependentUpon>frmHdPackEditor.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Forms\NetPlay\frmClientConfig.resx">
|
||||
<DependentUpon>frmClientConfig.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
|
|
|
@ -502,6 +502,50 @@ namespace Mesen.GUI
|
|||
yScroll = (int)(ppuScroll >> 16) & 0xFFFF;
|
||||
}
|
||||
|
||||
[DllImport(DLLPath)] public static extern void HdBuilderStartRecording(
|
||||
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]string saveFolder,
|
||||
ScaleFilterType filterType,
|
||||
UInt32 scale,
|
||||
HdPackRecordFlags flags,
|
||||
UInt32 chrRamBankSize);
|
||||
|
||||
[DllImport(DLLPath)] public static extern void HdBuilderStopRecording();
|
||||
|
||||
[DllImport(DLLPath, EntryPoint = "HdBuilderGetBankPreview")] private static extern void HdBuilderGetBankPreviewWrapper(UInt32 bankNumber, UInt32 pageNumber, IntPtr rgbBuffer);
|
||||
public static byte[] HdBuilderGetBankPreview(UInt32 bankNumber, int scale, UInt32 pageNumber)
|
||||
{
|
||||
byte[] frameData = new byte[128*128*4*scale*scale];
|
||||
|
||||
GCHandle hFrameData = GCHandle.Alloc(frameData, GCHandleType.Pinned);
|
||||
try {
|
||||
InteropEmu.HdBuilderGetBankPreviewWrapper(bankNumber, pageNumber, hFrameData.AddrOfPinnedObject());
|
||||
} finally {
|
||||
hFrameData.Free();
|
||||
}
|
||||
|
||||
return frameData;
|
||||
}
|
||||
|
||||
[DllImport(DLLPath, EntryPoint = "HdBuilderGetChrBankList")] private static extern void HdBuilderGetChrBankListWrapper(IntPtr bankList);
|
||||
public static UInt32[] HdBuilderGetChrBankList()
|
||||
{
|
||||
UInt32[] bankList = new UInt32[1024];
|
||||
GCHandle hBankList = GCHandle.Alloc(bankList, GCHandleType.Pinned);
|
||||
try {
|
||||
InteropEmu.HdBuilderGetChrBankListWrapper(hBankList.AddrOfPinnedObject());
|
||||
for(int i = 0; i < bankList.Length; i++) {
|
||||
if(bankList[i] == UInt32.MaxValue) {
|
||||
Array.Resize(ref bankList, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
hBankList.Free();
|
||||
}
|
||||
|
||||
return bankList;
|
||||
}
|
||||
|
||||
public static NsfHeader NsfGetHeader()
|
||||
{
|
||||
NsfHeader header = new NsfHeader();
|
||||
|
@ -1027,6 +1071,9 @@ namespace Mesen.GUI
|
|||
public UInt32 Crc32;
|
||||
public UInt32 PrgCrc32;
|
||||
public RomFormat Format;
|
||||
|
||||
[MarshalAs(UnmanagedType.I1)]
|
||||
public bool IsChrRam;
|
||||
}
|
||||
|
||||
public enum RomFormat
|
||||
|
@ -1043,6 +1090,7 @@ namespace Mesen.GUI
|
|||
public UInt32 Crc32;
|
||||
public UInt32 PrgCrc32;
|
||||
public RomFormat Format;
|
||||
public bool IsChrRam;
|
||||
|
||||
public RomInfo(InteropRomInfo romInfo)
|
||||
{
|
||||
|
@ -1050,6 +1098,7 @@ namespace Mesen.GUI
|
|||
this.Crc32 = romInfo.Crc32;
|
||||
this.PrgCrc32 = romInfo.PrgCrc32;
|
||||
this.Format = romInfo.Format;
|
||||
this.IsChrRam = romInfo.IsChrRam;
|
||||
}
|
||||
|
||||
public string GetRomName()
|
||||
|
@ -1292,6 +1341,17 @@ namespace Mesen.GUI
|
|||
CSCD = 2,
|
||||
}
|
||||
|
||||
public enum ScaleFilterType
|
||||
{
|
||||
xBRZ = 0,
|
||||
HQX = 1,
|
||||
Scale2x = 2,
|
||||
_2xSai = 3,
|
||||
Super2xSai = 4,
|
||||
SuperEagle = 5,
|
||||
Prescale = 6,
|
||||
}
|
||||
|
||||
public enum VideoFilterType
|
||||
{
|
||||
None = 0,
|
||||
|
@ -1370,6 +1430,15 @@ namespace Mesen.GUI
|
|||
Exec = 2,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum HdPackRecordFlags
|
||||
{
|
||||
None = 0,
|
||||
UseLargeSprites = 1,
|
||||
SortByUsageFrequency = 2,
|
||||
GroupBlankTiles = 4,
|
||||
}
|
||||
|
||||
public struct AddressTypeInfo
|
||||
{
|
||||
public Int32 Address;
|
||||
|
|
10
GUI.NET/Properties/Resources.Designer.cs
generated
10
GUI.NET/Properties/Resources.Designer.cs
generated
|
@ -360,6 +360,16 @@ namespace Mesen.GUI.Properties {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap HdPack {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("HdPack", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
|
|
|
@ -304,4 +304,7 @@
|
|||
<data name="VideoFilter" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\VideoFilter.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="HdPack" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\HdPack.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
</root>
|
BIN
GUI.NET/Resources/HdPack.png
Normal file
BIN
GUI.NET/Resources/HdPack.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 654 B |
|
@ -15,11 +15,13 @@
|
|||
#include "../Core/FDS.h"
|
||||
#include "../Core/VsControlManager.h"
|
||||
#include "../Core/SoundMixer.h"
|
||||
#include "../Core/FileLoader.h"
|
||||
#include "../Core/RomLoader.h"
|
||||
#include "../Core/NsfMapper.h"
|
||||
#include "../Core/IRenderingDevice.h"
|
||||
#include "../Core/IAudioDevice.h"
|
||||
#include "../Core/MovieManager.h"
|
||||
#include "../Core/HdPackBuilder.h"
|
||||
#include "../Utilities/AviWriter.h"
|
||||
|
||||
#ifdef WIN32
|
||||
|
@ -65,6 +67,7 @@ namespace InteropEmu {
|
|||
uint32_t Crc32;
|
||||
uint32_t PrgCrc32;
|
||||
RomFormat Format;
|
||||
bool IsChrRam;
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
|
@ -119,7 +122,7 @@ namespace InteropEmu {
|
|||
|
||||
DllExport const char* __stdcall GetArchiveRomList(char* filename) {
|
||||
std::ostringstream out;
|
||||
for(string romName : RomLoader::GetArchiveRomList(filename)) {
|
||||
for(string romName : FileLoader::GetArchiveRomList(filename)) {
|
||||
out << romName << "[!|!]";
|
||||
}
|
||||
_returnString = out.str();
|
||||
|
@ -184,9 +187,10 @@ namespace InteropEmu {
|
|||
romInfo.Crc32 = Console::GetCrc32();
|
||||
romInfo.PrgCrc32 = Console::GetPrgCrc32();
|
||||
romInfo.Format = Console::GetRomFormat();
|
||||
romInfo.IsChrRam = Console::IsChrRam();
|
||||
} else {
|
||||
RomLoader romLoader;
|
||||
if(romLoader.LoadFile(filename, nullptr, "", archiveFileIndex)) {
|
||||
if(romLoader.LoadFile(filename, archiveFileIndex)) {
|
||||
RomData romData = romLoader.GetRomData();
|
||||
|
||||
_returnString = romData.RomName;
|
||||
|
@ -194,12 +198,14 @@ namespace InteropEmu {
|
|||
romInfo.Crc32 = romData.Crc32;
|
||||
romInfo.PrgCrc32 = romData.PrgCrc32;
|
||||
romInfo.Format = RomFormat::Unknown;
|
||||
romInfo.IsChrRam = romData.ChrRom.size() == 0;
|
||||
} else {
|
||||
_returnString = "";
|
||||
romInfo.RomName = _returnString.c_str();
|
||||
romInfo.Crc32 = 0;
|
||||
romInfo.PrgCrc32 = 0;
|
||||
romInfo.Format = RomFormat::Unknown;
|
||||
romInfo.IsChrRam = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -462,5 +468,11 @@ namespace InteropEmu {
|
|||
vs->SetInputType(inputType);
|
||||
}
|
||||
}
|
||||
|
||||
DllExport void __stdcall HdBuilderStartRecording(char* saveFolder, ScaleFilterType filterType, uint32_t scale, uint32_t flags, uint32_t chrRamBankSize) { Console::StartRecordingHdPack(saveFolder, filterType, scale, flags, chrRamBankSize); }
|
||||
DllExport void __stdcall HdBuilderStopRecording() { Console::StopRecordingHdPack(); }
|
||||
|
||||
DllExport void __stdcall HdBuilderGetChrBankList(uint32_t* bankBuffer) { HdPackBuilder::GetChrBankList(bankBuffer); }
|
||||
DllExport void __stdcall HdBuilderGetBankPreview(uint32_t bankNumber, uint32_t pageNumber, uint8_t *rgbBuffer) { HdPackBuilder::GetBankPreview(bankNumber, pageNumber, rgbBuffer); }
|
||||
}
|
||||
}
|
|
@ -17,15 +17,10 @@ std::stringstream ArchiveReader::GetStream(string filename)
|
|||
{
|
||||
std::stringstream ss;
|
||||
if(_initialized) {
|
||||
uint8_t* buffer = nullptr;
|
||||
size_t size = 0;
|
||||
|
||||
ExtractFile(filename, &buffer, size);
|
||||
ss.write((char*)buffer, size);
|
||||
|
||||
delete[] buffer;
|
||||
vector<uint8_t> fileData;
|
||||
ExtractFile(filename, fileData);
|
||||
ss.write((char*)fileData.data(), fileData.size());
|
||||
}
|
||||
|
||||
return ss;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,5 +19,5 @@ public:
|
|||
|
||||
vector<string> GetFileList(std::initializer_list<string> extensions);
|
||||
|
||||
virtual void ExtractFile(string filename, uint8_t **fileBuffer, size_t &fileSize) = 0;
|
||||
virtual void ExtractFile(string filename, vector<uint8_t> &output) = 0;
|
||||
};
|
|
@ -44,6 +44,8 @@
|
|||
#endif
|
||||
|
||||
void HQX_CALLCONV hqxInit(void);
|
||||
void HQX_CALLCONV hqx(uint32_t scale, uint32_t * src, uint32_t * dest, int width, int height);
|
||||
|
||||
void HQX_CALLCONV hq2x_32( uint32_t * src, uint32_t * dest, int width, int height );
|
||||
void HQX_CALLCONV hq3x_32( uint32_t * src, uint32_t * dest, int width, int height );
|
||||
void HQX_CALLCONV hq4x_32( uint32_t * src, uint32_t * dest, int width, int height );
|
||||
|
|
|
@ -37,3 +37,12 @@ void HQX_CALLCONV hqxInit(void)
|
|||
RGBtoYUV[c] = (y << 16) + (u << 8) + v;
|
||||
}
|
||||
}
|
||||
|
||||
void HQX_CALLCONV hqx(uint32_t scale, uint32_t * src, uint32_t * dest, int width, int height)
|
||||
{
|
||||
switch(scale) {
|
||||
case 2: hq2x_32(src, dest, width, height); break;
|
||||
case 3: hq3x_32(src, dest, width, height); break;
|
||||
case 4: hq4x_32(src, dest, width, height); break;
|
||||
}
|
||||
}
|
|
@ -46,16 +46,16 @@ string HexUtilities::ToHex(uint16_t value)
|
|||
return _hexCache[value >> 8] + _hexCache[value & 0xFF];
|
||||
}
|
||||
|
||||
string HexUtilities::ToHex(uint32_t value)
|
||||
string HexUtilities::ToHex(uint32_t value, bool fullSize)
|
||||
{
|
||||
if(value <= 0xFF) {
|
||||
if(fullSize || value > 0xFFFFFF) {
|
||||
return _hexCache[value >> 24] + _hexCache[(value >> 16) & 0xFF] + _hexCache[(value >> 8) & 0xFF] + _hexCache[value & 0xFF];
|
||||
} else if(value <= 0xFF) {
|
||||
return ToHex((uint8_t)value);
|
||||
} else if(value <= 0xFFFF) {
|
||||
return ToHex((uint16_t)value);
|
||||
} else if(value <= 0xFFFFFF) {
|
||||
return _hexCache[(value >> 16) & 0xFF] + _hexCache[(value >> 8) & 0xFF] + _hexCache[value & 0xFF];
|
||||
} else {
|
||||
return _hexCache[value >> 24] + _hexCache[(value >> 16) & 0xFF] + _hexCache[(value >> 8) & 0xFF] + _hexCache[value & 0xFF];
|
||||
return _hexCache[(value >> 16) & 0xFF] + _hexCache[(value >> 8) & 0xFF] + _hexCache[value & 0xFF];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ private:
|
|||
public:
|
||||
static string ToHex(uint8_t addr);
|
||||
static string ToHex(uint16_t addr);
|
||||
static string ToHex(uint32_t addr);
|
||||
static string ToHex(uint32_t addr, bool fullSize = false);
|
||||
static string ToHex(vector<uint8_t> &data);
|
||||
|
||||
static int FromHex(string hex);
|
||||
|
|
|
@ -3,9 +3,16 @@
|
|||
#include "PNGHelper.h"
|
||||
#include "miniz.h"
|
||||
|
||||
bool PNGHelper::WritePNG(std::stringstream &stream, uint8_t* buffer, uint32_t xSize, uint32_t ySize, uint32_t bitsPerPixel)
|
||||
bool PNGHelper::WritePNG(std::stringstream &stream, uint32_t* buffer, uint32_t xSize, uint32_t ySize, uint32_t bitsPerPixel)
|
||||
{
|
||||
size_t pngSize = 0;
|
||||
|
||||
//ARGB -> ABGR
|
||||
uint32_t size = xSize * ySize * bitsPerPixel / 8 / 4;
|
||||
for(uint32_t i = 0; i < size; i++) {
|
||||
buffer[i] = (buffer[i] & 0xFF00FF00) | ((buffer[i] & 0xFF0000) >> 16) | ((buffer[i] & 0xFF) << 16);
|
||||
}
|
||||
|
||||
void *pngData = tdefl_write_image_to_png_file_in_memory_ex(buffer, xSize, ySize, bitsPerPixel / 8, &pngSize, MZ_DEFAULT_LEVEL, MZ_FALSE);
|
||||
if(!pngData) {
|
||||
std::cout << "tdefl_write_image_to_png_file_in_memory_ex() failed!" << std::endl;
|
||||
|
@ -17,7 +24,7 @@ bool PNGHelper::WritePNG(std::stringstream &stream, uint8_t* buffer, uint32_t xS
|
|||
}
|
||||
}
|
||||
|
||||
bool PNGHelper::WritePNG(string filename, uint8_t* buffer, uint32_t xSize, uint32_t ySize, uint32_t bitsPerPixel)
|
||||
bool PNGHelper::WritePNG(string filename, uint32_t* buffer, uint32_t xSize, uint32_t ySize, uint32_t bitsPerPixel)
|
||||
{
|
||||
std::stringstream stream;
|
||||
if(WritePNG(stream, buffer, xSize, ySize, bitsPerPixel)) {
|
||||
|
@ -31,7 +38,7 @@ bool PNGHelper::WritePNG(string filename, uint8_t* buffer, uint32_t xSize, uint3
|
|||
return false;
|
||||
}
|
||||
|
||||
void PNGHelper::ReadPNG(string filename, vector<uint8_t> &pngData, uint32_t &pngWidth, uint32_t &pngHeight)
|
||||
bool PNGHelper::ReadPNG(string filename, vector<uint8_t> &pngData, uint32_t &pngWidth, uint32_t &pngHeight)
|
||||
{
|
||||
unsigned long width;
|
||||
unsigned long height;
|
||||
|
@ -56,7 +63,11 @@ void PNGHelper::ReadPNG(string filename, vector<uint8_t> &pngData, uint32_t &png
|
|||
pngWidth = width;
|
||||
pngHeight = height;
|
||||
delete[] buffer;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -7,7 +7,7 @@ private:
|
|||
static int DecodePNG(vector<unsigned char>& out_image, unsigned long& image_width, unsigned long& image_height, const unsigned char* in_png, size_t in_size, bool convert_to_rgba32 = true);
|
||||
|
||||
public:
|
||||
static bool WritePNG(std::stringstream &stream, uint8_t* buffer, uint32_t xSize, uint32_t ySize, uint32_t bitsPerPixel = 32);
|
||||
static bool WritePNG(string filename, uint8_t* buffer, uint32_t xSize, uint32_t ySize, uint32_t bitsPerPixel = 32);
|
||||
static void ReadPNG(string filename, vector<uint8_t> &pngData, uint32_t &pngWidth, uint32_t &pngHeight);
|
||||
static bool WritePNG(std::stringstream &stream, uint32_t* buffer, uint32_t xSize, uint32_t ySize, uint32_t bitsPerPixel = 32);
|
||||
static bool WritePNG(string filename, uint32_t* buffer, uint32_t xSize, uint32_t ySize, uint32_t bitsPerPixel = 32);
|
||||
static bool ReadPNG(string filename, vector<uint8_t> &pngData, uint32_t &pngWidth, uint32_t &pngHeight);
|
||||
};
|
|
@ -26,7 +26,7 @@ bool SZReader::InternalLoadArchive(void* buffer, size_t size)
|
|||
return !SzArEx_Open(&_archive, &_lookStream.s, &allocImp, &allocTempImp);
|
||||
}
|
||||
|
||||
void SZReader::ExtractFile(string filename, uint8_t **fileBuffer, size_t &fileSize)
|
||||
void SZReader::ExtractFile(string filename, vector<uint8_t> &output)
|
||||
{
|
||||
if(_initialized) {
|
||||
char16_t *utf16Filename = (char16_t*)SzAlloc(nullptr, 2000);
|
||||
|
@ -49,9 +49,7 @@ void SZReader::ExtractFile(string filename, uint8_t **fileBuffer, size_t &fileSi
|
|||
WRes res = SzArEx_Extract(&_archive, &_lookStream.s, i, &blockIndex, &outBuffer, &outBufferSize, &offset, &outSizeProcessed, &_allocImp, &_allocTempImp);
|
||||
if(res == SZ_OK) {
|
||||
uint8_t* buf = new uint8_t[outSizeProcessed];
|
||||
memcpy(buf, outBuffer+offset, outSizeProcessed);
|
||||
*fileBuffer = buf;
|
||||
fileSize = outSizeProcessed;
|
||||
output = vector<uint8_t>(outBuffer+offset, outBuffer+offset+outSizeProcessed);
|
||||
}
|
||||
IAlloc_Free(&_allocImp, outBuffer);
|
||||
break;
|
||||
|
|
|
@ -24,5 +24,5 @@ public:
|
|||
SZReader();
|
||||
virtual ~SZReader();
|
||||
|
||||
void ExtractFile(string filename, uint8_t **fileBuffer, size_t &fileSize);
|
||||
void ExtractFile(string filename, vector<uint8_t> &output);
|
||||
};
|
|
@ -36,7 +36,7 @@ vector<string> ZipReader::InternalGetFileList()
|
|||
return fileList;
|
||||
}
|
||||
|
||||
void ZipReader::ExtractFile(string filename, uint8_t **fileBuffer, size_t &fileSize)
|
||||
void ZipReader::ExtractFile(string filename, vector<uint8_t> &output)
|
||||
{
|
||||
if(_initialized) {
|
||||
size_t uncompSize;
|
||||
|
@ -45,12 +45,9 @@ void ZipReader::ExtractFile(string filename, uint8_t **fileBuffer, size_t &fileS
|
|||
std::cout << "mz_zip_reader_extract_file_to_heap() failed!" << std::endl;
|
||||
}
|
||||
|
||||
*fileBuffer = new uint8_t[uncompSize];
|
||||
memcpy(*fileBuffer, p, uncompSize);
|
||||
output = vector<uint8_t>((uint8_t*)p, (uint8_t*)p + uncompSize);
|
||||
|
||||
// We're done.
|
||||
mz_free(p);
|
||||
|
||||
fileSize = uncompSize;
|
||||
}
|
||||
}
|
|
@ -16,5 +16,5 @@ public:
|
|||
ZipReader();
|
||||
virtual ~ZipReader();
|
||||
|
||||
void ExtractFile(string filename, uint8_t **fileBuffer, size_t &fileSize);
|
||||
void ExtractFile(string filename, vector<uint8_t> &output);
|
||||
};
|
Loading…
Add table
Reference in a new issue