Compare commits

...
Sign in to create a new pull request.

45 commits

Author SHA1 Message Date
220f8534f5 Use GCC since clang isn't working correctly. 2021-11-26 13:33:52 +01:00
NovaSquirrel
ab5b47c486
Merge pull request #51 from undisbeliever/fix-invisible-sprites
Fix invisible sprites
2021-10-26 12:44:06 -04:00
Marcus Rowe
bf961dc559 Fix invisible sprite when Y + Height >= 256 and Y < _vblankStartScanline 2021-10-26 19:52:09 +10:00
NovaSquirrel
dd9e689880
Merge pull request #47 from jeffythedragonslayer/master
Memory Access Counter columns are wider so ... does not appear
2021-10-19 23:09:55 -04:00
Jeff Linahan
56fb98ea11 Memory Access Counter columns are wider so ... does not appear 2021-10-19 23:00:01 -04:00
NovaSquirrel
73bc240164
Merge pull request #46 from mcgrew/preferences-save-fix
Fix for settings not saving under mono 6.12
2021-10-19 22:46:36 -04:00
NovaSquirrel
609cec58f5
Merge pull request #41 from kongmao45678/patch-1
Update Chinese translation resources.zh.xml
2021-10-19 22:45:45 -04:00
Thomas McGrew
c374ca8b9e Fix for settings not saving under mono 6.12 2021-10-19 22:41:56 -04:00
kongmao45678
782fba8e8a
Update Chinese translation resources.zh.xml
Update Chinese translation
2021-09-04 23:01:28 +08:00
NovaSquirrel
7af0bbcefc Add "SNES mouse (buttons only)" input device
This is intended for use with Lua scripts that update a mouse cursor's position directly
2021-06-30 17:39:34 -04:00
NovaSquirrel
c0e249e993 Revert "Merge branch 'reformat_code'"
This reverts commit daf3b57e89, reversing
changes made to 7a6e0b7d77.
2021-03-10 11:13:28 -05:00
ISSOtm
fe90e80881 Note how to debug the C++ code 2021-03-02 19:05:34 +01:00
ISSOtm
2ce3db3bb8 Link to new CI downloads 2021-03-02 19:05:21 +01:00
NovaSquirrel
d49c4be9f3
Merge pull request #28 from ISSOtm/actions
Enable CI jobs
2021-03-02 10:50:57 -05:00
ISSOtm
099d176e60 Add Linux CI build job 2021-03-02 16:21:38 +01:00
ISSOtm
c76f72df9e Add Windows CI build job 2021-03-02 16:19:50 +01:00
NovaSquirrel
834ff4338f Fixes #17 2020-12-27 22:24:23 -05:00
Vladimir Kononovich
daf3b57e89 Merge branch 'reformat_code' 2020-12-19 23:33:29 +03:00
Vladimir Kononovich
6c4907ed1d Reformat Windows (Resharper) 2020-12-19 23:33:11 +03:00
Vladimir Kononovich
c0aabf20a1 Reformat Utilities (Resharper) 2020-12-19 23:32:47 +03:00
Vladimir Kononovich
68c88a6b7c Reformat SevenZip (Resharper) 2020-12-19 23:32:06 +03:00
Vladimir Kononovich
4925698573 Reformat PGOHelper (Resharper) 2020-12-19 23:31:47 +03:00
Vladimir Kononovich
b792e0a3f0 Reformat Lua (Resharper) 2020-12-19 23:31:32 +03:00
Vladimir Kononovich
a6e89dd132 Reformat Libretro (Resharper) 2020-12-19 23:31:01 +03:00
Vladimir Kononovich
f3f15a32fe Reformat InteropDll (Resharper) 2020-12-19 23:30:40 +03:00
Vladimir Kononovich
3764af908f Reformat Core (Resharper) 2020-12-19 23:30:09 +03:00
Vladimir Kononovich
7a6e0b7d77 Moved libs linking to the project file. 2020-11-16 18:12:18 +03:00
Vladimir Kononovich
be6ed9d619 Merge branch 'get_breakpoints_and_cp_flags' 2020-11-01 16:53:07 +03:00
Vladimir Kononovich
320371740d Added api for getting breakpoints and cpu flags. 2020-11-01 16:52:30 +03:00
Vladimir Kononovich
a91ddf8c51 Merge branch 'master' into ui_regs_change 2020-10-29 02:19:37 +03:00
Vladimir Kononovich
28b5a3c503 Removed Id entity from a Breakpoint. Now BP manager deals with it. 2020-10-29 02:19:23 +03:00
Vladimir Kononovich
eb1006704a Implemented CPU flags changing. 2020-10-12 18:19:46 +03:00
Vladimir Kononovich
9df2e40060 Renamed CpuRegNmiFlag to CpuFlagNmi. 2020-10-12 18:19:17 +03:00
Vladimir Kononovich
27c6df32c3 Added UI registers change functionality. 2020-10-12 16:51:04 +03:00
Vladimir Kononovich
7a75651541 Fixes to registers change core. 2020-10-12 16:49:10 +03:00
Vladimir Kononovich
4ea538fbfe Fixed wrong Selection range if there's only one byte in selection. 2020-10-11 22:07:34 +03:00
NovaSquirrel
9d3d0bccc3
Merge pull request #12 from lab313ru/regs_write
Registers change APIs.
2020-10-11 14:34:31 -04:00
NovaSquirrel
0f0abe9788 Update Ppu.cpp 2020-10-11 14:33:50 -04:00
NovaSquirrel
f08c64e711 Fix/complete Cx4, remove PPU changes 2020-10-11 14:26:01 -04:00
Vladimir Kononovich
f514335bde Registers change APIs. 2020-10-11 13:57:01 +03:00
NovaSquirrel
c1c161b2a5 Revert "PPU: Fixed mosaic display when reading/writing to PPU registers in the middle of a scanline"
This reverts commit 98fe9a85d6.
2020-10-10 15:18:20 -04:00
NovaSquirrel
242dd77365 Port Watch Window from Mesen 2020-10-10 02:52:36 -04:00
NovaSquirrel
e25c69e54b Add aliases for processor flags, for conditions 2020-10-10 00:22:11 -04:00
NovaSquirrel
7853aaef77 Update build instructions 2020-10-09 22:49:17 -04:00
NovaSquirrel
b8ee5f2521
Merge pull request #3 from NovaSquirrel/History-Viewer
History viewer
2020-10-09 22:36:25 -04:00
72 changed files with 3464 additions and 1189 deletions

28
.github/workflows/linux-build.yml vendored Normal file
View file

