diff --git a/Core/BaseCartridge.cpp b/Core/BaseCartridge.cpp new file mode 100644 index 0000000..367db65 --- /dev/null +++ b/Core/BaseCartridge.cpp @@ -0,0 +1,128 @@ +#include "stdafx.h" +#include "BaseCartridge.h" +#include "RamHandler.h" +#include "RomHandler.h" +#include "MemoryManager.h" +#include "IMemoryHandler.h" +#include "../Utilities/VirtualFile.h" + +BaseCartridge::~BaseCartridge() +{ + delete[] _prgRom; + delete[] _saveRam; +} + +shared_ptr BaseCartridge::CreateCartridge(VirtualFile &romFile, VirtualFile &patchFile) +{ + if(romFile.IsValid()) { + vector romData; + romFile.ReadFile(romData); + + shared_ptr cart(new BaseCartridge()); + cart->_prgRomSize = (uint32_t)romData.size(); + cart->_prgRom = new uint8_t[cart->_prgRomSize]; + memcpy(cart->_prgRom, romData.data(), cart->_prgRomSize); + cart->Init(); + + return cart; + } else { + return nullptr; + } +} + +void BaseCartridge::Init() +{ + uint32_t headerOffset = 0; + if(((0x400 << _prgRom[0x7FD7]) == _prgRomSize && (_prgRom[0x7FD5] & 0x20)) || _prgRomSize < 0xFFFF) { + //LoROM + headerOffset = 0x7FB0; + } else if((0x400 << _prgRom[0xFFD7]) == _prgRomSize && (_prgRom[0xFFD5] & 0x20)) { + //HiROM + headerOffset = 0xFFB0; + } else if(_prgRom[0x7FD5] & 0x20) { + //LoROM + headerOffset = 0x7FB0; + } else if(_prgRom[0xFFD5] & 0x20) { + //HiROM + headerOffset = 0xFFB0; + } else { + throw new std::runtime_error("invalid rom (?)"); + } + + _cartInfo = *(SnesCartInformation*)(&_prgRom[headerOffset]); + + _saveRamSize = _cartInfo.SramSize > 0 ? 1024 * (1 << _cartInfo.SramSize) : 0; + _saveRam = new uint8_t[_saveRamSize]; +} + +CartFlags::CartFlags BaseCartridge::GetCartFlags() +{ + uint32_t flags = 0; + if(_cartInfo.MapMode & 0x04) { + flags |= CartFlags::ExHiRom; + } else if(_cartInfo.MapMode & 0x02) { + flags |= CartFlags::ExLoRom; + } else if(_cartInfo.MapMode & 0x01) { + flags |= CartFlags::HiRom; + } else { + flags |= CartFlags::LoRom; + } + + if(_cartInfo.MapMode & 0x10) { + flags |= CartFlags::FastRom; + } + + return (CartFlags::CartFlags)flags; +} + +void BaseCartridge::MapBanks(MemoryManager &mm, vector> &handlers, uint8_t startBank, uint8_t endBank, uint16_t startPage, uint16_t endPage, uint16_t pageIncrement, bool mirror) +{ + if(handlers.empty()) { + return; + } + + uint32_t pageNumber = 0; + for(uint32_t i = startBank; i <= endBank; i++) { + uint32_t baseAddress = i << 16; + pageNumber += pageIncrement; + for(uint32_t j = startPage; j <= endPage; j++) { + mm.RegisterHandler(baseAddress + (j * 0x1000), baseAddress + (j * 0x1000) | 0xFFF, handlers[pageNumber].get()); + //MessageManager::Log("Map [$" + HexUtilities::ToHex(i) + ":" + HexUtilities::ToHex(j)[1] + "xxx] to page number " + HexUtilities::ToHex(pageNumber)); + pageNumber++; + if(pageNumber >= handlers.size()) { + if(mirror) { + pageNumber = 0; + } else { + return; + } + } + } + } +} + +void BaseCartridge::RegisterHandlers(MemoryManager &mm) +{ + for(uint32_t i = 0; i < _prgRomSize; i += 0x1000) { + _prgRomHandlers.push_back(unique_ptr(new RomHandler(_prgRom + i))); + } + + for(uint32_t i = 0; i < _saveRamSize; i += 0x1000) { + _saveRamHandlers.push_back(unique_ptr(new RamHandler(_saveRam + i))); + } + + if(GetCartFlags() & CartFlags::LoRom) { + MapBanks(mm, _prgRomHandlers, 0x00, 0x6F, 0x08, 0x0F, 0, true); + MapBanks(mm, _saveRamHandlers, 0x70, 0x7D, 0x00, 0x0F, 0, true); + + MapBanks(mm, _prgRomHandlers, 0x80, 0xEF, 0x08, 0x0F, 0, true); + MapBanks(mm, _saveRamHandlers, 0xF0, 0xFF, 0x00, 0x0F, 0, true); + } else { + MapBanks(mm, _prgRomHandlers, 0x40, 0x7D, 0x00, 0x0F, 0, true); + MapBanks(mm, _prgRomHandlers, 0xC0, 0xFF, 0x00, 0x0F, 0, true); + MapBanks(mm, _prgRomHandlers, 0x00, 0x3F, 0x08, 0x0F, 8, true); + MapBanks(mm, _prgRomHandlers, 0x80, 0xBF, 0x08, 0x0F, 8, true); + + MapBanks(mm, _saveRamHandlers, 0x20, 0x3F, 0x06, 0x07, 0, true); + } + +} \ No newline at end of file diff --git a/Core/BaseCartridge.h b/Core/BaseCartridge.h index b117196..340e442 100644 --- a/Core/BaseCartridge.h +++ b/Core/BaseCartridge.h @@ -1,50 +1,72 @@ #pragma once #include "stdafx.h" #include "IMemoryHandler.h" -#include "../Utilities/VirtualFile.h" -class BaseCartridge : public IMemoryHandler +class MemoryManager; +class VirtualFile; + +struct SnesCartInformation +{ + uint8_t MakerCode[2]; + uint8_t GameCode[4]; + uint8_t Reserved[7]; + uint8_t ExpansionRamSize; + uint8_t SpecialVersion; + uint8_t CartridgeType; + + char CartName[21]; + uint8_t MapMode; + uint8_t RomType; + uint8_t RomSize; + uint8_t SramSize; + + uint8_t DestinationCode; + uint8_t Reserved2; + uint8_t Version; + + uint8_t ChecksumComplement[2]; + uint8_t Checksum[2]; +}; + +namespace CartFlags +{ + enum CartFlags + { + LoRom = 1, + HiRom = 2, + FastRom = 4, + ExLoRom = 8, + ExHiRom = 16 + }; +} + +class BaseCartridge { private: + vector> _prgRomHandlers; + vector> _saveRamHandlers; + SnesCartInformation _cartInfo; + uint8_t* _prgRom = nullptr; uint8_t* _saveRam = nullptr; uint32_t _prgRomSize = 0; uint32_t _saveRamSize = 0; + bool _isHiRom = false; + + void MapBanks(MemoryManager &mm, vector> &handlers, uint8_t startBank, uint8_t endBank, uint16_t startPage = 0, uint16_t endPage = 0x0F, uint16_t pageIncrement = 0, bool mirror = false); + public: - ~BaseCartridge() - { - delete[] _prgRom; - delete[] _saveRam; - } + ~BaseCartridge(); - static shared_ptr CreateCartridge(VirtualFile romFile, VirtualFile patchFile) - { - if(romFile.IsValid()) { - vector romData; - romFile.ReadFile(romData); + static shared_ptr CreateCartridge(VirtualFile &romFile, VirtualFile &patchFile); - shared_ptr cart(new BaseCartridge()); - cart->_prgRomSize = (uint32_t)romData.size(); - cart->_prgRom = new uint8_t[cart->_prgRomSize]; - memcpy(cart->_prgRom, romData.data(), cart->_prgRomSize); + void Init(); - return cart; - } else { - return nullptr; - } - } + CartFlags::CartFlags GetCartFlags(); - uint8_t Read(uint32_t addr) override - { - uint8_t bank = (addr >> 16) & 0x7F; - return _prgRom[((bank * 0x8000) | (addr & 0x7FFF)) & (_prgRomSize - 1)]; - } - - void Write(uint32_t addr, uint8_t value) override - { - } + void RegisterHandlers(MemoryManager &mm); uint8_t* DebugGetPrgRom() { return _prgRom; } uint8_t* DebugGetSaveRam() { return _saveRam; } diff --git a/Core/Console.cpp b/Core/Console.cpp index 580e208..b27034e 100644 --- a/Core/Console.cpp +++ b/Core/Console.cpp @@ -10,6 +10,7 @@ #include "VideoDecoder.h" #include "VideoRenderer.h" #include "DebugHud.h" +#include "MessageManager.h" #include "../Utilities/Timer.h" #include "../Utilities/VirtualFile.h" @@ -82,6 +83,8 @@ void Console::LoadRom(VirtualFile romFile, VirtualFile patchFile) shared_ptr cart = BaseCartridge::CreateCartridge(romFile, patchFile); if(cart) { + MessageManager::ClearLog(); + _ppu.reset(new Ppu(shared_from_this())); _spc.reset(new Spc(shared_from_this())); _cart = cart; diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj index ea3d949..222017c 100644 --- a/Core/Core.vcxproj +++ b/Core/Core.vcxproj @@ -82,6 +82,8 @@ + + @@ -95,6 +97,7 @@ + diff --git a/Core/Core.vcxproj.filters b/Core/Core.vcxproj.filters index bc9887a..9bdac9d 100644 --- a/Core/Core.vcxproj.filters +++ b/Core/Core.vcxproj.filters @@ -149,6 +149,12 @@ Misc + + SNES + + + SNES + @@ -230,6 +236,9 @@ Misc + + SNES + diff --git a/Core/DisassemblyInfo.cpp b/Core/DisassemblyInfo.cpp index 05814ec..42bf0b0 100644 --- a/Core/DisassemblyInfo.cpp +++ b/Core/DisassemblyInfo.cpp @@ -21,7 +21,7 @@ DisassemblyInfo::DisassemblyInfo(CpuState &state, MemoryManager *memoryManager) _opSize = GetOperandSize() + 1; for(int i = 1; i < _opSize; i++) { - _byteCode[i] = memoryManager->Peek(addr+i); + _byteCode[i] = memoryManager->Peek((addr+i) & 0xFFFFFF); } _emulationMode = state.EmulationMode; diff --git a/Core/DmaController.cpp b/Core/DmaController.cpp index d08a293..491c16b 100644 --- a/Core/DmaController.cpp +++ b/Core/DmaController.cpp @@ -1,6 +1,7 @@ #include "stdafx.h" #include "DmaController.h" #include "MemoryManager.h" +#include "MessageManager.h" DmaController::DmaController(MemoryManager *memoryManager) { @@ -37,6 +38,8 @@ void DmaController::RunDma(DmaChannelConfig &channel) //"Note, however, that writing $0000 to this register actually results in a transfer of $10000 bytes, not 0." uint32_t bytesLeft = channel.TransferSize ? channel.TransferSize : 0x10000; + MessageManager::Log("Run DMA: " + HexUtilities::ToHex(channel.DestAddress) + " -> " + HexUtilities::ToHex(channel.SrcAddress) + " Bytes: " + std::to_string(bytesLeft)); + while(bytesLeft > 0) { //Manual DMA transfers run to the end of the transfer when started RunSingleTransfer(channel, bytesLeft); @@ -55,6 +58,13 @@ void DmaController::Write(uint16_t addr, uint8_t value) } break; + case 0x420C: + //HDMAEN - HDMA Enable + if(value > 0) { + MessageManager::DisplayMessage("Debug", "Unsupported HDMA operation"); + } + break; + case 0x4300: case 0x4310: case 0x4320: case 0x4330: case 0x4340: case 0x4350: case 0x4360: case 0x4370: { //DMAPx - DMA Control for Channel x diff --git a/Core/MemoryManager.h b/Core/MemoryManager.h index caedeb4..ada3d97 100644 --- a/Core/MemoryManager.h +++ b/Core/MemoryManager.h @@ -3,9 +3,11 @@ #include "Console.h" #include "Ppu.h" #include "Spc.h" +#include "RamHandler.h" #include "DmaController.h" #include "BaseCartridge.h" #include "IMemoryHandler.h" +#include "MessageManager.h" #include "../Utilities/HexUtilities.h" class CpuRegisterHandler : public IMemoryHandler @@ -14,13 +16,18 @@ private: Ppu *_ppu; Spc *_spc; DmaController *_dmaController; + uint8_t *_workRam; + uint32_t _wramPosition; public: - CpuRegisterHandler(Ppu *ppu, Spc *spc, DmaController *dmaController) + CpuRegisterHandler(Ppu *ppu, Spc *spc, DmaController *dmaController, uint8_t *workRam) { _ppu = ppu; _spc = spc; _dmaController = dmaController; + + _workRam = workRam; + _wramPosition = 0; } uint8_t Read(uint32_t addr) override @@ -38,35 +45,25 @@ public: addr &= 0xFFFF; if(addr >= 0x2140 && addr <= 0x217F) { return _spc->Write(addr & 0x03, value); + } if(addr >= 0x2180 && addr <= 0x2183) { + switch(addr & 0xFFFF) { + case 0x2180: + _workRam[_wramPosition] = value; + _wramPosition = (_wramPosition + 1) & (0x1FFFF); + break; + + case 0x2181: _wramPosition = (_wramPosition & 0x1FF00) | value; break; + case 0x2182: _wramPosition = (_wramPosition & 0x100FF) | (value << 8); break; + case 0x2183: _wramPosition = (_wramPosition & 0xFFFF) | ((value & 0x01) << 16); break; + } + } else if(addr == 0x420B || addr == 0x420C || addr >= 0x4300) { + _dmaController->Write(addr, value); } else { _ppu->Write(addr, value); - _dmaController->Write(addr, value); } } }; -class WorkRamHandler : public IMemoryHandler -{ -private: - uint8_t *_workRam; - -public: - WorkRamHandler(uint8_t *workRam) - { - _workRam = workRam; - } - - uint8_t Read(uint32_t addr) override - { - return _workRam[addr & 0xFFF]; - } - - void Write(uint32_t addr, uint8_t value) override - { - _workRam[addr & 0xFFF] = value; - } -}; - class MemoryManager { public: @@ -75,15 +72,15 @@ public: private: shared_ptr _console; - uint8_t * _workRam; - IMemoryHandler* _handlers[0x100 * 0x10]; - vector> _workRamHandlers; shared_ptr _cart; shared_ptr _cpuRegisterHandler; shared_ptr _ppu; shared_ptr _dmaController; - uint32_t _wramPosition; + IMemoryHandler* _handlers[0x100 * 0x10]; + vector> _workRamHandlers; + + uint8_t * _workRam; uint64_t _masterClock; uint64_t _lastMasterClock; @@ -97,15 +94,16 @@ public: _cart = console->GetCartridge(); _ppu = console->GetPpu(); + _workRam = new uint8_t[MemoryManager::WorkRamSize]; + _dmaController.reset(new DmaController(console->GetMemoryManager().get())); - _cpuRegisterHandler.reset(new CpuRegisterHandler(_ppu.get(), console->GetSpc().get(), _dmaController.get())); + _cpuRegisterHandler.reset(new CpuRegisterHandler(_ppu.get(), console->GetSpc().get(), _dmaController.get(), _workRam)); memset(_handlers, 0, sizeof(_handlers)); - _workRam = new uint8_t[MemoryManager::WorkRamSize]; //memset(_workRam, 0, 128 * 1024); for(uint32_t i = 0; i < 128 * 1024; i += 0x1000) { - _workRamHandlers.push_back(unique_ptr(new WorkRamHandler(_workRam + i))); + _workRamHandlers.push_back(unique_ptr(new RamHandler(_workRam + i))); RegisterHandler(0x7E0000 | i, 0x7E0000 | (i + 0xFFF), _workRamHandlers[_workRamHandlers.size() - 1].get()); } @@ -117,13 +115,17 @@ public: RegisterHandler(((i | 0x80) << 16) | 0x4000, ((i | 0x80) << 16) | 0x4FFF, _cpuRegisterHandler.get()); } - RegisterHandler(0x0000, 0x0FFF, _workRamHandlers[0].get()); - RegisterHandler(0x1000, 0x1FFF, _workRamHandlers[1].get()); - - for(int bank = 0; bank < 0x20; bank++) { - RegisterHandler((bank << 16) | 0x8000, (bank << 16) | 0xFFFF, _cart.get()); - RegisterHandler(((0x80 | bank) << 16) | 0x8000, ((0x80 | bank) << 16) | 0xFFFF, _cart.get()); + for(int i = 0; i < 0x3F; i++) { + RegisterHandler((i << 16) | 0x0000, (i << 16) | 0x0FFF, _workRamHandlers[0].get()); + RegisterHandler((i << 16) | 0x1000, (i << 16) | 0x1FFF, _workRamHandlers[1].get()); } + + for(int i = 0x80; i < 0xBF; i++) { + RegisterHandler((i << 16) | 0x0000, (i << 16) | 0x0FFF, _workRamHandlers[0].get()); + RegisterHandler((i << 16) | 0x1000, (i << 16) | 0x1FFF, _workRamHandlers[1].get()); + } + + _cart->RegisterHandlers(*this); } ~MemoryManager() @@ -138,6 +140,10 @@ public: } for(uint32_t addr = startAddr; addr < endAddr; addr += 0x1000) { + if(_handlers[addr >> 12]) { + throw new std::runtime_error("handler already set"); + } + _handlers[addr >> 12] = handler; } } @@ -191,7 +197,10 @@ public: if(_handlers[addr >> 12]) { value = _handlers[addr >> 12]->Read(addr); } else { - //std::cout << "Read - missing handler: $" << HexUtilities::ToHex(addr) << std::endl; + //open bus + value = (addr>> 12); + + MessageManager::DisplayMessage("Debug", "Read - missing handler: $" + HexUtilities::ToHex(addr)); } _console->ProcessCpuRead(addr, value, type); return value; @@ -203,8 +212,6 @@ public: uint8_t value = 0; if(_handlers[addr >> 12]) { value = _handlers[addr >> 12]->Read(addr); - } else { - //std::cout << "Read - missing handler: $" << HexUtilities::ToHex(addr) << std::endl; } return value; } @@ -213,30 +220,11 @@ public: { IncrementMasterClock(addr); - switch(addr & 0xFFFF) { - case 0x2180: - _workRam[_wramPosition] = value; - _wramPosition++; - break; - - case 0x2181: - _wramPosition = (_wramPosition & 0x1FF00) | value; - break; - - case 0x2182: - _wramPosition = (_wramPosition & 0x100FF) | (value << 8); - break; - - case 0x2183: - _wramPosition = (_wramPosition & 0xFFFF) | ((value & 0x01) << 16); - break; - } - _console->ProcessCpuWrite(addr, value, type); if(_handlers[addr >> 12]) { return _handlers[addr >> 12]->Write(addr, value); } else { - //std::cout << "Write - missing handler: $" << HexUtilities::ToHex(addr) << " = " << HexUtilities::ToHex(value) << std::endl; + MessageManager::DisplayMessage("Debug", "Write - missing handler: $" + HexUtilities::ToHex(addr) + " = " + HexUtilities::ToHex(value)); } } diff --git a/Core/MessageManager.cpp b/Core/MessageManager.cpp index 616a076..9355ddc 100644 --- a/Core/MessageManager.cpp +++ b/Core/MessageManager.cpp @@ -172,6 +172,12 @@ void MessageManager::Log(string message) #endif } +void MessageManager::ClearLog() +{ + auto lock = _logLock.AcquireSafe(); + _log.clear(); +} + string MessageManager::GetLog() { auto lock = _logLock.AcquireSafe(); diff --git a/Core/MessageManager.h b/Core/MessageManager.h index af2d11b..577d897 100644 --- a/Core/MessageManager.h +++ b/Core/MessageManager.h @@ -27,5 +27,6 @@ public: static void DisplayMessage(string title, string message, string param1 = "", string param2 = ""); static void Log(string message = ""); + static void ClearLog(); static string GetLog(); }; diff --git a/Core/Ppu.cpp b/Core/Ppu.cpp index 7a39e73..16a5c70 100644 --- a/Core/Ppu.cpp +++ b/Core/Ppu.cpp @@ -192,6 +192,13 @@ uint8_t Ppu::Read(uint16_t addr) (_scanline >= 225 ? 0x80 : 0) | ((_cycle >= 0x121 || _cycle <= 0x15) ? 0x40 : 0) ); + + case 0x4216: return (uint8_t)_multResult; + case 0x4217: return (uint8_t)(_multResult >> 8); + + default: + MessageManager::DisplayMessage("Debug", "Unimplemented register read: " + HexUtilities::ToHex(addr)); + break; } return 0; @@ -284,10 +291,20 @@ void Ppu::Write(uint32_t addr, uint8_t value) //_autoJoypadRead = (value & 0x01) != 0; break; + case 0x4202: _multOperand1 = value; break; + case 0x4203: + _multOperand2 = value; + _multResult = _multOperand1 * _multOperand2; + break; + case 0x4207: _horizontalTimer = (_horizontalTimer & 0x100) | value; break; case 0x4208: _horizontalTimer = (_horizontalTimer & 0xFF) | ((value & 0x01) << 8); break; case 0x4209: _verticalTimer = (_verticalTimer & 0x100) | value; break; case 0x420A: _verticalTimer = (_verticalTimer & 0xFF) | ((value & 0x01) << 8); break; + + default: + MessageManager::DisplayMessage("Debug", "Unimplemented register write: " + HexUtilities::ToHex(addr)); + break; } } diff --git a/Core/Ppu.h b/Core/Ppu.h index f387d7d..f0572e8 100644 --- a/Core/Ppu.h +++ b/Core/Ppu.h @@ -35,6 +35,10 @@ private: uint8_t _vramIncrementValue; uint8_t _vramAddressRemapping; bool _vramAddrIncrementOnSecondReg; + + uint8_t _multOperand1 = 0; + uint8_t _multOperand2 = 0; + uint16_t _multResult = 0; uint16_t _cgramAddress; uint8_t _cgram[Ppu::CgRamSize]; diff --git a/Core/RamHandler.h b/Core/RamHandler.h new file mode 100644 index 0000000..6770d8a --- /dev/null +++ b/Core/RamHandler.h @@ -0,0 +1,25 @@ +#pragma once +#include "stdafx.h" +#include "IMemoryHandler.h" + +class RamHandler : public IMemoryHandler +{ +private: + uint8_t * _ram; + +public: + RamHandler(uint8_t *ram) + { + _ram = ram; + } + + uint8_t Read(uint32_t addr) override + { + return _ram[addr & 0xFFF]; + } + + void Write(uint32_t addr, uint8_t value) override + { + _ram[addr & 0xFFF] = value; + } +}; \ No newline at end of file diff --git a/Core/RomHandler.h b/Core/RomHandler.h new file mode 100644 index 0000000..58a7e3f --- /dev/null +++ b/Core/RomHandler.h @@ -0,0 +1,24 @@ +#pragma once +#include "stdafx.h" +#include "IMemoryHandler.h" + +class RomHandler : public IMemoryHandler +{ +private: + uint8_t * _rom; + +public: + RomHandler(uint8_t *rom) + { + _rom = rom; + } + + uint8_t Read(uint32_t addr) override + { + return _rom[addr & 0xFFF]; + } + + void Write(uint32_t addr, uint8_t value) override + { + } +}; \ No newline at end of file diff --git a/Core/TraceLogger.cpp b/Core/TraceLogger.cpp index 2ed1b1c..201758e 100644 --- a/Core/TraceLogger.cpp +++ b/Core/TraceLogger.cpp @@ -284,14 +284,6 @@ void TraceLogger::AddRow(DisassemblyInfo &disassemblyInfo, DebugState &state) _logCount++; } - if(_logToFile) { - GetTraceRow(_outputBuffer, state.Cpu, state.Ppu, disassemblyInfo); - if(_outputBuffer.size() > 32768) { - _outputFile << _outputBuffer; - _outputBuffer.clear(); - } - } - _currentPos = (_currentPos + 1) % ExecutionLogSize; } /* @@ -307,10 +299,20 @@ void TraceLogger::LogNonExec(OperationInfo& operationInfo) void TraceLogger::LogEffectiveAddress(uint32_t effectiveAddress) { + uint32_t pos; if(_currentPos > 0) { - _disassemblyCache[_currentPos - 1].SetEffectiveAddress(effectiveAddress); + pos = _currentPos - 1; } else { - _disassemblyCache[ExecutionLogSize - 1].SetEffectiveAddress(effectiveAddress); + pos = ExecutionLogSize - 1; + } + + _disassemblyCache[pos].SetEffectiveAddress(effectiveAddress); + if(_logToFile) { + GetTraceRow(_outputBuffer, _cpuStateCache[pos], _ppuStateCache[pos], _disassemblyCache[pos]); + if(_outputBuffer.size() > 32768) { + _outputFile << _outputBuffer; + _outputBuffer.clear(); + } } } diff --git a/Core/VideoDecoder.cpp b/Core/VideoDecoder.cpp index 86b523a..6abae4c 100644 --- a/Core/VideoDecoder.cpp +++ b/Core/VideoDecoder.cpp @@ -44,7 +44,7 @@ void VideoDecoder::GetScreenSize(ScreenSize &size, bool ignoreScale) size.Scale = scale;*/ - if(true || ignoreScale) { + if(ignoreScale) { size.Width = 256; size.Height = 224; } else { diff --git a/UI/Forms/frmLogWindow.cs b/UI/Forms/frmLogWindow.cs new file mode 100644 index 0000000..5d62992 --- /dev/null +++ b/UI/Forms/frmLogWindow.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace Mesen.GUI.Forms +{ + public partial class frmLogWindow : BaseForm + { + private string _currentLog; + public frmLogWindow() + { + InitializeComponent(); + } + + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + } + + protected override void OnShown(EventArgs e) + { + base.OnShown(e); + UpdateLog(EmuApi.GetLog()); + } + + private void UpdateLog(string log) + { + _currentLog = log; + txtLog.Text = _currentLog; + txtLog.SelectionLength = 0; + txtLog.SelectionStart = txtLog.Text.Length; + txtLog.ScrollToCaret(); + } + + private void btnClose_Click(object sender, EventArgs e) + { + this.Close(); + } + + private void tmrRefresh_Tick(object sender, EventArgs e) + { + string newLog = EmuApi.GetLog(); + if(_currentLog != newLog) { + UpdateLog(newLog); + } + } + } +} diff --git a/UI/Forms/frmLogWindow.designer.cs b/UI/Forms/frmLogWindow.designer.cs new file mode 100644 index 0000000..f54c252 --- /dev/null +++ b/UI/Forms/frmLogWindow.designer.cs @@ -0,0 +1,108 @@ +namespace Mesen.GUI.Forms +{ + partial class frmLogWindow + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if(disposing && (components != null)) { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + this.btnClose = new System.Windows.Forms.Button(); + this.txtLog = new System.Windows.Forms.TextBox(); + this.tmrRefresh = new System.Windows.Forms.Timer(this.components); + this.tableLayoutPanel1.SuspendLayout(); + this.SuspendLayout(); + // + // tableLayoutPanel1 + // + this.tableLayoutPanel1.ColumnCount = 2; + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel1.Controls.Add(this.txtLog, 0, 0); + this.tableLayoutPanel1.Controls.Add(this.btnClose, 1, 1); + this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0); + this.tableLayoutPanel1.Name = "tableLayoutPanel1"; + this.tableLayoutPanel1.RowCount = 2; + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel1.Size = new System.Drawing.Size(480, 377); + this.tableLayoutPanel1.TabIndex = 0; + // + // btnClose + // + this.btnClose.DialogResult = System.Windows.Forms.DialogResult.OK; + this.btnClose.Location = new System.Drawing.Point(407, 349); + this.btnClose.Name = "btnClose"; + this.btnClose.Size = new System.Drawing.Size(70, 25); + this.btnClose.TabIndex = 0; + this.btnClose.Text = "Close"; + this.btnClose.UseVisualStyleBackColor = true; + this.btnClose.Click += new System.EventHandler(this.btnClose_Click); + // + // txtLog + // + this.txtLog.BackColor = System.Drawing.Color.White; + this.tableLayoutPanel1.SetColumnSpan(this.txtLog, 2); + this.txtLog.Dock = System.Windows.Forms.DockStyle.Fill; + this.txtLog.Font = new System.Drawing.Font("Arial", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.txtLog.Location = new System.Drawing.Point(3, 3); + this.txtLog.Multiline = true; + this.txtLog.Name = "txtLog"; + this.txtLog.ReadOnly = true; + this.txtLog.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; + this.txtLog.Size = new System.Drawing.Size(474, 340); + this.txtLog.TabIndex = 1; + // + // tmrRefresh + // + this.tmrRefresh.Enabled = true; + this.tmrRefresh.Tick += new System.EventHandler(this.tmrRefresh_Tick); + // + // frmLogWindow + // + this.AcceptButton = this.btnClose; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.btnClose; + this.ClientSize = new System.Drawing.Size(480, 377); + this.Controls.Add(this.tableLayoutPanel1); + this.Name = "frmLogWindow"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Log Window"; + this.tableLayoutPanel1.ResumeLayout(false); + this.tableLayoutPanel1.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; + private System.Windows.Forms.TextBox txtLog; + private System.Windows.Forms.Button btnClose; + private System.Windows.Forms.Timer tmrRefresh; + } +} \ No newline at end of file diff --git a/UI/Forms/frmLogWindow.resx b/UI/Forms/frmLogWindow.resx new file mode 100644 index 0000000..b8422f0 --- /dev/null +++ b/UI/Forms/frmLogWindow.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 107, 17 + + \ No newline at end of file diff --git a/UI/Forms/frmMain.cs b/UI/Forms/frmMain.cs index efdffa2..0b0086b 100644 --- a/UI/Forms/frmMain.cs +++ b/UI/Forms/frmMain.cs @@ -32,6 +32,8 @@ namespace Mesen.GUI.Forms _notifListener = new NotificationListener(); _notifListener.OnNotification += OnNotificationReceived; + + new frmLogWindow().Show(); } protected override void OnFormClosing(FormClosingEventArgs e) diff --git a/UI/Interop/EmuApi.cs b/UI/Interop/EmuApi.cs index 9f3339e..9675c3f 100644 --- a/UI/Interop/EmuApi.cs +++ b/UI/Interop/EmuApi.cs @@ -39,5 +39,8 @@ namespace Mesen.GUI [DllImport(DllPath)] public static extern void SetMousePosition(double x, double y); [DllImport(DllPath)] public static extern void SetDisplayLanguage(Language lang); + + [DllImport(DllPath, EntryPoint = "GetLog")] private static extern IntPtr GetLogWrapper(); + public static string GetLog() { return Utf8Marshaler.PtrToStringUtf8(EmuApi.GetLogWrapper()).Replace("\n", Environment.NewLine); } } } diff --git a/UI/UI.csproj b/UI/UI.csproj index 0228770..e385d43 100644 --- a/UI/UI.csproj +++ b/UI/UI.csproj @@ -385,6 +385,12 @@ Form + + Form + + + frmLogWindow.cs + Form @@ -467,6 +473,9 @@ BaseInputForm.cs + + frmLogWindow.cs + frmMain.cs