@ -0,0 +1,28 @@
name: "Linux build"
on:
push:
workflow_dispatch:
jobs:
linux-build:
runs-on: ubuntu-latest
container: ubuntu:bionic
steps:
- uses: actions/checkout@v2
- name: Set up dependencies
run: |
apt-get update
apt-get install -yq --no-install-recommends gnupg ca-certificates
apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF
echo "deb https://download.mono-project.com/repo/ubuntu stable-bionic main" | tee /etc/apt/sources.list.d/mono-official-stable.list
apt-get update
apt-get install -yq --no-install-recommends g++ gcc zip unzip mono-devel libsdl2-dev libsdl2-2.0 gnome-themes-standard xvfb x11-apps
apt-get clean && rm -rf /var/cache/apt/lists/*
- name: Build
run: |
make -j$(nproc) USE_GCC=true
- name: Upload binary
uses: actions/upload-artifact@v1
with:
name: Mesen-S-Linux
path: bin/x64/Release/Mesen-S.exe

27
.github/workflows/win-build.yml vendored Normal file
View file

@ -0,0 +1,27 @@
name: "Windows build"
on: push
jobs:
win-build:
runs-on: windows-2019
steps:
- uses: actions/checkout@v2
- name: Set up dependencies
shell: bash
run: |
mkdir -p "bin/Any CPU/Release"
cp -v -r UI/Dependencies "bin/Any CPU/Release"
git describe --tags --dirty --always >"bin\Any CPU\Release\Dependencies\DevBuild.txt"
- name: Build core
working-directory: bin
shell: cmd
run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
msbuild ..\Mesen-S.sln /t:Build /p:Configuration=Release /p:Platform=x64
copy "x64\Release\MesenSCore.dll" "Any CPU\Release\Dependencies\MesenSCore.x64.dll"
msbuild ..\Mesen-S.sln /t:Build /p:Configuration=Release /p:Platform="Any CPU" /property:DefineConstants="HIDETESTMENU;AUTOBUILD"
- name: Upload binary
uses: actions/upload-artifact@v1
with:
name: Mesen-S-win
path: bin/Any CPU/Release/Mesen-S.exe

View file

@ -1,10 +1,14 @@
### Windows
Note: to debug the C++ code, go to `UI`'s properties, tick `Debug > Debugger engines > Enable native code debugging`, and save the changes.
#### *Standalone*
1) Open the solution in Visual Studio 2019
2) Compile as Release/x64
3) Run
2) Set "UI" as the Startup Project
3) Compile as Release/x64
4) Run the project from Visual Studio
5) If you got an error, try running it a second time
#### *Libretro*
@ -20,7 +24,7 @@ Note: It's also possible to build the Libretro core via MINGW by using the makef
To compile Mesen-S under Linux you will need a relatively recent version of clang or gcc that supports the C++17 filesystem API.) Additionally, Mesen-S has the following dependencies:
* Mono 5.18+ (package: mono-devel)
* Mono 5.18+ (package: mono-devel)
* SDL2 (package: libsdl2-dev)
**Note:** **Mono 5.18 or higher is recommended**, some older versions of Mono (e.g 4.2.2) have some stability and performance issues which can cause crashes and slow down the UI.
@ -29,9 +33,9 @@ The default Mono version in Ubuntu 18.04 is 4.6.2 (which also causes some layout
The makefile contains some more information at the top. Running "make" will build the x64 version by default, and then "make run" should start the emulator.
LTO is supported under clang, which gives a large performance boost (25-30%+), so turning it on is highly recommended (see makefile for details):
Examples:
`LTO=true make` will compile with clang and LTO.
`USE_GCC=true LTO=true make` will compile with gcc and LTO.
Examples:
`LTO=true make` will compile with clang and LTO.
`USE_GCC=true LTO=true make` will compile with gcc and LTO.
#### *Libretro*

View file

@ -5,63 +5,58 @@
bool Breakpoint::Matches(uint32_t memoryAddr, AddressInfo &info)
{
if(_memoryType <= DebugUtilities::GetLastCpuMemoryType() && !DebugUtilities::IsPpuMemory(info.Type)) {
if(_startAddr == -1) {
if(memoryType <= DebugUtilities::GetLastCpuMemoryType() && !DebugUtilities::IsPpuMemory(info.Type)) {
if(startAddr == -1) {
return true;
} else if(_endAddr == -1) {
return (int32_t)memoryAddr == _startAddr;
} else if(endAddr == -1) {
return (int32_t)memoryAddr == startAddr;
} else {
return (int32_t)memoryAddr >= _startAddr && (int32_t)memoryAddr <= _endAddr;
return (int32_t)memoryAddr >= startAddr && (int32_t)memoryAddr <= endAddr;
}
} else if(_memoryType == info.Type) {
if(_startAddr == -1) {
} else if(memoryType == info.Type) {
if(startAddr == -1) {
return true;
} else if(_endAddr == -1) {
return info.Address == _startAddr;
} else if(endAddr == -1) {
return info.Address == startAddr;
} else {
return info.Address >= _startAddr && info.Address <= _endAddr;
return info.Address >= startAddr && info.Address <= endAddr;
}
}
return false;
}
bool Breakpoint::HasBreakpointType(BreakpointType type)
bool Breakpoint::HasBreakpointType(BreakpointType bpType)
{
switch(type) {
switch(bpType) {
default:
case BreakpointType::Execute: return ((uint8_t)_type & (uint8_t)BreakpointTypeFlags::Execute) != 0;
case BreakpointType::Read: return ((uint8_t)_type & (uint8_t)BreakpointTypeFlags::Read) != 0;
case BreakpointType::Write: return ((uint8_t)_type & (uint8_t)BreakpointTypeFlags::Write) != 0;
case BreakpointType::Execute: return ((uint8_t)type & (uint8_t)BreakpointTypeFlags::Execute) != 0;
case BreakpointType::Read: return ((uint8_t)type & (uint8_t)BreakpointTypeFlags::Read) != 0;
case BreakpointType::Write: return ((uint8_t)type & (uint8_t)BreakpointTypeFlags::Write) != 0;
}
}
string Breakpoint::GetCondition()
{
return _condition;
return condition;
}
bool Breakpoint::HasCondition()
{
return _condition[0] != 0;
}
uint32_t Breakpoint::GetId()
{
return _id;
return condition[0] != 0;
}
CpuType Breakpoint::GetCpuType()
{
return _cpuType;
return cpuType;
}
bool Breakpoint::IsEnabled()
{
return _enabled;
return enabled;
}
bool Breakpoint::IsMarked()
{
return _markEvent;
return markEvent;
}

View file

@ -12,23 +12,20 @@ class Breakpoint
{
public:
bool Matches(uint32_t memoryAddr, AddressInfo &info);
bool HasBreakpointType(BreakpointType type);
bool HasBreakpointType(BreakpointType bpType);
string GetCondition();
bool HasCondition();
uint32_t GetId();
CpuType GetCpuType();
bool IsEnabled();
bool IsMarked();
private:
uint32_t _id;
CpuType _cpuType;
SnesMemoryType _memoryType;
BreakpointTypeFlags _type;
int32_t _startAddr;
int32_t _endAddr;
bool _enabled;
bool _markEvent;
char _condition[1000];
CpuType cpuType;
SnesMemoryType memoryType;
BreakpointTypeFlags type;
int32_t startAddr;
int32_t endAddr;
bool enabled;
bool markEvent;
char condition[1000];
};

View file

@ -36,14 +36,15 @@ void BreakpointManager::SetBreakpoints(Breakpoint breakpoints[], uint32_t count)
continue;
}
_breakpoints[i].push_back(bp);
int curIndex = _breakpoints[i].size();
_breakpoints[i].insert(std::make_pair(curIndex, bp));
if(bp.HasCondition()) {
bool success = true;
ExpressionData data = _bpExpEval->GetRpnList(bp.GetCondition(), success);
_rpnList[i].push_back(success ? data : ExpressionData());
_rpnList[i].insert(std::make_pair(curIndex, success ? data : ExpressionData()));
} else {
_rpnList[i].push_back(ExpressionData());
_rpnList[i].insert(std::make_pair(curIndex, ExpressionData()));
}
_hasBreakpoint = true;
@ -53,6 +54,30 @@ void BreakpointManager::SetBreakpoints(Breakpoint breakpoints[], uint32_t count)
}
}
void BreakpointManager::GetBreakpoints(Breakpoint* breakpoints, int& execs, int& reads, int& writes)
{
execs = _breakpoints[static_cast<int>(BreakpointType::Execute)].size();
reads = _breakpoints[static_cast<int>(BreakpointType::Read)].size();
writes = _breakpoints[static_cast<int>(BreakpointType::Write)].size();
if (breakpoints == NULL) {
return;
}
int offset = 0;
for (auto it = _breakpoints[static_cast<int>(BreakpointType::Execute)].cbegin(); it != _breakpoints[static_cast<int>(BreakpointType::Execute)].cend(); it++) {
breakpoints[offset++] = it->second;
}
for (auto it = _breakpoints[static_cast<int>(BreakpointType::Read)].cbegin(); it != _breakpoints[static_cast<int>(BreakpointType::Read)].cend(); it++) {
breakpoints[offset++] = it->second;
}
for (auto it = _breakpoints[static_cast<int>(BreakpointType::Write)].cbegin(); it != _breakpoints[static_cast<int>(BreakpointType::Write)].cend(); it++) {
breakpoints[offset++] = it->second;
}
}
BreakpointType BreakpointManager::GetBreakpointType(MemoryOperationType type)
{
switch(type) {
@ -82,15 +107,15 @@ int BreakpointManager::InternalCheckBreakpoint(MemoryOperationInfo operationInfo
DebugState state;
_debugger->GetState(state, false);
EvalResultType resultType;
vector<Breakpoint> &breakpoints = _breakpoints[(int)type];
for(size_t i = 0; i < breakpoints.size(); i++) {
if(breakpoints[i].Matches(operationInfo.Address, address)) {
if(!breakpoints[i].HasCondition() || _bpExpEval->Evaluate(_rpnList[(int)type][i], state, resultType, operationInfo)) {
if(breakpoints[i].IsMarked()) {
_eventManager->AddEvent(DebugEventType::Breakpoint, operationInfo, breakpoints[i].GetId());
unordered_map<int, Breakpoint> &breakpoints = _breakpoints[(int)type];
for (auto it = breakpoints.begin(); it != breakpoints.end(); it++) {
if (it->second.Matches(operationInfo.Address, address)) {
if (!it->second.HasCondition() || _bpExpEval->Evaluate(_rpnList[(int)type][it->first], state, resultType, operationInfo)) {
if (it->second.IsMarked()) {
_eventManager->AddEvent(DebugEventType::Breakpoint, operationInfo, it->first);
}
if(breakpoints[i].IsEnabled()) {
return breakpoints[i].GetId();
if (it->second.IsEnabled()) {
return it->first;
}
}
}

View file

@ -3,6 +3,7 @@
#include "Breakpoint.h"
#include "DebugTypes.h"
#include "DebugUtilities.h"
#include "ExpressionEvaluator.h"
class ExpressionEvaluator;
class Debugger;
@ -19,8 +20,8 @@ private:
CpuType _cpuType;
IEventManager *_eventManager;
vector<Breakpoint> _breakpoints[BreakpointTypeCount];
vector<ExpressionData> _rpnList[BreakpointTypeCount];
unordered_map<int, Breakpoint> _breakpoints[BreakpointTypeCount];
unordered_map<int, ExpressionData> _rpnList[BreakpointTypeCount];
bool _hasBreakpoint;
bool _hasBreakpointType[BreakpointTypeCount] = {};
@ -33,6 +34,7 @@ public:
BreakpointManager(Debugger *debugger, CpuType cpuType, IEventManager* eventManager = nullptr);
void SetBreakpoints(Breakpoint breakpoints[], uint32_t count);
void GetBreakpoints(Breakpoint* breakpoints, int& execs, int& reads, int& writes);
__forceinline int CheckBreakpoint(MemoryOperationInfo operationInfo, AddressInfo &address);
};

View file

@ -113,6 +113,7 @@ shared_ptr<BaseControlDevice> ControlManager::CreateControllerDevice(ControllerT
case ControllerType::SnesMouse: device.reset(new SnesMouse(console, port)); break;
case ControllerType::SuperScope: device.reset(new SuperScope(console, port, cfg.Controllers[port].Keys)); break;
case ControllerType::Multitap: device.reset(new Multitap(console, port, cfg.Controllers[port].Keys, cfg.Controllers[2].Keys, cfg.Controllers[3].Keys, cfg.Controllers[4].Keys)); break;
case ControllerType::SnesMouseButtonsOnly: device.reset(new SnesMouse(console, port)); break;
}
return device;

View file

@ -117,3 +117,28 @@ void Cpu::Write(uint32_t addr, uint8_t value, MemoryOperationType type)
UpdateIrqNmiFlags();
}
#endif
void Cpu::SetReg(CpuRegister reg, uint16_t value)
{
switch (reg) {
case CpuRegister::CpuRegA: { _state.A = value; } break;
case CpuRegister::CpuRegX: { _state.X = value; } break;
case CpuRegister::CpuRegY: { _state.Y = value; } break;
case CpuRegister::CpuRegSP: { _state.SP = value; } break;
case CpuRegister::CpuRegD: { _state.D = value; } break;
case CpuRegister::CpuRegPC: { _state.PC = value; } break;
case CpuRegister::CpuRegK: { _state.K = value & 0xFF; } break;
case CpuRegister::CpuRegDBR: { _state.DBR = value & 0xFF; } break;
case CpuRegister::CpuRegPS: { _state.PS = value & 0xFF; } break;
case CpuRegister::CpuFlagNmi: { _state.NmiFlag = value != 0; } break;
}
}
bool Cpu::GetCpuProcFlag(ProcFlags::ProcFlags flag) {
return _state.PS & static_cast<uint8_t>(flag);
}
void Cpu::SetCpuProcFlag(ProcFlags::ProcFlags flag, bool set)
{
_state.PS = set ? (_state.PS | static_cast<uint8_t>(flag)) : (_state.PS & ~static_cast<uint8_t>(flag));
}

View file

@ -7,6 +7,7 @@
#include "stdafx.h"
#include "CpuTypes.h"
#include "DebugTypes.h"
#include "../Utilities/ISerializable.h"
class MemoryMappings;
@ -330,6 +331,7 @@ public:
void Exec();
CpuState GetState();
bool GetCpuProcFlag(ProcFlags::ProcFlags flag);
uint64_t GetCycleCount();
template<uint64_t value>
@ -345,6 +347,9 @@ public:
// Inherited via ISerializable
void Serialize(Serializer &s) override;
void SetReg(CpuRegister reg, uint16_t value);
void SetCpuProcFlag(ProcFlags::ProcFlags flag, bool set);
#ifdef DUMMYCPU
private:
MemoryMappings* _memoryMappings;
@ -370,6 +375,8 @@ public:
#endif
};
void SetReg(CpuRegister reg, uint16_t value);
template<uint64_t count>
void Cpu::IncreaseCycleCount()
{

View file

@ -478,4 +478,37 @@ uint32_t Cx4::DebugGetDataRamSize()
Cx4State Cx4::GetState()
{
return _state;
}
void Cx4::SetReg(Cx4Register reg, uint32_t value)
{
switch (reg)
{
case Cx4Register::Cx4Reg0: case Cx4Register::Cx4Reg1: case Cx4Register::Cx4Reg2: case Cx4Register::Cx4Reg3:
case Cx4Register::Cx4Reg4: case Cx4Register::Cx4Reg5: case Cx4Register::Cx4Reg6: case Cx4Register::Cx4Reg7:
case Cx4Register::Cx4Reg8: case Cx4Register::Cx4Reg9: case Cx4Register::Cx4Reg10: case Cx4Register::Cx4Reg11:
case Cx4Register::Cx4Reg12: case Cx4Register::Cx4Reg13: case Cx4Register::Cx4Reg14: case Cx4Register::Cx4Reg15:
_state.Regs[(static_cast<int>(reg) - static_cast<int>(Cx4Register::Cx4Reg0)) & 0x0F] = value & 0xFFFFFF; // 24-bit
break;
case Cx4Register::Cx4RegPB:
{
_state.PB = value & 0xFFFF;
} break;
case Cx4Register::Cx4RegPC:
{
_state.PC = value & 0xFF;
} break;
case Cx4Register::Cx4RegA:
{
_state.A = value & 0xFFFFFF; // 24-bit
} break;
case Cx4Register::Cx4RegP:
{
_state.P = value & 0xFFFF;
} break;
case Cx4Register::Cx4RegSP:
{
_state.SP = value & 0xFF;
} break;
}
}

View file

@ -129,4 +129,6 @@ public:
uint8_t* DebugGetDataRam();
uint32_t DebugGetDataRamSize();
Cx4State GetState();
void SetReg(Cx4Register reg, uint32_t value);
};

View file

@ -284,3 +284,109 @@ enum class CpuType : uint8_t
Cx4,
Gameboy
};
enum class CpuRegister : uint8_t
{
CpuRegA,
CpuRegX,
CpuRegY,
CpuRegSP,
CpuRegD,
CpuRegPC,
CpuRegK,
CpuRegDBR,
CpuRegPS,
CpuFlagNmi
};
enum class Cx4Register : uint8_t
{
Cx4Reg0,
Cx4Reg1,
Cx4Reg2,
Cx4Reg3,
Cx4Reg4,
Cx4Reg5,
Cx4Reg6,
Cx4Reg7,
Cx4Reg8,
Cx4Reg9,
Cx4Reg10,
Cx4Reg11,
Cx4Reg12,
Cx4Reg13,
Cx4Reg14,
Cx4Reg15,
Cx4RegPB,
Cx4RegPC,
Cx4RegA,
Cx4RegP,
Cx4RegSP
};
enum class GbRegister : uint8_t
{
GbRegPC,
GbRegSP,
GbRegA,
GbRegFlags,
GbRegB,
GbRegC,
GbRegD,
GbRegE,
GbRegH,
GbRegL
};
enum class GsuRegister : uint8_t
{
GsuReg0,
GsuReg1,
GsuReg2,
GsuReg3,
GsuReg4,
GsuReg5,
GsuReg6,
GsuReg7,
GsuReg8,
GsuReg9,
GsuRegA,
GsuRegB,
GsuRegC,
GsuRegD,
GsuRegE,
GsuRegF,
GsuRegSFR
};
enum class NecDspRegister : uint8_t
{
NecDspRegA,
NecDspRegFlagsA,
NecDspRegB,
NecDspRegFlagsB,
NecDspRegTR,
NecDspRegTRB,
NecDspRegPC,
NecDspRegRP,
NecDspRegDP,
NecDspRegDR,
NecDspRegSR,
NecDspRegK,
NecDspRegL,
NecDspRegM,
NecDspRegN,
NecDspRegSerialOut,
NecDspRegSerialIn,
NecDspRegSP
};
enum class SpcRegister : uint8_t
{
SpcRegPC,
SpcRegA,
SpcRegX,
SpcRegY,
SpcRegSP,
SpcRegPS
};

View file

@ -511,6 +511,51 @@ void Debugger::GetState(DebugState &state, bool partialPpuState)
}
}
bool Debugger::GetCpuProcFlag(ProcFlags::ProcFlags flag)
{
return _cpu->GetCpuProcFlag(flag);
}
void Debugger::SetCpuRegister(CpuRegister reg, uint16_t value)
{
_cpu->SetReg(reg, value);
}
void Debugger::SetCpuProcFlag(ProcFlags::ProcFlags flag, bool set)
{
_cpu->SetCpuProcFlag(flag, set);
}
void Debugger::SetCx4Register(Cx4Register reg, uint32_t value)
{
_cart->GetCx4()->SetReg(reg, value);
}
void Debugger::SetGameboyRegister(GbRegister reg, uint16_t value)
{
_cart->GetGameboy()->SetReg(reg, value);
}
void Debugger::SetGsuRegister(GsuRegister reg, uint16_t value)
{
_cart->GetGsu()->SetReg(reg, value);
}
void Debugger::SetNecDspRegister(NecDspRegister reg, uint16_t value)
{
_cart->GetDsp()->SetReg(reg, value);
}
void Debugger::SetSa1Register(CpuRegister reg, uint16_t value)
{
_cart->GetSa1()->SetReg(reg, value);
}
void Debugger::SetSpcRegister(SpcRegister reg, uint16_t value)
{
_spc->SetReg(reg, value);
}
AddressInfo Debugger::GetAbsoluteAddress(AddressInfo relAddress)
{
if(relAddress.Type == SnesMemoryType::CpuMemory) {
@ -676,6 +721,39 @@ void Debugger::SetBreakpoints(Breakpoint breakpoints[], uint32_t length)
}
}
void Debugger::GetBreakpoints(CpuType cpuType, Breakpoint* breakpoints, int& execs, int& reads, int& writes)
{
switch (cpuType) {
case CpuType::Cpu: return _cpuDebugger->GetBreakpointManager()->GetBreakpoints(breakpoints, reads, writes, execs);
case CpuType::Spc: return _spcDebugger->GetBreakpointManager()->GetBreakpoints(breakpoints, reads, writes, execs);
case CpuType::Gsu: {
if (_gsuDebugger) {
return _gsuDebugger->GetBreakpointManager()->GetBreakpoints(breakpoints, reads, writes, execs);
}
} break;
case CpuType::Sa1: {
if (_sa1Debugger) {
return _sa1Debugger->GetBreakpointManager()->GetBreakpoints(breakpoints, reads, writes, execs);
}
} break;
case CpuType::NecDsp: {
if (_necDspDebugger) {
return _necDspDebugger->GetBreakpointManager()->GetBreakpoints(breakpoints, reads, writes, execs);
}
} break;
case CpuType::Cx4: {
if (_cx4Debugger) {
return _cx4Debugger->GetBreakpointManager()->GetBreakpoints(breakpoints, reads, writes, execs);
}
} break;
case CpuType::Gameboy: {
if (_gbDebugger) {
return _gbDebugger->GetBreakpointManager()->GetBreakpoints(breakpoints, reads, writes, execs);
}
} break;
}
}
void Debugger::Log(string message)
{
auto lock = _logLock.AcquireSafe();

View file

@ -127,7 +127,17 @@ public:
void ProcessBreakConditions(bool needBreak, BreakpointManager *bpManager, MemoryOperationInfo &operation, AddressInfo &addressInfo, BreakSource source = BreakSource::Unspecified);
void SleepUntilResume(BreakSource source, MemoryOperationInfo* operation = nullptr, int breakpointId = -1);
void GetState(DebugState &state, bool partialPpuState);
void GetState(DebugState& state, bool partialPpuState);
bool GetCpuProcFlag(ProcFlags::ProcFlags flag);
void SetCpuRegister(CpuRegister reg, uint16_t value);
void SetCpuProcFlag(ProcFlags::ProcFlags flag, bool set);
void SetCx4Register(Cx4Register reg, uint32_t value);
void SetGameboyRegister(GbRegister reg, uint16_t value);
void SetGsuRegister(GsuRegister reg, uint16_t value);
void SetNecDspRegister(NecDspRegister reg, uint16_t value);
void SetSa1Register(CpuRegister reg, uint16_t value);
void SetSpcRegister(SpcRegister reg, uint16_t value);
AddressInfo GetAbsoluteAddress(AddressInfo relAddress);
AddressInfo GetRelativeAddress(AddressInfo absAddress, CpuType cpuType);
@ -140,6 +150,7 @@ public:
void RebuildPrgCache(CpuType cpuType);
void SetBreakpoints(Breakpoint breakpoints[], uint32_t length);
void GetBreakpoints(CpuType cpuType, Breakpoint* breakpoints, int& execs, int& reads, int& writes);
void Log(string message);
string GetLog();

View file

@ -76,8 +76,10 @@ bool ExpressionEvaluator::CheckSpecialTokens(string expression, size_t &pos, str
tokenValue = ProcessGsuTokens(token);
} else if(_cpuType == CpuType::Gameboy) {
tokenValue = ProcessGameboyTokens(token);
} else {
tokenValue = ProcessCpuSpcTokens(token);
} else if(_cpuType == CpuType::Spc) {
tokenValue = ProcessCpuSpcTokens(token, true);
} else { // Cpu or Sa1
tokenValue = ProcessCpuSpcTokens(token, false);
}
if(tokenValue != -1) {
@ -108,7 +110,7 @@ bool ExpressionEvaluator::CheckSpecialTokens(string expression, size_t &pos, str
}
}
int64_t ExpressionEvaluator::ProcessCpuSpcTokens(string token)
int64_t ExpressionEvaluator::ProcessCpuSpcTokens(string token, bool spc700)
{
if(token == "a") {
return EvalValues::RegA;
@ -118,6 +120,32 @@ int64_t ExpressionEvaluator::ProcessCpuSpcTokens(string token)
return EvalValues::RegY;
} else if(token == "ps") {
return EvalValues::RegPS;
} else if (token == "pscarry") {
return EvalValues::RegPS_Carry;
} else if (token == "pszero") {
return EvalValues::RegPS_Zero;
} else if (token == "psinterrupt") {
return EvalValues::RegPS_Interrupt;
} else if (token == "psdecimal") {
return EvalValues::RegPS_Decimal;
} else if (token == "psoverflow") {
return EvalValues::RegPS_Overflow;
} else if (token == "psnegative") {
return EvalValues::RegPS_Negative;
} else if (token == "ps8bit" && !spc700) {
return EvalValues::RegPS_8bit;
} else if (token == "ps8bitindex" && !spc700) {
return EvalValues::RegPS_8bitIndex;
} else if (token == "ps16bit" && !spc700) {
return EvalValues::RegPS_16bit;
} else if (token == "ps16bitindex" && !spc700) {
return EvalValues::RegPS_16bitIndex;
} else if (token == "pshalfcarry" && spc700) {
return EvalValues::RegPS_HalfCarry;
} else if (token == "psbreak" && spc700) {
return EvalValues::RegPS_Break;
} else if (token == "psstackzp" && spc700) {
return EvalValues::RegPS_StackZeropage;
} else if(token == "sp") {
return EvalValues::RegSP;
} else if(token == "pc") {
@ -506,6 +534,16 @@ int32_t ExpressionEvaluator::Evaluate(ExpressionData &data, DebugState &state, E
case EvalValues::RegPC: token = state.Cpu.PC; break;
case EvalValues::Nmi: token = state.Cpu.NmiFlag; resultType = EvalResultType::Boolean; break;
case EvalValues::Irq: token = state.Cpu.IrqSource != 0; resultType = EvalResultType::Boolean; break;
case EvalValues::RegPS_Carry: token = (state.Cpu.PS & 1) != 0; break;
case EvalValues::RegPS_Zero: token = (state.Cpu.PS & 2) != 0; break;
case EvalValues::RegPS_Interrupt: token = (state.Cpu.PS & 4) != 0; break;
case EvalValues::RegPS_Decimal: token = (state.Cpu.PS & 8) != 0; break;
case EvalValues::RegPS_8bitIndex: token = (state.Cpu.PS & 16) != 0; break;
case EvalValues::RegPS_8bit: token = (state.Cpu.PS & 32) != 0; break;
case EvalValues::RegPS_16bitIndex: token = (state.Cpu.PS & 16) == 0; break;
case EvalValues::RegPS_16bit: token = (state.Cpu.PS & 32) == 0; break;
case EvalValues::RegPS_Overflow: token = (state.Cpu.PS & 64) != 0; break;
case EvalValues::RegPS_Negative: token = (state.Cpu.PS & 128) != 0; break;
}
break;
@ -517,6 +555,14 @@ int32_t ExpressionEvaluator::Evaluate(ExpressionData &data, DebugState &state, E
case EvalValues::RegSP: token = state.Spc.SP; break;
case EvalValues::RegPS: token = state.Spc.PS; break;
case EvalValues::RegPC: token = state.Spc.PC; break;
case EvalValues::RegPS_Carry: token = (state.Cpu.PS & 1) != 0; break;
case EvalValues::RegPS_Zero: token = (state.Cpu.PS & 2) != 0; break;
case EvalValues::RegPS_Interrupt: (state.Cpu.PS & 4) != 0; break;
case EvalValues::RegPS_HalfCarry: (state.Cpu.PS & 8) != 0; break;
case EvalValues::RegPS_Break: (state.Cpu.PS & 16) != 0; break;
case EvalValues::RegPS_StackZeropage: (state.Cpu.PS & 32) != 0; break;
case EvalValues::RegPS_Overflow: (state.Cpu.PS & 64) != 0; break;
case EvalValues::RegPS_Negative: (state.Cpu.PS & 128) != 0; break;
}
break;

View file

@ -90,6 +90,22 @@ enum EvalValues : int64_t
RomBR = 20000000141,
RamBR = 20000000142,
RegPS_Carry = 20000000150,
RegPS_Zero = 20000000151,
RegPS_Interrupt = 20000000152,
RegPS_Decimal = 20000000153,
RegPS_8bitIndex = 20000000154,
RegPS_8bit = 20000000155,
RegPS_Overflow = 20000000156,
RegPS_Negative = 20000000157,
RegPS_16bitIndex = 20000000158,
RegPS_16bit = 20000000159,
// SPC flags
RegPS_HalfCarry = 20000000153,
RegPS_Break = 20000000154,
RegPS_StackZeropage = 20000000155,
RegB = 20000000160,
RegC = 20000000161,
RegD = 20000000162,
@ -151,7 +167,7 @@ private:
bool IsOperator(string token, int &precedence, bool unaryOperator);
EvalOperators GetOperator(string token, bool unaryOperator);
bool CheckSpecialTokens(string expression, size_t &pos, string &output, ExpressionData &data);
int64_t ProcessCpuSpcTokens(string token);
int64_t ProcessCpuSpcTokens(string token, bool spc);
int64_t ProcessSharedTokens(string token);
int64_t ProcessGsuTokens(string token);
int64_t ProcessGameboyTokens(string token);

View file

@ -364,3 +364,8 @@ void Gameboy::Serialize(Serializer& s)
s.StreamArray(_spriteRam, Gameboy::SpriteRamSize);
s.StreamArray(_highRam, Gameboy::HighRamSize);
}
void Gameboy::SetReg(GbRegister reg, uint16_t value)
{
_cpu->SetReg(reg, value);
}

View file

@ -92,4 +92,6 @@ public:
uint64_t GetApuCycleCount();
void Serialize(Serializer& s) override;
void SetReg(GbRegister reg, uint16_t value);
};

View file

@ -1389,3 +1389,50 @@ void GbCpu::Serialize(Serializer& s)
_state.EiPending
);
}
void GbCpu::SetReg(GbRegister reg, uint16_t value)
{
switch (reg)
{
case GbRegister::GbRegPC:
{
_state.PC = value;
} break;
case GbRegister::GbRegSP:
{
_state.SP = value;
} break;
case GbRegister::GbRegA:
{
_state.A = value & 0xFF;
} break;
case GbRegister::GbRegFlags:
{
_state.Flags = value & 0xFF;
} break;
case GbRegister::GbRegB:
{
_state.B = value & 0xFF;
} break;
case GbRegister::GbRegC:
{
_state.C = value & 0xFF;
} break;
case GbRegister::GbRegD:
{
_state.D = value & 0xFF;
} break;
case GbRegister::GbRegE:
{
_state.E = value & 0xFF;
} break;
case GbRegister::GbRegH:
{
_state.H = value & 0xFF;
} break;
case GbRegister::GbRegL:
{
_state.L = value & 0xFF;
} break;
}
}

View file

@ -150,4 +150,6 @@ public:
void Exec();
void Serialize(Serializer& s) override;
void SetReg(GbRegister reg, uint16_t value);
};

View file

@ -651,3 +651,33 @@ uint32_t Gsu::DebugGetWorkRamSize()
{
return _gsuRamSize;
}
void Gsu::SetReg(GsuRegister reg, uint16_t value)
{
switch (reg)
{
case GsuRegister::GsuReg0:
case GsuRegister::GsuReg1:
case GsuRegister::GsuReg2:
case GsuRegister::GsuReg3:
case GsuRegister::GsuReg4:
case GsuRegister::GsuReg5:
case GsuRegister::GsuReg6:
case GsuRegister::GsuReg7:
case GsuRegister::GsuReg8:
case GsuRegister::GsuReg9:
case GsuRegister::GsuRegA:
case GsuRegister::GsuRegB:
case GsuRegister::GsuRegC:
case GsuRegister::GsuRegD:
case GsuRegister::GsuRegE:
case GsuRegister::GsuRegF:
{
_state.R[static_cast<int>(reg) & 0xF] = value;
} break;
case GsuRegister::GsuRegSFR:
{
_state.SFR.SetFlags(value);
} break;
}
}

View file

@ -170,4 +170,6 @@ public:
MemoryMappings* GetMemoryMappings();
uint8_t* DebugGetWorkRam();
uint32_t DebugGetWorkRamSize();
void SetReg(GsuRegister reg, uint16_t value);
};

View file

@ -39,6 +39,27 @@ struct GsuFlags
(Irq << 7)
);
}
void SetFlags(uint16_t flags)
{
// 0 bit is clear
Zero = flags & (1 << 1);
Carry = flags & (1 << 2);
Sign = flags & (1 << 3);
Overflow = flags & (1 << 4);
Running = flags & (1 << 5);
RomReadPending = flags & (1 << 6);
// 7 bit is clear
Alt1 = flags & (1 << (8 + 0));
Alt2 = flags & (1 << (8 + 1));
ImmLow = flags & (1 << (8 + 2));
ImmHigh = flags & (1 << (8 + 3));
Prefix = flags & (1 << (8 + 4));
// 5 bit is clear
// 6 bit is clear
Irq = flags & (1 << (8 + 7));
}
};
struct GsuPixelCache

View file

@ -165,7 +165,7 @@ void InputHud::DrawControllers(OverscanDimensions overscan, int frameNumber)
hud->DrawRectangle(pos.X - 1, pos.Y - 1, 3, 3, 0x00111111, true, 1, frameNumber);
hud->DrawRectangle(pos.X - 1, pos.Y - 1, 3, 3, 0x80CCCCCC, false, 1, frameNumber);
}
} else if(controllerData[i].Type == ControllerType::SnesMouse) {
} else if(controllerData[i].Type == ControllerType::SnesMouse || controllerData[i].Type == ControllerType::SnesMouseButtonsOnly) {
if(cfg.DisplayInputPort[i]) {
SnesMouse mouse(_console, 0);
mouse.SetRawState(controllerData[i].State);

View file

@ -28,7 +28,8 @@ const vector<string> ControllerTypeNames = {
"SnesController",
"SnesMouse",
"SuperScope",
"Multitap"
"Multitap",
"SnesMouseButtonsOnly"
};
const vector<string> RamStateNames = {

View file

@ -586,3 +586,82 @@ void NecDsp::Serialize(Serializer &s)
s.StreamArray<uint16_t>(_stack, _stackSize);
}
void NecDsp::SetReg(NecDspRegister reg, uint16_t value)
{
switch (reg)
{
case NecDspRegister::NecDspRegA:
{
_state.A = value;
} break;
case NecDspRegister::NecDspRegFlagsA:
{
_state.FlagsA.SetFlags(value & 0xFF);
} break;
case NecDspRegister::NecDspRegB:
{
_state.B = value;
} break;
case NecDspRegister::NecDspRegFlagsB:
{
_state.FlagsB.SetFlags(value & 0xFF);
} break;
case NecDspRegister::NecDspRegTR:
{
_state.TR = value;
} break;
case NecDspRegister::NecDspRegTRB:
{
_state.TRB = value;
} break;
case NecDspRegister::NecDspRegPC:
{
_state.PC = value;
} break;
case NecDspRegister::NecDspRegRP:
{
_state.RP = value;
} break;
case NecDspRegister::NecDspRegDP:
{
_state.DP = value;
} break;
case NecDspRegister::NecDspRegDR:
{
_state.DR = value;
} break;
case NecDspRegister::NecDspRegSR:
{
_state.SR = value;
} break;
case NecDspRegister::NecDspRegK:
{
_state.K = value;
} break;
case NecDspRegister::NecDspRegL:
{
_state.L = value;
} break;
case NecDspRegister::NecDspRegM:
{
_state.M = value;
} break;
case NecDspRegister::NecDspRegN:
{
_state.N = value;
} break;
case NecDspRegister::NecDspRegSerialOut:
{
_state.SerialOut = value;
} break;
case NecDspRegister::NecDspRegSerialIn:
{
_state.SerialIn = value;
} break;
case NecDspRegister::NecDspRegSP:
{
_state.SP = value & 0xFF;
} break;
}
}

View file

@ -82,4 +82,6 @@ public:
NecDspState GetState();
void Serialize(Serializer &s) override;
void SetReg(NecDspRegister reg, uint16_t value);
};

View file

@ -9,6 +9,16 @@ struct NecDspAccFlags
bool Overflow1;
bool Sign0;
bool Sign1;
void SetFlags(uint8_t flags)
{
Carry = flags & (1 << 0);
Zero = flags & (1 << 1);
Overflow0 = flags & (1 << 2);
Overflow1 = flags & (1 << 3);
Sign0 = flags & (1 << 4);
Sign1 = flags & (1 << 5);
}
};
namespace NecDspStatusFlags

View file

@ -949,7 +949,7 @@ void Ppu::RenderTilemap()
TileData* tileData = _layerData[layerIndex].Tiles;
uint8_t mosaicCounter = applyMosaic ? (_drawStartX % _state.MosaicSize) : 0;
uint8_t mosaicCounter = applyMosaic ? _state.MosaicSize - (_drawStartX % _state.MosaicSize) : 0;
uint8_t lookupIndex;
uint8_t chrDataOffset;
@ -988,7 +988,7 @@ void Ppu::RenderTilemap()
uint8_t priority = (tilemapData & 0x2000) ? highPriority : normalPriority;
if(applyMosaic) {
if(mosaicCounter == 0) {
if(mosaicCounter == _state.MosaicSize) {
mosaicCounter = 1;
if(hiResMode) {
color = hiresSubColor;
@ -997,9 +997,6 @@ void Ppu::RenderTilemap()
_mosaicPriority[layerIndex] = priority;
} else {
mosaicCounter++;
if(mosaicCounter == _state.MosaicSize) {
mosaicCounter = 0;
}
color = _mosaicColor[layerIndex] & 0xFF;
paletteIndex = _mosaicColor[layerIndex] >> 8;
priority = _mosaicPriority[layerIndex];
@ -1111,7 +1108,7 @@ void Ppu::RenderTilemapMode7()
//Keep the "scanline" to what it was at the start of this mosaic block
realY -= _state.MosaicSize - _mosaicScanlineCounter;
}
uint8_t mosaicCounter = applyMosaic ? (_drawStartX % _state.MosaicSize) : 0;
uint8_t mosaicCounter = applyMosaic ? _state.MosaicSize - (_drawStartX % _state.MosaicSize) : 0;
int32_t xValue = (
((_state.Mode7.Matrix[0] * clip(hScroll - centerX)) & ~63) +
@ -1178,15 +1175,12 @@ void Ppu::RenderTilemapMode7()
}
if(applyMosaic) {
if(mosaicCounter == 0) {
if(mosaicCounter == _state.MosaicSize) {
mosaicCounter = 1;
_mosaicColor[layerIndex] = colorIndex;
_mosaicPriority[layerIndex] = priority;
} else {
mosaicCounter++;
if(mosaicCounter == _state.MosaicSize) {
mosaicCounter = 0;
}
colorIndex = _mosaicColor[layerIndex];
priority = _mosaicPriority[layerIndex];
}
@ -1729,7 +1723,7 @@ uint8_t Ppu::Read(uint16_t addr)
if(_regs->GetIoPortOutput() & 0x80) {
_locationLatched = false;
//"The high/low selector is reset to <EFBFBD>elow<EFBFBD>f when $213F is read" (the selector is NOT reset when the counter is latched)
//"The high/low selector is reset to ?elow?f when $213F is read" (the selector is NOT reset when the counter is latched)
_horizontalLocToggle = false;
_verticalLocationToggle = false;
}
@ -1838,7 +1832,7 @@ void Ppu::Write(uint32_t addr, uint8_t value)
_state.MosaicSize = ((value & 0xF0) >> 4) + 1;
uint8_t mosaicEnabled = value & 0x0F;
if(!_state.MosaicEnabled && mosaicEnabled) {
//"If this register is set during the frame, the <EFBFBD>starting scanline is the current scanline, otherwise it is the first visible scanline of the frame."
//"If this register is set during the frame, the ?starting scanline is the current scanline, otherwise it is the first visible scanline of the frame."
//This is only done when mosaic is turned on from an off state (FF6 mosaic effect looks wrong otherwise)
//FF6's mosaic effect is broken on some screens without this.
_mosaicScanlineCounter = _state.MosaicSize + 1;
@ -2323,4 +2317,4 @@ void Ppu::RenderTilemapMode7()
} else {
RenderTilemapMode7<layerIndex, normalPriority, highPriority, applyMosaic, false>();
}
}
}

View file

@ -42,8 +42,9 @@ struct SpriteInfo
return false;
}
uint8_t endY = (Y + (interlace ? (Height >> 1) : Height)) & 0xFF;
return (scanline >= Y && scanline < endY) || (endY < Y && scanline < endY);
uint16_t endY = (Y + (interlace ? (Height >> 1) : Height));
uint8_t endY_8 = endY & 0xFF;
return (scanline >= Y && scanline < endY) || (endY_8 < Y && scanline < endY_8);
}
};

View file

@ -863,4 +863,9 @@ void Sa1::Serialize(Serializer &s)
UpdateSaveRamMappings();
ProcessInterrupts();
}
}
}
void Sa1::SetReg(CpuRegister reg, uint16_t value)
{
_cpu->SetReg(reg, value);
}

View file

@ -95,4 +95,6 @@ public:
MemoryMappings* GetMemoryMappings();
void LoadBattery() override;
void SaveBattery() override;
void SetReg(CpuRegister reg, uint16_t value);
};

View file

@ -142,4 +142,46 @@ uint16_t Sa1Cpu::GetResetVector()
void Sa1Cpu::IncreaseCycleCount(uint64_t cycleCount)
{
_state.CycleCount += cycleCount;
}
}
void Sa1Cpu::SetReg(CpuRegister reg, uint16_t value)
{
switch (reg) {
case CpuRegister::CpuRegA:
{
_state.A = value;
} break;
case CpuRegister::CpuRegX:
{
_state.X = value;
} break;
case CpuRegister::CpuRegY:
{
_state.Y = value;
} break;
case CpuRegister::CpuRegSP:
{
_state.SP = value;
} break;
case CpuRegister::CpuRegD:
{
_state.D = value;
} break;
case CpuRegister::CpuRegPC:
{
_state.PC = value;
} break;
case CpuRegister::CpuRegK:
{
_state.K = value & 0xFF;
} break;
case CpuRegister::CpuRegDBR:
{
_state.DBR = value & 0xFF;
} break;
case CpuRegister::CpuRegPS:
{
_state.PS = value & 0xFF;
} break;
}
}

View file

@ -1,6 +1,7 @@
#pragma once
#include "stdafx.h"
#include "CpuTypes.h"
#include "DebugTypes.h"
#include "../Utilities/ISerializable.h"
class Sa1;
@ -333,6 +334,8 @@ public:
// Inherited via ISerializable
void Serialize(Serializer &s) override;
void SetReg(CpuRegister reg, uint16_t value);
};
template<uint64_t count>

View file

@ -157,7 +157,8 @@ enum class ControllerType
SnesController = 1,
SnesMouse = 2,
SuperScope = 3,
Multitap = 4
Multitap = 4,
SnesMouseButtonsOnly = 5
};
struct KeyMapping

View file

@ -582,4 +582,35 @@ void Spc::LoadSpcFile(SpcFileData* data)
_state.Timer0.SetOutput(data->TimerOutput[0]);
_state.Timer1.SetOutput(data->TimerOutput[0]);
_state.Timer2.SetOutput(data->TimerOutput[0]);
}
}
void Spc::SetReg(SpcRegister reg, uint16_t value)
{
switch (reg)
{
case SpcRegister::SpcRegPC:
{
_state.PC = value;
} break;
case SpcRegister::SpcRegA:
{
_state.A = value & 0xFF;
} break;
case SpcRegister::SpcRegX:
{
_state.X = value & 0xFF;
} break;
case SpcRegister::SpcRegY:
{
_state.Y = value & 0xFF;
} break;
case SpcRegister::SpcRegSP:
{
_state.SP = value & 0xFF;
} break;
case SpcRegister::SpcRegPS:
{
_state.PS = value & 0xFF;
} break;
}
}

View file

@ -8,6 +8,7 @@
#include "stdafx.h"
#include "SpcTypes.h"
#include "CpuTypes.h"
#include "DebugTypes.h"
#include "SpcTimer.h"
#include "../Utilities/ISerializable.h"
@ -317,6 +318,8 @@ public:
void Serialize(Serializer &s) override;
void SetReg(SpcRegister reg, uint16_t value);
#ifdef DUMMYSPC
private:
uint32_t _writeCounter = 0;

View file

@ -61,13 +61,25 @@ extern "C"
DllExport const char* GetExecutionTrace(uint32_t lineCount) { return GetDebugger()->GetTraceLogger()->GetExecutionTrace(lineCount); }
DllExport void __stdcall SetBreakpoints(Breakpoint breakpoints[], uint32_t length) { GetDebugger()->SetBreakpoints(breakpoints, length); }
DllExport void __stdcall GetBreakpoints(CpuType cpuType, Breakpoint* breakpoints, int& execs, int& reads, int& writes) { GetDebugger()->GetBreakpoints(cpuType, breakpoints, execs, reads, writes); }
DllExport int32_t __stdcall EvaluateExpression(char* expression, CpuType cpuType, EvalResultType *resultType, bool useCache) { return GetDebugger()->EvaluateExpression(expression, cpuType, *resultType, useCache); }
DllExport void __stdcall GetCallstack(CpuType cpuType, StackFrameInfo *callstackArray, uint32_t &callstackSize) { GetDebugger()->GetCallstackManager(cpuType)->GetCallstack(callstackArray, callstackSize); }
DllExport void __stdcall GetProfilerData(CpuType cpuType, ProfiledFunction* profilerData, uint32_t& functionCount) { GetDebugger()->GetCallstackManager(cpuType)->GetProfiler()->GetProfilerData(profilerData, functionCount); }
DllExport void __stdcall ResetProfiler(CpuType cpuType) { GetDebugger()->GetCallstackManager(cpuType)->GetProfiler()->Reset(); }
DllExport void __stdcall GetState(DebugState& state) { GetDebugger()->GetState(state, false); }
DllExport bool __stdcall GetCpuProcFlag(ProcFlags::ProcFlags flag) { return GetDebugger()->GetCpuProcFlag(flag); }
DllExport void __stdcall SetCpuRegister(CpuRegister reg, uint16_t value) { GetDebugger()->SetCpuRegister(reg, value); }
DllExport void __stdcall SetCpuProcFlag(ProcFlags::ProcFlags flag, bool set) { GetDebugger()->SetCpuProcFlag(flag, set); };
DllExport void __stdcall SetSpcRegister(SpcRegister reg, uint16_t value) { GetDebugger()->SetSpcRegister(reg, value); }
DllExport void __stdcall SetNecDspRegister(NecDspRegister reg, uint16_t value) { GetDebugger()->SetNecDspRegister(reg, value); }
DllExport void __stdcall SetSa1Register(CpuRegister reg, uint16_t value) { GetDebugger()->SetSa1Register(reg, value); }
DllExport void __stdcall SetGsuRegister(GsuRegister reg, uint16_t value) { GetDebugger()->SetGsuRegister(reg, value); }
DllExport void __stdcall SetCx4Register(Cx4Register reg, uint32_t value) { GetDebugger()->SetCx4Register(reg, value); }
DllExport void __stdcall SetGameboyRegister(GbRegister reg, uint16_t value) { GetDebugger()->SetGameboyRegister(reg, value); }
DllExport const char* __stdcall GetDebuggerLog()
{
_logString = GetDebugger()->GetLog();

View file

@ -237,7 +237,7 @@
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>dinput8.lib;Xinput9_1_0.lib;d3d11.lib;d3dcompiler.lib;dxguid.lib;winmm.lib;comctl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;</AdditionalDependencies>
<AdditionalDependencies>Core.lib;Utilities.lib;Windows.lib;SevenZip.lib;Lua.lib;ws2_32.lib;DirectXTK.$(Configuration).Static.x86.lib;dinput8.lib;Xinput9_1_0.lib;d3d11.lib;d3dcompiler.lib;dxguid.lib;winmm.lib;comctl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib</AdditionalDependencies>
<AdditionalLibraryDirectories>$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalOptions>/ignore:4099 %(AdditionalOptions)</AdditionalOptions>
</Link>
@ -258,8 +258,8 @@
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>dinput8.lib;Xinput9_1_0.lib;d3d11.lib;d3dcompiler.lib;dxguid.lib;winmm.lib;comctl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;</AdditionalDependencies>
<AdditionalLibraryDirectories>$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>Core.lib;Utilities.lib;Windows.lib;SevenZip.lib;Lua.lib;ws2_32.lib;DirectXTK.$(Configuration).Static.x64.lib;dinput8.lib;Xinput9_1_0.lib;d3d11.lib;d3dcompiler.lib;dxguid.lib;winmm.lib;comctl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib</AdditionalDependencies>
<AdditionalLibraryDirectories>$(OutDir);$(SolutionDir)\Dependencies\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalOptions>/ignore:4099 %(AdditionalOptions)</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
@ -282,7 +282,7 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>dinput8.lib;Xinput9_1_0.lib;d3d11.lib;d3dcompiler.lib;dxguid.lib;winmm.lib;comctl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;</AdditionalDependencies>
<AdditionalDependencies>Core.lib;Utilities.lib;Windows.lib;SevenZip.lib;Lua.lib;ws2_32.lib;DirectXTK.$(Configuration).Static.x86.lib;dinput8.lib;Xinput9_1_0.lib;d3d11.lib;d3dcompiler.lib;dxguid.lib;winmm.lib;comctl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib</AdditionalDependencies>
<AdditionalLibraryDirectories>$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalOptions>/ignore:4099 %(AdditionalOptions)</AdditionalOptions>
</Link>
@ -306,7 +306,7 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>dinput8.lib;Xinput9_1_0.lib;d3d11.lib;d3dcompiler.lib;dxguid.lib;winmm.lib;comctl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;</AdditionalDependencies>
<AdditionalDependencies>Core.lib;Utilities.lib;Windows.lib;SevenZip.lib;Lua.lib;ws2_32.lib;DirectXTK.$(Configuration).Static.x86.lib;dinput8.lib;Xinput9_1_0.lib;d3d11.lib;d3dcompiler.lib;dxguid.lib;winmm.lib;comctl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib</AdditionalDependencies>
<AdditionalLibraryDirectories>$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalOptions>/ignore:4099 %(AdditionalOptions)</AdditionalOptions>
</Link>
@ -330,7 +330,7 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>dinput8.lib;Xinput9_1_0.lib;d3d11.lib;d3dcompiler.lib;dxguid.lib;winmm.lib;comctl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;</AdditionalDependencies>
<AdditionalDependencies>Core.lib;Utilities.lib;Windows.lib;SevenZip.lib;Lua.lib;ws2_32.lib;DirectXTK.$(Configuration).Static.x86.lib;dinput8.lib;Xinput9_1_0.lib;d3d11.lib;d3dcompiler.lib;dxguid.lib;winmm.lib;comctl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib</AdditionalDependencies>
<LinkTimeCodeGeneration>PGInstrument</LinkTimeCodeGeneration>
<AdditionalLibraryDirectories>$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalOptions>/ignore:4099 %(AdditionalOptions)</AdditionalOptions>
@ -354,7 +354,7 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>dinput8.lib;Xinput9_1_0.lib;d3d11.lib;d3dcompiler.lib;dxguid.lib;winmm.lib;comctl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;</AdditionalDependencies>
<AdditionalDependencies>Core.lib;Utilities.lib;Windows.lib;SevenZip.lib;Lua.lib;ws2_32.lib;DirectXTK.$(Configuration).Static.x86.lib;dinput8.lib;Xinput9_1_0.lib;d3d11.lib;d3dcompiler.lib;dxguid.lib;winmm.lib;comctl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib</AdditionalDependencies>
<LinkTimeCodeGeneration>PGOptimization</LinkTimeCodeGeneration>
<AdditionalLibraryDirectories>$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalOptions>/ignore:4099 %(AdditionalOptions)</AdditionalOptions>
@ -379,8 +379,8 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>dinput8.lib;Xinput9_1_0.lib;d3d11.lib;d3dcompiler.lib;dxguid.lib;winmm.lib;comctl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;</AdditionalDependencies>
<AdditionalLibraryDirectories>$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>Core.lib;Utilities.lib;Windows.lib;SevenZip.lib;Lua.lib;ws2_32.lib;DirectXTK.$(Configuration).Static.x64.lib;dinput8.lib;Xinput9_1_0.lib;d3d11.lib;d3dcompiler.lib;dxguid.lib;winmm.lib;comctl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib</AdditionalDependencies>
<AdditionalLibraryDirectories>$(OutDir);$(SolutionDir)\Dependencies\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalOptions>/ignore:4099 %(AdditionalOptions)</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
@ -403,8 +403,8 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>dinput8.lib;Xinput9_1_0.lib;d3d11.lib;d3dcompiler.lib;dxguid.lib;winmm.lib;comctl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;</AdditionalDependencies>
<AdditionalLibraryDirectories>$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>Core.lib;Utilities.lib;Windows.lib;SevenZip.lib;Lua.lib;ws2_32.lib;DirectXTK.$(Configuration).Static.x64.lib;dinput8.lib;Xinput9_1_0.lib;d3d11.lib;d3dcompiler.lib;dxguid.lib;winmm.lib;comctl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib</AdditionalDependencies>
<AdditionalLibraryDirectories>$(OutDir);$(SolutionDir)\Dependencies\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalOptions>/ignore:4099 %(AdditionalOptions)</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
@ -427,9 +427,9 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>dinput8.lib;Xinput9_1_0.lib;d3d11.lib;d3dcompiler.lib;dxguid.lib;winmm.lib;comctl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;</AdditionalDependencies>
<AdditionalDependencies>Core.lib;Utilities.lib;Windows.lib;SevenZip.lib;Lua.lib;ws2_32.lib;DirectXTK.$(Configuration).Static.x64.lib;dinput8.lib;Xinput9_1_0.lib;d3d11.lib;d3dcompiler.lib;dxguid.lib;winmm.lib;comctl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib</AdditionalDependencies>
<LinkTimeCodeGeneration>PGInstrument</LinkTimeCodeGeneration>
<AdditionalLibraryDirectories>$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalLibraryDirectories>$(OutDir);$(SolutionDir)\Dependencies\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalOptions>/ignore:4099 %(AdditionalOptions)</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
@ -451,9 +451,9 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>dinput8.lib;Xinput9_1_0.lib;d3d11.lib;d3dcompiler.lib;dxguid.lib;winmm.lib;comctl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;</AdditionalDependencies>
<AdditionalDependencies>Core.lib;Utilities.lib;Windows.lib;SevenZip.lib;Lua.lib;ws2_32.lib;DirectXTK.$(Configuration).Static.x64.lib;dinput8.lib;Xinput9_1_0.lib;d3d11.lib;d3dcompiler.lib;dxguid.lib;winmm.lib;comctl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib</AdditionalDependencies>
<LinkTimeCodeGeneration>PGOptimization</LinkTimeCodeGeneration>
<AdditionalLibraryDirectories>$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalLibraryDirectories>$(OutDir);$(SolutionDir)\Dependencies\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalOptions>/ignore:4099 %(AdditionalOptions)</AdditionalOptions>
</Link>
</ItemDefinitionGroup>

View file

@ -34,13 +34,13 @@
#endif
#if _WIN32 || _WIN64
#pragma comment(lib, "Core.lib")
#pragma comment(lib, "Utilities.lib")
#pragma comment(lib, "Windows.lib")
#pragma comment(lib, "SevenZip.lib")
#pragma comment(lib, "Lua.lib")
#pragma comment(lib, "ws2_32.lib") //Winsock Library
#pragma comment(lib, "../Dependencies/DirectXTK." MESEN_LIBRARY_DEBUG_SUFFIX ".Static." MESEN_LIBRARY_SUFFIX)
//#pragma comment(lib, "Core.lib")
//#pragma comment(lib, "Utilities.lib")
//#pragma comment(lib, "Windows.lib")
//#pragma comment(lib, "SevenZip.lib")
//#pragma comment(lib, "Lua.lib")
//#pragma comment(lib, "ws2_32.lib") //Winsock Library
//#pragma comment(lib, "../Dependencies/DirectXTK." MESEN_LIBRARY_DEBUG_SUFFIX ".Static." MESEN_LIBRARY_SUFFIX)
#define DllExport __declspec(dllexport)
#else
#define __stdcall

View file

@ -1,25 +1,27 @@
# Mesen-S
Mesen-S is a cross-platform SNES emulator for Windows & Linux built in C++ and C#.
Mesen-S is a cross-platform SNES emulator for Windows & Linux built in C++ and C#.
If you want to support this project, please consider making a donation:
[![Donate](https://www.mesen.ca/images/donate.png)](https://www.mesen.ca/Donate.php)
## Development Builds
Development builds of the latest commit are available from Appveyor. For release builds, see the **Releases** tab on GitHub.
Development builds of the latest commit are available from GitHub Actions. For release builds, see the **Releases** tab on GitHub.
**Warning:** These are development builds and may be ***unstable***. Using them may also increase the chances of your settings being corrupted, or having issues when upgrading to the next official release. Additionally, these builds are currently not optimized via PGO and will typically run a bit slower than the official release builds.
Windows: [![Build status](https://ci.appveyor.com/api/projects/status/cjk97u1yvwnae83x/branch/master?svg=true)](https://ci.appveyor.com/project/Sour/mesen-s/build/artifacts)
Follow either of these, select the top-most entry in the list, and then click the link under "Artifacts" near the bottom.
Linux: [![Build status](https://ci.appveyor.com/api/projects/status/arkaatgy94f23ll3/branch/master?svg=true)](https://ci.appveyor.com/project/Sour/mesen-s-hayo4/build/artifacts)
Windows: [![Build status](https://github.com/NovaSquirrel/Mesen-S/actions/workflows/win-build.yml/badge.svg)](https://github.com/NovaSquirrel/Mesen-S/actions/workflows/win-build.yml)
Linux: [![Build status](https://github.com/NovaSquirrel/Mesen-S/actions/workflows/linux-build.yml/badge.svg)](https://github.com/NovaSquirrel/Mesen-S/actions/workflows/linux-build.yml)
## Releases
### Windows / Ubuntu
The latest version is available from the [releases tab on GitHub](https://github.com/SourMesen/Mesen-S/releases).
The latest version is available from the [releases tab on GitHub](https://github.com/SourMesen/Mesen-S/releases).
### Arch Linux

View file

@ -32,6 +32,7 @@ namespace Mesen.GUI.Config
public bool NeedInputReinit2 = true;
public DefaultKeyMappingType DefaultKeyMappings = DefaultKeyMappingType.Xbox | DefaultKeyMappingType.ArrowKeys;
public HistoryViewerConfig HistoryViewer;
public WatchWindowConfig WatchWindow;
public Configuration()
{
@ -48,6 +49,7 @@ namespace Mesen.GUI.Config
Cheats = new CheatWindowConfig();
Netplay = new NetplayConfig();
HistoryViewer = new HistoryViewerConfig();
WatchWindow = new WatchWindowConfig();
}
~Configuration()

View file

@ -132,7 +132,8 @@ namespace Mesen.GUI.Config
SnesController = 1,
SnesMouse = 2,
SuperScope = 3,
Multitap = 4
Multitap = 4,
SnesMouseButtonsOnly = 5
}
public enum InputDisplayPosition

View file

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Mesen.GUI.Config
{
public class WatchWindowConfig
{
public Size WindowSize;
public Point WindowLocation;
}
}

View file

@ -201,10 +201,9 @@ namespace Mesen.GUI.Debugger
return false;
}
public InteropBreakpoint ToInteropBreakpoint(int breakpointId)
public InteropBreakpoint ToInteropBreakpoint()
{
InteropBreakpoint bp = new InteropBreakpoint() {
Id = breakpointId,
CpuType = CpuType,
MemoryType = MemoryType,
Type = Type,

View file

@ -127,14 +127,14 @@ namespace Mesen.GUI.Debugger
ReadOnlyCollection<Breakpoint> userBreakpoints = BreakpointManager.Breakpoints;
for(int i = 0; i < userBreakpoints.Count; i++) {
if(_activeCpuTypes.Contains(userBreakpoints[i].CpuType)) {
breakpoints.Add(userBreakpoints[i].ToInteropBreakpoint(breakpoints.Count));
breakpoints.Add(userBreakpoints[i].ToInteropBreakpoint());
}
}
List<Breakpoint> assertBreakpoints = BreakpointManager.Asserts;
for(int i = 0; i < assertBreakpoints.Count; i++) {
if(_activeCpuTypes.Contains(assertBreakpoints[i].CpuType)) {
breakpoints.Add(assertBreakpoints[i].ToInteropBreakpoint(breakpoints.Count));
breakpoints.Add(assertBreakpoints[i].ToInteropBreakpoint());
}
}

View file

@ -5,7 +5,6 @@ namespace Mesen.GUI.Debugger
{
public struct InteropBreakpoint
{
public Int32 Id;
public CpuType CpuType;
public SnesMemoryType MemoryType;
public BreakpointTypeFlags Type;

View file

@ -144,6 +144,8 @@ namespace Mesen.GUI.Debugger
"Note: Use the $ prefix to denote hexadecimal values." + Environment.NewLine + Environment.NewLine +
//"Note 2: Labels assigned to the code can be used (their value will match the label's address in CPU memory)." + Environment.NewLine + Environment.NewLine +
"A/X/Y/PS/SP: Value of registers" + Environment.NewLine +
"PsCarry/PsZero/PsInterrupt/PsDecimal/PsOverflow/PsNegative: Processor flags" + Environment.NewLine +
"Ps8bit/Ps16bit/Ps8bitIndex/Ps16bitIndex: Register sizes" + Environment.NewLine +
"PC: Program Counter" + Environment.NewLine +
"OpPC: Address of the current instruction's first byte" + Environment.NewLine +
"PreviousOpPC: Address of the previous instruction's first byte" + Environment.NewLine +

View file

@ -30,6 +30,7 @@ namespace Mesen.GUI.Config
public ProfilerConfig Profiler = new ProfilerConfig();
public AssemblerConfig Assembler = new AssemblerConfig();
public DebugLogConfig DebugLog = new DebugLogConfig();
public WatchWindowConfig WatchWindow = new WatchWindowConfig();
public DebugInfo()
{

View file

@ -97,6 +97,8 @@ namespace Mesen.GUI.Config
public XmlKeys OpenRegisterViewer = Keys.Control | Keys.K;
[ShortcutName("Open Debug Log")]
public XmlKeys OpenDebugLog = Keys.Control | Keys.B;
[ShortcutName("Open Watch Window")]
public XmlKeys OpenWatchWindow = Keys.Control | Keys.W;
[ShortcutName("Open Tilemap Viewer")]
public XmlKeys OpenTilemapViewer = Keys.Control | Keys.D1;

View file

@ -9,6 +9,7 @@ using System.Threading.Tasks;
using System.Windows.Forms;
using Mesen.GUI.Controls;
using Mesen.GUI.Forms;
using System.Globalization;
namespace Mesen.GUI.Debugger.Controls
{
@ -25,15 +26,24 @@ namespace Mesen.GUI.Debugger.Controls
}
_cpuBinder.Entity = new CpuState();
_cpuBinder.AddBinding(nameof(CpuState.A), txtA);
_cpuBinder.AddBinding(nameof(CpuState.X), txtX);
_cpuBinder.AddBinding(nameof(CpuState.Y), txtY);
_cpuBinder.AddBinding(nameof(CpuState.D), txtD);
_cpuBinder.AddBinding(nameof(CpuState.DBR), txtDB);
_cpuBinder.AddBinding(nameof(CpuState.SP), txtS);
_cpuBinder.AddBinding(nameof(CpuState.PS), txtP);
_cpuBinder.AddBinding(nameof(CpuState.A), txtA, onEditHandler: (s, e) => { DebugApi.SetCpuRegister(CpuRegister.CpuRegA, UInt16.Parse(txtA.Text, NumberStyles.HexNumber)); });
_cpuBinder.AddBinding(nameof(CpuState.X), txtX, onEditHandler: (s, e) => { DebugApi.SetCpuRegister(CpuRegister.CpuRegX, UInt16.Parse(txtX.Text, NumberStyles.HexNumber)); });
_cpuBinder.AddBinding(nameof(CpuState.Y), txtY, onEditHandler: (s, e) => { DebugApi.SetCpuRegister(CpuRegister.CpuRegY, UInt16.Parse(txtY.Text, NumberStyles.HexNumber)); });
_cpuBinder.AddBinding(nameof(CpuState.D), txtD, onEditHandler: (s, e) => { DebugApi.SetCpuRegister(CpuRegister.CpuRegD, UInt16.Parse(txtD.Text, NumberStyles.HexNumber)); });
_cpuBinder.AddBinding(nameof(CpuState.DBR), txtDB, onEditHandler: (s, e) => { DebugApi.SetCpuRegister(CpuRegister.CpuRegDBR, UInt16.Parse(txtDB.Text, NumberStyles.HexNumber)); });
_cpuBinder.AddBinding(nameof(CpuState.SP), txtS, onEditHandler: (s, e) => { DebugApi.SetCpuRegister(CpuRegister.CpuRegSP, UInt16.Parse(txtS.Text, NumberStyles.HexNumber)); });
_cpuBinder.AddBinding(nameof(CpuState.PS), txtP, onEditHandler: (s, e) => { DebugApi.SetCpuRegister(CpuRegister.CpuRegPS, UInt16.Parse(txtP.Text, NumberStyles.HexNumber)); });
_cpuBinder.AddBinding(nameof(CpuState.NmiFlag), chkNmi);
_cpuBinder.AddBinding(nameof(CpuState.NmiFlag), chkNmi, onEditHandler: (s, e) => { DebugApi.SetCpuRegister(CpuRegister.CpuFlagNmi, (UInt16)(chkNmi.Checked ? 1 : 0)); });
chkIndex.CheckedChanged += (s, e) => { DebugApi.SetCpuProcFlag(ProcFlags.IndexMode8, chkIndex.Checked); };
chkCarry.CheckedChanged += (s, e) => { DebugApi.SetCpuProcFlag(ProcFlags.Carry, chkCarry.Checked); };
chkDecimal.CheckedChanged += (s, e) => { DebugApi.SetCpuProcFlag(ProcFlags.Decimal, chkDecimal.Checked); };
chkInterrupt.CheckedChanged += (s, e) => { DebugApi.SetCpuProcFlag(ProcFlags.IrqDisable, chkInterrupt.Checked); };
chkNegative.CheckedChanged += (s, e) => { DebugApi.SetCpuProcFlag(ProcFlags.Negative, chkNegative.Checked); };
chkOverflow.CheckedChanged += (s, e) => { DebugApi.SetCpuProcFlag(ProcFlags.Overflow, chkOverflow.Checked); };
chkMemory.CheckedChanged += (s, e) => { DebugApi.SetCpuProcFlag(ProcFlags.MemoryMode8, chkMemory.Checked); };
chkZero.CheckedChanged += (s, e) => { DebugApi.SetCpuProcFlag(ProcFlags.Zero, chkZero.Checked); };
}
public void UpdateStatus(CpuState state)

View file

@ -220,6 +220,10 @@ namespace Mesen.GUI.Debugger.Controls
int start = _manager.Provider.GetLineAddress(firstLineOfSelection);
int end = _manager.Provider.GetLineAddress(firstLineAfterSelection) - 1;
if (firstLineOfSelection == firstLineAfterSelection) {
end = start;
}
if(start >= 0 && end >= 0) {
return new SelectedAddressRange() {
Start = new AddressInfo() { Address = start, Type = _manager.RelativeMemoryType },

View file

@ -51,6 +51,7 @@ namespace Mesen.GUI.Debugger
case DebugWindow.GbPaletteViewer: frm = new frmPaletteViewer(CpuType.Gameboy); frm.Icon = Properties.Resources.VideoFilter; break;
case DebugWindow.GbSpriteViewer: frm = new frmSpriteViewer(CpuType.Gameboy); frm.Icon = Properties.Resources.PerfTracker; break;
case DebugWindow.GbEventViewer: frm = new frmEventViewer(CpuType.Gameboy); frm.Icon = Properties.Resources.NesEventViewer; break;
case DebugWindow.WatchWindow: frm = new frmWatchWindow(); frm.Icon = Properties.Resources.Find; break;
}
if(_openedWindows.Count == 0) {
@ -203,6 +204,7 @@ namespace Mesen.GUI.Debugger
case DebugWindow.GbEventViewer: return _openedWindows.ToList().Find((form) => form.GetType() == typeof(frmEventViewer) && ((frmEventViewer)form).CpuType == CpuType.Gameboy);
case DebugWindow.Profiler: return _openedWindows.ToList().Find((form) => form.GetType() == typeof(frmProfiler));
case DebugWindow.DebugLog: return _openedWindows.ToList().Find((form) => form.GetType() == typeof(frmDebugLog));
case DebugWindow.WatchWindow: return _openedWindows.ToList().Find((form) => form.GetType() == typeof(frmWatchWindow));
}
return null;
@ -261,6 +263,7 @@ namespace Mesen.GUI.Debugger
Profiler,
Assembler,
DebugLog,
WatchWindow,
GbTileViewer,
GbTilemapViewer,

View file

@ -27,146 +27,150 @@
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.lblViewMemoryType = new System.Windows.Forms.Label();
this.cboMemoryType = new Mesen.GUI.Debugger.Controls.ctrlMemoryType();
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
this.btnReset = new System.Windows.Forms.Button();
this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel();
this.picWatchHelp = new System.Windows.Forms.PictureBox();
this.lblHint = new System.Windows.Forms.Label();
this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel();
this.lstCounters = new Mesen.GUI.Controls.DoubleBufferedListView();
this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader9 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader6 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader3 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader7 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader4 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader8 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader5 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
this.tableLayoutPanel1.SuspendLayout();
this.tableLayoutPanel3.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.picWatchHelp)).BeginInit();
this.tableLayoutPanel2.SuspendLayout();
this.SuspendLayout();
//
// lblViewMemoryType
//
this.lblViewMemoryType.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.lblViewMemoryType.AutoSize = true;
this.lblViewMemoryType.Location = new System.Drawing.Point(3, 7);
this.lblViewMemoryType.Name = "lblViewMemoryType";
this.lblViewMemoryType.Size = new System.Drawing.Size(33, 13);
this.lblViewMemoryType.TabIndex = 0;
this.lblViewMemoryType.Text = "View:";
//
// cboMemoryType
//
this.cboMemoryType.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed;
this.cboMemoryType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cboMemoryType.FormattingEnabled = true;
this.cboMemoryType.Location = new System.Drawing.Point(42, 3);
this.cboMemoryType.Name = "cboMemoryType";
this.cboMemoryType.Size = new System.Drawing.Size(162, 21);
this.cboMemoryType.TabIndex = 1;
this.cboMemoryType.SelectedIndexChanged += new System.EventHandler(this.cboMemoryType_SelectedIndexChanged);
//
// 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.btnReset, 1, 2);
this.tableLayoutPanel1.Controls.Add(this.tableLayoutPanel3, 0, 2);
this.tableLayoutPanel1.Controls.Add(this.tableLayoutPanel2, 0, 0);
this.tableLayoutPanel1.Controls.Add(this.lstCounters, 0, 1);
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(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(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
this.tableLayoutPanel1.Size = new System.Drawing.Size(641, 343);
this.tableLayoutPanel1.TabIndex = 3;
//
// btnReset
//
this.btnReset.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btnReset.Location = new System.Drawing.Point(566, 320);
this.btnReset.Margin = new System.Windows.Forms.Padding(0);
this.btnReset.Name = "btnReset";
this.btnReset.Size = new System.Drawing.Size(75, 23);
this.btnReset.TabIndex = 5;
this.btnReset.Text = "Reset";
this.btnReset.UseVisualStyleBackColor = true;
this.btnReset.Click += new System.EventHandler(this.btnReset_Click);
//
// 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.picWatchHelp, 0, 0);
this.tableLayoutPanel3.Controls.Add(this.lblHint, 1, 0);
this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel3.Location = new System.Drawing.Point(0, 320);
this.tableLayoutPanel3.Margin = new System.Windows.Forms.Padding(0);
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.Size = new System.Drawing.Size(566, 23);
this.tableLayoutPanel3.TabIndex = 2;
//
// picWatchHelp
//
this.picWatchHelp.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.picWatchHelp.Image = global::Mesen.GUI.Properties.Resources.Warning;
this.picWatchHelp.Location = new System.Drawing.Point(3, 3);
this.picWatchHelp.Name = "picWatchHelp";
this.picWatchHelp.Size = new System.Drawing.Size(16, 16);
this.picWatchHelp.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage;
this.picWatchHelp.TabIndex = 2;
this.picWatchHelp.TabStop = false;
//
// lblHint
//
this.lblHint.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.lblHint.AutoSize = true;
this.lblHint.Location = new System.Drawing.Point(25, 4);
this.lblHint.Name = "lblHint";
this.lblHint.Size = new System.Drawing.Size(530, 13);
this.lblHint.TabIndex = 0;
this.lblHint.Text = "Uninitialized read column is only accurate if the debugger was active when the ga" +
this.components = new System.ComponentModel.Container();
this.lblViewMemoryType = new System.Windows.Forms.Label();
this.cboMemoryType = new Mesen.GUI.Debugger.Controls.ctrlMemoryType();
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
this.btnReset = new System.Windows.Forms.Button();
this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel();
this.picWatchHelp = new System.Windows.Forms.PictureBox();
this.lblHint = new System.Windows.Forms.Label();
this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel();
this.lstCounters = new Mesen.GUI.Controls.DoubleBufferedListView();
this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader9 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader6 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader3 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader7 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader4 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader8 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader5 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.toolTip = new System.Windows.Forms.ToolTip(this.components);
this.tableLayoutPanel1.SuspendLayout();
this.tableLayoutPanel3.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.picWatchHelp)).BeginInit();
this.tableLayoutPanel2.SuspendLayout();
this.SuspendLayout();
//
// lblViewMemoryType
//
this.lblViewMemoryType.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.lblViewMemoryType.AutoSize = true;
this.lblViewMemoryType.Location = new System.Drawing.Point(8, 16);
this.lblViewMemoryType.Margin = new System.Windows.Forms.Padding(8, 0, 8, 0);
this.lblViewMemoryType.Name = "lblViewMemoryType";
this.lblViewMemoryType.Size = new System.Drawing.Size(85, 32);
this.lblViewMemoryType.TabIndex = 0;
this.lblViewMemoryType.Text = "View:";
//
// cboMemoryType
//
this.cboMemoryType.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed;
this.cboMemoryType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cboMemoryType.FormattingEnabled = true;
this.cboMemoryType.Location = new System.Drawing.Point(109, 7);
this.cboMemoryType.Margin = new System.Windows.Forms.Padding(8, 7, 8, 7);
this.cboMemoryType.Name = "cboMemoryType";
this.cboMemoryType.Size = new System.Drawing.Size(425, 39);
this.cboMemoryType.TabIndex = 1;
this.cboMemoryType.SelectedIndexChanged += new System.EventHandler(this.cboMemoryType_SelectedIndexChanged);
//
// 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.btnReset, 1, 2);
this.tableLayoutPanel1.Controls.Add(this.tableLayoutPanel3, 0, 2);
this.tableLayoutPanel1.Controls.Add(this.tableLayoutPanel2, 0, 0);
this.tableLayoutPanel1.Controls.Add(this.lstCounters, 0, 1);
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(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(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 48F));
this.tableLayoutPanel1.Size = new System.Drawing.Size(1709, 818);
this.tableLayoutPanel1.TabIndex = 3;
//
// btnReset
//
this.btnReset.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btnReset.Location = new System.Drawing.Point(1509, 763);
this.btnReset.Margin = new System.Windows.Forms.Padding(0);
this.btnReset.Name = "btnReset";
this.btnReset.Size = new System.Drawing.Size(200, 55);
this.btnReset.TabIndex = 5;
this.btnReset.Text = "Reset";
this.btnReset.UseVisualStyleBackColor = true;
this.btnReset.Click += new System.EventHandler(this.btnReset_Click);
//
// 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.picWatchHelp, 0, 0);
this.tableLayoutPanel3.Controls.Add(this.lblHint, 1, 0);
this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel3.Location = new System.Drawing.Point(0, 763);
this.tableLayoutPanel3.Margin = new System.Windows.Forms.Padding(0);
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.Size = new System.Drawing.Size(1509, 55);
this.tableLayoutPanel3.TabIndex = 2;
//
// picWatchHelp
//
this.picWatchHelp.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.picWatchHelp.Image = global::Mesen.GUI.Properties.Resources.Warning;
this.picWatchHelp.Location = new System.Drawing.Point(8, 7);
this.picWatchHelp.Margin = new System.Windows.Forms.Padding(8, 7, 8, 7);
this.picWatchHelp.Name = "picWatchHelp";
this.picWatchHelp.Size = new System.Drawing.Size(43, 38);
this.picWatchHelp.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage;
this.picWatchHelp.TabIndex = 2;
this.picWatchHelp.TabStop = false;
//
// lblHint
//
this.lblHint.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.lblHint.AutoSize = true;
this.lblHint.Location = new System.Drawing.Point(67, 10);
this.lblHint.Margin = new System.Windows.Forms.Padding(8, 0, 8, 0);
this.lblHint.Name = "lblHint";
this.lblHint.Size = new System.Drawing.Size(1399, 32);
this.lblHint.TabIndex = 0;
this.lblHint.Text = "Uninitialized read column is only accurate if the debugger was active when the ga" +
"me was loaded/power cycled";
this.lblHint.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//
// tableLayoutPanel2
//
this.tableLayoutPanel2.ColumnCount = 2;
this.tableLayoutPanel1.SetColumnSpan(this.tableLayoutPanel2, 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.cboMemoryType, 1, 0);
this.tableLayoutPanel2.Controls.Add(this.lblViewMemoryType, 0, 0);
this.tableLayoutPanel2.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel2.Location = new System.Drawing.Point(0, 0);
this.tableLayoutPanel2.Margin = new System.Windows.Forms.Padding(0);
this.tableLayoutPanel2.Name = "tableLayoutPanel2";
this.tableLayoutPanel2.RowCount = 1;
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel2.Size = new System.Drawing.Size(641, 27);
this.tableLayoutPanel2.TabIndex = 6;
//
// lstCounters
//
this.lstCounters.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.lblHint.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//
// tableLayoutPanel2
//
this.tableLayoutPanel2.ColumnCount = 2;
this.tableLayoutPanel1.SetColumnSpan(this.tableLayoutPanel2, 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.cboMemoryType, 1, 0);
this.tableLayoutPanel2.Controls.Add(this.lblViewMemoryType, 0, 0);
this.tableLayoutPanel2.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel2.Location = new System.Drawing.Point(0, 0);
this.tableLayoutPanel2.Margin = new System.Windows.Forms.Padding(0);
this.tableLayoutPanel2.Name = "tableLayoutPanel2";
this.tableLayoutPanel2.RowCount = 1;
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel2.Size = new System.Drawing.Size(1709, 64);
this.tableLayoutPanel2.TabIndex = 6;
//
// lstCounters
//
this.lstCounters.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.columnHeader1,
this.columnHeader9,
this.columnHeader2,
@ -176,86 +180,89 @@
this.columnHeader4,
this.columnHeader8,
this.columnHeader5});
this.tableLayoutPanel1.SetColumnSpan(this.lstCounters, 2);
this.lstCounters.Dock = System.Windows.Forms.DockStyle.Fill;
this.lstCounters.FullRowSelect = true;
this.lstCounters.Location = new System.Drawing.Point(0, 27);
this.lstCounters.Margin = new System.Windows.Forms.Padding(0);
this.lstCounters.Name = "lstCounters";
this.lstCounters.Size = new System.Drawing.Size(641, 293);
this.lstCounters.TabIndex = 7;
this.lstCounters.UseCompatibleStateImageBehavior = false;
this.lstCounters.View = System.Windows.Forms.View.Details;
this.lstCounters.VirtualMode = true;
this.lstCounters.ColumnClick += new System.Windows.Forms.ColumnClickEventHandler(this.lstCounters_ColumnClick);
this.lstCounters.RetrieveVirtualItem += new System.Windows.Forms.RetrieveVirtualItemEventHandler(this.lstCounters_RetrieveVirtualItem);
//
// columnHeader1
//
this.columnHeader1.Text = "Address";
//
// columnHeader9
//
this.columnHeader9.Text = "Value";
this.columnHeader9.Width = 40;
//
// columnHeader2
//
this.columnHeader2.Text = "Reads";
this.columnHeader2.Width = 70;
//
// columnHeader6
//
this.columnHeader6.Text = "Last Read";
this.columnHeader6.Width = 70;
//
// columnHeader3
//
this.columnHeader3.Text = "Writes";
this.columnHeader3.Width = 70;
//
// columnHeader7
//
this.columnHeader7.Text = "Last Write";
this.columnHeader7.Width = 70;
//
// columnHeader4
//
this.columnHeader4.Text = "Executes";
this.columnHeader4.Width = 70;
//
// columnHeader8
//
this.columnHeader8.Text = "Last Exec";
this.columnHeader8.Width = 70;
//
// columnHeader5
//
this.columnHeader5.Text = "Uninit Read";
this.columnHeader5.Width = 70;
//
// toolTip
//
this.toolTip.AutomaticDelay = 0;
this.toolTip.AutoPopDelay = 32700;
this.toolTip.InitialDelay = 10;
this.toolTip.ReshowDelay = 10;
//
// ctrlMemoryAccessCounters
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.tableLayoutPanel1);
this.Margin = new System.Windows.Forms.Padding(0);
this.Name = "ctrlMemoryAccessCounters";
this.Size = new System.Drawing.Size(641, 343);
this.tableLayoutPanel1.ResumeLayout(false);
this.tableLayoutPanel3.ResumeLayout(false);
this.tableLayoutPanel3.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.picWatchHelp)).EndInit();
this.tableLayoutPanel2.ResumeLayout(false);
this.tableLayoutPanel2.PerformLayout();
this.ResumeLayout(false);
this.tableLayoutPanel1.SetColumnSpan(this.lstCounters, 2);
this.lstCounters.Dock = System.Windows.Forms.DockStyle.Fill;
this.lstCounters.FullRowSelect = true;
this.lstCounters.HideSelection = false;
this.lstCounters.Location = new System.Drawing.Point(0, 64);
this.lstCounters.Margin = new System.Windows.Forms.Padding(0);
this.lstCounters.Name = "lstCounters";
this.lstCounters.Size = new System.Drawing.Size(1709, 699);
this.lstCounters.TabIndex = 7;
this.lstCounters.UseCompatibleStateImageBehavior = false;
this.lstCounters.View = System.Windows.Forms.View.Details;
this.lstCounters.VirtualMode = true;
this.lstCounters.ColumnClick += new System.Windows.Forms.ColumnClickEventHandler(this.lstCounters_ColumnClick);
this.lstCounters.RetrieveVirtualItem += new System.Windows.Forms.RetrieveVirtualItemEventHandler(this.lstCounters_RetrieveVirtualItem);
this.lstCounters.SelectedIndexChanged += new System.EventHandler(this.lstCounters_SelectedIndexChanged);
//
// columnHeader1
//
this.columnHeader1.Text = "Address";
this.columnHeader1.Width = 120;
//
// columnHeader9
//
this.columnHeader9.Text = "Value";
this.columnHeader9.Width = 120;
//
// columnHeader2
//
this.columnHeader2.Text = "Reads";
this.columnHeader2.Width = 140;
//
// columnHeader6
//
this.columnHeader6.Text = "Last Read";
this.columnHeader6.Width = 140;
//
// columnHeader3
//
this.columnHeader3.Text = "Writes";
this.columnHeader3.Width = 140;
//
// columnHeader7
//
this.columnHeader7.Text = "Last Write";
this.columnHeader7.Width = 140;
//
// columnHeader4
//
this.columnHeader4.Text = "Executes";
this.columnHeader4.Width = 140;
//
// columnHeader8
//
this.columnHeader8.Text = "Last Exec";
this.columnHeader8.Width = 140;
//
// columnHeader5
//
this.columnHeader5.Text = "Uninit Read";
this.columnHeader5.Width = 160;
//
// toolTip
//
this.toolTip.AutomaticDelay = 0;
this.toolTip.AutoPopDelay = 32700;
this.toolTip.InitialDelay = 10;
this.toolTip.ReshowDelay = 10;
//
// ctrlMemoryAccessCounters
//
this.AutoScaleDimensions = new System.Drawing.SizeF(16F, 31F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.tableLayoutPanel1);
this.Margin = new System.Windows.Forms.Padding(0);
this.Name = "ctrlMemoryAccessCounters";
this.Size = new System.Drawing.Size(1709, 818);
this.tableLayoutPanel1.ResumeLayout(false);
this.tableLayoutPanel3.ResumeLayout(false);
this.tableLayoutPanel3.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.picWatchHelp)).EndInit();
this.tableLayoutPanel2.ResumeLayout(false);
this.tableLayoutPanel2.PerformLayout();
this.ResumeLayout(false);
}

View file

@ -186,5 +186,10 @@ namespace Mesen.GUI.Debugger.Controls
ExecStamp,
UninitRead,
}
}
private void lstCounters_SelectedIndexChanged(object sender, EventArgs e)
{
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -121,6 +121,6 @@
<value>17, 17</value>
</metadata>
<metadata name="menuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>107, 17</value>
<value>195, 17</value>
</metadata>
</root>

74
UI/Debugger/frmWatchWindow.Designer.cs generated Normal file
View file

@ -0,0 +1,74 @@
namespace Mesen.GUI.Debugger
{
partial class frmWatchWindow
{
/// <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.ctrlWatch = new Mesen.GUI.Debugger.ctrlWatch();
this.picWatchHelp = new System.Windows.Forms.PictureBox();
((System.ComponentModel.ISupportInitialize)(this.picWatchHelp)).BeginInit();
this.SuspendLayout();
//
// ctrlWatch
//
this.ctrlWatch.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlWatch.Location = new System.Drawing.Point(0, 0);
this.ctrlWatch.Name = "ctrlWatch";
this.ctrlWatch.Size = new System.Drawing.Size(317, 322);
this.ctrlWatch.TabIndex = 0;
//
// picWatchHelp
//
this.picWatchHelp.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.picWatchHelp.Image = global::Mesen.GUI.Properties.Resources.Help;
this.picWatchHelp.Location = new System.Drawing.Point(297, 4);
this.picWatchHelp.Name = "picWatchHelp";
this.picWatchHelp.Size = new System.Drawing.Size(16, 16);
this.picWatchHelp.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage;
this.picWatchHelp.TabIndex = 2;
this.picWatchHelp.TabStop = false;
//
// frmWatchWindow
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(317, 322);
this.Controls.Add(this.picWatchHelp);
this.Controls.Add(this.ctrlWatch);
this.MinimumSize = new System.Drawing.Size(248, 137);
this.Name = "frmWatchWindow";
this.Text = "Watch Window";
((System.ComponentModel.ISupportInitialize)(this.picWatchHelp)).EndInit();
this.ResumeLayout(false);
}
#endregion
private ctrlWatch ctrlWatch;
private System.Windows.Forms.PictureBox picWatchHelp;
}
}

View file

@ -0,0 +1,78 @@
using Mesen.GUI.Config;
using Mesen.GUI.Forms;
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.Debugger
{
public partial class frmWatchWindow : BaseForm
{
private NotificationListener _notifListener;
public frmWatchWindow()
{
InitializeComponent();
if(!DesignMode) {
this.toolTip.SetToolTip(picWatchHelp, ctrlWatch.GetTooltipText());
}
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
// Allow more CPU types later
ctrlWatch.CpuType = EmuApi.GetRomInfo().CoprocessorType == CoprocessorType.Gameboy ? CpuType.Gameboy : CpuType.Cpu;
if(!DesignMode) {
RestoreLocation(ConfigManager.Config.WatchWindow.WindowLocation, ConfigManager.Config.WatchWindow.WindowSize);
_notifListener = new NotificationListener();
_notifListener.OnNotification += _notifListener_OnNotification;
ctrlWatch.UpdateWatch(true);
}
}
protected override void OnFormClosing(FormClosingEventArgs e)
{
base.OnFormClosing(e);
ConfigManager.Config.WatchWindow.WindowSize = this.WindowState != FormWindowState.Normal ? this.RestoreBounds.Size : this.Size;
ConfigManager.Config.WatchWindow.WindowLocation = this.WindowState != FormWindowState.Normal ? this.RestoreBounds.Location : this.Location;
ConfigManager.ApplyChanges();
}
protected override void OnFormClosed(FormClosedEventArgs e)
{
base.OnFormClosed(e);
if(_notifListener != null) {
_notifListener.Dispose();
_notifListener = null;
}
}
private void _notifListener_OnNotification(NotificationEventArgs e)
{
switch(e.NotificationType) {
case ConsoleNotificationType.PpuFrameDone:
this.BeginInvoke((MethodInvoker)(() => {
ctrlWatch.UpdateWatch(false);
}));
break;
case ConsoleNotificationType.CodeBreak:
this.BeginInvoke((MethodInvoker)(() => {
ctrlWatch.UpdateWatch(false);
}));
break;
}
}
}
}

View file

@ -0,0 +1,123 @@
<?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>
</root>

View file

@ -862,6 +862,7 @@
<Value ID="SnesMouse">SNES Mouse</Value>
<Value ID="SuperScope">Super Scope</Value>
<Value ID="Multitap">Super Multitap</Value>
<Value ID="SnesMouseButtonsOnly">SNES Mouse (buttons only)</Value>
</Enum>
<Enum ID="VideoAspectRatio">
<Value ID="NoStretching">Default (No Stretching)</Value>

File diff suppressed because it is too large Load diff

View file

@ -165,6 +165,7 @@ namespace Mesen.GUI.Emulation
switch(ConfigApi.GetControllerType(i)) {
case ControllerType.SnesMouse:
return true;
// Do not allow mouse capture on SnesMouseButtonsOnly because that's the whole point of that input method
}
}
return false;

View file

@ -140,11 +140,13 @@ namespace Mesen.GUI.Forms
private void btnOK_Click(object sender, EventArgs e)
{
this.DialogResult = ((Button)sender).DialogResult;
this.Close();
}
private void btnCancel_Click(object sender, EventArgs e)
{
this.DialogResult = ((Button)sender).DialogResult;
this.Close();
}
}

View file

@ -17,6 +17,7 @@ namespace Mesen.GUI.Forms
public class EntityBinder
{
private Dictionary<string, object> _bindings = new Dictionary<string, object>();
private Dictionary<string, EventHandler> _bindedHandlers = new Dictionary<string, EventHandler>();
private Dictionary<string, eNumberFormat> _fieldFormat = new Dictionary<string, eNumberFormat>();
private Dictionary<string, FieldInfoWrapper> _fieldInfo = null;
@ -29,7 +30,7 @@ namespace Mesen.GUI.Forms
public bool Updating { get; private set; }
public void AddBinding(string fieldName, object bindedField, eNumberFormat format = eNumberFormat.Default)
public void AddBinding(string fieldName, object bindedField, eNumberFormat format = eNumberFormat.Default, EventHandler onEditHandler = null)
{
if(BindedType == null) {
throw new Exception("Need to override BindedType to use bindings");
@ -54,6 +55,43 @@ namespace Mesen.GUI.Forms
BaseConfigForm.InitializeComboBox(((ComboBox)bindedField), fieldType);
}
_bindings[fieldName] = bindedField;
_bindedHandlers[fieldName] = onEditHandler;
if(bindedField is TextBox) {
((TextBox)bindedField).Leave += onEditHandler;
} else if(bindedField is ctrlPathSelection) {
((ctrlPathSelection)bindedField).Leave += onEditHandler;
} else if(bindedField is CheckBox) {
((CheckBox)bindedField).CheckedChanged += onEditHandler;
} else if(bindedField is ToolStripMenuItem) {
((ToolStripMenuItem)bindedField).CheckedChanged += onEditHandler;
} else if(bindedField is ctrlRiskyOption) {
((ctrlRiskyOption)bindedField).Click += onEditHandler;
} else if(bindedField is RadioButton) {
((RadioButton)bindedField).CheckedChanged += onEditHandler;
} else if(bindedField is PictureBox) {
((PictureBox)bindedField).BackColorChanged += onEditHandler;
} else if(bindedField is Panel) {
FieldInfoWrapper field = _fieldInfo[fieldName];
object value = field.GetValue(this.Entity);
RadioButton radio = ((Panel)bindedField).Controls.OfType<RadioButton>().FirstOrDefault(r => r.Tag.Equals(value));
if(radio != null) {
radio.CheckedChanged += onEditHandler;
} else {
throw new Exception("No radio button matching value found");
}
} else if(bindedField is ctrlTrackbar) {
((ctrlTrackbar)bindedField).ValueChanged += onEditHandler;
} else if(bindedField is ctrlHorizontalTrackbar) {
((ctrlHorizontalTrackbar)bindedField).ValueChanged += onEditHandler;
} else if(bindedField is TrackBar) {
((TrackBar)bindedField).ValueChanged += onEditHandler;
} else if(bindedField is MesenNumericUpDown) {
((MesenNumericUpDown)bindedField).ValueChanged += onEditHandler;
} else if(bindedField is ComboBox) {
((ComboBox)bindedField).SelectedIndexChanged += onEditHandler;
}
_fieldFormat[fieldName] = format;
} else {
throw new Exception("Invalid field name");

File diff suppressed because it is too large Load diff

View file

@ -302,6 +302,7 @@ namespace Mesen.GUI.Forms
mnuProfiler.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenProfiler));
mnuAssembler.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenAssembler));
mnuDebugLog.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenDebugLog));
mnuWatchWindow.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenWatchWindow));
mnuNoneFilter.Click += (s, e) => { _shortcuts.SetVideoFilter(VideoFilterType.None); };
mnuNtscFilter.Click += (s, e) => { _shortcuts.SetVideoFilter(VideoFilterType.NTSC); };
@ -369,6 +370,7 @@ namespace Mesen.GUI.Forms
mnuProfiler.Click += (s, e) => { DebugWindowManager.OpenDebugWindow(DebugWindow.Profiler); };
mnuAssembler.Click += (s, e) => { DebugWindowManager.OpenDebugWindow(DebugWindow.Assembler); };
mnuDebugLog.Click += (s, e) => { DebugWindowManager.OpenDebugWindow(DebugWindow.DebugLog); };
mnuWatchWindow.Click += (s, e) => { DebugWindowManager.OpenDebugWindow(DebugWindow.WatchWindow); };
mnuGbTilemapViewer.Click += (s, e) => { DebugWindowManager.OpenDebugWindow(DebugWindow.GbTilemapViewer); };
mnuGbTileViewer.Click += (s, e) => { DebugWindowManager.OpenDebugWindow(DebugWindow.GbTileViewer); };
@ -486,6 +488,7 @@ namespace Mesen.GUI.Forms
mnuProfiler.Enabled = running;
mnuAssembler.Enabled = running;
mnuDebugLog.Enabled = running;
mnuWatchWindow.Enabled = running;
bool isGameboyMode = coprocessor == CoprocessorType.Gameboy;
bool isSuperGameboy = coprocessor == CoprocessorType.SGB;
@ -827,5 +830,6 @@ namespace Mesen.GUI.Forms
_historyViewerWindow.Focus();
}
}
}
}

View file

@ -121,6 +121,6 @@
<value>17, 17</value>
</metadata>
<metadata name="mnuMain.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>107, 17</value>
<value>122, 17</value>
</metadata>
</root>

View file

@ -58,6 +58,16 @@ namespace Mesen.GUI
return state;
}
[DllImport(DllPath)] public static extern void SetCpuRegister(CpuRegister reg, UInt16 value);
[DllImport(DllPath)] public static extern void SetCpuProcFlag(ProcFlags flag, [MarshalAs(UnmanagedType.I1)]bool set);
[DllImport(DllPath)] public static extern void SetSpcRegister(SpcRegister reg, UInt16 value);
[DllImport(DllPath)] public static extern void SetNecDspRegister(NecDspRegister reg, UInt16 value);
[DllImport(DllPath)] public static extern void SetSa1Register(CpuRegister reg, UInt16 value);
[DllImport(DllPath)] public static extern void SetGsuRegister(GsuRegister reg, UInt16 value);
[DllImport(DllPath)] public static extern void SetCx4Register(Cx4Register reg, UInt32 value);
[DllImport(DllPath)] public static extern void SetGameboyRegister(GbRegister reg, UInt16 value);
[DllImport(DllPath)] public static extern void SetScriptTimeout(UInt32 timeout);
[DllImport(DllPath)] public static extern Int32 LoadScript([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))]string name, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))]string content, Int32 scriptId = -1);
[DllImport(DllPath)] public static extern void RemoveScript(Int32 scriptId);
@ -79,6 +89,7 @@ namespace Mesen.GUI
[DllImport(DllPath)] public static extern void ClearLabels();
[DllImport(DllPath)] public static extern void SetBreakpoints([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)]InteropBreakpoint[] breakpoints, UInt32 length);
[DllImport(DllPath)] public static extern void GetBreakpoints(CpuType cpuType, [In, Out] Breakpoint[] breakpoints, ref Int32 execs, ref Int32 reads, ref Int32 writes);
[DllImport(DllPath)] public static extern void SaveRomToDisk([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))]string filename, [MarshalAs(UnmanagedType.I1)]bool saveAsIps, CdlStripOption cdlStripOption);

View file

@ -925,4 +925,110 @@ namespace Mesen.GUI
public InternalRegisterState InternalRegs;
public AluState Alu;
}
public enum CpuRegister : byte
{
CpuRegA,
CpuRegX,
CpuRegY,
CpuRegSP,
CpuRegD,
CpuRegPC,
CpuRegK,
CpuRegDBR,
CpuRegPS,
CpuFlagNmi,
}
public enum Cx4Register : byte
{
Cx4Reg0,
Cx4Reg1,
Cx4Reg2,
Cx4Reg3,
Cx4Reg4,
Cx4Reg5,
Cx4Reg6,
Cx4Reg7,
Cx4Reg8,
Cx4Reg9,
Cx4Reg10,
Cx4Reg11,
Cx4Reg12,
Cx4Reg13,
Cx4Reg14,
Cx4Reg15,
Cx4RegPB,
Cx4RegPC,
Cx4RegA,
Cx4RegP,
Cx4RegSP,
}
public enum GbRegister : byte
{
GbRegPC,
GbRegSP,
GbRegA,
GbRegFlags,
GbRegB,
GbRegC,
GbRegD,
GbRegE,
GbRegH,
GbRegL,
}
public enum GsuRegister : byte
{
GsuReg0,
GsuReg1,
GsuReg2,
GsuReg3,
GsuReg4,
GsuReg5,
GsuReg6,
GsuReg7,
GsuReg8,
GsuReg9,
GsuRegA,
GsuRegB,
GsuRegC,
GsuRegD,
GsuRegE,
GsuRegF,
GsuRegSFR,
}
public enum NecDspRegister : byte
{
NecDspRegA,
NecDspRegFlagsA,
NecDspRegB,
NecDspRegFlagsB,
NecDspRegTR,
NecDspRegTRB,
NecDspRegPC,
NecDspRegRP,
NecDspRegDP,
NecDspRegDR,
NecDspRegSR,
NecDspRegK,
NecDspRegL,
NecDspRegM,
NecDspRegN,
NecDspRegSerialOut,
NecDspRegSerialIn,
NecDspRegSP,
}
public enum SpcRegister : byte
{
SpcRegPC,
SpcRegA,
SpcRegX,
SpcRegY,
SpcRegSP,
SpcRegPS,
}
}

View file

@ -229,6 +229,7 @@
<Compile Include="Config\EmulationConfig.cs" />
<Compile Include="Config\NetplayConfig.cs" />
<Compile Include="Config\VideoConfig.cs" />
<Compile Include="Config\WatchWindowConfig.cs" />
<Compile Include="Controls\ctrlLinkLabel.cs">
<SubType>Component</SubType>
</Compile>
@ -318,6 +319,12 @@
<Compile Include="Debugger\frmDebugLog.Designer.cs">
<DependentUpon>frmDebugLog.cs</DependentUpon>
</Compile>
<Compile Include="Debugger\frmWatchWindow.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Debugger\frmWatchWindow.Designer.cs">
<DependentUpon>frmWatchWindow.cs</DependentUpon>
</Compile>
<Compile Include="Debugger\Integration\RgbdsSymbolFile.cs" />
<Compile Include="Debugger\Integration\BassLabelFile.cs" />
<Compile Include="Debugger\MemoryTools\ctrlMemoryAccessCounters.cs">
@ -1110,6 +1117,9 @@
<EmbeddedResource Include="Debugger\frmDebugLog.resx">
<DependentUpon>frmDebugLog.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Debugger\frmWatchWindow.resx">
<DependentUpon>frmWatchWindow.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Debugger\MemoryTools\ctrlMemoryAccessCounters.resx">
<DependentUpon>ctrlMemoryAccessCounters.cs</DependentUpon>
</EmbeddedResource>