Add debug features

This commit is contained in:
shygoo 2017-08-18 00:08:22 -05:00
parent 631c471fe1
commit 47fd0632ff
84 changed files with 105912 additions and 999 deletions

View File

@ -54,6 +54,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginRSP", "Source\Android
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "JniBridge", "Source\Android\Bridge\Bridge.vcxproj", "{593B00E6-1987-415D-A62C-26533FC3E95C}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "duktape", "Source\3rdParty\duktape\duktape.vcxproj", "{E8D9A652-A354-4374-B6C5-A51EE62749FD}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Project64-video", "Source\Project64-video\Project64-video.vcxproj", "{A4D13408-A794-4199-8FC7-4A9A32505005}"
EndProject
Global
@ -173,6 +175,14 @@ Global
{593B00E6-1987-415D-A62C-26533FC3E95C}.Release|Win32.ActiveCfg = Release|Win32
{593B00E6-1987-415D-A62C-26533FC3E95C}.Release|Win32.Build.0 = Release|Win32
{593B00E6-1987-415D-A62C-26533FC3E95C}.Release|x64.ActiveCfg = Release|Win32
{E8D9A652-A354-4374-B6C5-A51EE62749FD}.Debug|Win32.ActiveCfg = Debug|Win32
{E8D9A652-A354-4374-B6C5-A51EE62749FD}.Debug|Win32.Build.0 = Debug|Win32
{E8D9A652-A354-4374-B6C5-A51EE62749FD}.Debug|x64.ActiveCfg = Debug|x64
{E8D9A652-A354-4374-B6C5-A51EE62749FD}.Debug|x64.Build.0 = Debug|x64
{E8D9A652-A354-4374-B6C5-A51EE62749FD}.Release|Win32.ActiveCfg = Release|Win32
{E8D9A652-A354-4374-B6C5-A51EE62749FD}.Release|Win32.Build.0 = Release|Win32
{E8D9A652-A354-4374-B6C5-A51EE62749FD}.Release|x64.ActiveCfg = Release|x64
{E8D9A652-A354-4374-B6C5-A51EE62749FD}.Release|x64.Build.0 = Release|x64
{A4D13408-A794-4199-8FC7-4A9A32505005}.Debug|Win32.ActiveCfg = Debug|Win32
{A4D13408-A794-4199-8FC7-4A9A32505005}.Debug|Win32.Build.0 = Debug|Win32
{A4D13408-A794-4199-8FC7-4A9A32505005}.Debug|x64.ActiveCfg = Debug|x64
@ -194,5 +204,6 @@ Global
{1133A1CC-A9E5-4026-B20D-6A2987130D4E} = {0E0FCAC2-E128-4886-8EE6-1BCA84551F58}
{B685BB34-D700-4FCC-8503-9B6AA1A0C95D} = {0E0FCAC2-E128-4886-8EE6-1BCA84551F58}
{593B00E6-1987-415D-A62C-26533FC3E95C} = {0E0FCAC2-E128-4886-8EE6-1BCA84551F58}
{E8D9A652-A354-4374-B6C5-A51EE62749FD} = {AA8F7F8E-5377-4911-859D-8A8817B0DB26}
EndGlobalSection
EndGlobal

1
Scripts/example.js Normal file
View File

@ -0,0 +1 @@
console.log("Hello world! See apidoc.htm for documentation.");

72
Source/3rdParty/duktape/AUTHORS.rst vendored Normal file
View File

@ -0,0 +1,72 @@
===============
Duktape authors
===============
Copyright
=========
Duktape copyrights are held by its authors. Each author has a copyright
to their contribution, and agrees to irrevocably license the contribution
under the Duktape ``LICENSE.txt``.
Authors
=======
Please include an e-mail address, a link to your GitHub profile, or something
similar to allow your contribution to be identified accurately.
The following people have contributed code, website contents, or Wiki contents,
and agreed to irrevocably license their contributions under the Duktape
``LICENSE.txt`` (in order of appearance):
* Sami Vaarala <sami.vaarala@iki.fi>
* Niki Dobrev
* Andreas Öman <andreas@lonelycoder.com>
* László Langó <llango.u-szeged@partner.samsung.com>
* Legimet <legimet.calc@gmail.com>
* Karl Skomski <karl@skomski.com>
* Bruce Pascoe <fatcerberus1@gmail.com>
* René Hollander <rene@rene8888.at>
* Julien Hamaide (https://github.com/crazyjul)
* Sebastian Götte (https://github.com/jaseg)
Other contributions
===================
The following people have contributed something other than code (e.g. reported
bugs, provided ideas, etc; roughly in order of appearance):
* Greg Burns
* Anthony Rabine
* Carlos Costa
* Aurélien Bouilland
* Preet Desai (Pris Matic)
* judofyr (http://www.reddit.com/user/judofyr)
* Jason Woofenden
* Michał Przybyś
* Anthony Howe
* Conrad Pankoff
* Jim Schimpf
* Rajaran Gaunker (https://github.com/zimbabao)
* Andreas Öman
* Doug Sanden
* Josh Engebretson (https://github.com/JoshEngebretson)
* Remo Eichenberger (https://github.com/remoe)
* Mamod Mehyar (https://github.com/mamod)
* David Demelier (https://github.com/markand)
* Tim Caswell (https://github.com/creationix)
* Mitchell Blank Jr (https://github.com/mitchblank)
* https://github.com/yushli
* Seo Sanghyeon (https://github.com/sanxiyn)
* Han ChoongWoo (https://github.com/tunz)
* Joshua Peek (https://github.com/josh)
* Bruce E. Pascoe (https://github.com/fatcerberus)
* https://github.com/Kelledin
* https://github.com/sstruchtrup
* Michael Drake (https://github.com/tlsa)
* https://github.com/chris-y
* Laurent Zubiaur (https://github.com/lzubiaur)
* Ole André Vadla Ravnås (https://github.com/oleavr)
If you are accidentally missing from this list, send me an e-mail
(``sami.vaarala@iki.fi``) and I'll fix the omission.

25
Source/3rdParty/duktape/LICENSE.txt vendored Normal file
View File

@ -0,0 +1,25 @@
===============
Duktape license
===============
(http://opensource.org/licenses/MIT)
Copyright (c) 2013-2016 by Duktape authors (see AUTHORS.rst)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

110
Source/3rdParty/duktape/README.rst vendored Normal file
View File

@ -0,0 +1,110 @@
=======
Duktape
=======
Duktape is a small and portable Ecmascript E5/E5.1 implementation. It is
intended to be easily embeddable into C programs, with a C API similar in
spirit to Lua's.
Duktape supports the full E5/E5.1 feature set including errors, Unicode
strings, and regular expressions, a subset of E6 features (e.g. Proxy
objects), Khronos/ES6 ArrayBuffer/TypedView, and Node.js Buffer bindings.
Duktape also provides a number of custom features such as error tracebacks,
additional data types for better C integration, combined reference counting
and mark-and sweep garbage collector, object finalizers, co-operative
threads a.k.a. coroutines, tail calls, built-in logging and module frameworks,
a built-in debugger protocol, function bytecode dump/load, and so on.
You can browse Duktape programmer's API and other documentation at:
* http://duktape.org/
In particular, you should read the getting started section:
* http://duktape.org/guide.html#gettingstarted
More examples and how-to articles are in the Duktape Wiki:
* http://wiki.duktape.org/
Building and integrating Duktape into your project is very straightforward:
* http://duktape.org/guide.html#compiling
See Makefile.hello for a concrete example::
$ cd <dist_root>
$ make -f Makefile.hello
[...]
$ ./hello
Hello world!
2+3=5
To build an example command line tool, use the following::
$ cd <dist_root>
$ make -f Makefile.cmdline
[...]
$ ./duk
((o) Duktape
duk> print('Hello world!');
Hello world!
= undefined
$ ./duk mandel.js
[...]
This distributable contains:
* ``src/``: main Duktape library in a "single source file" format (duktape.c,
duktape.h, and duk_config.h).
* ``src-noline/``: contains a variant of ``src/duktape.c`` with no ``#line``
directives which is preferable for some users. See discussion in
https://github.com/svaarala/duktape/pull/363.
* ``src-separate/``: main Duktape library in multiple files format.
* ``config/``: genconfig utility for creating duk_config.h configuration
files, see: http://wiki.duktape.org/Configuring.html.
* ``examples/``: further examples for using Duktape. Although Duktape
itself is widely portable, some of the examples are Linux only.
For instance the ``eventloop`` example illustrates how ``setTimeout()``
and other standard timer functions could be implemented on Unix/Linux.
* ``extras/``: utilities and modules which don't comfortably fit into the
main Duktape library because of footprint or portability concerns.
Extras are maintained and bug fixed code, but don't have the same version
guarantees as the main Duktape library.
* ``polyfills/``: a few replacement suggestions for non-standard Javascript
functions provided by other implementations.
* ``debugger/``: a debugger with a web UI, see ``debugger/README.rst`` and
https://github.com/svaarala/duktape/blob/master/doc/debugger.rst for
details on Duktape debugger support. Also contains a JSON debug proxy
(one written in Node.js and another in DukLuv) to make talking to the
debug target easier.
* ``licenses/``: licensing information.
You can find release notes at:
* https://github.com/svaarala/duktape/blob/master/RELEASES.rst
This distributable contains Duktape version 1.5.1, created from git
commit 2cc76e9ff1f64869e1146ad7317d8cbe33bbd27e (v1.5.1).
Duktape is copyrighted by its authors (see ``AUTHORS.rst``) and licensed
under the MIT license (see ``LICENSE.txt``). String hashing algorithms are
based on the algorithm from Lua (MIT license), djb2 hash, and Murmurhash2
(MIT license). Duktape module loader is based on the CommonJS module
loading specification (without sharing any code), CommonJS is under the
MIT license.
Have fun!
Sami Vaarala (sami.vaarala@iki.fi)

3804
Source/3rdParty/duktape/duk_config.h vendored Normal file

File diff suppressed because it is too large Load Diff

86566
Source/3rdParty/duktape/duktape.c vendored Normal file

File diff suppressed because it is too large Load Diff

1567
Source/3rdParty/duktape/duktape.h vendored Normal file

File diff suppressed because it is too large Load Diff

150
Source/3rdParty/duktape/duktape.vcproj vendored Normal file
View File

@ -0,0 +1,150 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="duktape"
ProjectGUID=""
RootNamespace="duktape"
TargetFrameworkVersion="0"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
ConfigurationType="4"
InheritedPropertySheets="..\..\..\PropertySheets\Win32.Debug.vsprops"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
WarningLevel="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
ConfigurationType="4"
InheritedPropertySheets="..\..\..\PropertySheets\Win32.Release.vsprops"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
WarningLevel="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90"
>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;fi;fd"
>
</Filter>
<Filter
Name="Resource Files"
Filter="ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
>
</Filter>
<Filter
Name="Minizip"
>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

49
Source/3rdParty/duktape/duktape.vcxproj vendored Normal file
View File

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{E8D9A652-A354-4374-B6C5-A51EE62749FD}</ProjectGuid>
<RootNamespace>duktape</RootNamespace>
</PropertyGroup>
<PropertyGroup Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<ImportGroup Label="PropertySheets">
<Import Project="$(SolutionDir)PropertySheets\Platform.$(Configuration).props" />
</ImportGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ItemDefinitionGroup>
<ClCompile>
<PrecompiledHeader />
<WarningLevel>Level4</WarningLevel>
<DisableSpecificWarnings>
</DisableSpecificWarnings>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="duktape.h" />
<ClInclude Include="duk_config.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="duktape.c" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{20a593ff-2e3f-48c3-89ef-81cd7bdd8898}</UniqueIdentifier>
<Extensions>cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{a3b93770-ecab-40a0-93dc-ace6e58b2384}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;fi;fd</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="duk_config.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="duktape.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="duktape.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@ -48,10 +48,10 @@ static bool TranslateToMemProtect(int OsMemProtection, MEM_PROTECTION & memProte
}
#endif
void* AllocateAddressSpace(size_t size)
void* AllocateAddressSpace(size_t size, LPVOID lpAddress)
{
#ifdef _WIN32
return VirtualAlloc(NULL, size, MEM_RESERVE | MEM_TOP_DOWN, PAGE_NOACCESS);
return VirtualAlloc(lpAddress, size, MEM_RESERVE | MEM_TOP_DOWN, PAGE_NOACCESS);
#else
void * ptr = mmap((void*)0, size, PROT_NONE, MAP_PRIVATE|MAP_ANON, -1, 0);
if (ptr == MAP_FAILED)

View File

@ -8,7 +8,7 @@ enum MEM_PROTECTION
MEM_EXECUTE_READWRITE,
};
void* AllocateAddressSpace(size_t size);
void* AllocateAddressSpace(size_t size, LPVOID lpAddress = NULL);
bool FreeAddressSpace(void* addr, size_t size);
void* CommitMemory(void* addr, size_t size, MEM_PROTECTION memProtection);
bool DecommitMemory(void* addr, size_t size);

View File

@ -34,6 +34,8 @@ Source: "{#BaseDir}\Plugin\GFX\Jabo_Direct3D8.dll"; DestDir: "{app}\Plugin\GFX"
Source: "{#BaseDir}\Plugin\GFX\Project64-Video.dll"; DestDir: "{app}\Plugin\GFX"
Source: "{#BaseDir}\Plugin\Input\PJ64_NRage.dll"; DestDir: "{app}\Plugin\Input"
Source: "{#BaseDir}\Plugin\RSP\RSP 1.7.dll"; DestDir: "{app}\Plugin\RSP"
Source: "{#BaseDir}\Scripts\example.js"; DestDir: "{app}\Scripts"
Source: "{#BaseDir}\apidoc.htm"; DestDir: "{app}\apidoc.htm"
[Dirs]
Name: "{app}\Config"; Permissions: everyone-full

View File

@ -13,4 +13,7 @@
__interface CDebugger
{
virtual void TLBChanged(void) = 0;
virtual bool CPUStepStarted(void) = 0;
virtual void CPUStep(void) = 0;
virtual void FrameDrawn(void) = 0;
};

View File

@ -8,8 +8,11 @@
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
* *
****************************************************************************/
#include "stdafx.h"
#include "InterpreterCPU.h"
#include "Debugger.h"
#include <Project64-core/N64System/SystemGlobals.h>
#include <Project64-core/N64System/N64Class.h>
#include <Project64-core/N64System/Mips/MemoryVirtualMem.h>
@ -295,15 +298,26 @@ void CInterpreterCPU::ExecuteCPU()
continue;
}
if (!g_Debugger->CPUStepStarted())
{
// Skip command if instructed by the debugger
PROGRAM_COUNTER += 4;
continue;
}
g_Debugger->CPUStep();
/* if (PROGRAM_COUNTER > 0x80000300 && PROGRAM_COUNTER < 0x80380000)
{
WriteTraceF((TraceType)(TraceError | TraceNoHeader),"%X: %s",*_PROGRAM_COUNTER,R4300iOpcodeName(Opcode.Hex,*_PROGRAM_COUNTER));
// WriteTraceF((TraceType)(TraceError | TraceNoHeader),"%X: %s t9: %08X v1: %08X",*_PROGRAM_COUNTER,R4300iOpcodeName(Opcode.Hex,*_PROGRAM_COUNTER),_GPR[0x19].UW[0],_GPR[0x03].UW[0]);
// WriteTraceF((TraceType)(TraceError | TraceNoHeader),"%X: %d %d",*_PROGRAM_COUNTER,*g_NextTimer,g_SystemTimer->CurrentType());
} */
m_R4300i_Opcode[Opcode.op]();
NextTimer -= CountPerOp;
PROGRAM_COUNTER += 4;
switch (R4300iOp::m_NextInstruction)
{
@ -354,6 +368,8 @@ void CInterpreterCPU::ExecuteCPU()
WriteTrace(TraceN64System, TraceDebug, "Done");
}
void CInterpreterCPU::ExecuteOps(int32_t Cycles)
{
bool & Done = g_System->m_EndEmulation;

View File

@ -20,7 +20,7 @@ public:
static void ExecuteCPU();
static void ExecuteOps(int32_t Cycles);
static void InPermLoop();
private:
CInterpreterCPU(); // Disable default constructor
CInterpreterCPU(const CInterpreterCPU&); // Disable copy constructor

View File

@ -2094,6 +2094,18 @@ void R4300iOp::REGIMM_BGEZAL()
m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4;
if ((*_PROGRAM_COUNTER) == m_JumpToLocation)
{
if (g_Settings->LoadBool(Debugger_Enabled))
{
if (g_Reg->m_PROGRAM_COUNTER < 0x80000400)
{
// Break out of possible checksum halt
g_Notify->DisplayMessage(5, "Broke out of permanent loop! Invalid checksum?");
m_JumpToLocation = (*_PROGRAM_COUNTER) + 8;
_GPR[31].DW = (int32_t)((*_PROGRAM_COUNTER) + 8);
R4300iOp::m_NextInstruction = DELAY_SLOT;
return;
}
}
if (!DelaySlotEffectsCompare((*_PROGRAM_COUNTER), m_Opcode.rs, 0))
{
CInterpreterCPU::InPermLoop();

View File

@ -1302,6 +1302,18 @@ void R4300iOp32::REGIMM_BGEZAL()
m_JumpToLocation = (*_PROGRAM_COUNTER) + ((int16_t)m_Opcode.offset << 2) + 4;
if ((*_PROGRAM_COUNTER) == m_JumpToLocation)
{
if (g_Settings->LoadBool(Debugger_Enabled))
{
if (g_Reg->m_PROGRAM_COUNTER < 0x80000400)
{
// Break out of possible checksum halt
g_Notify->DisplayMessage(5, "Broke out of permanent loop! Invalid checksum?");
m_JumpToLocation = (*_PROGRAM_COUNTER) + 8;
_GPR[31].DW = (int32_t)((*_PROGRAM_COUNTER) + 8);
R4300iOp::m_NextInstruction = DELAY_SLOT;
return;
}
}
if (!DelaySlotEffectsCompare((*_PROGRAM_COUNTER), m_Opcode.rs, 0))
{
CInterpreterCPU::InPermLoop();

View File

@ -59,6 +59,13 @@ union OPCODE
unsigned fmt : 5;
unsigned : 6;
};
struct
{
unsigned : 6;
unsigned code : 20;
unsigned : 6;
};
};
#pragma warning(pop)

File diff suppressed because it is too large Load Diff

View File

@ -14,34 +14,34 @@
#include <Project64-core/N64System/SystemGlobals.h>
#include <Project64-core/Logging.h>
const char * CRegName::GPR[32] = { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
"t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra" };
const char * CRegName::GPR[32] = { "R0", "AT", "V0", "V1", "A0", "A1", "A2", "A3",
"T0", "T1", "T2", "T3", "T4", "T5", "T6", "T7",
"S0", "S1", "S2", "S3", "S4", "S5", "S6", "S7",
"T8", "T9", "K0", "K1", "GP", "SP", "FP", "RA" };
const char *CRegName::GPR_Hi[32] = { "r0.HI", "at.HI", "v0.HI", "v1.HI", "a0.HI", "a1.HI",
"a2.HI", "a3.HI", "t0.HI", "t1.HI", "t2.HI", "t3.HI",
"t4.HI", "t5.HI", "t6.HI", "t7.HI", "s0.HI", "s1.HI",
"s2.HI", "s3.HI", "s4.HI", "s5.HI", "s6.HI", "s7.HI",
"t8.HI", "t9.HI", "k0.HI", "k1.HI", "gp.HI", "sp.HI",
"s8.HI", "ra.HI" };
"fp.HI", "ra.HI" };
const char *CRegName::GPR_Lo[32] = { "r0.LO", "at.LO", "v0.LO", "v1.LO", "a0.LO", "a1.LO",
"a2.LO", "a3.LO", "t0.LO", "t1.LO", "t2.LO", "t3.LO",
"t4.LO", "t5.LO", "t6.LO", "t7.LO", "s0.LO", "s1.LO",
"s2.LO", "s3.LO", "s4.LO", "s5.LO", "s6.LO", "s7.LO",
"t8.LO", "t9.LO", "k0.LO", "k1.LO", "gp.LO", "sp.LO",
"s8.LO", "ra.LO" };
"fp.LO", "ra.LO" };
const char * CRegName::Cop0[32] = { "Index", "Random", "EntryLo0", "EntryLo1", "Context", "PageMask", "Wired", "",
"BadVAddr", "Count", "EntryHi", "Compare", "Status", "Cause", "EPC", "PRId",
"Config", "LLAddr", "WatchLo", "WatchHi", "XContext", "", "", "",
"", "", "ECC", "CacheErr", "TagLo", "TagHi", "ErrEPC", "" };
const char * CRegName::FPR[32] = { "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
"f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
"f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
"f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31" };
const char * CRegName::FPR[32] = { "F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7",
"F8", "F9", "F10", "F11", "F12", "F13", "F14", "F15",
"F16", "F17", "F18", "F19", "F20", "F21", "F22", "F23",
"F24", "F25", "F26", "F27", "F28", "F29", "F30", "F31" };
const char * CRegName::FPR_Ctrl[32] = { "Revision", "Unknown", "Unknown", "Unknown", "Unknown",
"Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Unknown",
@ -574,4 +574,4 @@ void CRegisters::DoSysCallException(bool DelaySlot)
}
STATUS_REGISTER |= STATUS_EXL;
m_PROGRAM_COUNTER = 0x80000180;
}
}

View File

@ -1006,7 +1006,18 @@ void CN64System::ExecuteCPU()
_controlfp(_PC_53, _MCW_PC);
#endif
switch ((CPU_TYPE)g_Settings->LoadDword(Game_CpuType))
CPU_TYPE cpuType;
if (g_Settings->LoadBool(Setting_ForceInterpreterCPU))
{
cpuType = CPU_Interpreter;
}
else
{
cpuType = (CPU_TYPE)g_Settings->LoadDword(Game_CpuType);
}
switch (cpuType)
{
case CPU_Recompiler: ExecuteRecompiler(); break;
case CPU_SyncCores: ExecuteSyncCPU(); break;
@ -2128,6 +2139,7 @@ void CN64System::RefreshScreen()
{
WriteTrace(TraceGFXPlugin, TraceDebug, "UpdateScreen Starting");
g_Plugins->Gfx()->UpdateScreen();
g_Debugger->FrameDrawn();
WriteTrace(TraceGFXPlugin, TraceDebug, "UpdateScreen Done");
}
__except_catch()
@ -2201,4 +2213,4 @@ void CN64System::TLB_Changed()
{
g_Debugger->TLBChanged();
}
}
}

View File

@ -128,6 +128,7 @@
<ClInclude Include="3rdParty\7zip.h" />
<ClInclude Include="3rdParty\zip.h" />
<ClInclude Include="AppInit.h" />
<ClInclude Include="Debugger.h" />
<ClInclude Include="ExceptionHandler.h" />
<ClInclude Include="Logging.h" />
<ClInclude Include="Multilanguage.h" />
@ -235,4 +236,8 @@
</ProjectReference>
<ProjectReference Include="..\Common\Common.vcxproj" />
</ItemGroup>
<ItemGroup>
<None Include="ClassDiagram.cd" />
<None Include="ClassDiagram1.cd" />
</ItemGroup>
</Project>

View File

@ -539,6 +539,9 @@
<ClInclude Include="N64System\Recompiler\SectionInfo.h">
<Filter>Header Files\N64 System\Recompiler</Filter>
</ClInclude>
<ClInclude Include="N64System\Recompiler\X86ops.h">
<Filter>Header Files\N64 System\Recompiler</Filter>
</ClInclude>
<ClInclude Include="N64System\Mips\Audio.h">
<Filter>Header Files\N64 System\Mips</Filter>
</ClInclude>
@ -653,5 +656,12 @@
<ClInclude Include="N64System\Recompiler\x64-86\x64RegInfo.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Debugger.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="ClassDiagram.cd" />
<None Include="ClassDiagram1.cd" />
</ItemGroup>
</Project>

View File

@ -48,6 +48,7 @@ enum SettingID
Setting_AutoStart,
Setting_CheckEmuRunning,
Setting_EraseGameDefaults,
Setting_ForceInterpreterCPU,
Setting_AutoZipInstantSave,
Setting_RememberCheats,

View File

@ -112,6 +112,8 @@ void CSettings::AddHowToHandleSetting(const char * BaseDirectory)
AddHandler(Setting_AutoZipInstantSave, new CSettingTypeApplication("", "Auto Zip Saves", (uint32_t)true));
AddHandler(Setting_EraseGameDefaults, new CSettingTypeApplication("", "Erase on default", (uint32_t)true));
AddHandler(Setting_CheckEmuRunning, new CSettingTypeApplication("", "Check Running", (uint32_t)true));
AddHandler(Setting_ForceInterpreterCPU, new CSettingTypeApplication("", "Force Interpreter CPU", false));
AddHandler(Setting_RememberCheats, new CSettingTypeApplication("", "Remember Cheats", (uint32_t)false));
#ifdef ANDROID
@ -1277,4 +1279,4 @@ void CSettings::UnregisterChangeCB(SettingID Type, void * Data, SettingChangedFu
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
}
}

View File

@ -0,0 +1,343 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "stdafx.h"
#include "Assembler.h"
#include "Project64-core\N64System\Mips\OpCode.h"
REGISTER* lookup_register(char* name);
static int parse_error = 0;
static uint32_t m_Address = 0x00000000;
void to_lower(char* str)
{
while (*str)
{
if (*str >= 'A' && *str <= 'Z')
{
*str |= 0x20;
}
str++;
}
}
uint32_t pop_reg()
{
char* r = strtok(NULL, " \t,()");
if (r == NULL)
{
parse_error = ERR_EXPECTED_REG;
return 0;
}
REGISTER* reg = lookup_register(r);
if (reg == NULL)
{
parse_error = ERR_INVALID_REG;
return 0;
}
return reg->val;
}
uint32_t pop_val()
{
char* v = strtok(NULL, " \t,()");
if (isalpha(*v))
{
// todo lookup label value
return 0;
}
int base = 0; // hex or dec
if (*v == '$')
{
base = 16; // hex
v++;
}
char* endptr;
uint32_t val = strtoul(v, &endptr, base);
if (*endptr != '\0')
{
parse_error = ERR_EXPECTED_VAL;
return 0;
}
return val;
}
uint32_t base_op(uint32_t val)
{
return val << 26;
}
uint32_t base_spec(uint32_t val)
{
return val;
}
uint32_t base_regimm(uint32_t val)
{
return (R4300i_REGIMM << 26) | (val << 16);
}
void arg_reg_s(uint32_t* opcode)
{
*opcode |= pop_reg() << 21;
}
void arg_reg_t(uint32_t* opcode)
{
*opcode |= pop_reg() << 16;
}
void arg_reg_d(uint32_t* opcode)
{
*opcode |= pop_reg() << 11;
}
void arg_jump(uint32_t* opcode)
{
*opcode |= (pop_val() / 4) & 0x3FFFFFF;
}
void arg_imm16(uint32_t* opcode)
{
*opcode |= (pop_val() & 0xFFFF);
}
void arg_bra_target(uint32_t* opcode)
{
uint16_t relTarget = (((pop_val() - m_Address) / 4) & 0xFFFF) - 1;
*opcode |= relTarget;
}
void arg_shamt(uint32_t* opcode)
{
*opcode |= (pop_val() & 0x1F) << 6;
}
SYNTAX syn_jump[] = { arg_jump, NULL };
SYNTAX syn_loadstore[] = { arg_reg_t, arg_imm16, arg_reg_s, NULL };
SYNTAX syn_arith[] = { arg_reg_d, arg_reg_s, arg_reg_t, NULL };
SYNTAX syn_arith_i[] = { arg_reg_t, arg_reg_s, arg_imm16, NULL };
SYNTAX syn_load_i[] = { arg_reg_t, arg_imm16, NULL };
SYNTAX syn_branch_z[] = { arg_reg_s, arg_bra_target, NULL };
SYNTAX syn_branch[] = { arg_reg_s, arg_reg_t, arg_bra_target, NULL };
SYNTAX syn_branch_unc[] = { arg_bra_target, NULL };
SYNTAX syn_trap_i[] = { arg_reg_s, arg_imm16, NULL };
SYNTAX syn_shift[] = { arg_reg_d, arg_reg_t, arg_shamt, NULL };
SYNTAX syn_mf[] = { arg_reg_d, NULL };
SYNTAX syn_jr[] = { arg_reg_s, NULL };
INSTRUCTION instructions[] =
{
{ "j", R4300i_J, base_op, syn_jump },
{ "jal", R4300i_JAL, base_op, syn_jump },
{ "beq", R4300i_BEQ, base_op, syn_branch },
{ "beqz", R4300i_BEQ, base_op, syn_branch_z },
{ "b", R4300i_BEQ, base_op, syn_branch_unc },
{ "bne", R4300i_BNE, base_op, syn_branch },
{ "bnez", R4300i_BNE, base_op, syn_branch_z },
{ "blez", R4300i_BLEZ, base_op, syn_branch_z },
{ "bgtz", R4300i_BGTZ, base_op, syn_branch_z },
{ "addi", R4300i_ADDI, base_op, syn_arith_i },
{ "addiu", R4300i_ADDIU, base_op, syn_arith_i },
{ "slti", R4300i_SLTI, base_op, syn_arith_i },
{ "sltiu", R4300i_SLTIU, base_op, syn_arith_i },
{ "andi", R4300i_ANDI, base_op, syn_arith_i },
{ "ori", R4300i_ORI, base_op, syn_arith_i },
{ "xori", R4300i_XORI, base_op, syn_arith_i },
{ "lui", R4300i_LUI, base_op, syn_load_i },
// cp0 cp1
{ "beql", R4300i_BEQL, base_op, syn_branch },
{ "beqzl", R4300i_BEQL, base_op, syn_branch_z },
{ "bnel", R4300i_BNEL, base_op, syn_branch },
{ "bnezl", R4300i_BNEL, base_op, syn_branch_z },
{ "blezl", R4300i_BLEZL, base_op, syn_branch_z },
{ "bgtzl", R4300i_BGTZL, base_op, syn_branch_z },
{ "daddi", R4300i_DADDI, base_op, syn_arith_i },
{ "daddiu", R4300i_DADDI, base_op, syn_arith_i },
{ "ldl", R4300i_LDL, base_op, syn_loadstore },
{ "ldr", R4300i_LDR, base_op, syn_loadstore },
{ "lb", R4300i_LB, base_op, syn_loadstore },
{ "lh", R4300i_LH, base_op, syn_loadstore },
{ "lwl", R4300i_LWL, base_op, syn_loadstore },
{ "lw", R4300i_LW, base_op, syn_loadstore },
{ "lbu", R4300i_LBU, base_op, syn_loadstore },
{ "lhu", R4300i_LHU, base_op, syn_loadstore },
{ "lwr", R4300i_LWR, base_op, syn_loadstore },
{ "lwu", R4300i_LWU, base_op, syn_loadstore },
{ "sb", R4300i_SB, base_op, syn_loadstore },
{ "sh", R4300i_SH, base_op, syn_loadstore },
{ "swl", R4300i_SWL, base_op, syn_loadstore },
{ "sw", R4300i_SW, base_op, syn_loadstore },
{ "sdl", R4300i_SDL, base_op, syn_loadstore },
{ "sdr", R4300i_SDR, base_op, syn_loadstore },
{ "swr", R4300i_SWR, base_op, syn_loadstore },
//{ "cache", R4300i_CACHE, base_op, },
{ "ll", R4300i_LL, base_op, syn_loadstore },
{ "lwc1", R4300i_LWC1, base_op, syn_loadstore },
{ "ldc1", R4300i_LDC1, base_op, syn_loadstore },
{ "ld", R4300i_LD, base_op, syn_loadstore },
{ "sc", R4300i_SC, base_op, syn_loadstore },
{ "swc1", R4300i_SWC1, base_op, syn_loadstore },
{ "sdc1", R4300i_SDC1, base_op, syn_loadstore },
{ "sdc2", R4300i_SDC2, base_op, syn_loadstore },
{ "sd", R4300i_SD, base_op, syn_loadstore },
{ "bltz", R4300i_REGIMM_BLTZ, base_regimm, syn_branch_z },
{ "bgez", R4300i_REGIMM_BGEZ, base_regimm, syn_branch_z },
{ "bltzl", R4300i_REGIMM_BLTZL, base_regimm, syn_branch_z },
{ "bgezl", R4300i_REGIMM_BGEZL, base_regimm, syn_branch_z },
{ "tgei", R4300i_REGIMM_TGEI, base_regimm, syn_trap_i },
{ "tgeiu", R4300i_REGIMM_TGEIU, base_regimm, syn_trap_i },
{ "tlti", R4300i_REGIMM_TLTIU, base_regimm, syn_trap_i },
{ "tltiu", R4300i_REGIMM_TLTIU, base_regimm, syn_trap_i },
{ "teqi", R4300i_REGIMM_TEQI, base_regimm, syn_trap_i },
{ "tnei", R4300i_REGIMM_TNEI, base_regimm, syn_trap_i },
{ "bltzal", R4300i_REGIMM_BLTZAL, base_regimm, syn_branch_z },
{ "bgezal", R4300i_REGIMM_BGEZAL, base_regimm, syn_branch_z },
{ "bal", R4300i_REGIMM_BGEZAL, base_regimm, syn_branch_unc },
{ "bltzall", R4300i_REGIMM_BLTZALL, base_regimm, syn_branch_z },
{ "bgezall", R4300i_REGIMM_BGEZALL, base_regimm, syn_branch_z },
{ "sll", R4300i_SPECIAL_SLL, base_spec, syn_shift },
{ "nop", R4300i_SPECIAL_SLL, base_spec, NULL },
{ "srl", R4300i_SPECIAL_SRL, base_spec, syn_shift },
{ "sra", R4300i_SPECIAL_SRA, base_spec, syn_shift },
{ "jr", R4300i_SPECIAL_JR, base_spec, syn_jr },
{ "syscall", R4300i_SPECIAL_SYSCALL, base_spec, NULL },
{ "break", R4300i_SPECIAL_BREAK, base_spec, NULL },
{ "sync", R4300i_SPECIAL_SYNC, base_spec, NULL },
{ "mfhi", R4300i_SPECIAL_MFHI, base_spec, syn_mf },
{ "mthi", R4300i_SPECIAL_MTHI, base_spec, syn_mf },
{ "mflo", R4300i_SPECIAL_MFLO, base_spec, syn_mf },
{ "mtlo", R4300i_SPECIAL_MTLO, base_spec, syn_mf },
{ "add", R4300i_SPECIAL_ADD, base_spec, syn_arith },
{ "addu", R4300i_SPECIAL_ADDU, base_spec, syn_arith },
{ "sub", R4300i_SPECIAL_SUB, base_spec, syn_arith },
{ "subu", R4300i_SPECIAL_SUBU, base_spec, syn_arith },
{ "and", R4300i_SPECIAL_AND, base_spec, syn_arith },
{ "or", R4300i_SPECIAL_OR, base_spec, syn_arith },
{ "xor", R4300i_SPECIAL_XOR, base_spec, syn_arith },
{ "nor", R4300i_SPECIAL_NOR, base_spec, syn_arith },
{ "slt", R4300i_SPECIAL_SLT, base_spec, syn_arith },
{ "sltu", R4300i_SPECIAL_SLTU, base_spec, syn_arith },
{ "dadd", R4300i_SPECIAL_DADD, base_spec, syn_arith },
{ "daddu", R4300i_SPECIAL_DADDU, base_spec, syn_arith },
{ "dsub", R4300i_SPECIAL_DSUB, base_spec, syn_arith },
{ "dsubu", R4300i_SPECIAL_DSUBU, base_spec, syn_arith },
{ "dsll", R4300i_SPECIAL_DSLL, base_spec, syn_shift },
{ "dsrl", R4300i_SPECIAL_DSRL, base_spec, syn_shift },
{ "dsra", R4300i_SPECIAL_DSRA, base_spec, syn_shift },
{ "dsll32", R4300i_SPECIAL_DSLL32, base_spec, syn_shift },
{ "dsrl32", R4300i_SPECIAL_DSRL32, base_spec, syn_shift },
{ "dsra32", R4300i_SPECIAL_DSRA32, base_spec, syn_shift },
{ 0 }
};
REGISTER registers[] =
{
{ "r0", 0 },{ "at", 1 },{ "v0", 2 },{ "v1", 3 },{ "a0", 4 },{ "a1", 5 },{ "a2", 6 },{ "a3", 7 },
{ "t0", 8 },{ "t1", 9 },{ "t2", 10 },{ "t3", 11 },{ "t4", 12 },{ "t5", 13 },{ "t6", 14 },{ "t7", 15 },
{ "s0", 16 },{ "s1", 17 },{ "s2", 18 },{ "s3", 19 },{ "s4", 20 },{ "s5", 21 },{ "s6", 22 },{ "s7", 23 },
{ "t8", 24 },{ "t9", 25 },{ "k0", 26 },{ "k1", 27 },{ "gp", 28 },{ "sp", 29 },{ "s8", 30 },{ "ra", 31 },
{ "fp", 30 },
{ "f0", 0 },{ "f1", 1 },{ "f2", 2 },{ "f3", 3 },{ "f4", 4 },{ "f5", 5 },{ "f6", 6 },{ "f7", 7 },
{ "f8", 8 },{ "f9", 9 },{ "f10", 10 },{ "f11", 11 },{ "f12", 12 },{ "f13", 13 },{ "f14", 14 },{ "f15", 15 },
{ "f16", 16 },{ "f17", 17 },{ "f18", 18 },{ "f19", 19 },{ "f20", 20 },{ "f21", 21 },{ "f22", 22 },{ "f23", 23 },
{ "f24", 24 },{ "f25", 25 },{ "f26", 26 },{ "f27", 27 },{ "f28", 28 },{ "f29", 29 },{ "f30", 30 },{ "f31", 31 },
{ "r0", 0 },{ "r1", 1 },{ "r2", 2 },{ "r3", 3 },{ "r4", 4 },{ "r5", 5 },{ "r6", 6 },{ "r7", 7 },
{ "r8", 8 },{ "r9", 9 },{ "r10", 10 },{ "r11", 11 },{ "r12", 12 },{ "r13", 13 },{ "r14", 14 },{ "r15", 15 },
{ "r16", 16 },{ "r17", 17 },{ "r18", 18 },{ "r19", 19 },{ "r20", 20 },{ "r21", 21 },{ "r22", 22 },{ "r23", 23 },
{ "r24", 24 },{ "r25", 25 },{ "r26", 26 },{ "r27", 27 },{ "r28", 28 },{ "r29", 29 },{ "r30", 30 },{ "r31", 31 },
{ 0 }
};
INSTRUCTION* lookup_instruction(char* name)
{
for (int i = 0; instructions[i].name != NULL; i++)
{
if (strcmp(name, instructions[i].name) == 0)
{
return &instructions[i];
}
}
return NULL;
}
REGISTER* lookup_register(char* name)
{
for (int i = 0; registers[i].name != NULL; i++)
{
if (strcmp(name, registers[i].name) == 0)
{
return &registers[i];
}
}
return NULL;
}
bool CAssembler::AssembleLine(char* line, uint32_t* opcode, uint32_t address)
{
m_Address = address;
char line_c[128];
strncpy(line_c, line, 128);
to_lower(line_c);
if (line_c[0] == '\0')
{
*opcode = 0;
return true;
}
char* name = strtok(line_c, " \t");
INSTRUCTION* instruction = lookup_instruction(name);
if (instruction == NULL)
{
return false;
}
*opcode = instruction->base(instruction->val);
if (instruction->syntax == NULL)
{
// No parameters
return true;
}
for (int i = 0; instruction->syntax[i]; i++)
{
instruction->syntax[i](opcode);
}
return true;
}

View File

@ -0,0 +1,32 @@
#pragma once
#include <stdint.h>
typedef void(*SYNTAX)(uint32_t* opcode);
typedef struct {
const char* name;
uint32_t val;
uint32_t(*base)(uint32_t val); // value shift
SYNTAX* syntax; // arguments
} INSTRUCTION;
typedef struct {
const char* name;
uint32_t val;
} REGISTER;
enum ParseError
{
ERR_NONE,
ERR_EXPECTED_REG,
ERR_INVALID_REG,
ERR_EXPECTED_VAL
};
class CAssembler {
public:
static bool AssembleLine(char* line, uint32_t* opcode, uint32_t address = 0x00000000);
};

View File

@ -0,0 +1,190 @@
/****************************************************************************
* *
* Project64 - A Nintendo 64 emulator. *
* http://www.pj64-emu.com/ *
* Copyright (C) 2012 Project64. All rights reserved. *
* *
* License: *
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
* *
****************************************************************************/
#include "stdafx.h"
#include "Breakpoints.h"
#include <Project64-core/N64System/Mips/RegisterClass.h>
#include <Project64-core/N64System/SystemGlobals.h>
#include <Project64-core/N64System/Mips/OpcodeName.h>
#include <Project64-core/N64System/N64Class.h>
//BOOL CBreakpoints::m_Debugging = FALSE;
//BOOL CBreakpoints::m_Skipping = FALSE;
//
//std::vector<uint32_t> CBreakpoints::m_RBP;
//std::vector<uint32_t> CBreakpoints::m_WBP;
//std::vector<uint32_t> CBreakpoints::m_EBP;
//
//int CBreakpoints::m_nRBP = 0;
//int CBreakpoints::m_nWBP = 0;
//int CBreakpoints::m_nEBP = 0;
CBreakpoints::CBreakpoints()
{
m_Debugging = FALSE;
m_Skipping = FALSE;
m_nRBP = 0;
m_nWBP = 0;
m_nEBP = 0;
}
void CBreakpoints::Pause()
{
KeepDebugging();
g_System->Pause();
}
void CBreakpoints::Resume()
{
g_System->ExternalEvent(SysEvent_ResumeCPU_FromMenu);
}
BOOL CBreakpoints::isDebugging()
{
return m_Debugging;
}
void CBreakpoints::KeepDebugging()
{
m_Debugging = TRUE;
}
void CBreakpoints::StopDebugging()
{
m_Debugging = FALSE;
}
void CBreakpoints::Skip()
{
m_Skipping = TRUE;
}
bool CBreakpoints::RBPAdd(uint32_t address, bool bTemporary)
{
if (!RBPExists(address))
{
m_RBP.push_back({ address, bTemporary });
m_nRBP = m_RBP.size();
return true;
}
return false;
}
bool CBreakpoints::WBPAdd(uint32_t address, bool bTemporary)
{
if (!WBPExists(address))
{
m_WBP.push_back({ address, bTemporary });
m_nWBP = m_WBP.size();
return true;
}
return false;
}
bool CBreakpoints::EBPAdd(uint32_t address, bool bTemporary)
{
if (!EBPExists(address))
{
m_EBP.push_back({ address, bTemporary });
m_nEBP = m_EBP.size();
return true;
}
return false;
}
void CBreakpoints::RBPRemove(uint32_t address)
{
for (int i = 0; i < m_nRBP; i++)
{
if (m_RBP[i].address == address)
{
m_RBP.erase(m_RBP.begin() + i);
m_nRBP = m_RBP.size();
return;
}
}
}
void CBreakpoints::WBPRemove(uint32_t address)
{
for (int i = 0; i < m_nWBP; i++)
{
if (m_WBP[i].address == address)
{
m_WBP.erase(m_WBP.begin() + i);
m_nWBP = m_WBP.size();
return;
}
}
}
void CBreakpoints::EBPRemove(uint32_t address)
{
for (int i = 0; i < m_nEBP; i++)
{
if (m_EBP[i].address == address)
{
m_EBP.erase(m_EBP.begin() + i);
m_nEBP = m_EBP.size();
return;
}
}
}
void CBreakpoints::RBPToggle(uint32_t address, bool bTemporary)
{
if (RBPAdd(address, bTemporary) == false)
{
RBPRemove(address);
}
}
void CBreakpoints::WBPToggle(uint32_t address, bool bTemporary)
{
if (WBPAdd(address, bTemporary) == false)
{
WBPRemove(address);
}
}
void CBreakpoints::EBPToggle(uint32_t address, bool bTemporary)
{
if (EBPAdd(address, bTemporary) == false)
{
EBPRemove(address);
}
}
void CBreakpoints::RBPClear()
{
m_RBP.clear();
m_nRBP = 0;
}
void CBreakpoints::WBPClear()
{
m_WBP.clear();
m_nWBP = 0;
}
void CBreakpoints::EBPClear()
{
m_EBP.clear();
m_nEBP = 0;
}
void CBreakpoints::BPClear()
{
RBPClear();
WBPClear();
EBPClear();
}

View File

@ -0,0 +1,143 @@
/****************************************************************************
* *
* Project64 - A Nintendo 64 emulator. *
* http://www.pj64-emu.com/ *
* Copyright (C) 2012 Project64. All rights reserved. *
* *
* License: *
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
* *
****************************************************************************/
#pragma once
#include <stdint.h>
class CBreakpoints {
private:
public:
typedef struct {
uint32_t address;
bool bTemporary;
} BREAKPOINT;
enum BPSTATE {
BP_NOT_SET = FALSE,
BP_SET,
BP_SET_TEMP
};
CBreakpoints();
BOOL m_Debugging;
BOOL m_Skipping;
std::vector<BREAKPOINT> m_RBP;
std::vector<BREAKPOINT> m_WBP;
std::vector<BREAKPOINT> m_EBP;
int m_nRBP;
int m_nWBP;
int m_nEBP;
void Pause();
void Resume();
void Skip();
BOOL isDebugging();
void KeepDebugging();
void StopDebugging();
inline BOOL isSkipping()
{
BOOL ret = m_Skipping;
m_Skipping = FALSE;
return ret;
}
bool RBPAdd(uint32_t address, bool bTemporary = false);
void RBPRemove(uint32_t address);
void RBPToggle(uint32_t address, bool bTemporary = false);
void RBPClear();
bool WBPAdd(uint32_t address, bool bTemporary = false);
void WBPRemove(uint32_t address);
void WBPToggle(uint32_t address, bool bTemporary = false);
void WBPClear();
bool EBPAdd(uint32_t address, bool bTemporary = false);
void EBPRemove(uint32_t address);
void EBPToggle(uint32_t address, bool bTemporary = false);
void EBPClear();
void BPClear();
// inlines
inline BPSTATE RBPExists(uint32_t address, bool bRemoveTemp = false)
{
for (int i = 0; i < m_nRBP; i++)
{
if (m_RBP[i].address != address)
{
continue;
}
if (m_RBP[i].bTemporary)
{
if (bRemoveTemp)
{
RBPRemove(address);
}
return BP_SET_TEMP;
}
return BP_SET;
}
return BP_NOT_SET;
}
inline BPSTATE WBPExists(uint32_t address, bool bRemoveTemp = false)
{
for (int i = 0; i < m_nWBP; i++)
{
if (m_WBP[i].address != address)
{
continue;
}
if (m_WBP[i].bTemporary)
{
if (bRemoveTemp)
{
WBPRemove(address);
}
return BP_SET_TEMP;
}
return BP_SET;
}
return BP_NOT_SET;
}
inline BPSTATE EBPExists(uint32_t address, bool bRemoveTemp = false)
{
for (int i = 0; i < m_nEBP; i++)
{
if (m_EBP[i].address != address)
{
continue;
}
if (m_EBP[i].bTemporary)
{
if (bRemoveTemp)
{
EBPRemove(address);
}
return BP_SET_TEMP;
}
return BP_SET;
}
return BP_NOT_SET;
}
};

View File

@ -0,0 +1,111 @@
/****************************************************************************
* *
* Project64 - A Nintendo 64 emulator. *
* http://www.pj64-emu.com/ *
* Copyright (C) 2012 Project64. All rights reserved. *
* *
* License: *
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
* *
****************************************************************************/
#include "stdafx.h"
#include "DMALog.h"
void CDMALog::AddEntry(uint32_t romAddr, uint32_t ramAddr, uint32_t length)
{
DMALOGENTRY entry = { romAddr, ramAddr, length };
m_Log.push_back(entry);
}
void CDMALog::ClearEntries()
{
m_Log.clear();
}
size_t CDMALog::GetNumEntries()
{
return m_Log.size();
}
DMALOGENTRY* CDMALog::GetEntryByIndex(uint32_t index)
{
if (index < m_Log.size())
{
return &m_Log[index];
}
return NULL;
}
DMALOGENTRY* CDMALog::GetEntryByRamAddress(uint32_t ramAddr)
{
uint32_t nEntries = GetNumEntries();
if (nEntries == 0)
{
return NULL;
}
for (uint32_t i = nEntries - 1; i-- > 0;)
{
uint32_t min = m_Log[i].ramAddr;
uint32_t max = min + m_Log[i].length - 1;
if (ramAddr >= min && ramAddr <= max)
{
return &m_Log[i];
}
}
return NULL;
}
DMALOGENTRY* CDMALog::GetEntryByRamAddress(uint32_t ramAddr, uint32_t* lpRomAddr, uint32_t* lpOffset)
{
DMALOGENTRY* lpEntry = GetEntryByRamAddress(ramAddr);
if (lpEntry == NULL)
{
return NULL;
}
*lpOffset = ramAddr - lpEntry->ramAddr;
*lpRomAddr = lpEntry->romAddr + *lpOffset;
return lpEntry;
}
DMALOGENTRY* CDMALog::GetEntryByRomAddress(uint32_t romAddr)
{
uint32_t nEntries = GetNumEntries();
if (nEntries == 0)
{
return NULL;
}
for (uint32_t i = nEntries - 1; i-- > 0; )
{
uint32_t min = m_Log[i].romAddr;
uint32_t max = min + m_Log[i].length - 1;
if (romAddr >= min && romAddr <= max)
{
return &m_Log[i];
}
}
return NULL;
}
DMALOGENTRY* CDMALog::GetEntryByRomAddress(uint32_t romAddr, uint32_t* lpRamAddr, uint32_t* lpOffset)
{
DMALOGENTRY* lpEntry = GetEntryByRomAddress(romAddr);
if (lpEntry == NULL)
{
return NULL;
}
*lpOffset = romAddr - lpEntry->romAddr;
*lpRamAddr = lpEntry->ramAddr + *lpOffset;
return lpEntry;
}

View File

@ -0,0 +1,36 @@
/****************************************************************************
* *
* Project64 - A Nintendo 64 emulator. *
* http://www.pj64-emu.com/ *
* Copyright (C) 2012 Project64. All rights reserved. *
* *
* License: *
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
* *
****************************************************************************/
#pragma once
#include <stdafx.h>
struct DMALOGENTRY
{
uint32_t romAddr;
uint32_t ramAddr;
uint32_t length;
};
class CDMALog
{
private:
vector<DMALOGENTRY> m_Log;
public:
void AddEntry(uint32_t romAddr, uint32_t ramAddr, uint32_t length);
void ClearEntries();
size_t GetNumEntries();
DMALOGENTRY* GetEntryByIndex(uint32_t index);
DMALOGENTRY* GetEntryByRamAddress(uint32_t ramAddr);
DMALOGENTRY* GetEntryByRamAddress(uint32_t ramAddr, uint32_t* lpRomAddr, uint32_t* lpOffset);
DMALOGENTRY* GetEntryByRomAddress(uint32_t romAddr);
DMALOGENTRY* GetEntryByRomAddress(uint32_t romAddr, uint32_t* lpRamAddr, uint32_t* lpOffset);
};

View File

@ -0,0 +1,58 @@
/****************************************************************************
* *
* Project64 - A Nintendo 64 emulator. *
* http://www.pj64-emu.com/ *
* Copyright (C) 2012 Project64. All rights reserved. *
* *
* License: *
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
* *
****************************************************************************/
#include "stdafx.h"
#include "DebuggerUI.h"
LRESULT CAddBreakpointDlg::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
CenterWindow();
m_AddressEdit.Attach(GetDlgItem(IDC_ADDR_EDIT));
m_ReadCheck.Attach(GetDlgItem(IDC_CHK_READ));
m_WriteCheck.Attach(GetDlgItem(IDC_CHK_WRITE));
m_ExecuteCheck.Attach(GetDlgItem(IDC_CHK_EXEC));
return FALSE;
}
LRESULT CAddBreakpointDlg::OnClicked(WORD /*wNotifyCode*/, WORD wID, HWND, BOOL& /*bHandled*/)
{
switch (wID)
{
case IDOK:
{
char addrStr[9];
m_AddressEdit.GetWindowTextA(addrStr, 9);
uint32_t address = strtoul(addrStr, NULL, 16);
CBreakpoints* breakpoints = m_Debugger->Breakpoints();
if (m_ReadCheck.GetCheck())
{
breakpoints->RBPAdd(address);
}
if (m_WriteCheck.GetCheck())
{
breakpoints->WBPAdd(address);
}
if (m_ExecuteCheck.GetCheck())
{
breakpoints->EBPAdd(address);
}
EndDialog(0);
break;
}
case IDCANCEL:
EndDialog(0);
break;
}
return FALSE;
}

View File

@ -0,0 +1,47 @@
/****************************************************************************
* *
* Project64 - A Nintendo 64 emulator. *
* http://www.pj64-emu.com/ *
* Copyright (C) 2012 Project64. All rights reserved. *
* *
* License: *
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
* *
****************************************************************************/
#pragma once
// Modal add breakpoint dialog
class CAddBreakpointDlg : public CDialogImpl<CAddBreakpointDlg>
{
public:
enum { IDD = IDD_Debugger_AddBreakpoint };
INT_PTR CAddBreakpointDlg::DoModal(CDebuggerUI* debugger)
{
m_Debugger = debugger;
return CDialogImpl<CAddBreakpointDlg>::DoModal();
}
private:
CDebuggerUI* m_Debugger;
CButton m_ReadCheck;
CButton m_WriteCheck;
CButton m_ExecuteCheck;
CEdit m_AddressEdit;
LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
LRESULT OnClicked(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
LRESULT OnDestroy(void)
{
return 0;
}
BEGIN_MSG_MAP_EX(CAddBreakpointDlg)
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
COMMAND_CODE_HANDLER(BN_CLICKED, OnClicked)
MSG_WM_DESTROY(OnDestroy)
END_MSG_MAP()
};

View File

@ -0,0 +1,131 @@
/****************************************************************************
* *
* Project64 - A Nintendo 64 emulator. *
* http://www.pj64-emu.com/ *
* Copyright (C) 2012 Project64. All rights reserved. *
* *
* License: *
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
* *
****************************************************************************/
#include "stdafx.h"
#include "DebuggerUI.h"
#include "Symbols.h"
LRESULT CAddSymbolDlg::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
CenterWindow();
m_AddressEdit.Attach(GetDlgItem(IDC_ADDR_EDIT));
m_AddressEdit.SetDisplayType(CEditNumber::DisplayHex);
m_TypeComboBox.Attach(GetDlgItem(IDC_TYPE_COMBOBOX));
m_NameEdit.Attach(GetDlgItem(IDC_NAME_EDIT));
m_DescriptionEdit.Attach(GetDlgItem(IDC_DESC_EDIT));
for (int i = 0;; i++)
{
char* type = CSymbols::SymbolTypes[i];
if (type == NULL)
{
break;
}
m_TypeComboBox.AddString(type);
}
m_AddressEdit.SetWindowTextA("");
m_AddressEdit.SetFocus();
if (m_bHaveAddress)
{
m_AddressEdit.SetValue(m_InitAddress, false, true);
m_TypeComboBox.SetFocus();
}
if(m_bHaveType)
{
m_TypeComboBox.SetCurSel(m_InitType);
m_NameEdit.SetFocus();
}
else
{
m_TypeComboBox.SetCurSel(CSymbols::TYPE_DATA);
}
return FALSE;
}
LRESULT CAddSymbolDlg::OnClicked(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
{
switch (wID)
{
case IDCANCEL:
EndDialog(0);
break;
case IDOK:
int addrLen = m_AddressEdit.GetWindowTextLengthA();
if (!addrLen)
{
MessageBox("Address required", "Error", MB_OK);
return 0;
}
uint32_t address = m_AddressEdit.GetValue();
int type = m_TypeComboBox.GetCurSel();
int nameLen = m_NameEdit.GetWindowTextLengthA();
int descLen = m_DescriptionEdit.GetWindowTextLengthA();
if (!nameLen && !descLen)
{
MessageBox("Name and/or description required", "Error", MB_OK);
return 0;
}
char name[128];
char description[256];
m_NameEdit.GetWindowTextA(name, nameLen + 1);
m_DescriptionEdit.GetWindowTextA(description, descLen + 1);
CSymbols::EnterCriticalSection();
CSymbols::Add(type, address, name, description);
CSymbols::Save();
CSymbols::LeaveCriticalSection();
m_Debugger->Debug_RefreshSymbolsWindow();
EndDialog(0);
break;
}
return 0;
}
INT_PTR CAddSymbolDlg::DoModal(CDebuggerUI* debugger)
{
m_Debugger = debugger;
m_bHaveAddress = false;
m_bHaveType = false;
return CDialogImpl<CAddSymbolDlg>::DoModal();
}
INT_PTR CAddSymbolDlg::DoModal(CDebuggerUI* debugger, uint32_t initAddress)
{
m_Debugger = debugger;
m_bHaveAddress = true;
m_bHaveType = false;
m_InitAddress = initAddress;
return CDialogImpl<CAddSymbolDlg>::DoModal();
}
INT_PTR CAddSymbolDlg::DoModal(CDebuggerUI* debugger, uint32_t initAddress, int initType)
{
m_Debugger = debugger;
m_bHaveAddress = true;
m_bHaveType = true;
m_InitAddress = initAddress;
m_InitType = initType;
return CDialogImpl<CAddSymbolDlg>::DoModal();
}

View File

@ -0,0 +1,50 @@
/****************************************************************************
* *
* Project64 - A Nintendo 64 emulator. *
* http://www.pj64-emu.com/ *
* Copyright (C) 2012 Project64. All rights reserved. *
* *
* License: *
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
* *
****************************************************************************/
#pragma once
// Modal add symbol dialog
class CAddSymbolDlg : public CDialogImpl<CAddSymbolDlg>
{
public:
enum { IDD = IDD_Debugger_AddSymbol };
INT_PTR DoModal(CDebuggerUI* debugger);
INT_PTR DoModal(CDebuggerUI* debugger, uint32_t initAddress);
INT_PTR DoModal(CDebuggerUI* debugger, uint32_t initAddress, int initType);
private:
CDebuggerUI* m_Debugger;
bool m_bHaveAddress;
bool m_bHaveType;
uint32_t m_InitAddress;
int m_InitType;
CEditNumber m_AddressEdit;
CComboBox m_TypeComboBox;
CEdit m_NameEdit;
CEdit m_DescriptionEdit;
LRESULT OnClicked(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
LRESULT OnDestroy(void)
{
return 0;
}
BEGIN_MSG_MAP_EX(CAddSymbolDlg)
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
COMMAND_CODE_HANDLER(BN_CLICKED, OnClicked)
MSG_WM_DESTROY(OnDestroy)
END_MSG_MAP()
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,271 @@
/****************************************************************************
* *
* Project64 - A Nintendo 64 emulator. *
* http://www.pj64-emu.com/ *
* Copyright (C) 2012 Project64. All rights reserved. *
* *
* License: *
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
* *
****************************************************************************/
#pragma once
#include "OpInfo.h"
#include "Breakpoints.h"
#include "Debugger-AddBreakpoint.h"
#include "Debugger-RegisterTabs.h"
#include <Project64/UserInterface/WTLControls/TooltipDialog.h>
class CCommandList : public CWindowImpl<CCommandList, CListViewCtrl>
{
public:
enum {
COL_ARROWS,
COL_ADDRESS,
COL_COMMAND,
COL_PARAMETERS,
COL_SYMBOL
};
enum {
ROW_HEIGHT = 13,
};
void Attach(HWND hWndNew)
{
CListViewCtrl::Attach(hWndNew);
ModifyStyle(LVS_OWNERDRAWFIXED, 0, 0);
SetExtendedListViewStyle(LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER | LVS_EX_LABELTIP);
AddColumn("", COL_ARROWS);
AddColumn("Address", COL_ADDRESS);
AddColumn("Command", COL_COMMAND);
AddColumn("Parameters", COL_PARAMETERS);
AddColumn("Symbol", COL_SYMBOL);
SetColumnWidth(COL_ARROWS, 30);
SetColumnWidth(COL_ADDRESS, 65);
SetColumnWidth(COL_COMMAND, 60);
SetColumnWidth(COL_PARAMETERS, 120);
SetColumnWidth(COL_SYMBOL, 140);
}
BEGIN_MSG_MAP_EX(CCommandsList)
END_MSG_MAP()
};
class CEditOp;
class CDebugCommandsView;
class CEditOp : public CWindowImpl<CEditOp, CEdit>
{
private:
CDebugCommandsView* m_CommandsWindow;
LRESULT OnKeyDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnKeyUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
if (wParam == VK_RETURN || wParam == VK_ESCAPE)
{
bHandled = TRUE;
return 0;
}
bHandled = FALSE;
return 0;
}
BEGIN_MSG_MAP_EX(CEditOp)
MESSAGE_HANDLER(WM_KEYDOWN, OnKeyDown)
MESSAGE_HANDLER(WM_KEYUP, OnKeyUp)
MESSAGE_HANDLER(WM_CHAR, OnKeyUp)
END_MSG_MAP()
public:
void SetCommandsWindow(CDebugCommandsView* commandsWindow);
BOOL Attach(HWND hWndNew);
};
class CDebugCommandsView :
public CDebugDialog<CDebugCommandsView>,
public CDialogResize<CDebugCommandsView>,
public CToolTipDialog<CDebugCommandsView>
{
friend class CEditOp;
public:
enum { IDD = IDD_Debugger_Commands };
CDebugCommandsView(CDebuggerUI * debugger);
virtual ~CDebugCommandsView(void);
void ShowAddress(DWORD address, BOOL top);
void ShowPIRegTab();
void Reset();
private:
CBreakpoints* m_Breakpoints;
vector<uint32_t> m_History;
int m_HistoryIndex;
CAddBreakpointDlg m_AddBreakpointDlg;
CAddSymbolDlg m_AddSymbolDlg;
DWORD m_StartAddress;
CRect m_DefaultWindowRect;
CEditNumber m_PCEdit;
bool m_bIgnorePCChange;
CEditNumber m_AddressEdit;
bool m_bIgnoreAddrChange;
CCommandList m_CommandList;
int m_CommandListRows;
CListBox m_BreakpointList;
CScrollBar m_Scrollbar;
CRegisterTabs m_RegisterTabs;
CButton m_BackButton;
CButton m_ForwardButton;
CButton m_ViewPCButton;
CButton m_StepButton;
CButton m_SkipButton;
CButton m_GoButton;
bool m_bEditing;
CEditOp m_OpEdit;
uint32_t m_SelectedAddress;
COpInfo m_SelectedOpInfo;
OPCODE& m_SelectedOpCode = m_SelectedOpInfo.m_OpCode;
uint32_t m_FollowAddress;
typedef struct {
uint32_t address;
uint32_t originalOp;
} EditedOp;
vector<EditedOp> m_EditedOps;
typedef struct {
int startPos;
int endPos;
int startMargin;
int endMargin;
int margin;
} BRANCHARROW;
vector<BRANCHARROW> m_BranchArrows;
void AddBranchArrow(int startPos, int endPos);
void ClearBranchArrows();
void DrawBranchArrows(HDC listDC);
vector<bool> m_bvAnnotatedLines;
void ClearEditedOps();
void EditOp(uint32_t address, uint32_t op);
void RestoreOp(uint32_t address);
void RestoreAllOps();
BOOL IsOpEdited(uint32_t address);
void BeginOpEdit(uint32_t address);
void EndOpEdit();
void GotoEnteredAddress();
void CheckCPUType();
void RefreshBreakpointList();
void RemoveSelectedBreakpoints();
bool AddressSafe(uint32_t vaddr);
void HistoryPushState();
void ToggleHistoryButtons();
static CDebugCommandsView* _this;
static HHOOK hWinMessageHook;
static LRESULT CALLBACK HookProc(int nCode, WPARAM wParam, LPARAM lParam);
void InterceptKeyDown(WPARAM wParam, LPARAM lParam);
void InterceptMouseWheel(WPARAM wParam, LPARAM lParam);
static const char* GetCodeAddressNotes(uint32_t vAddr);
static const char* GetDataAddressNotes(uint32_t vAddr);
void CPUSkip();
void CPUStepInto();
void CPUResume();
LRESULT OnInitDialog (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnActivate (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnSizing (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnScroll (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnMeasureItem (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnAddrChanged (WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
LRESULT OnPCChanged (WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
LRESULT OnListBoxClicked (WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
LRESULT OnClicked (WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
LRESULT OnOpKeyDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnCommandListClicked(NMHDR* pNMHDR);
LRESULT OnCommandListDblClicked(NMHDR* pNMHDR);
LRESULT OnCommandListRightClicked (NMHDR* pNMHDR);
LRESULT OnRegisterTabChange (NMHDR* pNMHDR);
LRESULT OnCustomDrawList (NMHDR* pNMHDR);
LRESULT OnDestroy (void);
BEGIN_MSG_MAP_EX(CDebugCommandsView)
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
MESSAGE_HANDLER(WM_ACTIVATE, OnActivate)
MESSAGE_HANDLER(WM_SIZING, OnSizing)
MESSAGE_HANDLER(WM_GETMINMAXINFO, OnGetMinMaxInfo)
MESSAGE_HANDLER(WM_VSCROLL, OnScroll)
MESSAGE_HANDLER(WM_MEASUREITEM, OnMeasureItem)
COMMAND_HANDLER(IDC_ADDR_EDIT, EN_CHANGE, OnAddrChanged)
COMMAND_HANDLER(IDC_PC_EDIT, EN_CHANGE, OnPCChanged)
COMMAND_CODE_HANDLER(LBN_DBLCLK, OnListBoxClicked)
COMMAND_CODE_HANDLER(BN_CLICKED, OnClicked)
NOTIFY_HANDLER_EX(IDC_CMD_LIST, NM_CLICK, OnCommandListClicked)
NOTIFY_HANDLER_EX(IDC_CMD_LIST, NM_DBLCLK, OnCommandListDblClicked)
NOTIFY_HANDLER_EX(IDC_CMD_LIST, NM_RCLICK, OnCommandListRightClicked)
NOTIFY_HANDLER_EX(IDC_REG_TABS, TCN_SELCHANGE, OnRegisterTabChange)
NOTIFY_HANDLER_EX(IDC_CMD_LIST, NM_CUSTOMDRAW, OnCustomDrawList)
MSG_WM_DESTROY(OnDestroy)
CHAIN_MSG_MAP(CDialogResize<CDebugCommandsView>)
END_MSG_MAP()
BEGIN_DLGRESIZE_MAP(CDebugCommandsView)
DLGRESIZE_CONTROL(IDC_GO_BTN, DLSZ_MOVE_X)
DLGRESIZE_CONTROL(IDC_STEP_BTN, DLSZ_MOVE_X)
DLGRESIZE_CONTROL(IDC_SKIP_BTN, DLSZ_MOVE_X)
DLGRESIZE_CONTROL(IDC_ADDR_EDIT, DLSZ_MOVE_X)
DLGRESIZE_CONTROL(IDC_SYMBOLS_BTN, DLSZ_MOVE_X)
DLGRESIZE_CONTROL(IDC_OPCODE_BOX, DLSZ_MOVE_X)
DLGRESIZE_CONTROL(IDC_BP_LIST, DLSZ_MOVE_X)
DLGRESIZE_CONTROL(IDC_ADDBP_BTN, DLSZ_MOVE_X)
DLGRESIZE_CONTROL(IDC_RMBP_BTN, DLSZ_MOVE_X)
DLGRESIZE_CONTROL(IDC_CLEARBP_BTN, DLSZ_MOVE_X)
DLGRESIZE_CONTROL(IDC_REG_TABS, DLSZ_MOVE_X)
DLGRESIZE_CONTROL(IDC_BACK_BTN, DLSZ_MOVE_X)
DLGRESIZE_CONTROL(IDC_FORWARD_BTN, DLSZ_MOVE_X)
DLGRESIZE_CONTROL(IDC_PC_STATIC, DLSZ_MOVE_X)
DLGRESIZE_CONTROL(IDC_PC_EDIT, DLSZ_MOVE_X)
DLGRESIZE_CONTROL(IDC_VIEWPC_BTN, DLSZ_MOVE_X)
DLGRESIZE_CONTROL(IDC_CMD_LIST, DLSZ_SIZE_X | DLSZ_SIZE_Y)
DLGRESIZE_CONTROL(IDC_SCRL_BAR, DLSZ_MOVE_X | DLSZ_SIZE_Y)
END_DLGRESIZE_MAP()
BEGIN_TOOLTIP_MAP()
TOOLTIP(IDC_SKIP_BTN, "Skip (F1)")
TOOLTIP(IDC_STEP_BTN, "Step (F2)")
TOOLTIP(IDC_GO_BTN, "Go (F4)")
TOOLTIP(IDC_ADDBP_BTN, "Add breakpoint...")
TOOLTIP(IDC_RMBP_BTN, "Remove selected breakpoint")
TOOLTIP(IDC_CLEARBP_BTN, "Remove all breakpoints")
TOOLTIP(IDC_VIEWPC_BTN, "Jump to program counter")
TOOLTIP(IDC_BP_LIST, "Active breakpoints")
TOOLTIP(IDC_SYMBOLS_BTN, "Symbols...")
END_TOOLTIP_MAP()
};

View File

@ -0,0 +1,338 @@
/****************************************************************************
* *
* Project64 - A Nintendo 64 emulator. *
* http://www.pj64-emu.com/ *
* Copyright (C) 2012 Project64. All rights reserved. *
* *
* License: *
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
* *
****************************************************************************/
#include "stdafx.h"
#include "DebuggerUI.h"
#include "DMALog.h"
CDebugDMALogView::CDebugDMALogView(CDebuggerUI* debugger) :
CDebugDialog<CDebugDMALogView>(debugger)
{
m_DMALog = debugger->DMALog();
m_bFilterChanged = false;
m_bUniqueRomAddresses = true;
m_bCustomDrawClrNext = false;
}
CDebugDMALogView::~CDebugDMALogView()
{
}
/*
bool CDebugDMALogView::FilterEntry(int dmaLogIndex)
{
DMALogEntry entry = m_Debugger->DMALog()->at(dmaLogIndex);
for (int i = 0; i < dmaLogIndex; i++)
{
DMALogEntry testEntry = m_Debugger->DMALog()->at(i);
// Don't show if another entry has the same ROM address
if (entry.romAddr == testEntry.romAddr)
{
return false;
}
}
return true;
}
*/
void CDebugDMALogView::RefreshList()
{
if (g_Rom == NULL)
{
return;
}
uint8_t* rom = g_Rom->GetRomAddress();
// Get scrollbar state
SCROLLINFO scroll;
scroll.cbSize = sizeof(SCROLLINFO);
scroll.fMask = SIF_ALL;
m_DMAList.GetScrollInfo(SB_VERT, &scroll);
bool bScrolledDown = false;
if ((scroll.nPage + scroll.nPos) - 1 == scroll.nMax)
{
bScrolledDown = true;
}
int startIndex;
int dmaLogSize = m_Debugger->DMALog()->GetNumEntries();
if (dmaLogSize == 0)
{
// Reset
m_DMAList.DeleteAllItems();
startIndex = 0;
m_bFilterChanged = false;
}
else
{
// Continue from last index
startIndex = m_nLastStartIndex;
}
m_DMAList.SetRedraw(FALSE);
int itemIndex = m_DMAList.GetItemCount();
for (int i = startIndex; i < dmaLogSize; i++)
{
DMALOGENTRY* lpEntry = m_DMALog->GetEntryByIndex(i);
//if (!FilterEntry(i))
//{
// continue;
//}
m_DMAList.AddItem(itemIndex, 0, stdstr_f("%08X", lpEntry->romAddr).c_str());
m_DMAList.AddItem(itemIndex, 1, stdstr_f("%08X", lpEntry->ramAddr).c_str());
m_DMAList.AddItem(itemIndex, 2, stdstr_f("%08X (%d)", lpEntry->length, lpEntry->length).c_str());
uint32_t sig = *(uint32_t*)&rom[lpEntry->romAddr];
sig = _byteswap_ulong(sig);
char sigc[5];
memcpy(sigc, &sig, 4);
sigc[4] = '\0';
// Todo checkbox to display all in hex
if (isalnum(sigc[0]) && isalnum(sigc[1]) && isalnum(sigc[2]) && isalnum(sigc[3]))
{
m_DMAList.AddItem(itemIndex, 4, sigc);
}
itemIndex++;
}
if (bScrolledDown)
{
m_DMAList.EnsureVisible(m_DMAList.GetItemCount() - 1, FALSE);
}
m_DMAList.SetRedraw(TRUE);
m_nLastStartIndex = dmaLogSize;
}
DWORD WINAPI CDebugDMALogView::AutoRefreshProc(void* _this)
{
CDebugDMALogView* self = (CDebugDMALogView*)_this;
while (true)
{
self->RefreshList();
Sleep(100);
}
}
LRESULT CDebugDMALogView::OnActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
//RefreshList();
return FALSE;
}
LRESULT CDebugDMALogView::OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
DlgResize_Init(false, true);
m_bConvertingAddress = false;
m_nLastStartIndex = 0;
m_DMAList.Attach(GetDlgItem(IDC_DMA_LIST));
m_DMAList.ModifyStyle(LVS_OWNERDRAWFIXED, 0, 0);
m_DMAList.AddColumn("ROM", 0);
m_DMAList.AddColumn("RAM", 1);
m_DMAList.AddColumn("Length", 2);
m_DMAList.AddColumn("Symbol (RAM)", 3);
m_DMAList.AddColumn("Signature", 4);
m_DMAList.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER);
m_DMAList.SetColumnWidth(0, 65);
m_DMAList.SetColumnWidth(1, 65);
m_DMAList.SetColumnWidth(2, 120);
//m_DMAList.SetColumnWidth(3, 50);
//m_DMAList.SetColumnWidth(4, 50);
//m_DMAList.SetColumnWidth(5, 50);
m_DMARamEdit.Attach(GetDlgItem(IDC_DMA_RAM_EDIT));
m_DMARamEdit.SetLimitText(8);
m_DMARomEdit.Attach(GetDlgItem(IDC_DMA_ROM_EDIT));
m_DMARomEdit.SetLimitText(8);
m_BlockInfo.Attach(GetDlgItem(IDC_BLOCK_INFO));
RefreshList();
WindowCreated();
m_AutoRefreshThread = CreateThread(NULL, 0, AutoRefreshProc, (void*)this, 0, NULL);
return TRUE;
}
LRESULT CDebugDMALogView::OnDestroy(void)
{
if (m_AutoRefreshThread != NULL)
{
TerminateThread(m_AutoRefreshThread, 0);
CloseHandle(m_AutoRefreshThread);
}
return 0;
}
LRESULT CDebugDMALogView::OnClicked(WORD /*wNotifyCode*/, WORD wID, HWND, BOOL& /*bHandled*/)
{
switch (wID)
{
case IDOK:
EndDialog(0);
break;
case IDCANCEL:
EndDialog(0);
break;
case IDC_CLEAR_BTN:
m_DMALog->ClearEntries();
RefreshList();
break;
}
return FALSE;
}
LRESULT CDebugDMALogView::OnRamAddrChanged(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
{
if (m_bConvertingAddress)
{
return FALSE;
}
char szRamAddr[9];
char szRomAddr[9];
m_DMARamEdit.GetWindowTextA(szRamAddr, 9);
uint32_t ramAddr = strtoul(szRamAddr, NULL, 16);
uint32_t romAddr, offset;
DMALOGENTRY* lpEntry = m_DMALog->GetEntryByRamAddress(ramAddr, &romAddr, &offset);
if (lpEntry != NULL)
{
sprintf(szRomAddr, "%08X", romAddr);
stdstr blockInfo = stdstr_f("Block: %08X -> %08X [%X] +%X", romAddr, ramAddr, lpEntry->length, offset);
m_BlockInfo.SetWindowTextA(blockInfo.c_str());
}
else
{
sprintf(szRomAddr, "????????");
m_BlockInfo.SetWindowTextA("Block: ?");
}
m_bConvertingAddress = true;
m_DMARomEdit.SetWindowTextA(szRomAddr);
m_bConvertingAddress = false;
return FALSE;
}
LRESULT CDebugDMALogView::OnRomAddrChanged(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
{
if (m_bConvertingAddress)
{
return FALSE;
}
char szRamAddr[9];
char szRomAddr[9];
m_DMARomEdit.GetWindowTextA(szRomAddr, 9);
uint32_t romAddr = strtoul(szRomAddr, NULL, 16);
uint32_t ramAddr, offset;
DMALOGENTRY* lpEntry = m_DMALog->GetEntryByRomAddress(romAddr, &ramAddr, &offset);
if (lpEntry != NULL)
{
sprintf(szRamAddr, "%08X", ramAddr);
stdstr blockInfo = stdstr_f("Block: %08X -> %08X [%X] +%X", romAddr, ramAddr, lpEntry->length, offset);
m_BlockInfo.SetWindowTextA(blockInfo.c_str());
}
else
{
sprintf(szRamAddr, "????????");
m_BlockInfo.SetWindowTextA("Block: ?");
}
m_bConvertingAddress = true;
m_DMARamEdit.SetWindowTextA(szRamAddr);
m_bConvertingAddress = false;
return FALSE;
}
LRESULT CDebugDMALogView::OnCustomDrawList(NMHDR* pNMHDR)
{
NMLVCUSTOMDRAW* pLVCD = reinterpret_cast<NMLVCUSTOMDRAW*>(pNMHDR);
DWORD drawStage = pLVCD->nmcd.dwDrawStage;
switch (drawStage)
{
case CDDS_PREPAINT: return CDRF_NOTIFYITEMDRAW;
case CDDS_ITEMPREPAINT: return CDRF_NOTIFYSUBITEMDRAW;
case (CDDS_ITEMPREPAINT | CDDS_SUBITEM): break;
default: return CDRF_DODEFAULT;
}
DWORD nItem = pLVCD->nmcd.dwItemSpec;
DWORD nSubItem = pLVCD->iSubItem;
if (nSubItem != 0)
{
return CDRF_DODEFAULT;
}
size_t nEntries = m_DMALog->GetNumEntries();
if (nEntries == 0)
{
return CDRF_DODEFAULT;
}
DMALOGENTRY* lpEntry = m_DMALog->GetEntryByIndex(nItem);
if (nItem >= 1) // continuation
{
DMALOGENTRY* lpPrevEntry = m_DMALog->GetEntryByIndex(nItem - 1);
if (lpEntry->romAddr == lpPrevEntry->romAddr + lpPrevEntry->length)
{
pLVCD->clrTextBk = RGB(0xFF, 0xFF, 0xCC);
return CDRF_DODEFAULT;
}
}
if (nEntries >= 2 && nItem <= nEntries - 2) // head
{
DMALOGENTRY* lpNextEntry = m_DMALog->GetEntryByIndex(nItem + 1);
if (lpNextEntry->romAddr == lpEntry->romAddr + lpEntry->length)
{
pLVCD->clrTextBk = RGB(0xFF, 0xFF, 0x88);
return CDRF_DODEFAULT;
}
}
return CDRF_DODEFAULT;
}

View File

@ -0,0 +1,79 @@
/****************************************************************************
* *
* Project64 - A Nintendo 64 emulator. *
* http://www.pj64-emu.com/ *
* Copyright (C) 2012 Project64. All rights reserved. *
* *
* License: *
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
* *
****************************************************************************/
#pragma once
#include <stdafx.h>
#include "DebuggerUI.h"
class CDebugDMALogView :
public CDebugDialog<CDebugDMALogView>,
public CDialogResize<CDebugDMALogView>
{
public:
enum { IDD = IDD_Debugger_DMALog };
CDebugDMALogView(CDebuggerUI * debugger);
virtual ~CDebugDMALogView(void);
void RefreshList();
private:
CDMALog* m_DMALog;
int m_nLastStartIndex;
bool m_bConvertingAddress;
bool m_bUniqueRomAddresses;
bool m_bFilterChanged;
HANDLE m_AutoRefreshThread;
static DWORD WINAPI AutoRefreshProc(void* _this);
// Return true if entry meets requirements
bool FilterEntry(int dmaLogIndex);
CListViewCtrl m_DMAList;
CEdit m_DMARamEdit;
CEdit m_DMARomEdit;
CStatic m_BlockInfo;
bool m_bCustomDrawClrNext;
LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
LRESULT OnClicked(WORD wNotifyCode, WORD wID, HWND /*hWndCtl*/, BOOL& bHandled);
LRESULT OnActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnRamAddrChanged(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
LRESULT OnRomAddrChanged(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
LRESULT OnCustomDrawList(NMHDR* pNMHDR);
LRESULT OnDestroy(void);
BEGIN_MSG_MAP_EX(CDebugDMALogView)
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
COMMAND_CODE_HANDLER(BN_CLICKED, OnClicked)
MESSAGE_HANDLER(WM_ACTIVATE, OnActivate)
COMMAND_HANDLER(IDC_DMA_RAM_EDIT, EN_CHANGE, OnRamAddrChanged)
COMMAND_HANDLER(IDC_DMA_ROM_EDIT, EN_CHANGE, OnRomAddrChanged)
NOTIFY_HANDLER_EX(IDC_DMA_LIST, NM_CUSTOMDRAW, OnCustomDrawList)
CHAIN_MSG_MAP(CDialogResize<CDebugDMALogView>)
END_MSG_MAP()
BEGIN_DLGRESIZE_MAP(CDebugDMALogView)
DLGRESIZE_CONTROL(IDC_DMA_LIST, DLSZ_SIZE_X | DLSZ_SIZE_Y)
DLGRESIZE_CONTROL(IDC_TRACE_STATIC, DLSZ_MOVE_Y)
DLGRESIZE_CONTROL(IDC_BLOCK_INFO, DLSZ_MOVE_Y)
DLGRESIZE_CONTROL(IDC_RAM_STATIC, DLSZ_MOVE_Y)
DLGRESIZE_CONTROL(IDC_ROM_STATIC, DLSZ_MOVE_Y)
DLGRESIZE_CONTROL(IDC_DMA_ROM_EDIT, DLSZ_MOVE_Y)
DLGRESIZE_CONTROL(IDC_DMA_RAM_EDIT, DLSZ_MOVE_Y)
DLGRESIZE_CONTROL(IDC_CLEAR_BTN, DLSZ_MOVE_X | DLSZ_MOVE_Y)
DLGRESIZE_CONTROL(IDC_BUTTON1, DLSZ_MOVE_X | DLSZ_MOVE_Y)
END_DLGRESIZE_MAP()
};

View File

@ -12,6 +12,8 @@
#include "DebuggerUI.h"
#include <Project64-core/N64System/Mips/OpCodeName.h>
CDumpMemory::CDumpMemory(CDebuggerUI * debugger) :
CDebugDialog<CDumpMemory>(debugger)
{
@ -26,18 +28,27 @@ LRESULT CDumpMemory::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lPa
m_StartAddress.Attach(GetDlgItem(IDC_E_START_ADDR));
m_EndAddress.Attach(GetDlgItem(IDC_E_END_ADDR));
m_PC.Attach(GetDlgItem(IDC_E_ALT_PC));
m_FormatList.Attach(GetDlgItem(IDC_FORMAT));
m_FileName.Attach(GetDlgItem(IDC_FILENAME));
m_StartAddress.SetDisplayType(CEditNumber::DisplayHex);
m_EndAddress.SetDisplayType(CEditNumber::DisplayHex);
m_PC.SetDisplayType(CEditNumber::DisplayHex);
m_StartAddress.SetValue(0x80000000, true, true);
m_EndAddress.SetValue(0x803FFFF0, true, true);
m_PC.SetValue(0x80000000);
HWND hFormatList = GetDlgItem(IDC_FORMAT);
int pos = ::SendMessage(hFormatList, CB_ADDSTRING, (WPARAM)0, (LPARAM)"TEXT - Disassembly + PC");
::SendMessage(hFormatList, CB_SETITEMDATA, (WPARAM)pos, (LPARAM)DisassemblyWithPC);
::SendMessage(hFormatList, CB_SETCURSEL, (WPARAM)0, (LPARAM)0);
uint32_t startAddress = 0x80000000;
uint32_t endAddress = startAddress + (g_MMU ? g_MMU->RdramSize() : 0x400000);
m_StartAddress.SetValue(startAddress, true, true);
m_EndAddress.SetValue(endAddress, true, true);
m_PC.SetValue(startAddress);
int nIndex = m_FormatList.AddString("TEXT - Disassembly + PC");
m_FormatList.SetItemData(nIndex, (DWORD_PTR)DisassemblyWithPC);
nIndex = m_FormatList.AddString("RAW - Big Endian (N64)");
m_FormatList.SetItemData(nIndex, (LPARAM)RawBigEndian);
m_FormatList.SetCurSel(0);
WindowCreated();
return TRUE;
@ -54,13 +65,28 @@ LRESULT CDumpMemory::OnClicked(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/,
{
g_BaseSystem->ExternalEvent(SysEvent_PauseCPU_DumpMemory);
int CurrentFormatSel = m_FormatList.GetCurSel();
DumpFormat Format = (DumpFormat)m_FormatList.GetItemData(CurrentFormatSel);
const char* FileFilter;
if (Format == RawBigEndian)
{
FileFilter = "Binary file (*.bin)\0*.bin;\0All files (*.*)\0*.*\0";
}
else if (Format == DisassemblyWithPC)
{
FileFilter = "Text file (*.txt)\0*.txt;\0All files (*.*)\0*.*\0";
}
CPath FileName;
if (FileName.SelectFile(m_hWnd, CPath(CPath::MODULE_DIRECTORY), "Text file (*.txt)\0*.txt;\0All files (*.*)\0*.*\0", false))
if (FileName.SelectFile(m_hWnd, CPath(CPath::MODULE_DIRECTORY), FileFilter, false))
{
if (FileName.GetExtension().length() == 0)
{
FileName.SetExtension("txt");
SetDlgItemText(IDC_FILENAME, FileName);
FileName.SetExtension(Format == RawBigEndian ? "bin" : "txt");
m_FileName.SetWindowTextA(FileName);
}
}
g_BaseSystem->ExternalEvent(SysEvent_ResumeCPU_DumpMemory);
@ -69,8 +95,9 @@ LRESULT CDumpMemory::OnClicked(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/,
case IDOK:
{
TCHAR FileName[MAX_PATH];
int CurrentFormatSel = SendDlgItemMessage(IDC_FORMAT, CB_GETCURSEL, 0, 0);
DumpFormat Format = (DumpFormat)SendDlgItemMessage(IDC_FORMAT, CB_GETITEMDATA, CurrentFormatSel, 0);
int CurrentFormatSel = m_FormatList.GetCurSel();
DumpFormat Format = (DumpFormat) m_FormatList.GetItemData(CurrentFormatSel);
DWORD StartPC = m_StartAddress.GetValue();
DWORD EndPC = m_EndAddress.GetValue();
DWORD DumpPC = m_PC.GetValue();
@ -83,7 +110,7 @@ LRESULT CDumpMemory::OnClicked(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/,
}
if (SendDlgItemMessage(IDC_USE_ALT_PC, BM_GETSTATE, 0, 0) != BST_CHECKED)
{
DumpPC = g_Reg->m_PROGRAM_COUNTER;
DumpPC = StartPC;
}
//disable buttons
::EnableWindow(GetDlgItem(IDC_E_START_ADDR), FALSE);
@ -110,35 +137,71 @@ LRESULT CDumpMemory::OnClicked(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/,
return FALSE;
}
bool CDumpMemory::DumpMemory(LPCSTR FileName, DumpFormat Format, DWORD StartPC, DWORD EndPC, DWORD /*DumpPC*/)
bool CDumpMemory::DumpMemory(LPCSTR FileName, DumpFormat Format, DWORD StartPC, DWORD EndPC, DWORD DumpPC)
{
switch (Format)
{
case DisassemblyWithPC:
{
CLog LogFile;
if (!LogFile.Open(FileName))
{
g_Notify->DisplayError(stdstr_f("Failed to open\n%s", FileName).c_str());
return false;
}
LogFile.SetFlush(false);
LogFile.SetTruncateFile(false);
g_Notify->BreakPoint(__FILE__, __LINE__);
#ifdef legacycode
char Command[200];
for (COpcode OpCode(StartPC); OpCode.PC() < EndPC; OpCode.Next())
{
const char * szOpName = OpCode.OpcodeName();
OpCode.OpcodeParam(Command);
LogFile.LogF("%X: %-15s%s\r\n",OpCode.PC(),szOpName,Command);
}
#endif
m_StartAddress.SetValue(StartPC, true, true);
m_EndAddress.SetValue(EndPC, true, true);
return true;
}
break;
}
if (Format == DisassemblyWithPC)
{
CLog LogFile;
if (!LogFile.Open(FileName))
{
g_Notify->DisplayError(stdstr_f("Failed to open\n%s", FileName).c_str());
return false;
}
LogFile.SetFlush(false);
LogFile.SetTruncateFile(false);
for (uint32_t pc = StartPC; pc < EndPC; pc += 4, DumpPC += 4)
{
OPCODE opcode;
g_MMU->LW_VAddr(pc, opcode.Hex);
const char* command = R4300iOpcodeName(opcode.Hex, DumpPC);
char* cmdName = strtok((char*)command, "\t");
char* cmdArgs = strtok(NULL, "\t");
cmdArgs = cmdArgs ? cmdArgs : "";
LogFile.LogF("%X: %-15s%s\r\n", DumpPC, cmdName, cmdArgs);
}
m_StartAddress.SetValue(StartPC, true, true);
m_EndAddress.SetValue(EndPC, true, true);
return true;
}
if (Format == RawBigEndian)
{
CFile dumpFile;
if (!dumpFile.Open(FileName, CFile::modeCreate | CFile::modeWrite))
{
g_Notify->DisplayError(stdstr_f("Failed to open\n%s", FileName).c_str());
return false;
}
uint32_t dumpLen = EndPC - StartPC;
uint8_t* dumpBuf = (uint8_t*)malloc(dumpLen);
uint32_t dumpIdx = 0;
for (uint32_t pc = StartPC; pc < EndPC; pc++, dumpIdx++)
{
bool bReadable = g_MMU->LB_VAddr(pc, dumpBuf[dumpIdx]);
if (!bReadable)
{
g_Notify->DisplayError(stdstr_f("Address error\n%s", FileName).c_str());
dumpFile.Close();
free(dumpBuf);
return false;
}
}
dumpFile.SeekToBegin();
dumpFile.Write(dumpBuf, dumpLen);
dumpFile.Close();
free(dumpBuf);
return true;
}
return false;
}

View File

@ -26,7 +26,8 @@ private:
enum DumpFormat
{
DisassemblyWithPC
DisassemblyWithPC,
RawBigEndian
};
BEGIN_MSG_MAP_EX(CDumpMemory)
@ -39,5 +40,7 @@ private:
bool DumpMemory(LPCSTR FileName, DumpFormat Format, DWORD StartPC, DWORD EndPC, DWORD DumpPC);
CComboBox m_FormatList;
CEdit m_FileName;
CEditNumber m_StartAddress, m_EndAddress, m_PC;
};

View File

@ -188,6 +188,20 @@ LRESULT CDebugMemorySearch::OnResultRClick(LPNMHDR /*lpnmh*/)
return true;
}
LRESULT CDebugMemorySearch::OnResultDblClick(LPNMHDR)
{
LONG iItem = m_SearchResults.GetNextItem(-1, LVNI_SELECTED);
if (iItem == -1)
{
return true;
}
// view in memory
int ItemId = m_SearchResults.GetItemData(iItem);
SearchResultItem & Result = m_SearchResult[ItemId];
m_Debugger->Debug_ShowMemoryLocation(Result.PAddr, false);
}
void CDebugMemorySearch::EnableValueOptions(bool Enable)
{
if (Enable)
@ -261,6 +275,8 @@ void CDebugMemorySearch::SearchForValue(void)
DisplayStr = "0x%04X";
}
m_SearchResults.SetRedraw(FALSE);
if (!m_HaveResults)
{
m_HaveResults = true;
@ -268,7 +284,7 @@ void CDebugMemorySearch::SearchForValue(void)
FixUnknownOptions(false);
m_SearchResults.DeleteAllItems();
DWORD ItemsAdded = 0;
while (SearchForValue(Value, Size, StartAddress, Len))
{
SearchResultItem Result;
@ -294,6 +310,7 @@ void CDebugMemorySearch::SearchForValue(void)
break;
}
}
::SetWindowText(GetDlgItem(IDC_BTN_SEARCH), "Search Results");
::ShowWindow(GetDlgItem(IDC_RESET_BUTTON), SW_SHOW);
::EnableWindow(GetDlgItem(IDC_VALUE_ALIGN), false);
@ -347,6 +364,9 @@ void CDebugMemorySearch::SearchForValue(void)
}
}
}
m_SearchResults.SetRedraw(TRUE);
::SetWindowText(GetDlgItem(IDC_BORDER_RESULTS), stdstr_f("Results (%d)", m_SearchResults.GetItemCount()).c_str());
}

View File

@ -53,11 +53,13 @@ private:
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
COMMAND_CODE_HANDLER(BN_CLICKED, OnClicked)
NOTIFY_HANDLER_EX(IDC_LST_RESULTS, NM_RCLICK, OnResultRClick)
NOTIFY_HANDLER_EX(IDC_LST_RESULTS, NM_DBLCLK, OnResultDblClick)
END_MSG_MAP()
LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
LRESULT OnClicked(WORD wNotifyCode, WORD wID, HWND /*hWndCtl*/, BOOL& bHandled);
LRESULT OnResultRClick(LPNMHDR lpnmh);
LRESULT OnResultDblClick(LPNMHDR lpnmh);
void EnableUnknownOptions(bool Enable);
void EnableValueOptions(bool Enable);

View File

@ -0,0 +1,803 @@
/****************************************************************************
* *
* Project64 - A Nintendo 64 emulator. *
* http://www.pj64-emu.com/ *
* Copyright (C) 2012 Project64. All rights reserved. *
* *
* License: *
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
* *
****************************************************************************/
#include "stdafx.h"
#include "Debugger-RegisterTabs.h"
#include "OpInfo.h"
bool CRegisterTabs::m_bColorsEnabled = false;
void CRegisterTabs::Attach(HWND hWndNew)
{
m_TabWindows.clear();
CTabCtrl::Attach(hWndNew);
HFONT monoFont = CreateFont(-11, 0, 0, 0,
FW_DONTCARE, FALSE, FALSE, FALSE, DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
CLEARTYPE_QUALITY, FF_DONTCARE, "Consolas"
);
m_GPRTab = AddTab("GPR", IDD_Debugger_RegGPR, TabProcGPR);
m_FPRTab = AddTab("FPR", IDD_Debugger_RegFPR, TabProcFPR);
m_COP0Tab = AddTab("COP0", IDD_Debugger_RegCOP0, TabProcDefault);
m_RDRAMTab = AddTab("RDRAM", IDD_Debugger_RegRDRAM, TabProcDefault);
m_SPTab = AddTab("SP", IDD_Debugger_RegSP, TabProcDefault);
m_DPCTab = AddTab("DPC", IDD_Debugger_RegDPC, TabProcDefault);
m_MITab = AddTab("MI", IDD_Debugger_RegMI, TabProcDefault);
m_VITab = AddTab("VI", IDD_Debugger_RegVI, TabProcDefault);
m_AITab = AddTab("AI", IDD_Debugger_RegAI, TabProcDefault);
m_PITab = AddTab("PI", IDD_Debugger_RegPI, TabProcDefault);
m_RITab = AddTab("RI", IDD_Debugger_RegRI, TabProcDefault);
m_SITab = AddTab("SI", IDD_Debugger_RegSI, TabProcDefault);
m_DDTab = AddTab("DD", IDD_Debugger_RegDD, TabProcDefault);
InitRegisterEdits64(m_GPRTab, m_GPREdits, GPREditIds, monoFont);
InitRegisterEdit64(m_GPRTab, m_HIEdit, IDC_HI_EDIT, monoFont);
InitRegisterEdit64(m_GPRTab, m_LOEdit, IDC_LO_EDIT, monoFont);
InitRegisterEdits(m_FPRTab, m_FPREdits, FPREditIds, monoFont);
InitRegisterEdit(m_FPRTab, m_FCSREdit, IDC_FCSR_EDIT, monoFont);
InitRegisterEdits(m_COP0Tab, m_COP0Edits, COP0EditIds, monoFont);
m_CauseTip.Attach(m_COP0Tab.GetDlgItem(IDC_CAUSE_TIP));
InitRegisterEdits(m_RDRAMTab, m_RDRAMEdits, RDRAMEditIds, monoFont);
InitRegisterEdits(m_SPTab, m_SPEdits, SPEditIds, monoFont);
InitRegisterEdit(m_SPTab, m_SPPCEdit, IDC_SP_PC_EDIT, monoFont);
InitRegisterEdits(m_DPCTab, m_DPCEdits, DPCEditIds, monoFont);
InitRegisterEdits(m_MITab, m_MIEdits, MIEditIds, monoFont);
InitRegisterEdits(m_VITab, m_VIEdits, VIEditIds, monoFont);
InitRegisterEdits(m_AITab, m_AIEdits, AIEditIds, monoFont);
InitRegisterEdits(m_PITab, m_PIEdits, PIEditIds, monoFont);
InitRegisterEdits(m_RITab, m_RIEdits, RIEditIds, monoFont);
InitRegisterEdits(m_SITab, m_SIEdits, SIEditIds, monoFont);
InitRegisterEdits(m_DDTab, m_DDEdits, DDEditIds, monoFont);
SetColorsEnabled(false);
RefreshEdits();
RedrawCurrentTab();
}
void CRegisterTabs::RefreshEdits()
{
if (g_Reg == NULL)
{
ZeroRegisterEdits64(m_GPREdits, GPREditIds);
ZeroRegisterEdit64(m_HIEdit);
ZeroRegisterEdit64(m_LOEdit);
ZeroRegisterEdits(m_FPREdits, FPREditIds);
ZeroRegisterEdit(m_FCSREdit);
ZeroRegisterEdits(m_COP0Edits, COP0EditIds);
ZeroRegisterEdits(m_RDRAMEdits, RDRAMEditIds);
ZeroRegisterEdits(m_SPEdits, SPEditIds);
ZeroRegisterEdit(m_SPPCEdit);
ZeroRegisterEdits(m_DPCEdits, DPCEditIds);
ZeroRegisterEdits(m_MIEdits, MIEditIds);
ZeroRegisterEdits(m_VIEdits, VIEditIds);
ZeroRegisterEdits(m_AIEdits, AIEditIds);
ZeroRegisterEdits(m_PIEdits, PIEditIds);
ZeroRegisterEdits(m_RIEdits, RIEditIds);
ZeroRegisterEdits(m_SIEdits, SIEditIds);
ZeroRegisterEdits(m_DDEdits, DDEditIds);
return;
}
for (int i = 0; i < 32; i++)
{
m_GPREdits[i].SetValue(g_Reg->m_GPR[i].UDW);
m_FPREdits[i].SetValue(*(uint32_t *)g_Reg->m_FPR_S[i], false, true);
}
m_HIEdit.SetValue(g_Reg->m_HI.UDW);
m_LOEdit.SetValue(g_Reg->m_LO.UDW);
m_FCSREdit.SetValue(g_Reg->m_FPCR[31], false, true);
m_COP0Edits[0].SetValue(g_Reg->INDEX_REGISTER, false, true);
m_COP0Edits[1].SetValue(g_Reg->RANDOM_REGISTER, false, true);
m_COP0Edits[2].SetValue(g_Reg->ENTRYLO0_REGISTER, false, true);
m_COP0Edits[3].SetValue(g_Reg->ENTRYLO1_REGISTER, false, true);
m_COP0Edits[4].SetValue(g_Reg->CONTEXT_REGISTER, false, true);
m_COP0Edits[5].SetValue(g_Reg->PAGE_MASK_REGISTER, false, true);
m_COP0Edits[6].SetValue(g_Reg->WIRED_REGISTER, false, true);
m_COP0Edits[7].SetValue(g_Reg->BAD_VADDR_REGISTER, false, true);
m_COP0Edits[8].SetValue(g_Reg->COUNT_REGISTER, false, true);
m_COP0Edits[9].SetValue(g_Reg->ENTRYHI_REGISTER, false, true);
m_COP0Edits[10].SetValue(g_Reg->COMPARE_REGISTER, false, true);
m_COP0Edits[11].SetValue(g_Reg->STATUS_REGISTER, false, true);
m_COP0Edits[12].SetValue(g_Reg->CAUSE_REGISTER, false, true);
m_COP0Edits[13].SetValue(g_Reg->EPC_REGISTER, false, true);
m_COP0Edits[14].SetValue(g_Reg->CONFIG_REGISTER, false, true);
m_COP0Edits[15].SetValue(g_Reg->TAGLO_REGISTER, false, true);
m_COP0Edits[16].SetValue(g_Reg->TAGHI_REGISTER, false, true);
m_COP0Edits[17].SetValue(g_Reg->ERROREPC_REGISTER, false, true);
m_COP0Edits[18].SetValue(g_Reg->FAKE_CAUSE_REGISTER, false, true);
CAUSE cause;
cause.intval = g_Reg->CAUSE_REGISTER;
const char* szExceptionCode = ExceptionCodes[cause.exceptionCode];
m_CauseTip.SetWindowTextA(szExceptionCode);
m_RDRAMEdits[0].SetValue(g_Reg->RDRAM_CONFIG_REG, false, true); // or device type
m_RDRAMEdits[1].SetValue(g_Reg->RDRAM_DEVICE_ID_REG, false, true);
m_RDRAMEdits[2].SetValue(g_Reg->RDRAM_DELAY_REG, false, true);
m_RDRAMEdits[3].SetValue(g_Reg->RDRAM_MODE_REG, false, true);
m_RDRAMEdits[4].SetValue(g_Reg->RDRAM_REF_INTERVAL_REG, false, true);
m_RDRAMEdits[5].SetValue(g_Reg->RDRAM_REF_ROW_REG, false, true);
m_RDRAMEdits[6].SetValue(g_Reg->RDRAM_RAS_INTERVAL_REG, false, true);
m_RDRAMEdits[7].SetValue(g_Reg->RDRAM_MIN_INTERVAL_REG, false, true);
m_RDRAMEdits[8].SetValue(g_Reg->RDRAM_ADDR_SELECT_REG, false, true);
m_RDRAMEdits[9].SetValue(g_Reg->RDRAM_DEVICE_MANUF_REG, false, true);
m_SPEdits[0].SetValue(g_Reg->SP_MEM_ADDR_REG, false, true);
m_SPEdits[1].SetValue(g_Reg->SP_DRAM_ADDR_REG, false, true);
m_SPEdits[2].SetValue(g_Reg->SP_RD_LEN_REG, false, true);
m_SPEdits[3].SetValue(g_Reg->SP_WR_LEN_REG, false, true);
m_SPEdits[4].SetValue(g_Reg->SP_STATUS_REG, false, true);
m_SPEdits[5].SetValue(g_Reg->SP_DMA_FULL_REG, false, true);
m_SPEdits[6].SetValue(g_Reg->SP_DMA_BUSY_REG, false, true);
m_SPEdits[7].SetValue(g_Reg->SP_SEMAPHORE_REG, false, true);
m_SPPCEdit.SetValue(g_Reg->SP_PC_REG, false, true);
m_DPCEdits[0].SetValue(g_Reg->DPC_START_REG, false, true);
m_DPCEdits[1].SetValue(g_Reg->DPC_END_REG, false, true);
m_DPCEdits[2].SetValue(g_Reg->DPC_CURRENT_REG, false, true);
m_DPCEdits[3].SetValue(g_Reg->DPC_STATUS_REG, false, true);
m_DPCEdits[4].SetValue(g_Reg->DPC_CLOCK_REG, false, true);
m_DPCEdits[5].SetValue(g_Reg->DPC_BUFBUSY_REG, false, true);
m_DPCEdits[6].SetValue(g_Reg->DPC_PIPEBUSY_REG, false, true);
m_DPCEdits[7].SetValue(g_Reg->DPC_TMEM_REG, false, true);
m_MIEdits[0].SetValue(g_Reg->MI_INIT_MODE_REG, false, true);
m_MIEdits[1].SetValue(g_Reg->MI_VERSION_REG, false, true);
m_MIEdits[2].SetValue(g_Reg->MI_INTR_REG, false, true);
m_MIEdits[3].SetValue(g_Reg->MI_INTR_MASK_REG, false, true);
m_VIEdits[0].SetValue(g_Reg->VI_STATUS_REG, false, true);
m_VIEdits[1].SetValue(g_Reg->VI_ORIGIN_REG, false, true);
m_VIEdits[2].SetValue(g_Reg->VI_WIDTH_REG, false, true);
m_VIEdits[3].SetValue(g_Reg->VI_INTR_REG, false, true);
m_VIEdits[4].SetValue(g_Reg->VI_CURRENT_REG, false, true);
m_VIEdits[5].SetValue(g_Reg->VI_BURST_REG, false, true);
m_VIEdits[6].SetValue(g_Reg->VI_V_SYNC_REG, false, true);
m_VIEdits[7].SetValue(g_Reg->VI_H_SYNC_REG, false, true);
m_VIEdits[8].SetValue(g_Reg->VI_LEAP_REG, false, true);
m_VIEdits[9].SetValue(g_Reg->VI_H_START_REG, false, true);
m_VIEdits[10].SetValue(g_Reg->VI_V_START_REG, false, true);
m_VIEdits[11].SetValue(g_Reg->VI_V_BURST_REG, false, true);
m_VIEdits[12].SetValue(g_Reg->VI_X_SCALE_REG, false, true);
m_VIEdits[13].SetValue(g_Reg->VI_Y_SCALE_REG, false, true);
m_AIEdits[0].SetValue(g_Reg->AI_DRAM_ADDR_REG, false, true);
m_AIEdits[1].SetValue(g_Reg->AI_LEN_REG, false, true);
m_AIEdits[2].SetValue(g_Reg->AI_CONTROL_REG, false, true);
m_AIEdits[3].SetValue(g_Reg->AI_STATUS_REG, false, true);
m_AIEdits[4].SetValue(g_Reg->AI_DACRATE_REG, false, true);
m_AIEdits[5].SetValue(g_Reg->AI_BITRATE_REG, false, true);
m_PIEdits[0].SetValue(g_Reg->PI_DRAM_ADDR_REG, false, true);
m_PIEdits[1].SetValue(g_Reg->PI_CART_ADDR_REG, false, true);
m_PIEdits[2].SetValue(g_Reg->PI_RD_LEN_REG, false, true);
m_PIEdits[3].SetValue(g_Reg->PI_WR_LEN_REG, false, true);
m_PIEdits[4].SetValue(g_Reg->PI_STATUS_REG, false, true);
m_PIEdits[5].SetValue(g_Reg->PI_BSD_DOM1_LAT_REG, false, true);
m_PIEdits[6].SetValue(g_Reg->PI_BSD_DOM1_PWD_REG, false, true);
m_PIEdits[7].SetValue(g_Reg->PI_BSD_DOM1_PGS_REG, false, true);
m_PIEdits[8].SetValue(g_Reg->PI_BSD_DOM1_RLS_REG, false, true);
m_PIEdits[9].SetValue(g_Reg->PI_BSD_DOM2_LAT_REG, false, true);
m_PIEdits[10].SetValue(g_Reg->PI_BSD_DOM2_PWD_REG, false, true);
m_PIEdits[11].SetValue(g_Reg->PI_BSD_DOM2_PGS_REG, false, true);
m_PIEdits[12].SetValue(g_Reg->PI_BSD_DOM2_RLS_REG, false, true);
m_RIEdits[0].SetValue(g_Reg->RI_MODE_REG, false, true);
m_RIEdits[1].SetValue(g_Reg->RI_CONFIG_REG, false, true);
m_RIEdits[2].SetValue(g_Reg->RI_CURRENT_LOAD_REG, false, true);
m_RIEdits[3].SetValue(g_Reg->RI_SELECT_REG, false, true);
m_RIEdits[4].SetValue(g_Reg->RI_REFRESH_REG, false, true); // or ri count
m_RIEdits[5].SetValue(g_Reg->RI_LATENCY_REG, false, true);
m_RIEdits[6].SetValue(g_Reg->RI_RERROR_REG, false, true);
m_RIEdits[7].SetValue(g_Reg->RI_WERROR_REG, false, true);
m_SIEdits[0].SetValue(g_Reg->SI_DRAM_ADDR_REG, false, true);
m_SIEdits[1].SetValue(g_Reg->SI_PIF_ADDR_RD64B_REG, false, true);
m_SIEdits[2].SetValue(g_Reg->SI_PIF_ADDR_WR64B_REG, false, true);
m_SIEdits[3].SetValue(g_Reg->SI_STATUS_REG, false, true);
m_DDEdits[0].SetValue(g_Reg->ASIC_DATA, false, true);
m_DDEdits[1].SetValue(g_Reg->ASIC_MISC_REG, false, true);
m_DDEdits[2].SetValue(g_Reg->ASIC_STATUS, false, true);
m_DDEdits[3].SetValue(g_Reg->ASIC_CUR_TK, false, true);
m_DDEdits[4].SetValue(g_Reg->ASIC_BM_STATUS, false, true);
m_DDEdits[5].SetValue(g_Reg->ASIC_ERR_SECTOR, false, true);
m_DDEdits[6].SetValue(g_Reg->ASIC_SEQ_STATUS, false, true);
m_DDEdits[7].SetValue(g_Reg->ASIC_CUR_SECTOR, false, true);
m_DDEdits[8].SetValue(g_Reg->ASIC_HARD_RESET, false, true);
m_DDEdits[9].SetValue(g_Reg->ASIC_C1_S0, false, true);
m_DDEdits[10].SetValue(g_Reg->ASIC_HOST_SECBYTE, false, true);
m_DDEdits[11].SetValue(g_Reg->ASIC_C1_S2, false, true);
m_DDEdits[12].SetValue(g_Reg->ASIC_SEC_BYTE, false, true);
m_DDEdits[13].SetValue(g_Reg->ASIC_C1_S4, false, true);
m_DDEdits[14].SetValue(g_Reg->ASIC_C1_S6, false, true);
m_DDEdits[15].SetValue(g_Reg->ASIC_CUR_ADDR, false, true);
m_DDEdits[16].SetValue(g_Reg->ASIC_ID_REG, false, true);
m_DDEdits[17].SetValue(g_Reg->ASIC_TEST_REG, false, true);
m_DDEdits[18].SetValue(g_Reg->ASIC_TEST_PIN_SEL, false, true);
}
void CRegisterTabs::RegisterChanged(HWND hDlg, TAB_ID srcTabId, WPARAM wParam)
{
CBreakpoints* breakpoints = ((CDebuggerUI*)g_Debugger)->Breakpoints();
if (g_Reg == NULL || !breakpoints->isDebugging())
{
return;
}
int ctrlId = LOWORD(wParam);
CWindow editCtrl = ::GetDlgItem(hDlg, ctrlId);
char text[20];
editCtrl.GetWindowText(text, 20);
if (srcTabId == TabGPR)
{
uint64_t value = CEditReg64::ParseValue(text);
if (ctrlId == IDC_HI_EDIT)
{
g_Reg->m_HI.UDW = value;
}
else if (ctrlId == IDC_LO_EDIT)
{
g_Reg->m_LO.UDW = value;
}
else
{
int nReg = MapEditRegNum(ctrlId, GPREditIds);
g_Reg->m_GPR[nReg].UDW = value;
}
return;
}
uint32_t value = strtoul(text, NULL, 16);
sprintf(text, "%08X", value);
editCtrl.SetWindowText(text); // reformat text
if (srcTabId == TabFPR)
{
if (ctrlId == IDC_FCSR_EDIT)
{
g_Reg->m_FPCR[31] = value;
return;
}
int nReg = MapEditRegNum(ctrlId, FPREditIds);
*(uint32_t*)g_Reg->m_FPR_S[nReg] = value;
return;
}
switch (ctrlId)
{
case IDC_COP0_0_EDIT: g_Reg->INDEX_REGISTER = value; break;
case IDC_COP0_1_EDIT: g_Reg->RANDOM_REGISTER = value; break;
case IDC_COP0_2_EDIT: g_Reg->ENTRYLO0_REGISTER = value; break;
case IDC_COP0_3_EDIT: g_Reg->ENTRYLO1_REGISTER = value; break;
case IDC_COP0_4_EDIT: g_Reg->CONTEXT_REGISTER = value; break;
case IDC_COP0_5_EDIT: g_Reg->PAGE_MASK_REGISTER = value; break;
case IDC_COP0_6_EDIT: g_Reg->WIRED_REGISTER = value; break;
case IDC_COP0_7_EDIT: g_Reg->BAD_VADDR_REGISTER = value; break;
case IDC_COP0_8_EDIT: g_Reg->COUNT_REGISTER = value; break;
case IDC_COP0_9_EDIT: g_Reg->ENTRYHI_REGISTER = value; break;
case IDC_COP0_10_EDIT: g_Reg->COMPARE_REGISTER = value; break;
case IDC_COP0_11_EDIT: g_Reg->STATUS_REGISTER = value; break;
case IDC_COP0_12_EDIT: g_Reg->CAUSE_REGISTER = value; break;
case IDC_COP0_13_EDIT: g_Reg->EPC_REGISTER = value; break;
case IDC_COP0_14_EDIT: g_Reg->CONFIG_REGISTER = value; break;
case IDC_COP0_15_EDIT: g_Reg->TAGLO_REGISTER = value; break;
case IDC_COP0_16_EDIT: g_Reg->TAGHI_REGISTER = value; break;
case IDC_COP0_17_EDIT: g_Reg->ERROREPC_REGISTER = value; break;
case IDC_COP0_18_EDIT: g_Reg->FAKE_CAUSE_REGISTER = value; break;
case IDC_RDRAM00_EDIT: g_Reg->RDRAM_CONFIG_REG = value; break; // or device_type
case IDC_RDRAM04_EDIT: g_Reg->RDRAM_DEVICE_ID_REG = value; break;
case IDC_RDRAM08_EDIT: g_Reg->RDRAM_DELAY_REG = value; break;
case IDC_RDRAM0C_EDIT: g_Reg->RDRAM_MODE_REG = value; break;
case IDC_RDRAM10_EDIT: g_Reg->RDRAM_REF_INTERVAL_REG = value; break;
case IDC_RDRAM14_EDIT: g_Reg->RDRAM_REF_ROW_REG = value; break;
case IDC_RDRAM18_EDIT: g_Reg->RDRAM_RAS_INTERVAL_REG = value; break;
case IDC_RDRAM1C_EDIT: g_Reg->RDRAM_MIN_INTERVAL_REG = value; break;
case IDC_RDRAM20_EDIT: g_Reg->RDRAM_ADDR_SELECT_REG = value; break;
case IDC_RDRAM24_EDIT: g_Reg->RDRAM_DEVICE_MANUF_REG = value; break;
case IDC_SP00_EDIT: g_Reg->SP_MEM_ADDR_REG = value; break;
case IDC_SP04_EDIT: g_Reg->SP_DRAM_ADDR_REG = value; break;
case IDC_SP08_EDIT: g_Reg->SP_RD_LEN_REG = value; break;
case IDC_SP0C_EDIT: g_Reg->SP_WR_LEN_REG = value; break;
case IDC_SP10_EDIT: g_Reg->SP_STATUS_REG = value; break;
case IDC_SP14_EDIT: g_Reg->SP_DMA_FULL_REG = value; break;
case IDC_SP18_EDIT: g_Reg->SP_DMA_BUSY_REG = value; break;
case IDC_SP1C_EDIT: g_Reg->SP_SEMAPHORE_REG = value; break;
case IDC_SP_PC_EDIT: g_Reg->SP_PC_REG = value; break;
case IDC_DPC00_EDIT: g_Reg->DPC_START_REG = value; break;
case IDC_DPC04_EDIT: g_Reg->DPC_END_REG = value; break;
case IDC_DPC08_EDIT: g_Reg->DPC_CURRENT_REG = value; break;
case IDC_DPC0C_EDIT: g_Reg->DPC_STATUS_REG = value; break;
case IDC_DPC10_EDIT: g_Reg->DPC_CLOCK_REG = value; break;
case IDC_DPC14_EDIT: g_Reg->DPC_BUFBUSY_REG = value; break;
case IDC_DPC18_EDIT: g_Reg->DPC_PIPEBUSY_REG = value; break;
case IDC_DPC1C_EDIT: g_Reg->DPC_TMEM_REG = value; break;
case IDC_MI00_EDIT: g_Reg->MI_INIT_MODE_REG = value; break; // or MI_MODE ?
case IDC_MI04_EDIT: g_Reg->MI_VERSION_REG = value; break; // or MI_NOOP ?
case IDC_MI08_EDIT: g_Reg->MI_INTR_REG = value; break; // or MI_INTR ?
case IDC_MI0C_EDIT: g_Reg->MI_INTR_MASK_REG = value; break; // or MI_INTR_MASK ?
case IDC_VI00_EDIT: g_Reg->VI_STATUS_REG = value; break;
case IDC_VI04_EDIT: g_Reg->VI_ORIGIN_REG = value; break;
case IDC_VI08_EDIT: g_Reg->VI_WIDTH_REG = value; break;
case IDC_VI0C_EDIT: g_Reg->VI_INTR_REG = value; break;
case IDC_VI10_EDIT: g_Reg->VI_CURRENT_REG = value; break;
case IDC_VI14_EDIT: g_Reg->VI_BURST_REG = value; break;
case IDC_VI18_EDIT: g_Reg->VI_V_SYNC_REG = value; break;
case IDC_VI1C_EDIT: g_Reg->VI_H_SYNC_REG = value; break;
case IDC_VI20_EDIT: g_Reg->VI_LEAP_REG = value; break;
case IDC_VI24_EDIT: g_Reg->VI_H_START_REG = value; break;
case IDC_VI28_EDIT: g_Reg->VI_V_START_REG = value; break;
case IDC_VI2C_EDIT: g_Reg->VI_V_BURST_REG = value; break;
case IDC_VI30_EDIT: g_Reg->VI_X_SCALE_REG = value; break;
case IDC_VI34_EDIT: g_Reg->VI_Y_SCALE_REG = value; break;
case IDC_AI00_EDIT: g_Reg->AI_DRAM_ADDR_REG = value; break;
case IDC_AI04_EDIT: g_Reg->AI_LEN_REG = value; break;
case IDC_AI08_EDIT: g_Reg->AI_CONTROL_REG = value; break;
case IDC_AI0C_EDIT: g_Reg->AI_STATUS_REG = value; break;
case IDC_AI10_EDIT: g_Reg->AI_DACRATE_REG = value; break;
case IDC_AI14_EDIT: g_Reg->AI_BITRATE_REG = value; break;
case IDC_PI00_EDIT: g_Reg->PI_DRAM_ADDR_REG = value; break;
case IDC_PI04_EDIT: g_Reg->PI_CART_ADDR_REG = value; break;
case IDC_PI08_EDIT: g_Reg->PI_RD_LEN_REG = value; break;
case IDC_PI0C_EDIT: g_Reg->PI_WR_LEN_REG = value; break;
case IDC_PI10_EDIT: g_Reg->PI_STATUS_REG = value; break;
case IDC_PI14_EDIT: g_Reg->PI_BSD_DOM1_LAT_REG = value; break;
case IDC_PI18_EDIT: g_Reg->PI_BSD_DOM1_PWD_REG = value; break;
case IDC_PI1C_EDIT: g_Reg->PI_BSD_DOM1_PGS_REG = value; break;
case IDC_PI20_EDIT: g_Reg->PI_BSD_DOM1_RLS_REG = value; break;
case IDC_PI24_EDIT: g_Reg->PI_BSD_DOM2_LAT_REG = value; break;
case IDC_PI28_EDIT: g_Reg->PI_BSD_DOM2_PWD_REG = value; break;
case IDC_PI2C_EDIT: g_Reg->PI_BSD_DOM2_PGS_REG = value; break;
case IDC_PI30_EDIT: g_Reg->PI_BSD_DOM2_RLS_REG = value; break;
case IDC_RI00_EDIT: g_Reg->RI_MODE_REG = value; break;
case IDC_RI04_EDIT: g_Reg->RI_CONFIG_REG = value; break;
case IDC_RI08_EDIT: g_Reg->RI_CURRENT_LOAD_REG = value; break;
case IDC_RI0C_EDIT: g_Reg->RI_SELECT_REG = value; break;
case IDC_RI10_EDIT: g_Reg->RI_REFRESH_REG = value; break;
case IDC_RI14_EDIT: g_Reg->RI_LATENCY_REG = value; break;
case IDC_RI18_EDIT: g_Reg->RI_RERROR_REG = value; break;
case IDC_RI1C_EDIT: g_Reg->RI_WERROR_REG = value; break;
case IDC_SI00_EDIT: g_Reg->SI_DRAM_ADDR_REG = value; break;
case IDC_SI04_EDIT: g_Reg->SI_PIF_ADDR_RD64B_REG = value; break;
case IDC_SI08_EDIT: g_Reg->SI_PIF_ADDR_WR64B_REG = value; break;
case IDC_SI0C_EDIT: g_Reg->SI_STATUS_REG = value; break;
case IDC_DD00_EDIT: g_Reg->ASIC_DATA = value; break;
case IDC_DD04_EDIT: g_Reg->ASIC_MISC_REG = value; break;
case IDC_DD08_EDIT: g_Reg->ASIC_STATUS = value; break;
case IDC_DD0C_EDIT: g_Reg->ASIC_CUR_TK = value; break;
case IDC_DD10_EDIT: g_Reg->ASIC_BM_STATUS = value; break;
case IDC_DD14_EDIT: g_Reg->ASIC_ERR_SECTOR = value; break;
case IDC_DD18_EDIT: g_Reg->ASIC_SEQ_STATUS = value; break;
case IDC_DD1C_EDIT: g_Reg->ASIC_CUR_SECTOR = value; break;
case IDC_DD20_EDIT: g_Reg->ASIC_HARD_RESET = value; break;
case IDC_DD24_EDIT: g_Reg->ASIC_C1_S0 = value; break;
case IDC_DD28_EDIT: g_Reg->ASIC_HOST_SECBYTE = value; break;
case IDC_DD2C_EDIT: g_Reg->ASIC_C1_S2 = value; break;
case IDC_DD30_EDIT: g_Reg->ASIC_SEC_BYTE = value; break;
case IDC_DD34_EDIT: g_Reg->ASIC_C1_S4 = value; break;
case IDC_DD38_EDIT: g_Reg->ASIC_C1_S6 = value; break;
case IDC_DD3C_EDIT: g_Reg->ASIC_CUR_ADDR = value; break;
case IDC_DD40_EDIT: g_Reg->ASIC_ID_REG = value; break;
case IDC_DD44_EDIT: g_Reg->ASIC_TEST_REG = value; break;
case IDC_DD48_EDIT: g_Reg->ASIC_TEST_PIN_SEL = value; break;
}
}
INT_PTR CALLBACK CRegisterTabs::TabProcDefault(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (msg == WM_INITDIALOG)
{
return TRUE;
}
if (msg != WM_COMMAND)
{
return FALSE;
}
WORD notification = HIWORD(wParam);
if (notification == EN_KILLFOCUS)
{
RegisterChanged(hDlg, TabDefault, wParam);
}
return FALSE;
}
INT_PTR CALLBACK CRegisterTabs::TabProcGPR(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (msg == WM_INITDIALOG)
{
return TRUE;
}
if (msg == WM_CTLCOLOREDIT)
{
HDC hdc = (HDC)wParam;
COLORREF colorBg = RGB(255, 255, 255);
COLORREF colorRead = RGB(200, 200, 255);
COLORREF colorWrite = RGB(255, 200, 200);
COLORREF colorBoth = RGB(255, 200, 255);
if (!m_bColorsEnabled || g_Reg == NULL || g_MMU == NULL)
{
return FALSE;
}
HWND hWnd = (HWND)lParam;
int ctrlId = ::GetWindowLong(hWnd, GWL_ID);
COpInfo opInfo;
g_MMU->LW_VAddr(g_Reg->m_PROGRAM_COUNTER, opInfo.m_OpCode.Hex);
bool bOpReads = false;
bool bOpWrites = false;
if (ctrlId == IDC_LO_EDIT)
{
bOpReads = opInfo.ReadsLO();
bOpWrites = !bOpReads && opInfo.WritesLO();
}
else if (ctrlId == IDC_HI_EDIT)
{
bOpReads = opInfo.ReadsHI();
bOpWrites = !bOpReads && opInfo.WritesHI();
}
else
{
int nReg = MapEditRegNum(ctrlId, GPREditIds);
bOpReads = opInfo.ReadsGPR(nReg);
bOpWrites = opInfo.WritesGPR(nReg);
}
if (bOpReads && bOpWrites)
{
colorBg = colorBoth;
}
else if(bOpReads)
{
colorBg = colorRead;
}
else if (bOpWrites)
{
colorBg = colorWrite;
}
SetBkColor(hdc, colorBg);
SetDCBrushColor(hdc, colorBg);
return (LRESULT)GetStockObject(DC_BRUSH);
}
if (msg != WM_COMMAND)
{
return FALSE;
}
WORD notification = HIWORD(wParam);
if (notification == EN_KILLFOCUS)
{
RegisterChanged(hDlg, TabGPR, wParam);
}
return FALSE;
}
INT_PTR CALLBACK CRegisterTabs::TabProcFPR(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (msg == WM_INITDIALOG)
{
return TRUE;
}
if (msg != WM_COMMAND)
{
return FALSE;
}
WORD notification = HIWORD(wParam);
if (notification == EN_KILLFOCUS)
{
RegisterChanged(hDlg, TabFPR, wParam);
}
return FALSE;
}
CRect CRegisterTabs::GetPageRect()
{
CWindow parentWin = GetParent();
CRect pageRect;
GetWindowRect(&pageRect);
parentWin.ScreenToClient(&pageRect);
AdjustRect(FALSE, &pageRect);
return pageRect;
}
CWindow CRegisterTabs::AddTab(char* caption, int dialogId, DLGPROC dlgProc)
{
AddItem(caption);
CWindow parentWin = GetParent();
CWindow tabWin = ::CreateDialog(NULL, MAKEINTRESOURCE(dialogId), parentWin, dlgProc);
CRect pageRect = GetPageRect();
::SetParent(tabWin, parentWin);
::SetWindowPos(
tabWin,
m_hWnd,
pageRect.left,
pageRect.top,
pageRect.Width(),
pageRect.Height(),
SWP_HIDEWINDOW
);
m_TabWindows.push_back(tabWin);
int index = m_TabWindows.size() - 1;
if (index == 0)
{
ShowTab(0);
}
return tabWin;
}
void CRegisterTabs::ShowTab(int nPage)
{
for (int i = 0; i < m_TabWindows.size(); i++)
{
::ShowWindow(m_TabWindows[i], SW_HIDE);
}
CRect pageRect = GetPageRect();
::SetWindowPos(
m_TabWindows[nPage],
HWND_TOP,
pageRect.left,
pageRect.top,
pageRect.Width(),
pageRect.Height(),
SWP_SHOWWINDOW
);
}
void CRegisterTabs::RedrawCurrentTab()
{
int nPage = GetCurSel();
CRect pageRect = GetPageRect();
::SetWindowPos(
m_TabWindows[nPage],
HWND_TOP,
pageRect.left,
pageRect.top,
pageRect.Width(),
pageRect.Height(),
SWP_SHOWWINDOW
);
}
void CRegisterTabs::SetColorsEnabled(bool bColorsEnabled)
{
m_bColorsEnabled = bColorsEnabled;
}
void CRegisterTabs::InitRegisterEdit(CWindow& tab, CEditNumber& edit, WORD ctrlId, HFONT font)
{
edit.Attach(tab.GetDlgItem(ctrlId));
edit.SetDisplayType(CEditNumber::DisplayHex);
edit.SetFont(font);
}
void CRegisterTabs::InitRegisterEdits(CWindow& tab, CEditNumber* edits, const DWORD* ctrlIds, HFONT font)
{
for (int i = 0; i < ctrlIds[i] != 0; i++)
{
InitRegisterEdit(tab, edits[i], ctrlIds[i], font);
}
}
void CRegisterTabs::InitRegisterEdit64(CWindow& tab, CEditReg64& edit, WORD ctrlId, HFONT font)
{
edit.Attach(tab.GetDlgItem(ctrlId));
edit.SetFont(font);
}
void CRegisterTabs::InitRegisterEdits64(CWindow& tab, CEditReg64* edits, const DWORD* ctrlIds, HFONT font)
{
for (int i = 0; i < ctrlIds[i] != 0; i++)
{
InitRegisterEdit64(tab, edits[i], ctrlIds[i], font);
}
}
void CRegisterTabs::ZeroRegisterEdit(CEditNumber& edit)
{
edit.SetValue(0, false, true);
}
void CRegisterTabs::ZeroRegisterEdits(CEditNumber* edits, const DWORD* ctrlIds)
{
for (int i = 0; ctrlIds[i] != 0; i++)
{
ZeroRegisterEdit(edits[i]);
}
}
void CRegisterTabs::ZeroRegisterEdit64(CEditReg64& edit)
{
edit.SetValue(0);
}
void CRegisterTabs::ZeroRegisterEdits64(CEditReg64* edits, const DWORD* ctrlIds)
{
for (int i = 0; ctrlIds[i] != 0; i++)
{
ZeroRegisterEdit64(edits[i]);
}
}
// CEditReg64 for GPR
uint64_t CEditReg64::ParseValue(char* wordPair)
{
uint32_t a, b;
uint64_t ret;
a = strtoul(wordPair, &wordPair, 16);
if (*wordPair == ' ')
{
wordPair++;
b = strtoul(wordPair, NULL, 16);
ret = (uint64_t)a << 32;
ret |= b;
return ret;
}
return (uint64_t)a;
}
BOOL CEditReg64::Attach(HWND hWndNew)
{
return SubclassWindow(hWndNew);
}
LRESULT CEditReg64::OnChar(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
CBreakpoints* breakpoints = ((CDebuggerUI*)g_Debugger)->Breakpoints();
if (!breakpoints->isDebugging())
{
goto canceled;
}
char charCode = wParam;
if (!isxdigit(charCode) && charCode != ' ')
{
if (!isalnum(charCode))
{
goto unhandled;
}
goto canceled;
}
if (isalpha(charCode) && !isupper(charCode))
{
SendMessage(uMsg, toupper(wParam), lParam);
goto canceled;
}
char text[20];
GetWindowText(text, 20);
int textLen = strlen(text);
if (textLen >= 17)
{
int selStart, selEnd;
GetSel(selStart, selEnd);
if (selEnd - selStart == 0)
{
goto canceled;
}
}
if (charCode == ' ' && strchr(text, ' ') != NULL)
{
goto canceled;
}
unhandled:
bHandled = FALSE;
return 0;
canceled:
bHandled = TRUE;
return 0;
}
uint64_t CEditReg64::GetValue()
{
char text[20];
GetWindowText(text, 20);
return ParseValue(text);
}
LRESULT CEditReg64::OnLostFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
SetValue(GetValue()); // clean up
bHandled = FALSE;
return 0;
}
void CEditReg64::SetValue(uint32_t h, uint32_t l)
{
char text[20];
sprintf(text, "%08X %08X", h, l);
SetWindowText(text);
}
void CEditReg64::SetValue(uint64_t value)
{
uint32_t h = (value & 0xFFFFFFFF00000000LL) >> 32;
uint32_t l = (value & 0x00000000FFFFFFFFLL);
SetValue(h, l);
}

View File

@ -0,0 +1,282 @@
/****************************************************************************
* *
* Project64 - A Nintendo 64 emulator. *
* http://www.pj64-emu.com/ *
* Copyright (C) 2012 Project64. All rights reserved. *
* *
* License: *
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
* *
****************************************************************************/
#pragma once
#include "stdafx.h"
#include "Breakpoints.h"
#ifndef COUNT_OF
#define COUNT_OF(a) (sizeof(a) / sizeof(a[0]))
#endif
class CEditReg64 : public CWindowImpl<CEditReg64, CEdit>
{
public:
static uint64_t ParseValue(char* wordPair);
BOOL Attach(HWND hWndNew);
LRESULT OnChar(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnLostFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
uint64_t GetValue();
void SetValue(uint32_t h, uint32_t l);
void SetValue(uint64_t value);
BEGIN_MSG_MAP_EX(CRegEdit64)
MESSAGE_HANDLER(WM_CHAR, OnChar)
MESSAGE_HANDLER(WM_KILLFOCUS, OnLostFocus)
END_MSG_MAP()
};
class CRegisterTabs : public CTabCtrl
{
private:
typedef union
{
uint32_t intval;
struct {
unsigned : 2;
unsigned exceptionCode : 5;
unsigned : 1;
unsigned pendingInterrupts : 8;
unsigned : 12;
unsigned coprocessor : 2;
unsigned : 1;
unsigned fromDelaySlot : 1;
};
} CAUSE;
enum TAB_ID {
TabDefault,
TabGPR,
TabFPR
};
static constexpr DWORD GPREditIds[] = {
IDC_R0_EDIT, IDC_R1_EDIT, IDC_R2_EDIT, IDC_R3_EDIT,
IDC_R4_EDIT, IDC_R5_EDIT, IDC_R6_EDIT, IDC_R7_EDIT,
IDC_R8_EDIT, IDC_R9_EDIT, IDC_R10_EDIT, IDC_R11_EDIT,
IDC_R12_EDIT, IDC_R13_EDIT, IDC_R14_EDIT, IDC_R15_EDIT,
IDC_R16_EDIT, IDC_R17_EDIT, IDC_R18_EDIT, IDC_R19_EDIT,
IDC_R20_EDIT, IDC_R21_EDIT, IDC_R22_EDIT, IDC_R23_EDIT,
IDC_R24_EDIT, IDC_R25_EDIT, IDC_R26_EDIT, IDC_R27_EDIT,
IDC_R28_EDIT, IDC_R29_EDIT, IDC_R30_EDIT, IDC_R31_EDIT,
0
};
static constexpr DWORD FPREditIds[] = {
IDC_F0_EDIT, IDC_F1_EDIT, IDC_F2_EDIT, IDC_F3_EDIT,
IDC_F4_EDIT, IDC_F5_EDIT, IDC_F6_EDIT, IDC_F7_EDIT,
IDC_F8_EDIT, IDC_F9_EDIT, IDC_F10_EDIT, IDC_F11_EDIT,
IDC_F12_EDIT, IDC_F13_EDIT, IDC_F14_EDIT, IDC_F15_EDIT,
IDC_F16_EDIT, IDC_F17_EDIT, IDC_F18_EDIT, IDC_F19_EDIT,
IDC_F20_EDIT, IDC_F21_EDIT, IDC_F22_EDIT, IDC_F23_EDIT,
IDC_F24_EDIT, IDC_F25_EDIT, IDC_F26_EDIT, IDC_F27_EDIT,
IDC_F28_EDIT, IDC_F29_EDIT, IDC_F30_EDIT, IDC_F31_EDIT,
0
};
static constexpr DWORD COP0EditIds[] = {
IDC_COP0_0_EDIT, IDC_COP0_1_EDIT, IDC_COP0_2_EDIT, IDC_COP0_3_EDIT,
IDC_COP0_4_EDIT, IDC_COP0_5_EDIT, IDC_COP0_6_EDIT, IDC_COP0_7_EDIT,
IDC_COP0_8_EDIT, IDC_COP0_9_EDIT, IDC_COP0_10_EDIT, IDC_COP0_11_EDIT,
IDC_COP0_12_EDIT, IDC_COP0_13_EDIT, IDC_COP0_14_EDIT, IDC_COP0_15_EDIT,
IDC_COP0_16_EDIT, IDC_COP0_17_EDIT, IDC_COP0_18_EDIT,
0
};
static constexpr DWORD RDRAMEditIds[] = {
IDC_RDRAM00_EDIT, IDC_RDRAM04_EDIT, IDC_RDRAM08_EDIT, IDC_RDRAM0C_EDIT,
IDC_RDRAM10_EDIT, IDC_RDRAM14_EDIT, IDC_RDRAM18_EDIT, IDC_RDRAM1C_EDIT,
IDC_RDRAM20_EDIT, IDC_RDRAM24_EDIT,
0
};
static constexpr DWORD SPEditIds[] = {
IDC_SP00_EDIT, IDC_SP04_EDIT, IDC_SP08_EDIT, IDC_SP0C_EDIT,
IDC_SP10_EDIT, IDC_SP14_EDIT, IDC_SP18_EDIT, IDC_SP1C_EDIT,
0
};
static constexpr DWORD DPCEditIds[] = {
IDC_DPC00_EDIT, IDC_DPC04_EDIT, IDC_DPC08_EDIT, IDC_DPC0C_EDIT,
IDC_DPC10_EDIT, IDC_DPC14_EDIT, IDC_DPC18_EDIT, IDC_DPC1C_EDIT,
0
};
static constexpr DWORD MIEditIds[] = {
IDC_MI00_EDIT, IDC_MI04_EDIT, IDC_MI08_EDIT, IDC_MI0C_EDIT,
0
};
static constexpr DWORD VIEditIds[] = {
IDC_VI00_EDIT, IDC_VI04_EDIT, IDC_VI08_EDIT, IDC_VI0C_EDIT,
IDC_VI10_EDIT, IDC_VI14_EDIT, IDC_VI18_EDIT, IDC_VI1C_EDIT,
IDC_VI20_EDIT, IDC_VI24_EDIT, IDC_VI28_EDIT, IDC_VI2C_EDIT,
IDC_VI30_EDIT, IDC_VI34_EDIT,
0
};
static constexpr DWORD AIEditIds[] = {
IDC_AI00_EDIT, IDC_AI04_EDIT, IDC_AI08_EDIT, IDC_AI0C_EDIT,
IDC_AI10_EDIT, IDC_AI14_EDIT,
0
};
static constexpr DWORD PIEditIds[] = {
IDC_PI00_EDIT, IDC_PI04_EDIT, IDC_PI08_EDIT, IDC_PI0C_EDIT,
IDC_PI10_EDIT, IDC_PI14_EDIT, IDC_PI18_EDIT, IDC_PI1C_EDIT,
IDC_PI20_EDIT, IDC_PI24_EDIT, IDC_PI28_EDIT, IDC_PI2C_EDIT,
IDC_PI30_EDIT,
0
};
static constexpr DWORD RIEditIds[] = {
IDC_RI00_EDIT, IDC_RI04_EDIT, IDC_RI08_EDIT, IDC_RI0C_EDIT,
IDC_RI10_EDIT, IDC_RI14_EDIT, IDC_RI18_EDIT, IDC_RI1C_EDIT,
0
};
static constexpr DWORD SIEditIds[] = {
IDC_SI00_EDIT, IDC_SI04_EDIT, IDC_SI08_EDIT, IDC_SI0C_EDIT,
0
};
static constexpr DWORD DDEditIds[] = {
IDC_DD00_EDIT, IDC_DD04_EDIT, IDC_DD08_EDIT, IDC_DD0C_EDIT,
IDC_DD10_EDIT, IDC_DD14_EDIT, IDC_DD18_EDIT, IDC_DD1C_EDIT,
IDC_DD20_EDIT, IDC_DD24_EDIT, IDC_DD28_EDIT, IDC_DD2C_EDIT,
IDC_DD30_EDIT, IDC_DD34_EDIT, IDC_DD38_EDIT, IDC_DD3C_EDIT,
IDC_DD40_EDIT, IDC_DD44_EDIT, IDC_DD48_EDIT,
0
};
static int MapEditRegNum(DWORD controlId, const DWORD* edits)
{
for (int i = 0; edits[i] != 0; i++)
{
if (edits[i] == controlId)
{
return i;
}
}
return -1;
}
static constexpr char* ExceptionCodes[] = {
"Interrupt",
"TLB mod",
"TLB load/fetch",
"TLB store",
"Address error (load/fetch)",
"Address error (store)",
"Bus error (instruction fetch)",
"Bus error (data load/store)",
"Syscall",
"Breakpoint",
"Reserved instruction",
"Coprocessor unusable",
"Arithmetic overflow",
"Trap",
"Virtual coherency (instruction)",
"Floating-point",
"? 16",
"? 17",
"? 18",
"? 19",
"? 20",
"? 21",
"? 22",
"Watch",
"? 24",
"? 25",
"? 26",
"? 27",
"? 28",
"? 29",
"? 30",
"Virtual coherency (data)"
};
// for static dlgprocs, assumes single instance
static bool m_bColorsEnabled;
vector<CWindow> m_TabWindows;
CWindow m_GPRTab;
CEditReg64 m_GPREdits[COUNT_OF(GPREditIds) - 1];
CEditReg64 m_HIEdit;
CEditReg64 m_LOEdit;
CWindow m_FPRTab;
CEditNumber m_FPREdits[COUNT_OF(FPREditIds) - 1];
CEditNumber m_FCSREdit;
CWindow m_COP0Tab;
CEditNumber m_COP0Edits[COUNT_OF(COP0EditIds) - 1];
CStatic m_CauseTip;
CWindow m_RDRAMTab;
CEditNumber m_RDRAMEdits[COUNT_OF(RDRAMEditIds) - 1];
CWindow m_SPTab;
CEditNumber m_SPEdits[COUNT_OF(SPEditIds) - 1];
CEditNumber m_SPPCEdit;
CWindow m_DPCTab;
CEditNumber m_DPCEdits[COUNT_OF(DPCEditIds) - 1];
CWindow m_MITab;
CEditNumber m_MIEdits[COUNT_OF(MIEditIds) - 1];
CWindow m_VITab;
CEditNumber m_VIEdits[COUNT_OF(VIEditIds) - 1];
CWindow m_AITab;
CEditNumber m_AIEdits[COUNT_OF(AIEditIds) - 1];
CWindow m_PITab;
CEditNumber m_PIEdits[COUNT_OF(PIEditIds) - 1];
CWindow m_RITab;
CEditNumber m_RIEdits[COUNT_OF(RIEditIds) - 1];
CWindow m_SITab;
CEditNumber m_SIEdits[COUNT_OF(SIEditIds) - 1];
CWindow m_DDTab;
CEditNumber m_DDEdits[COUNT_OF(DDEditIds) - 1];
static void RegisterChanged(HWND hDlg, TAB_ID srcTabId, WPARAM wParam);
static INT_PTR CALLBACK TabProcDefault(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
static INT_PTR CALLBACK TabProcGPR(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
static INT_PTR CALLBACK TabProcFPR(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
static void InitRegisterEdit(CWindow& tab, CEditNumber& edit, WORD ctrlId, HFONT font);
static void InitRegisterEdits(CWindow& tab, CEditNumber* edits, const DWORD* ctrlIds, HFONT font);
static void InitRegisterEdit64(CWindow& tab, CEditReg64& edit, WORD ctrlId, HFONT font);
static void InitRegisterEdits64(CWindow& tab, CEditReg64* edits, const DWORD* ctrlIds, HFONT font);
static void ZeroRegisterEdit(CEditNumber& edit);
static void ZeroRegisterEdits(CEditNumber* edits, const DWORD* ctrlIds);
static void ZeroRegisterEdit64(CEditReg64& edit);
static void ZeroRegisterEdits64(CEditReg64* edits, const DWORD* ctrlIds);
public:
void Attach(HWND hWndNew);
CWindow AddTab(char* caption, int dialogId, DLGPROC dlgProc);
void ShowTab(int nPage);
CRect GetPageRect();
void RedrawCurrentTab();
void RefreshEdits();
void SetColorsEnabled(bool bColorsEnabled);
};

View File

@ -0,0 +1,396 @@
/****************************************************************************
* *
* Project64 - A Nintendo 64 emulator. *
* http://www.pj64-emu.com/ *
* Copyright (C) 2012 Project64. All rights reserved. *
* *
* License: *
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
* *
****************************************************************************/
#include "stdafx.h"
#include "DebuggerUI.h"
//char* CEditEval::m_EvalString;
CDebugScripts::CDebugScripts(CDebuggerUI* debugger) :
CDebugDialog<CDebugScripts>(debugger)
{
m_SelectedScriptName = (char*)malloc(MAX_PATH);
//CScriptSystem::SetScriptsWindow(this);
}
CDebugScripts::~CDebugScripts(void)
{
free(m_SelectedScriptName);
}
LRESULT CDebugScripts::OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
DlgResize_Init(false, true);
HFONT monoFont = CreateFont(-11, 0, 0, 0,
FW_DONTCARE, FALSE, FALSE, FALSE, DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
CLEARTYPE_QUALITY, FF_DONTCARE, "Consolas"
);
m_InstanceInfoEdit.Attach(GetDlgItem(IDC_CTX_INFO_EDIT));
m_ScriptList.Attach(GetDlgItem(IDC_SCRIPT_LIST));
m_ScriptList.AddColumn("Script", 0, 0);
m_ScriptList.SetColumnWidth(0, 100);
m_ScriptList.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER);
m_ScriptList.ModifyStyle(LVS_OWNERDRAWFIXED, 0, 0);
m_EvalEdit.Attach(GetDlgItem(IDC_EVAL_EDIT));
m_EvalEdit.SetScriptWindow(this);
m_EvalEdit.SetFont(monoFont);
m_EvalEdit.EnableWindow(FALSE);
m_ConsoleEdit.Attach(GetDlgItem(IDC_CONSOLE_EDIT));
m_ConsoleEdit.SetLimitText(0);
m_ConsoleEdit.SetFont(monoFont);
RefreshList();
WindowCreated();
return 0;
}
void CDebugScripts::ConsolePrint(const char* text)
{
::ShowWindow(*this, SW_SHOWNOACTIVATE);
int textPos = m_ConsoleEdit.GetWindowTextLengthA();
// Get scrollbar state
SCROLLINFO scroll;
scroll.cbSize = sizeof(SCROLLINFO);
scroll.fMask = SIF_ALL;
m_ConsoleEdit.GetScrollInfo(SB_VERT, &scroll);
m_ConsoleEdit.SetRedraw(FALSE);
m_ConsoleEdit.AppendText(text);
m_ConsoleEdit.SetRedraw(TRUE);
if ((scroll.nPage + scroll.nPos) - 1 == scroll.nMax)
{
m_ConsoleEdit.ScrollCaret();
}
}
void CDebugScripts::RefreshConsole()
{
m_Debugger->Debug_ShowScriptsWindow();
CScriptSystem* scriptSystem = m_Debugger->ScriptSystem();
vector<char*>* logData = scriptSystem->LogData();
while(logData->size() != 0)
{
ConsolePrint((*logData)[0]);
free((*logData)[0]);
logData->erase(logData->begin() + 0);
}
}
void CDebugScripts::ConsoleClear()
{
m_ConsoleEdit.SetWindowTextA("");
}
void CDebugScripts::ConsoleCopy()
{
if (!OpenClipboard())
{
return;
}
EmptyClipboard();
size_t nChars = m_ConsoleEdit.GetWindowTextLengthA() + 1;
HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, nChars);
char* memBuf = (char*) GlobalLock(hMem);
m_ConsoleEdit.GetWindowTextA(memBuf, nChars);
GlobalUnlock(hMem);
HANDLE hRes = SetClipboardData(CF_TEXT, hMem);
GlobalFree(hMem);
CloseClipboard();
}
void CDebugScripts::RefreshList()
{
int nIndex = m_ScriptList.GetSelectedIndex();
CPath SearchPath("Scripts", "*");
if (!SearchPath.FindFirst(CPath::FIND_ATTRIBUTE_ALLFILES))
{
return;
}
m_ScriptList.SetRedraw(false);
m_ScriptList.DeleteAllItems();
do
{
stdstr scriptFileName = SearchPath.GetNameExtension();
m_ScriptList.AddItem(0, 0, scriptFileName.c_str());
} while (SearchPath.FindNext());
m_ScriptList.SetRedraw(true);
m_ScriptList.Invalidate();
if (nIndex >= 0)
{
m_ScriptList.SelectItem(nIndex);
RefreshStatus();
}
}
LRESULT CDebugScripts::OnClicked(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
switch (wID)
{
case IDCANCEL:
EndDialog(0);
break;
case ID_POPUP_RUN:
RunSelected();
break;
case ID_POPUP_STOP:
StopSelected();
break;
case IDC_CLEAR_BTN:
ConsoleClear();
break;
case IDC_COPY_BTN:
ConsoleCopy();
break;
}
return FALSE;
}
LRESULT CDebugScripts::OnScriptListDblClicked(NMHDR* pNMHDR)
{
// Run script on double click
NMITEMACTIVATE* pIA = reinterpret_cast<NMITEMACTIVATE*>(pNMHDR);
int nItem = pIA->iItem;
m_ScriptList.SelectItem(nItem);
RunSelected();
return 0;
}
void CDebugScripts::RefreshStatus()
{
INSTANCE_STATE state = m_Debugger->ScriptSystem()->GetInstanceState(m_SelectedScriptName);
char* szState;
switch (state)
{
case STATE_RUNNING: szState = "Running"; break;
case STATE_STARTED: szState = "Started"; break;
case STATE_STOPPED: szState = "Stopped"; break;
case STATE_INVALID: szState = "Not running"; break;
}
stdstr instanceInfo = stdstr_f("%s (%s)", m_SelectedScriptName, szState);
m_InstanceInfoEdit.SetWindowTextA(instanceInfo.c_str());
if (state == STATE_RUNNING)
{
m_EvalEdit.EnableWindow(TRUE);
}
else
{
m_EvalEdit.EnableWindow(FALSE);
}
}
LRESULT CDebugScripts::OnScriptListClicked(NMHDR* pNMHDR)
{
// Select instance for console input
NMITEMACTIVATE* pIA = reinterpret_cast<NMITEMACTIVATE*>(pNMHDR);
int nItem = pIA->iItem;
m_ScriptList.GetItemText(nItem, 0, m_SelectedScriptName, MAX_PATH);
RefreshStatus();
return 0;
}
LRESULT CDebugScripts::OnScriptListRClicked(NMHDR* pNMHDR)
{
OnScriptListClicked(pNMHDR);
HMENU hMenu = LoadMenu(GetModuleHandle(NULL), MAKEINTRESOURCE(IDR_SCRIPT_POPUP));
HMENU hPopupMenu = GetSubMenu(hMenu, 0);
/*
if (m_Breakpoints->m_RBP.size() == 0 && m_Breakpoints->m_WBP.size() == 0)
{
EnableMenuItem(hPopupMenu, ID_POPUPMENU_CLEARALLBPS, MF_DISABLED | MF_GRAYED);
}
*/
POINT mouse;
GetCursorPos(&mouse);
TrackPopupMenu(hPopupMenu, TPM_LEFTALIGN, mouse.x, mouse.y, 0, m_hWnd, NULL);
DestroyMenu(hMenu);
return 0;
}
LRESULT CDebugScripts::OnScriptListCustomDraw(NMHDR* pNMHDR)
{
NMLVCUSTOMDRAW* pLVCD = reinterpret_cast<NMLVCUSTOMDRAW*>(pNMHDR);
DWORD drawStage = pLVCD->nmcd.dwDrawStage;
switch (drawStage)
{
case CDDS_PREPAINT:
return CDRF_NOTIFYITEMDRAW;
case CDDS_ITEMPREPAINT:
return CDRF_NOTIFYSUBITEMDRAW;
case (CDDS_ITEMPREPAINT | CDDS_SUBITEM):
break;
default:
return CDRF_DODEFAULT;
}
DWORD nItem = pLVCD->nmcd.dwItemSpec;
char scriptName[MAX_PATH];
m_ScriptList.GetItemText(nItem, 0, scriptName, MAX_PATH);
INSTANCE_STATE state = m_Debugger->ScriptSystem()->GetInstanceState(scriptName);
if (state == STATE_STARTED)
{
pLVCD->clrTextBk = RGB(0xFF, 0xFF, 0xAA);
}
else if (state == STATE_RUNNING)
{
pLVCD->clrTextBk = RGB(0xAA, 0xFF, 0xAA);
}
return CDRF_DODEFAULT;
}
void CDebugScripts::EvaluateInSelectedInstance(char* code)
{
INSTANCE_STATE state = m_Debugger->ScriptSystem()->GetInstanceState(m_SelectedScriptName);
if (state == STATE_RUNNING || state == STATE_STARTED)
{
CScriptInstance* instance = m_Debugger->ScriptSystem()->GetInstance(m_SelectedScriptName);
//instance->EvalAsync(code);
instance->Eval(code);
}
}
// Console input
LRESULT CEditEval::OnKeyDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
if (wParam == VK_UP)
{
if (m_HistoryIdx > 0)
{
char* code = m_History[--m_HistoryIdx];
SetWindowTextA(code);
int selEnd = strlen(code);
SetSel(selEnd, selEnd);
}
}
else if (wParam == VK_DOWN)
{
int size = m_History.size();
if (m_HistoryIdx < size - 1)
{
char* code = m_History[++m_HistoryIdx];
SetWindowTextA(code);
int selEnd = strlen(code);
SetSel(selEnd, selEnd);
}
else if (m_HistoryIdx < size)
{
SetWindowTextA("");
m_HistoryIdx++;
}
}
else if (wParam == VK_RETURN)
{
if (m_ScriptWindow == NULL)
{
bHandled = FALSE;
return 0;
}
size_t codeLength = GetWindowTextLength() + 1;
char* code = (char*)malloc(codeLength);
GetWindowTextA(code, codeLength);
m_ScriptWindow->EvaluateInSelectedInstance(code);
SetWindowTextA("");
int historySize = m_History.size();
// remove duplicate
for (int i = 0; i < historySize; i++)
{
if (strcmp(code, m_History[i]) == 0)
{
free(m_History[i]);
m_History.erase(m_History.begin() + i);
historySize--;
break;
}
}
// remove oldest if maxed
if (historySize >= HISTORY_MAX_ENTRIES)
{
m_History.erase(m_History.begin() + 0);
historySize--;
}
m_History.push_back(code);
m_HistoryIdx = ++historySize;
}
bHandled = FALSE;
return 0;
}
void CDebugScripts::RunSelected()
{
INSTANCE_STATE state = m_Debugger->ScriptSystem()->GetInstanceState(m_SelectedScriptName);
if (state == STATE_INVALID || state == STATE_STOPPED)
{
m_Debugger->ScriptSystem()->RunScript(m_SelectedScriptName);
}
else
{
m_Debugger->Debug_LogScriptsWindow("[Error: Script is already running]\n");
}
}
void CDebugScripts::StopSelected()
{
m_Debugger->ScriptSystem()->StopScript(m_SelectedScriptName);
}

View File

@ -0,0 +1,143 @@
/****************************************************************************
* *
* Project64 - A Nintendo 64 emulator. *
* http://www.pj64-emu.com/ *
* Copyright (C) 2012 Project64. All rights reserved. *
* *
* License: *
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
* *
****************************************************************************/
#pragma once
#include "DebuggerUI.h"
#include "ScriptSystem.h"
class CScriptList : public CListViewCtrl
{
public:
BEGIN_MSG_MAP_EX(CScriptList)
END_MSG_MAP()
};
class CEditEval : public CWindowImpl<CEditEval, CEdit>
{
private:
//static char* m_EvalString;
static const int HISTORY_MAX_ENTRIES = 20;
vector<char*> m_History;
int m_HistoryIdx;
CDebugScripts* m_ScriptWindow;
public:
CEditEval()
{
m_HistoryIdx = 0;
}
void SetScriptWindow(CDebugScripts* scriptWindow)
{
m_ScriptWindow = scriptWindow;
}
LRESULT OnKeyDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
BOOL Attach(HWND hWndNew)
{
return SubclassWindow(hWndNew);
}
BEGIN_MSG_MAP_EX(CEditEval)
MESSAGE_HANDLER(WM_KEYDOWN, OnKeyDown)
END_MSG_MAP()
};
class CEditConsole : public CWindowImpl<CEditEval, CEdit>
{
private:
LRESULT OnKeyDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
if (GetKeyState(VK_CONTROL) < 0)
{
if (wParam == 'A')
{
this->SetSelAll();
}
}
return FALSE;
}
public:
BOOL Attach(HWND hWndNew)
{
return SubclassWindow(hWndNew);
}
BEGIN_MSG_MAP_EX(CEditEval)
MESSAGE_HANDLER(WM_KEYDOWN, OnKeyDown)
END_MSG_MAP()
};
class CDebugScripts :
public CDebugDialog < CDebugScripts >,
public CDialogResize<CDebugScripts>
{
private:
CEdit m_InstanceInfoEdit;
CEditEval m_EvalEdit;
CEditConsole m_ConsoleEdit;
CScriptList m_ScriptList;
char* m_SelectedScriptName;
void RefreshStatus();
public:
enum { IDD = IDD_Debugger_Scripts };
CDebugScripts(CDebuggerUI * debugger);
virtual ~CDebugScripts(void);
void ConsolePrint(const char* text);
void ConsoleClear();
void ConsoleCopy();
void RefreshList();
void RefreshConsole();
void EvaluateInSelectedInstance(char* code);
void RunSelected();
void StopSelected();
LRESULT OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnDestroy(void)
{
return 0;
}
LRESULT OnClicked(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnScriptListDblClicked(NMHDR* pNMHDR);
LRESULT OnScriptListClicked(NMHDR* pNMHDR);
LRESULT OnScriptListRClicked(NMHDR* pNMHDR);
LRESULT OnScriptListCustomDraw(NMHDR* pNMHDR);
BEGIN_MSG_MAP_EX(CDebugScripts)
COMMAND_CODE_HANDLER(BN_CLICKED, OnClicked)
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
NOTIFY_HANDLER_EX(IDC_SCRIPT_LIST, NM_DBLCLK, OnScriptListDblClicked)
NOTIFY_HANDLER_EX(IDC_SCRIPT_LIST, NM_CLICK, OnScriptListClicked)
NOTIFY_HANDLER_EX(IDC_SCRIPT_LIST, NM_RCLICK, OnScriptListRClicked)
NOTIFY_HANDLER_EX(IDC_SCRIPT_LIST, NM_CUSTOMDRAW, OnScriptListCustomDraw)
CHAIN_MSG_MAP_MEMBER(m_ScriptList)
MSG_WM_DESTROY(OnDestroy)
CHAIN_MSG_MAP(CDialogResize<CDebugScripts>)
END_MSG_MAP()
BEGIN_DLGRESIZE_MAP(CDebugScripts)
DLGRESIZE_CONTROL(IDC_CTX_INFO_EDIT, DLSZ_SIZE_X)
DLGRESIZE_CONTROL(IDC_EVAL_EDIT, DLSZ_SIZE_X | DLSZ_MOVE_Y)
DLGRESIZE_CONTROL(IDC_CONSOLE_EDIT, DLSZ_SIZE_X | DLSZ_SIZE_Y)
DLGRESIZE_CONTROL(IDC_SCRIPT_LIST, DLSZ_SIZE_Y)
DLGRESIZE_CONTROL(IDC_CLEAR_BTN, DLSZ_MOVE_X)
DLGRESIZE_CONTROL(IDC_COPY_BTN, DLSZ_MOVE_X)
END_DLGRESIZE_MAP()
};

View File

@ -0,0 +1,104 @@
/****************************************************************************
* *
* Project64 - A Nintendo 64 emulator. *
* http://www.pj64-emu.com/ *
* Copyright (C) 2012 Project64. All rights reserved. *
* *
* License: *
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
* *
****************************************************************************/
#include "stdafx.h"
#include "DebuggerUI.h"
CDebugStackTrace::CDebugStackTrace(CDebuggerUI* debugger) :
CDebugDialog<CDebugStackTrace>(debugger)
{
}
CDebugStackTrace::~CDebugStackTrace()
{
}
LRESULT CDebugStackTrace::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
DlgResize_Init();
m_List.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT, 0);
m_List.Attach(GetDlgItem(IDC_STACKTRACE_LIST));
m_List.AddColumn("Routine", 0);
m_List.AddColumn("Name", 1);
m_List.SetColumnWidth(0, 60);
m_List.SetColumnWidth(1, 100);
WindowCreated();
return TRUE;
}
LRESULT CDebugStackTrace::OnActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
RefreshList();
return FALSE;
}
LRESULT CDebugStackTrace::OnDestroy(void)
{
return FALSE;
}
LRESULT CDebugStackTrace::OnClicked(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
switch (wID)
{
case IDCANCEL:
EndDialog(0);
break;
}
return FALSE;
}
LRESULT CDebugStackTrace::OnListDblClicked(NMHDR* pNMHDR)
{
NMITEMACTIVATE* pIA = reinterpret_cast<NMITEMACTIVATE*>(pNMHDR);
int nItem = pIA->iItem;
uint32_t address = m_List.GetItemData(nItem);
m_Debugger->Debug_ShowCommandsLocation(address, true);
return 0;
}
void CDebugStackTrace::RefreshList()
{
vector<uint32_t>* stackTrace = m_Debugger->StackTrace();
m_List.SetRedraw(FALSE);
m_List.DeleteAllItems();
int count = stackTrace->size();
if (count > 4000)
{
count = 4000;
}
for (int i = 0; i < count; i++)
{
uint32_t address = stackTrace->at(i);
char szAddress[9];
sprintf(szAddress, "%08X", address);
m_List.AddItem(i, 0, szAddress);
m_List.AddItem(i, 1, "symbol");
m_List.SetItemData(i, address);
}
m_List.SetRedraw(TRUE);
}

View File

@ -0,0 +1,51 @@
/****************************************************************************
* *
* Project64 - A Nintendo 64 emulator. *
* http://www.pj64-emu.com/ *
* Copyright (C) 2012 Project64. All rights reserved. *
* *
* License: *
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
* *
****************************************************************************/
#pragma once
#include "DebuggerUI.h"
class CDebugStackTrace :
public CDebugDialog<CDebugStackTrace>,
public CDialogResize<CDebugStackTrace>
{
public:
enum { IDD = IDD_Debugger_StackTrace };
CDebugStackTrace(CDebuggerUI * debugger);
virtual ~CDebugStackTrace(void);
void RefreshList();
private:
HANDLE m_AutoRefreshThread;
static DWORD WINAPI AutoRefreshProc(void* _this);
CListViewCtrl m_List;
LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
LRESULT OnActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnClicked(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnListDblClicked(NMHDR* pNMHDR);
LRESULT OnDestroy(void);
BEGIN_MSG_MAP_EX(CDebugStackTrace)
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
MESSAGE_HANDLER(WM_ACTIVATE, OnActivate)
COMMAND_CODE_HANDLER(BN_CLICKED, OnClicked)
NOTIFY_HANDLER_EX(IDC_STACKTRACE_LIST, NM_DBLCLK, OnListDblClicked)
CHAIN_MSG_MAP(CDialogResize<CDebugStackTrace>)
END_MSG_MAP()
BEGIN_DLGRESIZE_MAP(CDebugStackTrace)
DLGRESIZE_CONTROL(IDC_STACKTRACE_LIST, DLSZ_SIZE_X | DLSZ_SIZE_Y)
END_DLGRESIZE_MAP()
};

View File

@ -0,0 +1,108 @@
/****************************************************************************
* *
* Project64 - A Nintendo 64 emulator. *
* http://www.pj64-emu.com/ *
* Copyright (C) 2012 Project64. All rights reserved. *
* *
* License: *
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
* *
****************************************************************************/
#include "stdafx.h"
#include "DebuggerUI.h"
CDebugStackView::CDebugStackView(CDebuggerUI * debugger) :
CDebugDialog<CDebugStackView>(debugger)
{
}
CDebugStackView::~CDebugStackView(void)
{
}
LRESULT CDebugStackView::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
DlgResize_Init(false, true);
m_StackList.Attach(GetDlgItem(IDC_STACK_LIST));
m_StackList.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER);
m_StackList.AddColumn("#", 0);
m_StackList.AddColumn("00", 1);
m_StackList.AddColumn("04", 2);
m_StackList.AddColumn("08", 3);
m_StackList.AddColumn("0C", 4);
m_StackList.SetColumnWidth(0, 22);
m_StackList.SetColumnWidth(1, 64);
m_StackList.SetColumnWidth(2, 64);
m_StackList.SetColumnWidth(3, 64);
m_StackList.SetColumnWidth(4, 64);
m_SPStatic.Attach(GetDlgItem(IDC_SP_STATIC));
WindowCreated();
return 0;
}
LRESULT CDebugStackView::OnDestroy(void)
{
return 0;
}
LRESULT CDebugStackView::OnClicked(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
switch (wID)
{
case IDC_MEM_BTN:
if (g_Reg != NULL)
{
m_Debugger->Debug_ShowMemoryLocation(g_Reg->m_GPR[29].UW[0], true);
}
break;
case IDCANCEL:
EndDialog(0);
break;
}
return 0;
}
void CDebugStackView::Refresh()
{
m_StackList.SetRedraw(FALSE);
m_StackList.DeleteAllItems();
uint32_t spBase;
if (g_Reg != NULL)
{
spBase = g_Reg->m_GPR[29].UW[0];
m_SPStatic.SetWindowTextA(stdstr_f("SP: %08X", spBase).c_str());
}
for (int i = 0; i < 0x10; i++)
{
char t[4];
sprintf(t, "%02X", i * 0x10);
m_StackList.AddItem(i, 0, t);
for (int j = 0; j < 4; j++)
{
if (g_MMU == NULL)
{
m_StackList.AddItem(i, j + 1, "????????");
continue;
}
uint32_t val;
g_MMU->LW_VAddr(spBase + i * 0x10 + j * 4, val);
char valStr[9];
sprintf(valStr, "%08X", val);
m_StackList.AddItem(i, j + 1, valStr);
}
}
m_StackList.SetRedraw(TRUE);
}

View File

@ -0,0 +1,45 @@
/****************************************************************************
* *
* Project64 - A Nintendo 64 emulator. *
* http://www.pj64-emu.com/ *
* Copyright (C) 2012 Project64. All rights reserved. *
* *
* License: *
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
* *
****************************************************************************/
#pragma once
class CDebugStackView :
public CDebugDialog<CDebugStackView>,
public CDialogResize<CDebugStackView>
{
public:
enum { IDD = IDD_Debugger_Stack };
CDebugStackView(CDebuggerUI * debugger);
virtual ~CDebugStackView(void);
void Refresh();
private:
CListViewCtrl m_StackList;
CStatic m_SPStatic;
LRESULT OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnDestroy(void);
LRESULT OnClicked(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
BEGIN_MSG_MAP_EX(CDebugStackView)
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
MSG_WM_DESTROY(OnDestroy)
COMMAND_CODE_HANDLER(BN_CLICKED, OnClicked)
CHAIN_MSG_MAP(CDialogResize<CDebugStackView>)
END_MSG_MAP()
BEGIN_DLGRESIZE_MAP(CDebugStackView)
DLGRESIZE_CONTROL(IDC_STACK_LIST, DLSZ_SIZE_X | DLSZ_SIZE_Y)
END_DLGRESIZE_MAP()
};

View File

@ -0,0 +1,176 @@
/****************************************************************************
* *
* Project64 - A Nintendo 64 emulator. *
* http://www.pj64-emu.com/ *
* Copyright (C) 2012 Project64. All rights reserved. *
* *
* License: *
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
* *
****************************************************************************/
#include "stdafx.h"
#include "DebuggerUI.h"
#include <stdio.h>
#include <Common/path.h>
#include "Symbols.h"
CDebugSymbols::CDebugSymbols(CDebuggerUI * debugger) :
CDebugDialog<CDebugSymbols>(debugger)
{
}
LRESULT CDebugSymbols::OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
DlgResize_Init(false, true);
m_SymbolsListView.Attach(GetDlgItem(IDC_SYMBOLS_LIST));
m_SymbolsListView.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER);
m_SymbolsListView.AddColumn("Address", 0);
m_SymbolsListView.AddColumn("Type", 1);
m_SymbolsListView.AddColumn("Name", 2);
m_SymbolsListView.AddColumn("Value", 3);
m_SymbolsListView.AddColumn("Description", 4);
m_SymbolsListView.SetColumnWidth(0, 70);
m_SymbolsListView.SetColumnWidth(1, 40);
m_SymbolsListView.SetColumnWidth(2, 120);
m_SymbolsListView.SetColumnWidth(3, 100);
m_SymbolsListView.SetColumnWidth(4, 120);
Refresh();
m_AutoRefreshThread = CreateThread(NULL, 0, AutoRefreshProc, (void*)this, 0, NULL);
WindowCreated();
return 0;
}
LRESULT CDebugSymbols::OnDestroy(void)
{
if (m_AutoRefreshThread != NULL)
{
TerminateThread(m_AutoRefreshThread, 0);
CloseHandle(m_AutoRefreshThread);
}
return 0;
}
DWORD WINAPI CDebugSymbols::AutoRefreshProc(void* _this)
{
CDebugSymbols* self = (CDebugSymbols*)_this;
while (true)
{
self->RefreshValues();
Sleep(100);
}
}
LRESULT CDebugSymbols::OnClicked(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
switch (wID)
{
case IDCANCEL:
EndDialog(0);
break;
case IDC_ADDSYMBOL_BTN:
m_AddSymbolDlg.DoModal(m_Debugger);
break;
case IDC_REMOVESYMBOL_BTN:
{
int id = m_SymbolsListView.GetItemData(m_SymbolsListView.GetSelectedIndex());
CSymbols::EnterCriticalSection();
CSymbols::RemoveEntryById(id);
CSymbols::Save();
CSymbols::LeaveCriticalSection();
Refresh();
break;
}
}
return FALSE;
}
LRESULT CDebugSymbols::OnListDblClicked(NMHDR* pNMHDR)
{
// Open it in memory viewer/commands viewer
NMITEMACTIVATE* pIA = reinterpret_cast<NMITEMACTIVATE*>(pNMHDR);
int nItem = pIA->iItem;
int id = m_SymbolsListView.GetItemData(nItem);
CSymbolEntry* symbol = CSymbols::GetEntryById(id);
if (symbol->m_Type == 0) // code
{
m_Debugger->Debug_ShowCommandsLocation(symbol->m_Address, true);
}
else // data/number
{
m_Debugger->Debug_ShowMemoryLocation(symbol->m_Address, true);
}
return 0;
}
void CDebugSymbols::Refresh()
{
m_SymbolsListView.SetRedraw(FALSE);
m_SymbolsListView.DeleteAllItems();
CSymbols::EnterCriticalSection();
int count = CSymbols::GetCount();
for (int i = 0; i < count; i++)
{
CSymbolEntry* lpSymbol = CSymbols::GetEntryByIndex(i);
stdstr addrStr = stdstr_f("%08X", lpSymbol->m_Address);
m_SymbolsListView.AddItem(i, 0, addrStr.c_str());
m_SymbolsListView.AddItem(i, 1, lpSymbol->TypeName());
m_SymbolsListView.AddItem(i, 2, lpSymbol->m_Name);
m_SymbolsListView.AddItem(i, 4, lpSymbol->m_Description);
m_SymbolsListView.SetItemData(i, lpSymbol->m_Id);
if (g_MMU)
{
char szValue[64];
CSymbols::GetValueString(szValue, lpSymbol);
m_SymbolsListView.AddItem(i, 3, szValue);
}
}
CSymbols::LeaveCriticalSection();
m_SymbolsListView.SetRedraw(TRUE);
}
void CDebugSymbols::RefreshValues()
{
if (g_MMU == NULL)
{
return;
}
int count = m_SymbolsListView.GetItemCount();
CSymbols::EnterCriticalSection();
for (int i = 0; i < count; i++)
{
int symbolId = m_SymbolsListView.GetItemData(i);
CSymbolEntry* lpSymbol = CSymbols::GetEntryById(symbolId);
char szValue[64];
CSymbols::GetValueString(szValue, lpSymbol);
m_SymbolsListView.SetItemText(i, 3, szValue);
}
CSymbols::LeaveCriticalSection();
}

View File

@ -0,0 +1,61 @@
/****************************************************************************
* *
* Project64 - A Nintendo 64 emulator. *
* http://www.pj64-emu.com/ *
* Copyright (C) 2012 Project64. All rights reserved. *
* *
* License: *
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
* *
****************************************************************************/
#pragma once
#include "DebuggerUI.h"
// todo maybe add char* ownerName and use a TreeView
class CDebugSymbols :
public CDebugDialog<CDebugSymbols>,
public CDialogResize<CDebugSymbols>
{
private:
CListViewCtrl m_SymbolsListView;
CAddSymbolDlg m_AddSymbolDlg;
HANDLE m_AutoRefreshThread;
static DWORD WINAPI CDebugSymbols::AutoRefreshProc(void* _this);
public:
enum { IDD = IDD_Debugger_Symbols };
CDebugSymbols(CDebuggerUI * debugger);
//virtual ~CDebugScripts(void);
void Refresh();
void RefreshValues();
LRESULT OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnClicked(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnListDblClicked(NMHDR* pNMHDR);
LRESULT OnDestroy(void);
BEGIN_MSG_MAP_EX(CDebugSymbols)
COMMAND_CODE_HANDLER(BN_CLICKED, OnClicked)
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
MSG_WM_DESTROY(OnDestroy)
NOTIFY_HANDLER_EX(IDC_SYMBOLS_LIST, NM_DBLCLK, OnListDblClicked)
//NOTIFY_HANDLER_EX(IDC_CMD_LIST, NM_RCLICK, OnListClicked)
CHAIN_MSG_MAP(CDialogResize<CDebugSymbols>)
END_MSG_MAP()
BEGIN_DLGRESIZE_MAP(CDebugSymbols)
DLGRESIZE_CONTROL(IDC_FILTER_EDIT, DLSZ_MOVE_Y)
DLGRESIZE_CONTROL(IDC_FILTER_STATIC, DLSZ_MOVE_Y)
DLGRESIZE_CONTROL(IDC_REMOVESYMBOL_BTN, DLSZ_MOVE_X | DLSZ_MOVE_Y)
DLGRESIZE_CONTROL(IDC_ADDSYMBOL_BTN, DLSZ_MOVE_X | DLSZ_MOVE_Y)
DLGRESIZE_CONTROL(IDC_SYMBOLS_LIST, DLSZ_SIZE_X | DLSZ_SIZE_Y)
END_DLGRESIZE_MAP()
};

View File

@ -11,6 +11,8 @@
#include "stdafx.h"
#include "DebuggerUI.h"
#include "Symbols.h"
#include "DMALog.h"
CDebugMemoryView::CDebugMemoryView(CDebuggerUI * debugger) :
CDebugDialog<CDebugMemoryView>(debugger),
@ -21,6 +23,9 @@ m_MemoryList(NULL)
m_MemoryList = new CListCtrl;
m_MemoryList->RegisterClass();
}
m_Breakpoints = m_Debugger->Breakpoints();
}
CDebugMemoryView::~CDebugMemoryView()
@ -29,6 +34,8 @@ CDebugMemoryView::~CDebugMemoryView()
LRESULT CDebugMemoryView::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
m_SymbolColorStride = 0;
m_SymbolColorPhase = 0;
m_DataStartLoc = (DWORD)-1;
m_CompareStartLoc = (DWORD)-1;
memset(m_CompareData, 0, sizeof(m_CompareData));
@ -50,7 +57,7 @@ LRESULT CDebugMemoryView::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM
m_MemAddr.Attach(GetDlgItem(IDC_ADDR_EDIT));
m_MemAddr.SetDisplayType(CEditNumber::DisplayHex);
m_MemAddr.SetValue(0x80000000, true, true);
m_MemAddr.SetValue(0x80000000, false, true);
SendDlgItemMessage(IDC_CHK_VADDR, BM_SETCHECK, BST_CHECKED, 0);
@ -97,8 +104,6 @@ LRESULT CDebugMemoryView::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM
SetWindowPos(NULL, 0, 0, MemoryListWindow.right - MemoryListWindow.left, (MemoryListWindow.bottom - MemoryListWindow.top) + (height - MemoryListRect.bottom), SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOZORDER);
RECT DlgItemRect = { 0 };
::GetWindowRect(GetDlgItem(IDC_BORDER), &DlgItemRect);
::SetWindowPos(GetDlgItem(IDC_BORDER), NULL, 0, 0, DlgItemRect.right - DlgItemRect.left, (DlgItemRect.bottom - DlgItemRect.top) + (height - MemoryListRect.bottom), SWP_NOMOVE);
::GetWindowRect(GetDlgItem(IDC_MEM_DETAILS), &DlgItemRect);
::SetWindowPos(GetDlgItem(IDC_MEM_DETAILS), NULL, 0, 0, DlgItemRect.right - DlgItemRect.left, (DlgItemRect.bottom - DlgItemRect.top) + (height - MemoryListRect.bottom), SWP_NOMOVE);
@ -106,12 +111,34 @@ LRESULT CDebugMemoryView::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM
::GetWindowRect(GetDlgItem(IDC_SCRL_BAR), &DlgItemRect);
::SetWindowPos(GetDlgItem(IDC_SCRL_BAR), NULL, 0, 0, DlgItemRect.right - DlgItemRect.left, (DlgItemRect.bottom - DlgItemRect.top) + (height - MemoryListRect.bottom), SWP_NOMOVE);
}
m_SymInfo.Attach(GetDlgItem(IDC_SYM_INFO));
m_DMAInfo.Attach(GetDlgItem(IDC_DMA_INFO));
WindowCreated();
m_AutoRefreshThread = CreateThread(NULL, 0, AutoRefreshProc, (void*)this, 0, NULL);
return TRUE;
}
DWORD WINAPI CDebugMemoryView::AutoRefreshProc(void* _this)
{
CDebugMemoryView* self = (CDebugMemoryView*)_this;
while (true)
{
self->RefreshMemory(true);
Sleep(100);
}
}
LRESULT CDebugMemoryView::OnDestroy(void)
{
if (m_AutoRefreshThread != NULL)
{
TerminateThread(m_AutoRefreshThread, 0);
CloseHandle(m_AutoRefreshThread);
}
if (m_MemoryList)
{
m_MemoryList->UnsubclassWindow();
@ -137,60 +164,138 @@ LRESULT CDebugMemoryView::OnClicked(WORD /*wNotifyCode*/, WORD wID, HWND, BOOL&
case IDC_SEARCH_MEM:
m_Debugger->Debug_ShowMemorySearch();
break;
case IDC_SYMBOLS_BTN:
m_Debugger->Debug_ShowSymbolsWindow();
break;
case IDCANCEL:
EndDialog(0);
break;
case ID_POPUPMENU_TOGGLERBP:
m_Breakpoints->RBPToggle(m_CtxMenuAddr);
RefreshMemory(true);
break;
case ID_POPUPMENU_TOGGLEWBP:
m_Breakpoints->WBPToggle(m_CtxMenuAddr);
RefreshMemory(true);
break;
case ID_POPUPMENU_CLEARALLBPS:
m_Breakpoints->RBPClear();
m_Breakpoints->WBPClear();
RefreshMemory(true);
break;
case ID_POPUPMENU_VIEWDISASM:
m_Debugger->Debug_ShowCommandsLocation(m_CtxMenuAddr, true);
break;
case ID_POPUPMENU_ADDSYMBOL:
m_AddSymbolDlg.DoModal(m_Debugger, m_CtxMenuAddr);
break;
}
return FALSE;
}
LRESULT CDebugMemoryView::OnMemoryRightClicked(LPNMHDR lpNMHDR)
{
uint32_t address;
bool bData = GetItemAddress(lpNMHDR, address);
if (!bData)
{
return 0;
}
m_CtxMenuAddr = address;
HMENU hMenu = LoadMenu(GetModuleHandle(NULL), MAKEINTRESOURCE(IDR_MEM_BP_POPUP));
HMENU hPopupMenu = GetSubMenu(hMenu, 0);
if (m_Breakpoints->m_RBP.size() == 0 && m_Breakpoints->m_WBP.size() == 0)
{
EnableMenuItem(hPopupMenu, ID_POPUPMENU_CLEARALLBPS, MF_DISABLED | MF_GRAYED);
}
POINT mouse;
GetCursorPos(&mouse);
TrackPopupMenu(hPopupMenu, TPM_LEFTALIGN, mouse.x, mouse.y, 0, m_hWnd, NULL);
DestroyMenu(hMenu);
return 0;
}
LRESULT CDebugMemoryView::OnHotItemChanged(LPNMHDR lpNMHDR)
{
uint32_t address;
bool bData = GetItemAddress(lpNMHDR, address);
if (!bData)
{
return 0;
}
CSymbols::EnterCriticalSection();
CSymbolEntry* lpSymbol = CSymbols::GetEntryByAddress(address);
stdstr symbolInfo;
if (lpSymbol != NULL)
{
char* desc = lpSymbol->m_Description;
desc = desc ? desc : "";
symbolInfo = stdstr_f("%08X: %s %s // %s", address, lpSymbol->TypeName(), lpSymbol->m_Name, desc);
}
else
{
symbolInfo = stdstr_f("%08X", address);
}
CSymbols::LeaveCriticalSection();
m_SymInfo.SetWindowTextA(symbolInfo.c_str());
uint32_t romAddr, offset;
DMALOGENTRY* lpEntry = m_Debugger->DMALog()->GetEntryByRamAddress(address, &romAddr, &offset);
stdstr dmaInfo;
if (lpEntry != NULL)
{
dmaInfo = stdstr_f("Last DMA: %08X -> %08X [%X] (%08X, +%X) ", lpEntry->romAddr, lpEntry->ramAddr, lpEntry->length, romAddr, offset);
}
else
{
dmaInfo = stdstr_f("Last DMA: ?");
}
m_DMAInfo.SetWindowTextA(dmaInfo.c_str());
return 0;
}
LRESULT CDebugMemoryView::OnMemoryModified(LPNMHDR lpNMHDR)
{
uint32_t Pos = 0;
bool bData = GetItemOffset(lpNMHDR, Pos);
if (!bData)
{
return 0;
}
CListNotify *pListNotify = reinterpret_cast<CListNotify *>(lpNMHDR);
int LineNumber = pListNotify->m_nItem;
int Pos = ((LineNumber << 4) + (pListNotify->m_nSubItem - 1));
if (pListNotify->m_nSubItem >= 6 && pListNotify->m_nSubItem < 10)
{
Pos = ((LineNumber << 4) + (pListNotify->m_nSubItem - 2));
}
if (pListNotify->m_nSubItem >= 11 && pListNotify->m_nSubItem < 15)
{
Pos = ((LineNumber << 4) + (pListNotify->m_nSubItem - 3));
}
if (pListNotify->m_nSubItem >= 16 && pListNotify->m_nSubItem < 20)
{
Pos = ((LineNumber << 4) + (pListNotify->m_nSubItem - 4));
}
LPCSTR strValue = m_MemoryList->GetItemText(pListNotify->m_nItem, pListNotify->m_nSubItem);
int Finish = strlen(strValue);
if (Finish > 8)
{
Finish = 8;
}
DWORD Value = 0;
for (int i = 0; i < Finish; i++)
{
Value = (Value << 4);
if (strValue[i] <= '9' && strValue[i] >= '0')
{
Value |= strValue[i] - '0';
}
else if (strValue[i] <= 'f' && strValue[i] >= 'a')
{
Value |= strValue[i] - 'a' + 10;
}
else if (strValue[i] <= 'F' && strValue[i] >= 'A')
{
Value |= strValue[i] - 'A' + 10;
}
}
DWORD Value = strtoull(strValue, NULL, 16);
if (m_CurrentData[Pos] == Value)
{
return 0;
}
if (m_CompareStartLoc != m_DataStartLoc ||
m_CompareVAddrr != m_DataVAddrr)
{
@ -200,10 +305,10 @@ LRESULT CDebugMemoryView::OnMemoryModified(LPNMHDR lpNMHDR)
memcpy(m_CompareData, m_CurrentData, sizeof(m_CurrentData));
memcpy(m_CompareValid, m_DataValid, sizeof(m_CompareValid));
}
m_CompareData[Pos] = m_CurrentData[Pos];
m_CurrentData[Pos] = (BYTE)Value;
//sb
if (m_DataVAddrr)
{
@ -224,6 +329,54 @@ LRESULT CDebugMemoryView::OnMemoryModified(LPNMHDR lpNMHDR)
return 0;
}
void CDebugMemoryView::OnAddrChanged(UINT /*Code*/, int /*id*/, HWND /*ctl*/)
{
RefreshMemory(false);
}
void CDebugMemoryView::OnVScroll(int request, short Pos, HWND ctrl)
{
if (ctrl != GetDlgItem(IDC_SCRL_BAR))
{
return;
}
DWORD Location = m_MemAddr.GetValue();
switch (request)
{
case SB_LINEDOWN:
m_MemAddr.SetValue(Location < 0xFFFFFFEF ? Location + 0x10 : 0xFFFFFFFF, false, true);
break;
case SB_LINEUP:
m_MemAddr.SetValue(Location > 0x10 ? Location - 0x10 : 0, false, true);
break;
case SB_PAGEDOWN:
m_MemAddr.SetValue(Location < 0xFFFFFEFF ? Location + 0x100 : 0xFFFFFFFF, false, true);
break;
case SB_PAGEUP:
m_MemAddr.SetValue(Location > 0x100 ? Location - 0x100 : 0, false, true);
break;
case SB_THUMBPOSITION:
m_MemAddr.SetValue((DWORD)Pos << 0x10, false, true);
break;
default:
break;
}
}
LRESULT CDebugMemoryView::OnActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
WORD type = LOWORD(wParam);
if (type == WA_INACTIVE)
{
return FALSE;
}
RefreshMemory(false);
return FALSE;
}
void CDebugMemoryView::ShowAddress(DWORD Address, bool VAddr)
{
if (m_hWnd == NULL)
@ -232,7 +385,7 @@ void CDebugMemoryView::ShowAddress(DWORD Address, bool VAddr)
}
SendDlgItemMessage(IDC_CHK_VADDR, BM_SETCHECK, VAddr ? BST_CHECKED : BST_UNCHECKED, 0);
m_MemAddr.SetValue(Address, true, true);
m_MemAddr.SetValue(Address, false, true);
RefreshMemory(true);
}
@ -284,15 +437,22 @@ void CDebugMemoryView::Insert_MemoryLineDump(int LineNumber)
{
Changed = true;
}
sprintf(Hex, "%02X", m_CurrentData[Pos]);
m_MemoryList->SetItemText(LineNumber, col, Hex);
m_MemoryList->SetItemText(LineNumber, col, Hex);
m_MemoryList->SetItemFormat(LineNumber, col, ITEM_FORMAT_EDIT, ITEM_FLAGS_EDIT_HEX);
m_MemoryList->SetItemMaxEditLen(LineNumber, col, 2);
m_MemoryList->SetItemColours(LineNumber, col, GetSysColor(COLOR_WINDOW),
Changed ? RGB(255, 0, 0) : GetSysColor(COLOR_WINDOWTEXT));
m_MemoryList->SetItemHighlightColours(LineNumber, col,
Changed ? RGB(255, 0, 0) : GetSysColor(COLOR_HIGHLIGHTTEXT));
if (m_CurrentData[Pos] < 30)
uint32_t vaddr = 0x80000000 | (m_DataStartLoc + Pos);
COLORREF bgColor, fgColor, fgHiColor;
SelectColors(vaddr, Changed, bgColor, fgColor, fgHiColor);
m_MemoryList->SetItemColours(LineNumber, col, bgColor, fgColor);
m_MemoryList->SetItemHighlightColours(LineNumber, col, fgHiColor);
if (m_CurrentData[Pos] < 30)
{
strcat(Ascii, ".");
}
@ -324,42 +484,15 @@ void CDebugMemoryView::Insert_MemoryLineDump(int LineNumber)
}
}
void CDebugMemoryView::OnAddrChanged(UINT /*Code*/, int /*id*/, HWND /*ctl*/)
{
RefreshMemory(false);
}
void CDebugMemoryView::OnVScroll(int request, short Pos, HWND ctrl)
{
if (ctrl != GetDlgItem(IDC_SCRL_BAR))
{
return;
}
DWORD Location = m_MemAddr.GetValue();
switch (request)
{
case SB_LINEDOWN:
m_MemAddr.SetValue(Location < 0xFFFFFFEF ? Location + 0x10 : 0xFFFFFFFF, true, true);
break;
case SB_LINEUP:
m_MemAddr.SetValue(Location > 0x10 ? Location - 0x10 : 0, true, true);
break;
case SB_PAGEDOWN:
m_MemAddr.SetValue(Location < 0xFFFFFEFF ? Location + 0x100 : 0xFFFFFFFF, true, true);
break;
case SB_PAGEUP:
m_MemAddr.SetValue(Location > 0x100 ? Location - 0x100 : 0, true, true);
break;
case SB_THUMBPOSITION:
m_MemAddr.SetValue((DWORD)Pos << 0x10, true, true);
break;
default:
break;
}
}
void CDebugMemoryView::RefreshMemory(bool ResetCompare)
{
m_SymbolColorPhase = 0;
if (g_MMU == NULL)
{
return;
}
if (m_MemoryList && m_MemoryList->GetHasEditItem())
{
m_MemoryList->SetFocus();
@ -402,14 +535,22 @@ void CDebugMemoryView::RefreshMemory(bool ResetCompare)
if (m_DataVAddrr)
{
if (!g_MMU->LW_VAddr(m_DataStartLoc & ~3, word.UW))
if (!AddressSafe(m_DataStartLoc & ~3))
{
ValidData = false;
}
else if (!g_MMU->LW_VAddr(m_DataStartLoc & ~3, word.UW))
{
ValidData = false;
}
}
else
{
if (!g_MMU->LW_PAddr(m_DataStartLoc & ~3, word.UW))
if ((m_DataStartLoc & ~3) >= g_MMU->RdramSize())
{
ValidData = false;
}
else if (!g_MMU->LW_PAddr(m_DataStartLoc & ~3, word.UW))
{
ValidData = false;
}
@ -438,14 +579,22 @@ void CDebugMemoryView::RefreshMemory(bool ResetCompare)
if (m_DataVAddrr)
{
if (!g_MMU->LW_VAddr(Pos, word.UW))
if (!AddressSafe(Pos))
{
ValidData = false;
}
else if (!g_MMU->LW_VAddr(Pos, word.UW))
{
ValidData = false;
}
}
else
{
if (!g_MMU->LW_PAddr(Pos, word.UW))
if (Pos >= g_MMU->RdramSize())
{
ValidData = false;
}
else if (!g_MMU->LW_PAddr(Pos, word.UW))
{
ValidData = false;
}
@ -469,4 +618,102 @@ void CDebugMemoryView::RefreshMemory(bool ResetCompare)
{
Insert_MemoryLineDump(count);
}
}
bool CDebugMemoryView::GetItemOffset(LPNMHDR lpNMHDR, uint32_t &offset)
{
CListNotify *pListNotify = reinterpret_cast<CListNotify *>(lpNMHDR);
int nRow = pListNotify->m_nItem;
int nCol = pListNotify->m_nSubItem - 1;
if (nCol < 0 || (nCol % 5) == 4)
{
return false;
}
offset = (nRow * 0x10) + (nCol / 5) * 4 + (nCol % 5);
return true;
}
bool CDebugMemoryView::GetItemAddress(LPNMHDR lpNMHDR, uint32_t &address)
{
uint32_t offset;
bool bData = GetItemOffset(lpNMHDR, offset);
if (!bData)
{
return false;
}
address = 0x80000000 | (m_DataStartLoc + offset);
return true;
}
void CDebugMemoryView::SelectColors(uint32_t vaddr, bool changed, COLORREF& bgColor, COLORREF& fgColor, COLORREF& fgHiColor)
{
CSymbols::EnterCriticalSection();
CSymbolEntry* lpSymbol = CSymbols::GetEntryByAddress(vaddr);
if (lpSymbol != NULL)
{
m_SymbolColorStride = lpSymbol->TypeSize();
m_SymbolColorPhase = m_SymbolColorPhase ? 0 : 1;
}
CSymbols::LeaveCriticalSection();
bool bHaveReadBP = m_Breakpoints->RBPExists(vaddr);
bool bHaveWriteBP = m_Breakpoints->WBPExists(vaddr);
fgHiColor = RGB(0x00, 0x00, 0x00);
if (bHaveReadBP && bHaveWriteBP)
{
bgColor = RGB(0xAA, 0xDD, 0xDD);
}
else if (bHaveReadBP)
{
bgColor = RGB(0xDD, 0xDD, 0xAA);
}
else if (bHaveWriteBP)
{
bgColor = RGB(0xAA, 0xAA, 0xDD);
}
else if (m_SymbolColorStride > 0)
{
bgColor = m_SymbolColorPhase ? RGB(0xD0, 0xF0, 0xD0) : RGB(0xAA, 0xCC, 0xAA);
}
else
{
bgColor = GetSysColor(COLOR_WINDOW);
fgHiColor = (changed ? RGB(255, 0, 0) : GetSysColor(COLOR_HIGHLIGHTTEXT));
fgColor = (changed ? RGB(255, 0, 0) : GetSysColor(COLOR_WINDOWTEXT));
}
if (m_SymbolColorStride > 0)
{
m_SymbolColorStride--;
}
}
// Check if KSEG0 addr is out of bounds
bool CDebugMemoryView::AddressSafe(uint32_t vaddr)
{
if (g_MMU == NULL)
{
return false;
}
if (vaddr >= 0x80000000 && vaddr <= 0x9FFFFFFF)
{
if ((vaddr & 0x1FFFFFFF) >= g_MMU->RdramSize())
{
return false;
}
}
return true;
}

View File

@ -10,6 +10,8 @@
****************************************************************************/
#pragma once
#include "Debugger-AddSymbol.h"
class CDebugMemoryView :
public CDebugDialog < CDebugMemoryView >
{
@ -22,29 +24,53 @@ public:
void ShowAddress(DWORD Address, bool VAddr);
private:
BEGIN_MSG_MAP_EX(CDebugMemoryView)
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
COMMAND_CODE_HANDLER(BN_CLICKED, OnClicked)
COMMAND_HANDLER_EX(IDC_ADDR_EDIT, EN_CHANGE, OnAddrChanged)
NOTIFY_HANDLER_EX(IDC_MEM_DETAILS, LCN_MODIFIED, OnMemoryModified)
BEGIN_MSG_MAP_EX(CDebugMemoryView)
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
COMMAND_CODE_HANDLER(BN_CLICKED, OnClicked)
COMMAND_HANDLER_EX(IDC_ADDR_EDIT, EN_CHANGE, OnAddrChanged)
NOTIFY_HANDLER_EX(IDC_MEM_DETAILS, LCN_MODIFIED, OnMemoryModified)
NOTIFY_HANDLER_EX(IDC_MEM_DETAILS, LCN_RIGHTCLICK, OnMemoryRightClicked)
NOTIFY_HANDLER_EX(IDC_MEM_DETAILS, LCN_HOTITEMCHANGED, OnHotItemChanged)
MESSAGE_HANDLER(WM_ACTIVATE, OnActivate)
MSG_WM_DESTROY(OnDestroy)
MSG_WM_VSCROLL(OnVScroll)
END_MSG_MAP()
LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
LRESULT OnClicked(WORD wNotifyCode, WORD wID, HWND /*hWndCtl*/, BOOL& bHandled);
void OnAddrChanged(UINT Code, int id, HWND ctl);
void OnVScroll(int request, short Pos, HWND ctrl);
LRESULT OnMemoryModified(LPNMHDR lpNMHDR);
LRESULT OnDestroy(void);
LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
LRESULT OnClicked(WORD wNotifyCode, WORD wID, HWND /*hWndCtl*/, BOOL& bHandled);
void OnAddrChanged(UINT Code, int id, HWND ctl);
void OnVScroll(int request, short Pos, HWND ctrl);
LRESULT OnActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnMemoryModified(LPNMHDR lpNMHDR);
LRESULT OnMemoryRightClicked(LPNMHDR lpNMHDR);
LRESULT OnHotItemChanged(LPNMHDR lpNMHDR);
LRESULT OnDestroy(void);
void Insert_MemoryLineDump(int LineNumber);
void RefreshMemory(bool ResetCompare);
enum { MemoryToDisplay = 0x100 };
HANDLE m_AutoRefreshThread;
static DWORD WINAPI AutoRefreshProc(void* _this);
void SelectColors(uint32_t address, bool changed, COLORREF& bgColor, COLORREF& fgColor, COLORREF& fgHiColor);
bool GetItemOffset(LPNMHDR lpNMHDR, uint32_t &offset);
bool GetItemAddress(LPNMHDR lpNMHDR, uint32_t &address);
bool AddressSafe(uint32_t vaddr);
enum { MemoryToDisplay = 0x100 };
CEditNumber m_MemAddr;
CListCtrl * m_MemoryList;
CAddSymbolDlg m_AddSymbolDlg;
CStatic m_SymInfo;
CStatic m_DMAInfo;
CBreakpoints* m_Breakpoints;
int m_SymbolColorStride;
int m_SymbolColorPhase;
DWORD m_CtxMenuAddr;
DWORD m_DataStartLoc;
bool m_DataVAddrr;
@ -55,4 +81,4 @@ private:
bool m_CompareVAddrr;
BYTE m_CompareData[MemoryToDisplay];
bool m_CompareValid[MemoryToDisplay];
};
};

View File

@ -10,6 +10,10 @@
****************************************************************************/
#include "stdafx.h"
#include "DebuggerUI.h"
#include "ScriptHook.h"
#include "DMALog.h"
#include "Symbols.h"
CPj64Module _Module;
@ -17,8 +21,28 @@ CDebuggerUI::CDebuggerUI() :
m_MemoryDump(NULL),
m_MemoryView(NULL),
m_MemorySearch(NULL),
m_DebugTLB(NULL)
m_DebugTLB(NULL),
m_CommandsView(NULL),
m_Scripts(NULL),
m_Symbols(NULL),
m_Breakpoints(NULL),
m_ScriptSystem(NULL),
m_DMALogView(NULL),
m_StackTraceView(NULL),
m_StackView(NULL),
m_DMALog(NULL)
{
g_Debugger = this;
//m_DMALog = new vector<DMALogEntry>;
m_StackTrace = new vector<uint32_t>;
m_Breakpoints = new CBreakpoints();
m_ScriptSystem = new CScriptSystem(this);
m_DMALog = new CDMALog();
CSymbols::InitializeCriticalSection();
g_Settings->RegisterChangeCB(GameRunning_InReset, this, (CSettings::SettingChangedFunc)GameReset);
}
@ -26,15 +50,48 @@ CDebuggerUI::~CDebuggerUI(void)
{
g_Settings->UnregisterChangeCB(GameRunning_InReset, this, (CSettings::SettingChangedFunc)GameReset);
Debug_Reset();
delete m_MemoryView;
delete m_CommandsView;
delete m_Scripts;
delete m_ScriptSystem;
delete m_Breakpoints;
delete m_Symbols;
delete m_DMALogView;
delete m_MemorySearch;
delete m_DMALog;
CSymbols::DeleteCriticalSection();
m_StackTrace->clear();
}
void CDebuggerUI::GameReset(CDebuggerUI * _this)
{
if (!g_Settings->LoadBool(GameRunning_InReset))
{
return;
}
_this->Debug_Reset();
if (!g_Settings->LoadBool(GameRunning_InReset))
{
return;
}
if (_this->m_CommandsView)
{
_this->m_CommandsView->Reset();
}
if (_this->m_DMALog)
{
_this->m_DMALog->ClearEntries();
}
CSymbols::EnterCriticalSection();
CSymbols::Load();
CSymbols::LeaveCriticalSection();
if (_this->m_Symbols)
{
CSymbols::EnterCriticalSection();
_this->m_Symbols->Refresh();
CSymbols::LeaveCriticalSection();
}
}
void CDebuggerUI::Debug_Reset(void)
@ -45,12 +102,6 @@ void CDebuggerUI::Debug_Reset(void)
delete m_MemoryDump;
m_MemoryDump = NULL;
}
if (m_MemoryView)
{
m_MemoryView->HideWindow();
delete m_MemoryView;
m_MemoryView = NULL;
}
if (m_MemorySearch)
{
m_MemorySearch->HideWindow();
@ -63,6 +114,48 @@ void CDebuggerUI::Debug_Reset(void)
delete m_DebugTLB;
m_DebugTLB = NULL;
}
if (m_MemoryView)
{
m_MemoryView->HideWindow();
delete m_MemoryView;
m_MemoryView = NULL;
}
if (m_CommandsView)
{
m_CommandsView->HideWindow();
delete m_CommandsView;
m_CommandsView = NULL;
}
if (m_Scripts)
{
m_Scripts->HideWindow();
delete m_Scripts;
m_Scripts = NULL;
}
if (m_Symbols)
{
m_Symbols->HideWindow();
delete m_Symbols;
m_Symbols = NULL;
}
if (m_DMALogView)
{
m_DMALogView->HideWindow();
delete m_DMALogView;
m_DMALogView = NULL;
}
if (m_StackTraceView)
{
m_StackTraceView->HideWindow();
delete m_StackTraceView;
m_StackTraceView = NULL;
}
if (m_StackView)
{
m_StackView->HideWindow();
delete m_StackView;
m_StackView = NULL;
}
}
void CDebuggerUI::Debug_ShowMemoryDump()
@ -142,7 +235,289 @@ void CDebuggerUI::Debug_ShowMemorySearch()
}
}
void CDebuggerUI::Debug_ShowCommandsWindow()
{
if (m_CommandsView == NULL)
{
m_CommandsView = new CDebugCommandsView(this);
}
m_CommandsView->ShowWindow();
}
void CDebuggerUI::Debug_ShowCommandsLocation(uint32_t address, bool top)
{
Debug_ShowCommandsWindow();
if (m_CommandsView)
{
m_CommandsView->ShowAddress(address, top);
}
}
void CDebuggerUI::Debug_ShowScriptsWindow()
{
if (m_Scripts == NULL)
{
m_Scripts = new CDebugScripts(this);
}
m_Scripts->ShowWindow();
}
void CDebuggerUI::Debug_RefreshScriptsWindow()
{
if (m_Scripts != NULL)
{
m_Scripts->RefreshList();
}
}
void CDebuggerUI::Debug_LogScriptsWindow(const char* text)
{
if (m_Scripts != NULL)
{
m_Scripts->ConsolePrint(text);
}
}
void CDebuggerUI::Debug_ClearScriptsWindow()
{
if (m_Scripts != NULL)
{
m_Scripts->ConsoleClear();
}
}
void CDebuggerUI::Debug_ShowSymbolsWindow()
{
if (m_Symbols == NULL)
{
m_Symbols = new CDebugSymbols(this);
}
m_Symbols->ShowWindow();
}
void CDebuggerUI::Debug_RefreshSymbolsWindow()
{
if (m_Symbols != NULL)
{
m_Symbols->Refresh();
}
}
void CDebuggerUI::Debug_ShowDMALogWindow(void)
{
if (m_DMALogView == NULL)
{
m_DMALogView = new CDebugDMALogView(this);
}
m_DMALogView->ShowWindow();
}
void CDebuggerUI::Debug_ShowStackTrace(void)
{
if (m_StackTraceView == NULL)
{
m_StackTraceView = new CDebugStackTrace(this);
}
m_StackTraceView->ShowWindow();
}
void CDebuggerUI::Debug_ShowStackWindow(void)
{
if (m_StackView == NULL)
{
m_StackView = new CDebugStackView(this);
}
m_StackView->ShowWindow();
}
void CDebuggerUI::Debug_RefreshStackWindow(void)
{
if (m_StackView != NULL)
{
m_StackView->Refresh();
}
}
CBreakpoints* CDebuggerUI::Breakpoints()
{
return m_Breakpoints;
}
CScriptSystem* CDebuggerUI::ScriptSystem()
{
return m_ScriptSystem;
}
CDebugScripts* CDebuggerUI::ScriptConsole()
{
return m_Scripts;
}
CDMALog* CDebuggerUI::DMALog()
{
return m_DMALog;
}
vector<uint32_t> * CDebuggerUI::StackTrace()
{
return m_StackTrace;
}
void CDebuggerUI::BreakpointHit()
{
m_Breakpoints->KeepDebugging();
Debug_ShowCommandsLocation(g_Reg->m_PROGRAM_COUNTER, false);
m_Breakpoints->Pause();
}
// CDebugger implementation
void CDebuggerUI::TLBChanged()
{
Debug_RefreshTLBWindow();
Debug_RefreshTLBWindow();
}
// Called from the interpreter core at the beginning of every CPU step
// Returns false when the instruction should be skipped
bool CDebuggerUI::CPUStepStarted()
{
uint32_t PROGRAM_COUNTER = g_Reg->m_PROGRAM_COUNTER;
uint32_t JumpToLocation = R4300iOp::m_JumpToLocation;
m_ScriptSystem->HookCPUExec()->InvokeByParamInRange(PROGRAM_COUNTER);
// PC breakpoints
if (m_Breakpoints->EBPExists(PROGRAM_COUNTER, true))
{
goto breakpoint_hit;
}
// Memory breakpoints
OPCODE Opcode = R4300iOp::m_Opcode;
uint32_t op = Opcode.op;
if (op >= R4300i_LDL && op <= R4300i_SD && op != R4300i_CACHE) // Read and write instructions
{
uint32_t memoryAddress = g_Reg->m_GPR[Opcode.base].UW[0] + (int16_t)Opcode.offset;
if ((op <= R4300i_LWU || (op >= R4300i_LL && op <= R4300i_LD))) // Read instructions
{
m_ScriptSystem->HookCPURead()->InvokeByParamInRange(memoryAddress);
if (m_Breakpoints->RBPExists(memoryAddress))
{
goto breakpoint_hit;
}
}
else // Write instructions
{
m_ScriptSystem->HookCPUWrite()->InvokeByParamInRange(memoryAddress);
if (m_Breakpoints->WBPExists(memoryAddress))
{
goto breakpoint_hit;
}
// Catch cart -> rdram dma
if (memoryAddress == 0xA460000C) // PI_WR_LEN_REG
{
uint32_t dmaRomAddr = g_Reg->PI_CART_ADDR_REG & 0x0FFFFFFF;
uint32_t dmaRamAddr = g_Reg->PI_DRAM_ADDR_REG | 0x80000000;
uint32_t dmaLen = g_Reg->m_GPR[Opcode.rt].UW[0] + 1;
uint32_t endAddr = dmaRamAddr + dmaLen;
m_DMALog->AddEntry(dmaRomAddr, dmaRamAddr, dmaLen);
for (int i = 0; i < m_Breakpoints->m_nWBP; i++)
{
uint32_t wbpAddr = m_Breakpoints->m_WBP[i].address;
if (wbpAddr >= dmaRamAddr && wbpAddr < endAddr)
{
goto breakpoint_hit;
}
}
}
}
}
if (!m_Breakpoints->isDebugging())
{
return !m_Breakpoints->isSkipping();
}
if (R4300iOp::m_NextInstruction != JUMP)
{
goto breakpoint_hit;
}
if (JumpToLocation == PROGRAM_COUNTER + 4)
{
// Only pause on delay slots when branch isn't taken
goto breakpoint_hit;
}
return !m_Breakpoints->isSkipping();
breakpoint_hit:
BreakpointHit();
return !m_Breakpoints->isSkipping();
}
void CDebuggerUI::CPUStep()
{
OPCODE Opcode = R4300iOp::m_Opcode;
uint32_t op = Opcode.op;
uint32_t funct = Opcode.funct;
if (op == R4300i_JAL || funct == R4300i_SPECIAL_JALR) // JAL or JALR
{
//m_StackTrace->push_back(R4300iOp::m_JumpToLocation);
}
else if (funct == R4300i_SPECIAL_JR && Opcode.rs == 31) // JR RA
{
//m_StackTrace->pop_back();
}
}
void CDebuggerUI::FrameDrawn()
{
static HWND hMainWnd = NULL;
static HFONT monoFont = CreateFont(-11, 0, 0, 0,
FW_DONTCARE, FALSE, FALSE, FALSE, DEFAULT_CHARSET,
OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS,
PROOF_QUALITY, FF_DONTCARE, "Consolas"
);
if (hMainWnd == NULL)
{
RenderWindow* mainWindow = g_Plugins->MainWindow();
if (mainWindow == NULL)
{
return;
}
hMainWnd = (HWND)mainWindow->GetWindowHandle();
}
HDC hdc = GetDC(hMainWnd);
CRect rt;
GetClientRect(hMainWnd, &rt);
SetBkColor(hdc, RGB(0, 0, 0));
SelectObject(hdc, monoFont);
SetTextColor(hdc, RGB(255, 255, 255));
SetBkColor(hdc, RGB(0, 0, 0));
m_ScriptSystem->SetScreenDC(hdc);
m_ScriptSystem->HookFrameDrawn()->InvokeAll();
ReleaseDC(hMainWnd, hdc);
}

View File

@ -7,3 +7,11 @@
#include "Debugger-ViewMemory.h"
#include "Debugger-MemoryDump.h"
#include "Debugger-TLB.h"
#include "Debugger-Commands.h"
#include "Debugger-Scripts.h"
#include "Debugger-Symbols.h"
#include "Debugger-AddBreakpoint.h"
#include "Debugger-AddSymbol.h"
#include "Debugger-DMALogView.h"
#include "Debugger-StackView.h"
#include "Debugger-StackTrace.h"

View File

@ -0,0 +1,322 @@
/****************************************************************************
* *
* Project64 - A Nintendo 64 emulator. *
* http://www.pj64-emu.com/ *
* Copyright (C) 2012 Project64. All rights reserved. *
* *
* License: *
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
* *
****************************************************************************/
#pragma once
#include <stdafx.h>
#include <Project64-core\N64System\Mips\OpCode.h>
class COpInfo
{
public:
OPCODE m_OpCode;
bool IsStaticJump()
{
// j, jal
uint32_t op = m_OpCode.op;
if (op == R4300i_J || op == R4300i_JAL)
{
return true;
}
return false;
}
bool IsJump()
{
// j, jal, jr, jalr, exception
uint32_t op = m_OpCode.op;
if (op == R4300i_J || op == R4300i_JAL)
{
return true;
}
if (op == R4300i_SPECIAL)
{
uint32_t fn = m_OpCode.funct;
if (fn >= R4300i_SPECIAL_JR && fn <= R4300i_SPECIAL_BREAK)
{
return true;
}
}
if (op == R4300i_REGIMM)
{
uint32_t rt = m_OpCode.rt;
if (rt >= R4300i_REGIMM_TGEI && rt <= R4300i_REGIMM_TNEI)
{
return true;
}
}
if (op == R4300i_CP0)
{
if ((m_OpCode.rs & 0x10) != 0)
{
uint32_t fn = m_OpCode.funct;
if (fn == R4300i_COP0_CO_ERET)
{
return true;
}
}
}
return false;
}
bool IsBranch()
{
uint32_t op = m_OpCode.op;
if (op >= R4300i_BEQ && op <= R4300i_BGTZ)
{
return true;
}
if (op >= R4300i_BEQL && op <= R4300i_BGTZL)
{
return true;
}
if (op == R4300i_REGIMM)
{
uint32_t rt = m_OpCode.rt;
if (rt >= R4300i_REGIMM_BLTZ && rt <= R4300i_REGIMM_BGEZL)
{
return true;
}
if (rt >= R4300i_REGIMM_BLTZAL && rt <= R4300i_REGIMM_BGEZALL)
{
return true;
}
}
if (op == R4300i_CP1 && m_OpCode.fmt == R4300i_COP1_BC)
{
return true;
}
return false;
}
bool IsNOP()
{
if (m_OpCode.Hex == 0)
{
return true;
}
return false;
}
bool IsLoadStore()
{
return (m_OpCode.op >= R4300i_LDL && m_OpCode.op <= R4300i_SD && m_OpCode.op != R4300i_CACHE);
}
bool IsStackShift()
{
return (m_OpCode.op == R4300i_ADDIU || m_OpCode.op == R4300i_ADDI) && m_OpCode.rt == 29;
}
bool IsStackAlloc()
{
if (!IsStackShift())
{
return false;
}
return (short)m_OpCode.immediate < 0;
}
bool IsStackFree()
{
if (!IsStackShift())
{
return false;
}
return (short)m_OpCode.immediate > 0;
}
bool ReadsGPR(int nReg)
{
uint32_t op = m_OpCode.op;
if (op >= R4300i_LDL && op <= R4300i_LWU ||
op >= R4300i_ADDI && op <= R4300i_XORI ||
op == R4300i_LD ||
op == R4300i_BGTZ || op == R4300i_BGTZL ||
op == R4300i_BLEZ || op == R4300i_BLEZL)
{
if (m_OpCode.rs == nReg)
{
return true;
}
}
if (op >= R4300i_SB && op <= R4300i_SWR ||
op >= R4300i_SC && op <= R4300i_SD ||
op == R4300i_BEQ || op == R4300i_BEQL ||
op == R4300i_BNE || op == R4300i_BNEL)
{
// stores read value and index
if (m_OpCode.rs == nReg || m_OpCode.rt == nReg)
{
return true;
}
}
if (op == R4300i_SPECIAL)
{
uint32_t fn = m_OpCode.funct;
switch (fn)
{
case R4300i_SPECIAL_MTLO:
case R4300i_SPECIAL_MTHI:
case R4300i_SPECIAL_JR:
case R4300i_SPECIAL_JALR:
if (m_OpCode.rs == nReg)
{
return true;
}
break;
case R4300i_SPECIAL_SLL:
case R4300i_SPECIAL_SRL:
case R4300i_SPECIAL_SRA:
if (m_OpCode.rt == nReg)
{
return true;
}
break;
}
if (fn >= R4300i_SPECIAL_SLLV && fn <= R4300i_SPECIAL_SRAV ||
fn >= R4300i_SPECIAL_DSLLV && fn <= R4300i_SPECIAL_DSRAV ||
fn >= R4300i_SPECIAL_DIVU && fn <= R4300i_SPECIAL_DSUBU)
{
// two register operands
if (m_OpCode.rt == nReg || m_OpCode.rs == nReg)
{
return true;
}
}
}
return false;
}
bool WritesGPR(int nReg)
{
uint32_t op = m_OpCode.op;
if (op >= R4300i_LDL && op <= R4300i_LWU ||
op >= R4300i_ADDI && op <= R4300i_XORI ||
op == R4300i_LUI || op == R4300i_LD)
{
// loads write value
if (m_OpCode.rt == nReg)
{
return true;
}
}
if (op == R4300i_JAL)
{
if (nReg == 31) // RA
{
return true;
}
}
if (op == R4300i_SPECIAL)
{
uint32_t fn = m_OpCode.funct;
switch (fn)
{
case R4300i_SPECIAL_MFLO:
case R4300i_SPECIAL_MFHI:
case R4300i_SPECIAL_SLL:
case R4300i_SPECIAL_SRL:
case R4300i_SPECIAL_SRA:
if (m_OpCode.rd == nReg)
{
return true;
}
break;
}
if (fn >= R4300i_SPECIAL_SLLV && fn <= R4300i_SPECIAL_SRAV ||
fn >= R4300i_SPECIAL_DSLLV && fn <= R4300i_SPECIAL_DSRAV ||
fn >= R4300i_SPECIAL_DIVU && fn <= R4300i_SPECIAL_DSUBU ||
fn == R4300i_SPECIAL_JALR)
{
// result register
if (m_OpCode.rd == nReg)
{
return true;
}
}
}
return false;
}
bool ReadsLO()
{
if (m_OpCode.op == R4300i_SPECIAL && m_OpCode.funct == R4300i_SPECIAL_MFLO)
{
return true;
}
return false;
}
bool WritesLO()
{
if (m_OpCode.op == R4300i_SPECIAL && m_OpCode.funct == R4300i_SPECIAL_MTLO)
{
return true;
}
return false;
}
// todo add mult, div etc
bool ReadsHI()
{
if (m_OpCode.op == R4300i_SPECIAL && m_OpCode.funct == R4300i_SPECIAL_MFHI)
{
return true;
}
return false;
}
bool WritesHI()
{
if (m_OpCode.op == R4300i_SPECIAL && m_OpCode.funct == R4300i_SPECIAL_MTHI)
{
return true;
}
return false;
}
};

View File

@ -0,0 +1,126 @@
#include <stdafx.h>
#include "ScriptHook.h"
#include "ScriptInstance.h"
#include "ScriptSystem.h"
int CScriptHook::Add(CScriptInstance* scriptInstance, void* heapptr, uint32_t param, uint32_t param2, bool bOnce)
{
JSCALLBACK jsCallback;
jsCallback.scriptInstance = scriptInstance;
jsCallback.heapptr = heapptr;
jsCallback.callbackId = m_ScriptSystem->GetNextCallbackId();
jsCallback.param = param;
jsCallback.param2 = param2;
jsCallback.bOnce = bOnce;
m_Callbacks.push_back(jsCallback);
return jsCallback.callbackId;
}
void CScriptHook::InvokeById(int callbackId)
{
int nCallbacks = m_Callbacks.size();
for (int i = 0; i < nCallbacks; i++)
{
if (m_Callbacks[i].callbackId == callbackId)
{
m_Callbacks[i].scriptInstance->Invoke(m_Callbacks[i].heapptr);
return;
}
}
}
void CScriptHook::InvokeByParam(uint32_t param)
{
int nCallbacks = m_Callbacks.size();
for (int i = 0; i < nCallbacks; i++)
{
if (m_Callbacks[i].param == param)
{
m_Callbacks[i].scriptInstance->Invoke(m_Callbacks[i].heapptr, param);
return;
}
}
}
void CScriptHook::InvokeByParamInRange(uint32_t param)
{
int nCallbacks = m_Callbacks.size();
for (int i = 0; i < nCallbacks; i++)
{
if (param == m_Callbacks[i].param || (param >= m_Callbacks[i].param && param < m_Callbacks[i].param2))
{
m_Callbacks[i].scriptInstance->Invoke(m_Callbacks[i].heapptr, param);
return;
}
}
}
void CScriptHook::InvokeAll()
{
int nCallbacks = m_Callbacks.size();
for (int i = 0; i < nCallbacks; i++)
{
m_Callbacks[i].scriptInstance->Invoke(m_Callbacks[i].heapptr);
}
}
void CScriptHook::RemoveById(int callbackId)
{
int nCallbacks = m_Callbacks.size();
for (int i = 0; i < nCallbacks; i++)
{
if (m_Callbacks[i].callbackId == callbackId)
{
m_Callbacks.erase(m_Callbacks.begin() + i);
return;
}
}
}
void CScriptHook::RemoveByParam(uint32_t param)
{
int nCallbacks = m_Callbacks.size();
for (int i = 0; i < nCallbacks; i++)
{
if (m_Callbacks[i].param == param)
{
m_Callbacks.erase(m_Callbacks.begin() + i);
return;
}
}
}
void CScriptHook::RemoveByInstance(CScriptInstance* scriptInstance)
{
int lastIndex = m_Callbacks.size() - 1;
for (int i = lastIndex; i >= 0; i--)
{
if (m_Callbacks[i].scriptInstance == scriptInstance)
{
m_Callbacks.erase(m_Callbacks.begin() + i);
}
}
}
bool CScriptHook::HasContext(CScriptInstance* scriptInstance)
{
for (int i = 0; i < m_Callbacks.size(); i++)
{
if (m_Callbacks[i].scriptInstance == scriptInstance)
{
return true;
}
}
return false;
}
CScriptHook::CScriptHook(CScriptSystem* scriptSystem)
{
m_ScriptSystem = scriptSystem;
}
CScriptHook::~CScriptHook()
{
m_Callbacks.clear();
}

View File

@ -0,0 +1,39 @@
#pragma once
#include <stdafx.h>
class CScriptInstance;
class CScriptSystem;
class CScriptHook
{
private:
typedef struct {
CScriptInstance* scriptInstance;
void* heapptr;
uint32_t param;
uint32_t param2;
int callbackId;
bool bOnce;
} JSCALLBACK;
CScriptSystem* m_ScriptSystem;
//int m_NextCallbackId;
vector<JSCALLBACK> m_Callbacks;
public:
CScriptHook(CScriptSystem* scriptSystem);
~CScriptHook();
int Add(CScriptInstance* scriptInstance, void* heapptr, uint32_t param = 0, uint32_t param2 = 0, bool bOnce = false);
void InvokeAll();
void InvokeById(int callbackId);
void InvokeByParam(uint32_t param);
/* invoke if param >= cb.param && param < cb.param2*/
void InvokeByParamInRange(uint32_t param);
void RemoveById(int callbackId);
void RemoveByParam(uint32_t tag);
void RemoveByInstance(CScriptInstance* scriptInstance);
bool HasContext(CScriptInstance* scriptInstance);
//bool HasTag(uint32_t tag);
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,206 @@
#pragma once
#include "stdafx.h"
#include <3rdParty/duktape/duktape.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <mswsock.h>
#pragma comment(lib, "Ws2_32.lib")
#pragma comment(lib, "Mswsock.lib")
class CScriptSystem;
typedef enum {
STATE_STARTED, // initial evaluation & execution
STATE_RUNNING, // event loop running with pending events
STATE_STOPPED, // no pending events
STATE_INVALID
} INSTANCE_STATE;
class CScriptInstance
{
typedef enum {
EVENT_READ,
EVENT_WRITE,
EVENT_ACCEPT,
EVENT_CONNECT
} IOEVENTTYPE;
typedef struct {
OVERLAPPED ovl;
IOEVENTTYPE eventType;
HANDLE fd;
HANDLE childFd; // accepted socket
bool bSocket;
UINT id;
void* data;
DWORD dataLen; // changed to bytes transferred after event is fired
void* callback;
} IOLISTENER;
// Wrapper for file/socket descriptor and completion port
typedef struct {
HANDLE fd;
HANDLE iocp;
bool bSocket;
} IOFD;
typedef enum {
EVENT_STATUS_OK,
EVENT_STATUS_INTERRUPTED,
EVENT_STATUS_ERROR
} EVENT_STATUS;
public:
CScriptInstance(CDebuggerUI* debugger);
~CScriptInstance();
void Start(char* path);
void ForceStop();
void Invoke(void* heapptr, uint32_t param = 0);
INSTANCE_STATE GetState();
friend class PendingEval;
void EvalAsync(const char* jsCode);
const char* Eval(const char* jsCode);
private:
duk_context* m_Ctx;
duk_context* DukContext();
char* m_TempPath;
HANDLE m_hThread;
HANDLE m_hIOCompletionPort;
CRITICAL_SECTION m_CriticalSection;
vector<IOFD> m_Files;
vector<IOLISTENER*> m_Listeners;
UINT m_NextListenerId;
CDebuggerUI* m_Debugger;
CScriptSystem* m_ScriptSystem;
INSTANCE_STATE m_State;
static DWORD CALLBACK StartThread(CScriptInstance* _this);
void StartScriptProc();
void StartEventLoop();
bool HaveEvents();
EVENT_STATUS WaitForEvent(IOLISTENER** lpListener);
void SetState(INSTANCE_STATE state);
void StateChanged();
void QueueAPC(PAPCFUNC userProc, ULONG_PTR param = 0);
void AddFile(HANDLE fd, bool bSocket = false);
void CloseFile(HANDLE fd);
void CloseAllFiles();
void RemoveFile(HANDLE fd);
HANDLE CreateSocket();
IOLISTENER* AddListener(HANDLE fd, IOEVENTTYPE evt, void* jsCallback, void* data = NULL, int dataLen = 0);
void RemoveListener(IOLISTENER* lpListener);
void RemoveListenerByIndex(UINT index);
void RemoveListenersByFd(HANDLE fd);
void InvokeListenerCallback(IOLISTENER* lpListener);
static void CALLBACK EvalAsyncCallback(ULONG_PTR evalWait);
const char* EvalFile(const char* jsPath);
// Lookup list of CScriptInstance instances for static js_* functions
static vector<CScriptInstance*> Cache;
static void CacheInstance(CScriptInstance* _this);
static void UncacheInstance(CScriptInstance* _this);
static CScriptInstance* FetchInstance(duk_context* ctx);
// Bound functions (_native object)
static duk_ret_t js_ioSockCreate (duk_context*);
static duk_ret_t js_ioSockListen (duk_context*);
static duk_ret_t js_ioSockAccept (duk_context*); // async
static duk_ret_t js_ioSockConnect (duk_context*); // async
static duk_ret_t js_ioRead (duk_context*); // async
static duk_ret_t js_ioWrite (duk_context*); // async
static duk_ret_t js_ioClose (duk_context*); // (fd) ; file or socket
static duk_ret_t js_MsgBox (duk_context*); // (message, caption)
static duk_ret_t js_AddCallback (duk_context*); // (hookId, callback, tag) ; external events
static duk_ret_t js_RemoveCallback (duk_context*); // (callbackId)
static duk_ret_t js_GetPCVal (duk_context*); // ()
static duk_ret_t js_SetPCVal (duk_context*); // (value)
static duk_ret_t js_GetHIVal (duk_context*); // (bUpper)
static duk_ret_t js_SetHIVal (duk_context*); // (bUpper, value)
static duk_ret_t js_GetLOVal (duk_context*); // (bUpper)
static duk_ret_t js_SetLOVal (duk_context*); // (bUpper, value)
static duk_ret_t js_GetGPRVal (duk_context*); // (regNum, bUpper)
static duk_ret_t js_SetGPRVal (duk_context*); // (regNum, bUpper, value)
static duk_ret_t js_GetFPRVal (duk_context*); // (regNum, bDouble)
static duk_ret_t js_SetFPRVal (duk_context*); // (regNum, bDouble, value)
static duk_ret_t js_GetROMInt (duk_context*); // (address, bitwidth, signed)
static duk_ret_t js_GetROMFloat (duk_context*); // (address, bDouble)
static duk_ret_t js_GetROMBlock (duk_context*); // (address, nBytes) ; returns Buffer
static duk_ret_t js_GetROMString (duk_context*); // (address[, maxLen]) ; fetch zero terminated string from memory
static duk_ret_t js_GetRDRAMInt (duk_context*); // (address, bitwidth, signed)
static duk_ret_t js_SetRDRAMInt (duk_context*); // (address, bitwidth, signed, newValue)
static duk_ret_t js_GetRDRAMFloat (duk_context*); // (address, bDouble)
static duk_ret_t js_SetRDRAMFloat (duk_context*); // (address, bDouble, newValue)
static duk_ret_t js_GetRDRAMBlock (duk_context*); // (address, nBytes) ; returns Buffer
static duk_ret_t js_GetRDRAMString (duk_context*); // (address[, maxLen]) ; fetch zero terminated string from memory
static duk_ret_t js_ConsolePrint (duk_context*);
static duk_ret_t js_ConsoleClear (duk_context*);
static duk_ret_t js_Pause(duk_context*); // () ; pauses emulation
static duk_ret_t js_ShowCommands(duk_context*); // ([address]) ; shows commands window
static duk_ret_t js_ScreenPrint(duk_context*); // (x, y, text)
static constexpr duk_function_list_entry NativeFunctions[] =
{
{ "addCallback", js_AddCallback, DUK_VARARGS },
{ "removeCallback", js_RemoveCallback, DUK_VARARGS },
{ "setPCVal", js_SetPCVal, DUK_VARARGS },
{ "getPCVal", js_GetPCVal, DUK_VARARGS },
{ "setHIVal", js_SetHIVal, DUK_VARARGS },
{ "getHIVal", js_GetHIVal, DUK_VARARGS },
{ "setLOVal", js_SetLOVal, DUK_VARARGS },
{ "getLOVal", js_GetLOVal, DUK_VARARGS },
{ "setGPRVal", js_SetGPRVal, DUK_VARARGS },
{ "getGPRVal", js_GetGPRVal, DUK_VARARGS },
{ "setFPRVal", js_SetFPRVal, DUK_VARARGS },
{ "getFPRVal", js_GetFPRVal, DUK_VARARGS },
{ "getROMInt", js_GetROMInt, DUK_VARARGS },
{ "getROMFloat", js_GetROMFloat, DUK_VARARGS },
{ "getROMString", js_GetROMString, DUK_VARARGS },
{ "getROMBlock", js_GetROMBlock, DUK_VARARGS },
{ "getRDRAMInt", js_GetRDRAMInt, DUK_VARARGS },
{ "setRDRAMInt", js_SetRDRAMInt, DUK_VARARGS },
{ "getRDRAMFloat", js_GetRDRAMFloat, DUK_VARARGS },
{ "setRDRAMFloat", js_SetRDRAMFloat, DUK_VARARGS },
{ "getRDRAMBlock", js_GetRDRAMBlock, DUK_VARARGS },
{ "getRDRAMString", js_GetRDRAMString, DUK_VARARGS },
{ "sockCreate", js_ioSockCreate, DUK_VARARGS },
{ "sockListen", js_ioSockListen, DUK_VARARGS },
{ "sockAccept", js_ioSockAccept, DUK_VARARGS },
{ "sockConnect", js_ioSockConnect, DUK_VARARGS },
{ "close", js_ioClose, DUK_VARARGS },
{ "write", js_ioWrite, DUK_VARARGS },
{ "read", js_ioRead, DUK_VARARGS },
{ "msgBox", js_MsgBox, DUK_VARARGS },
{ "consolePrint", js_ConsolePrint, DUK_VARARGS },
{ "consoleClear", js_ConsoleClear, DUK_VARARGS },
{ "pause", js_Pause, DUK_VARARGS },
{ "showCommands", js_ShowCommands, DUK_VARARGS },
{ "screenPrint", js_ScreenPrint, DUK_VARARGS },
{ NULL, NULL, 0 }
};
};

View File

@ -0,0 +1,183 @@
/****************************************************************************
* *
* Project64 - A Nintendo 64 emulator. *
* http://www.pj64-emu.com/ *
* Copyright (C) 2012 Project64. All rights reserved. *
* *
* License: *
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
* *
****************************************************************************/
#include <stdafx.h>
#include "ScriptSystem.h"
#include "Debugger-Scripts.h"
#include "ScriptInstance.h"
#include "ScriptHook.h"
CScriptSystem::CScriptSystem(CDebuggerUI* debugger)
{
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
m_NextCallbackId = 0;
m_Debugger = debugger;
m_HookCPUExec = new CScriptHook(this);
m_HookCPURead = new CScriptHook(this);
m_HookCPUWrite = new CScriptHook(this);
m_HookFrameDrawn = new CScriptHook(this);
RegisterHook("exec", m_HookCPUExec);
RegisterHook("read", m_HookCPURead);
RegisterHook("write", m_HookCPUWrite);
RegisterHook("draw", m_HookFrameDrawn);
HMODULE hInst = GetModuleHandle(NULL);
HRSRC hRes = FindResource(hInst, MAKEINTRESOURCE(IDR_JSAPI_TEXT), "TEXT");
HGLOBAL hGlob = LoadResource(hInst, hRes);
DWORD resSize = SizeofResource(hInst, hRes);
m_APIScript = (char*) malloc(resSize + 1);
void* resData = LockResource(hGlob);
memcpy(m_APIScript, resData, resSize);
m_APIScript[resSize] = '\0';
FreeResource(hGlob);
}
CScriptSystem::~CScriptSystem()
{
for (int i = 0; i < m_Hooks.size(); i++)
{
delete m_Hooks[i].cbList;
}
UnregisterHooks();
free(m_APIScript);
}
const char* CScriptSystem::APIScript()
{
return m_APIScript;
}
void CScriptSystem::RunScript(char* path)
{
CScriptInstance* scriptInstance = new CScriptInstance(m_Debugger);
char* pathSaved = (char*)malloc(strlen(path)); // freed via DeleteStoppedInstances
strcpy(pathSaved, path);
m_RunningInstances.push_back({ pathSaved, scriptInstance });
scriptInstance->Start(pathSaved);
}
void CScriptSystem::StopScript(char* path)
{
int nInstances = m_RunningInstances.size();
CScriptInstance* scriptInstance = GetInstance(path);
if (scriptInstance == NULL)
{
return;
}
scriptInstance->ForceStop();
}
void CScriptSystem::DeleteStoppedInstances()
{
int lastIndex = m_RunningInstances.size() - 1;
for (int i = lastIndex; i >= 0; i--)
{
if (m_RunningInstances[i].scriptInstance->GetState() == STATE_STOPPED)
{
free(m_RunningInstances[i].path);
CScriptInstance* instance = m_RunningInstances[i].scriptInstance;
delete instance;
m_RunningInstances.erase(m_RunningInstances.begin() + i);
}
}
}
INSTANCE_STATE CScriptSystem::GetInstanceState(char* path)
{
for (int i = 0; i < m_RunningInstances.size(); i++)
{
if (strcmp(m_RunningInstances[i].path, path) == 0)
{
return m_RunningInstances[i].scriptInstance->GetState();
}
}
return STATE_INVALID;
}
CScriptInstance* CScriptSystem::GetInstance(char* path)
{
for (int i = 0; i < m_RunningInstances.size(); i++)
{
if (strcmp(m_RunningInstances[i].path, path) == 0)
{
return m_RunningInstances[i].scriptInstance;
}
}
return NULL;
}
bool CScriptSystem::HasCallbacksForInstance(CScriptInstance* scriptInstance)
{
for (int i = 0; i < m_Hooks.size(); i++)
{
if (m_Hooks[i].cbList->HasContext(scriptInstance))
{
return true;
}
}
return false;
}
void CScriptSystem::ClearCallbacksForInstance(CScriptInstance* scriptInstance)
{
for (int i = 0; i < m_Hooks.size(); i++)
{
m_Hooks[i].cbList->RemoveByInstance(scriptInstance);
}
}
void CScriptSystem::RemoveCallbackById(int callbackId)
{
for (int i = 0; i < m_Hooks.size(); i++)
{
m_Hooks[i].cbList->RemoveById(callbackId);
}
}
void CScriptSystem::RegisterHook(const char* hookId, CScriptHook* cbList)
{
HOOKENTRY hook = { hookId, cbList };
m_Hooks.push_back(hook);
}
void CScriptSystem::UnregisterHooks()
{
m_Hooks.clear();
}
CScriptHook* CScriptSystem::GetHook(const char* hookId)
{
int size = m_Hooks.size();
for (int i = 0; i < size; i++)
{
if (strcmp(m_Hooks[i].hookId, hookId) == 0)
{
return m_Hooks[i].cbList;
}
}
return NULL;
}
int CScriptSystem::GetNextCallbackId()
{
return m_NextCallbackId++;
}

View File

@ -0,0 +1,128 @@
/****************************************************************************
* *
* Project64 - A Nintendo 64 emulator. *
* http://www.pj64-emu.com/ *
* Copyright (C) 2012 Project64. All rights reserved. *
* *
* License: *
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
* *
****************************************************************************/
#pragma once
#include <stdafx.h>
#include <3rdParty/duktape/duktape.h>
#include "ScriptInstance.h"
class CScriptHook;
class CScriptSystem
{
public:
CScriptSystem(CDebuggerUI* debugger);
~CScriptSystem();
// Run a script in its own context/thread
void RunScript(char* path);
// Kill a script context/thread by its path
void StopScript(char* path);
const char* APIScript();
private:
typedef struct {
const char* hookId;
CScriptHook* cbList;
} HOOKENTRY;
typedef struct {
char* path;
CScriptInstance* scriptInstance;
} INSTANCE_ENTRY;
CDebuggerUI* m_Debugger;
char* m_APIScript;
vector<HOOKENTRY> m_Hooks;
vector<INSTANCE_ENTRY> m_RunningInstances;
vector<char*> m_LogData;
CScriptHook* m_HookCPUExec;
CScriptHook* m_HookCPURead;
CScriptHook* m_HookCPUWrite;
CScriptHook* m_HookFrameDrawn;
void RegisterHook(const char* hookId, CScriptHook* cbList); // associate string id with callback list
void UnregisterHooks();
HDC m_ScreenDC;
int m_NextCallbackId;
public:
// Returns true if any of the script hooks have callbacks for scriptInstance
void SetScreenDC(HDC hdc)
{
m_ScreenDC = hdc;
}
HDC GetScreenDC()
{
return m_ScreenDC;
}
inline vector<char*>* LogData()
{
return &m_LogData;
}
inline void LogText(const char* text)
{
char* newStr = (char*)malloc(strlen(text));
strcpy(newStr, text);
m_LogData.push_back(newStr);
m_Debugger->Debug_RefreshScriptsWindow();
}
bool HasCallbacksForInstance(CScriptInstance* scriptInstance);
// Remove all hooked callbacks for an instance
void ClearCallbacksForInstance(CScriptInstance* scriptInstance);
void RemoveCallbackById(int callbackId);
CScriptHook* GetHook(const char* hookId);
int GetNextCallbackId();
void DeleteStoppedInstances();
INSTANCE_STATE GetInstanceState(char* scriptName);
CScriptInstance* GetInstance(char* scriptName);
CScriptHook* HookCPUExec()
{
return m_HookCPUExec;
}
CScriptHook* HookCPURead()
{
return m_HookCPURead;
}
CScriptHook* HookCPUWrite()
{
return m_HookCPUWrite;
}
CScriptHook* HookFrameDrawn()
{
return m_HookFrameDrawn;
}
};

View File

@ -0,0 +1,469 @@
#include "stdafx.h"
#include "Symbols.h"
bool CSymbols::m_bInitialized = false;
vector<CSymbolEntry*> CSymbols::m_Symbols;
int CSymbols::m_NextSymbolId;
CFile CSymbols::m_SymFileHandle;
char* CSymbols::m_SymFileBuffer;
size_t CSymbols::m_SymFileSize;
char CSymbols::m_ParserDelimeter;
char* CSymbols::m_ParserToken;
size_t CSymbols::m_ParserTokenLength;
bool CSymbols::m_bHaveFirstToken;
char* CSymbols::m_SymFileParseBuffer;
CRITICAL_SECTION CSymbols::m_CriticalSection = {0};
int CSymbols::GetTypeNumber(char* typeName)
{
const char* name;
for (int i = 0; (name = SymbolTypes[i]) != NULL; i++)
{
if (strcmp(typeName, name) == 0)
{
return i;
}
}
return -1;
}
const char* CSymbols::GetTypeName(int typeNumber)
{
if (typeNumber > 11)
{
return NULL;
}
return SymbolTypes[typeNumber];
}
// Open symbols file for game and parse into list
CPath CSymbols::GetSymFilePath()
{
stdstr symFileName;
symFileName.Format("%s.sym", g_Settings->LoadStringVal(Game_GameName).c_str());
CPath symFilePath(g_Settings->LoadStringVal(Directory_NativeSave).c_str(), symFileName.c_str());
if (g_Settings->LoadBool(Setting_UniqueSaveDir))
{
symFilePath.AppendDirectory(g_Settings->LoadStringVal(Game_UniqueSaveDir).c_str());
}
if (!symFilePath.DirectoryExists())
{
symFilePath.DirectoryCreate();
}
return symFilePath;
}
void CSymbols::ParserInit()
{
m_SymFileParseBuffer = (char*)malloc(m_SymFileSize + 1);
strcpy(m_SymFileParseBuffer, m_SymFileBuffer);
m_bHaveFirstToken = false;
}
void CSymbols::ParserDone()
{
free(m_SymFileParseBuffer);
}
void CSymbols::ParserFetchToken(const char* delim)
{
if (!m_bHaveFirstToken)
{
m_ParserToken = strtok(m_SymFileParseBuffer, delim);
m_bHaveFirstToken = true;
}
else
{
m_ParserToken = strtok(NULL, delim);
}
if (m_ParserToken != NULL)
{
m_ParserTokenLength = strlen(m_ParserToken);
m_ParserDelimeter = m_SymFileBuffer[m_ParserToken - m_SymFileParseBuffer + m_ParserTokenLength];
}
else
{
m_ParserTokenLength = 0;
m_ParserDelimeter = '\0';
}
}
void CSymbols::Load()
{
m_NextSymbolId = 0;
Reset();
if (g_Settings->LoadStringVal(Game_GameName).length() == 0)
{
MessageBox(NULL, "Game must be loaded", "Symbols", MB_ICONWARNING | MB_OK);
return;
}
CPath symFilePath = GetSymFilePath();
bool bOpened = m_SymFileHandle.Open(symFilePath, CFileBase::modeRead);
if (!bOpened)
{
return;
}
m_SymFileSize = m_SymFileHandle.GetLength();
m_SymFileBuffer = (char*)malloc(m_SymFileSize + 1);
m_SymFileHandle.Read(m_SymFileBuffer, m_SymFileSize);
m_SymFileHandle.Close();
m_SymFileBuffer[m_SymFileSize] = '\0';
ParseError errorCode = ERR_SUCCESS;
int lineNumber = 1;
ParserInit();
while (true)
{
uint32_t address = 0;
int type = 0;
char* name = NULL;
char* description = NULL;
// Address
ParserFetchToken(",\n\0");
if (m_ParserToken == NULL || m_ParserTokenLength == 0)
{
// Empty line @EOF
errorCode = ERR_SUCCESS;
break;
}
char* endptr;
address = strtoull(m_ParserToken, &endptr, 16);
if (endptr == m_ParserToken)
{
errorCode = ERR_INVALID_ADDR;
break;
}
// Type
if (m_ParserDelimeter != ',')
{
errorCode = ERR_MISSING_FIELDS;
break;
}
ParserFetchToken(",\n\0");
type = GetTypeNumber(m_ParserToken);
if (type == -1)
{
errorCode = ERR_INVALID_TYPE;
break;
}
// Name
if (m_ParserDelimeter != ',')
{
errorCode = ERR_MISSING_FIELDS;
break;
}
ParserFetchToken(",\n\0");
name = m_ParserToken;
// Optional description
if (m_ParserDelimeter == ',')
{
ParserFetchToken("\n\0");
description = m_ParserToken;
}
// Add symbol object to the vector
Add(type, address, name, description);
if (m_ParserDelimeter == '\0')
{
errorCode = ERR_SUCCESS;
break;
}
lineNumber++;
}
ParserDone();
free(m_SymFileBuffer);
switch (errorCode)
{
case ERR_SUCCESS:
break;
case ERR_INVALID_ADDR:
ParseErrorAlert("Invalid address", lineNumber);
break;
case ERR_INVALID_TYPE:
ParseErrorAlert("Invalid type", lineNumber);
break;
case ERR_INVALID_NAME:
ParseErrorAlert("Invalid name", lineNumber);
break;
case ERR_MISSING_FIELDS:
ParseErrorAlert("Missing required field(s)", lineNumber);
break;
}
}
void CSymbols::Save()
{
int nSymbols = m_Symbols.size();
char* symfile;
int symfile_size = 0;
int symfile_idx = 0;
// Determine file size
for (int i = 0; i < nSymbols; i++)
{
CSymbolEntry* symbol = m_Symbols[i];
symfile_size += 11; // address 8, required commas 2, newline 1
symfile_size += strlen(symbol->m_Name);
symfile_size += strlen(symbol->TypeName());
if (symbol->m_Description != NULL && strlen(symbol->m_Description) != 0)
{
symfile_size += 1; // comma
symfile_size += strlen(symbol->m_Description);
}
}
if (symfile_size == 0)
{
return;
}
symfile = (char*) malloc(symfile_size + 1);
symfile[symfile_size] = '\0';
// Write out
for (int i = 0; i < nSymbols; i++)
{
CSymbolEntry* symbol = m_Symbols[i];
symfile_idx += sprintf(&symfile[symfile_idx], "%08X,%s,%s", symbol->m_Address, symbol->TypeName(), symbol->m_Name);
if (symbol->m_Description != NULL)
{
symfile_idx += sprintf(&symfile[symfile_idx], ",%s", symbol->m_Description);
}
symfile_idx += sprintf(&symfile[symfile_idx], "\n");
}
m_SymFileHandle.Open(GetSymFilePath(), CFileBase::modeCreate | CFileBase::modeReadWrite);
m_SymFileHandle.SeekToBegin();
m_SymFileHandle.Write(symfile, symfile_size);
m_SymFileHandle.SetEndOfFile();
m_SymFileHandle.Close();
free(symfile);
}
void CSymbols::GetValueString(char* dest, CSymbolEntry* lpSymbol)
{
uint8_t v8;
uint16_t v16;
uint32_t v32;
uint64_t v64;
float vf;
double vd;
uint32_t address = lpSymbol->m_Address;
switch (lpSymbol->m_Type)
{
case TYPE_CODE:
case TYPE_DATA:
sprintf(dest, "");
break;
case TYPE_U8:
g_MMU->LB_VAddr(address, v8);
sprintf(dest, "%u", v8);
break;
case TYPE_U16:
g_MMU->LH_VAddr(address, v16);
sprintf(dest, "%u", v16);
break;
case TYPE_U32:
g_MMU->LW_VAddr(address, v32);
sprintf(dest, "%u", v32);
break;
case TYPE_U64:
g_MMU->LD_VAddr(address, v64);
sprintf(dest, "%ull", v64);
break;
case TYPE_S8:
g_MMU->LB_VAddr(address, v8);
sprintf(dest, "%ihh", v8);
break;
case TYPE_S16:
g_MMU->LH_VAddr(address, v16);
sprintf(dest, "%i", v16);
break;
case TYPE_S32:
g_MMU->LW_VAddr(address, v32);
sprintf(dest, "%i", v32);
break;
case TYPE_S64:
g_MMU->LD_VAddr(address, v64);
sprintf(dest, "%ill", v64);
break;
case TYPE_FLOAT:
g_MMU->LW_VAddr(address, *(uint32_t*)&vf);
sprintf(dest, "%f", vf);
break;
case TYPE_DOUBLE:
g_MMU->LD_VAddr(address, *(uint64_t*)&vd);
sprintf(dest, "%f", vd);
break;
default:
MessageBox(NULL, "unkown type", "", MB_OK);
break;
}
}
void CSymbols::ParseErrorAlert(char* message, int lineNumber)
{
stdstr messageFormatted = stdstr_f("%s\nLine %d", message, lineNumber);
MessageBox(NULL, messageFormatted.c_str(), "Parse error", MB_OK | MB_ICONWARNING);
}
void CSymbols::Reset()
{
for (int i = 0; i < GetCount(); i++)
{
delete m_Symbols[i];
}
m_Symbols.clear();
}
const char* CSymbols::GetNameByAddress(uint32_t address)
{
int len = GetCount();
for (uint32_t i = 0; i < len; i++)
{
if (m_Symbols[i]->m_Address == address)
{
return m_Symbols[i]->m_Name;
}
}
return NULL;
}
bool CSymbols::SortFunction(CSymbolEntry* a, CSymbolEntry* b)
{
return (a->m_Address < b->m_Address);
}
void CSymbols::Add(int type, uint32_t address, char* name, char* description)
{
if (name == NULL || strlen(name) == 0)
{
return;
}
if (description == NULL || strlen(description) == 0)
{
description = NULL;
}
int id = m_NextSymbolId++;
CSymbolEntry* symbol = new CSymbolEntry(id, type, address, name, description);
m_Symbols.push_back(symbol);
sort(m_Symbols.begin(), m_Symbols.end(), SortFunction);
}
int CSymbols::GetCount()
{
return m_Symbols.size();
}
CSymbolEntry* CSymbols::GetEntryByIndex(int index)
{
if (index < 0 || index >= GetCount())
{
return NULL;
}
return m_Symbols[index];
}
CSymbolEntry* CSymbols::GetEntryByAddress(uint32_t address)
{
for (int i = 0; i < GetCount(); i++)
{
if (m_Symbols[i]->m_Address == address)
{
return m_Symbols[i];
}
}
return NULL;
}
CSymbolEntry* CSymbols::GetEntryById(int id)
{
for (int i = 0; i < GetCount(); i++)
{
if (m_Symbols[i]->m_Id == id)
{
return m_Symbols[i];
}
}
return NULL;
}
void CSymbols::RemoveEntryById(int id)
{
for (int i = 0; i < GetCount(); i++)
{
if (m_Symbols[i]->m_Id == id)
{
delete m_Symbols[i];
m_Symbols.erase(m_Symbols.begin() + i);
break;
}
}
}
void CSymbols::EnterCriticalSection()
{
::EnterCriticalSection(&m_CriticalSection);
}
void CSymbols::LeaveCriticalSection()
{
::LeaveCriticalSection(&m_CriticalSection);
}
void CSymbols::InitializeCriticalSection()
{
if (!m_bInitialized)
{
m_bInitialized = true;
::InitializeCriticalSection(&m_CriticalSection);
}
}
void CSymbols::DeleteCriticalSection()
{
if (m_bInitialized)
{
m_bInitialized = false;
::DeleteCriticalSection(&m_CriticalSection);
}
}

View File

@ -0,0 +1,159 @@
#pragma once
#include "stdafx.h"
class CSymbolEntry;
class CSymbols
{
public:
typedef enum {
ERR_SUCCESS,
ERR_INVALID_TYPE,
ERR_INVALID_ADDR,
ERR_INVALID_NAME,
ERR_MISSING_FIELDS,
} ParseError;
typedef enum {
TYPE_CODE,
TYPE_DATA,
TYPE_U8,
TYPE_U16,
TYPE_U32,
TYPE_U64,
TYPE_S8,
TYPE_S16,
TYPE_S32,
TYPE_S64,
TYPE_FLOAT,
TYPE_DOUBLE
} DataType;
static constexpr char* SymbolTypes[] = {
"code", // 0
"data", // 1
"u8",
"u16",
"u32",
"u64",
"s8",
"s16",
"s32",
"s64",
"float",
"double",
NULL
};
static constexpr int TypeSizes[] = {
1, 1, // code data
1, 2, 4, 8, // u8 u16 u32 u64
1, 2, 4, 8, // s8 s16 s32 s64
4, 8 // float double
};
private:
static bool m_bInitialized;
static vector<CSymbolEntry*> m_Symbols;
static int m_NextSymbolId;
static CFile m_SymFileHandle;
static char* m_SymFileBuffer;
static size_t m_SymFileSize;
static CRITICAL_SECTION m_CriticalSection;
static char* m_ParserToken;
static size_t m_ParserTokenLength;
static char m_ParserDelimeter;
static char* m_SymFileParseBuffer;
static bool m_bHaveFirstToken;
static void ParserInit();
static void ParserDone();
static void ParserFetchToken(const char* delim);
static bool SortFunction(CSymbolEntry* a, CSymbolEntry* b);
public:
static CPath GetSymFilePath();
static void Load();
static void Save();
static void ParseErrorAlert(char* message, int lineNumber);
static void Add(int type, uint32_t address, char* name, char* description = NULL);
static void RemoveEntryById(int id);
static void Reset();
static const char* GetTypeName(int typeNumber);
static int GetTypeNumber(char* typeName);
static void GetValueString(char* str, CSymbolEntry* lpSymbol);
static int GetCount();
static CSymbolEntry* GetEntryById(int id);
static CSymbolEntry* GetEntryByIndex(int id);
static CSymbolEntry* GetEntryByAddress(uint32_t address);
static const char* GetNameByAddress(uint32_t address);
static void InitializeCriticalSection();
static void DeleteCriticalSection();
static void EnterCriticalSection();
static void LeaveCriticalSection();
};
class CSymbolEntry {
public:
int m_Id;
int m_Type;
uint32_t m_Address;
char* m_Name;
char* m_Description;
CSymbolEntry(int id, int type, uint32_t address, char* name, char* description) :
m_Name(NULL),
m_Description(NULL),
m_Id(id),
m_Type(type),
m_Address(address)
{
if (name != NULL)
{
size_t nameLen = strlen(name);
m_Name = (char*)malloc(nameLen + 1);
strcpy(m_Name, name);
}
if (description != NULL)
{
size_t descLen = strlen(description);
m_Description = (char*)malloc(descLen + 1);
strcpy(m_Description, description);
}
}
~CSymbolEntry()
{
if (m_Name != NULL)
{
free(m_Name);
}
if (m_Description != NULL)
{
free(m_Description);
}
}
const char* TypeName()
{
return CSymbols::SymbolTypes[m_Type];
}
int TypeSize()
{
return CSymbols::TypeSizes[m_Type];
}
};

View File

@ -14,34 +14,82 @@ class CDumpMemory;
class CDebugMemoryView;
class CDebugMemorySearch;
class CDebugTlb;
class CDebugCommandsView;
class CDebugScripts;
class CDebugSymbols;
class CDebugDMALogView;
class CDebugStackView;
class CDebugStackTrace;
class CDMALog;
class CBreakpoints;
class CScriptSystem;
__interface CDebugger
{
virtual void TLBChanged ( void ) = 0;
virtual bool CPUStepStarted ( void ) = 0;
virtual void CPUStep ( void ) = 0;
virtual void FrameDrawn ( void ) = 0;
};
class CDebuggerUI :
public CDebugger
{
CDumpMemory * m_MemoryDump;
CDebugMemoryView * m_MemoryView;
CDebugMemorySearch * m_MemorySearch;
CDebugTlb * m_DebugTLB;
CDumpMemory * m_MemoryDump;
CDebugMemoryView * m_MemoryView;
CDebugMemorySearch * m_MemorySearch;
CDebugTlb * m_DebugTLB;
CDebugCommandsView * m_CommandsView;
CDebugScripts * m_Scripts;
CDebugSymbols * m_Symbols;
CDebugDMALogView * m_DMALogView;
CDebugStackTrace * m_StackTraceView;
CDebugStackView * m_StackView;
CBreakpoints * m_Breakpoints;
CScriptSystem * m_ScriptSystem;
CDMALog * m_DMALog;
vector<uint32_t> * m_StackTrace;
void BreakpointHit(void);
protected:
CDebuggerUI();
virtual ~CDebuggerUI();
void TLBChanged ( void );
bool CPUStepStarted ( void );
void CPUStep ( void );
void FrameDrawn ( void );
public:
void Debug_Reset ( void );
void Debug_ShowMemoryDump ( void );
void Debug_ShowMemoryWindow ( void );
void Debug_ShowMemoryLocation ( uint32_t Address, bool VAddr );
void Debug_ShowMemorySearch ( void );
void Debug_ShowTLBWindow ( void );
void Debug_RefreshTLBWindow ( void );
void Debug_Reset ( void );
void Debug_ShowMemoryDump ( void );
void Debug_ShowMemoryWindow ( void );
void Debug_ShowMemoryLocation ( uint32_t Address, bool VAddr );
void Debug_ShowMemorySearch ( void );
void Debug_ShowTLBWindow ( void );
void Debug_RefreshTLBWindow ( void );
void Debug_ShowCommandsWindow ( void );
void Debug_ShowCommandsLocation ( uint32_t address, bool top );
void Debug_ShowScriptsWindow ( void );
void Debug_LogScriptsWindow ( const char* text );
void Debug_ClearScriptsWindow ( void );
void Debug_RefreshScriptsWindow ( void );
void Debug_RefreshSymbolsWindow ( void );
void Debug_ShowSymbolsWindow ( void );
void Debug_ShowStackTrace ( void );
void Debug_ShowStackWindow ( void );
void Debug_RefreshStackWindow ( void );
void Debug_ShowDMALogWindow ( void );
static void GameReset ( CDebuggerUI * _this );
CBreakpoints* Breakpoints();
CDebugSymbols* Symbols();
CScriptSystem* ScriptSystem();
CDebugScripts* ScriptConsole();
CDMALog* DMALog();
vector<uint32_t> * StackTrace();
static void GameReset ( CDebuggerUI * _this );
};

View File

@ -31,6 +31,12 @@
</ImportGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<GenerateManifest>false</GenerateManifest>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<GenerateManifest>false</GenerateManifest>
</PropertyGroup>
<ItemDefinitionGroup>
<Link>
<SubSystem>Windows</SubSystem>
@ -42,19 +48,53 @@
<Manifest Condition="'$(PlatformToolset)'!='v90'">
<EnableDPIAwareness>true</EnableDPIAwareness>
</Manifest>
<ClCompile>
<Optimization Condition="'$(Configuration)|$(Platform)'=='Release|x64'">MaxSpeed</Optimization>
</ClCompile>
<ClCompile>
<FavorSizeOrSpeed Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Speed</FavorSizeOrSpeed>
</ClCompile>
<ClCompile>
<OmitFramePointers Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</OmitFramePointers>
</ClCompile>
<ClCompile>
<Optimization Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">MinSpace</Optimization>
</ClCompile>
<ClCompile>
<FavorSizeOrSpeed Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Size</FavorSizeOrSpeed>
</ClCompile>
<ClCompile>
<OmitFramePointers Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</OmitFramePointers>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="N64System\Debugger\Debugger-StackView.cpp" />
<ClCompile Include="N64System\Debugger\Assembler.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="Multilanguage\LanguageSelector.cpp" />
<ClCompile Include="N64System\Debugger\Debugger-AddSymbol.cpp" />
<ClCompile Include="N64System\Debugger\Debugger-MemoryDump.cpp" />
<ClCompile Include="N64System\Debugger\Debugger-MemorySearch.cpp" />
<ClCompile Include="N64System\Debugger\Debugger-RegisterTabs.cpp" />
<ClCompile Include="N64System\Debugger\Debugger-TLB.cpp" />
<ClCompile Include="N64System\Debugger\Debugger-ViewMemory.cpp" />
<ClCompile Include="N64System\Debugger\Debugger.cpp" />
<ClCompile Include="N64System\Debugger\Breakpoints.cpp" />
<ClCompile Include="N64System\Debugger\DMALog.cpp" />
<ClCompile Include="N64System\Debugger\ScriptSystem.cpp" />
<ClCompile Include="Plugins\PluginList.cpp" />
<ClCompile Include="Settings\GuiSettings.cpp" />
<ClCompile Include="Settings\NotificationSettings.cpp" />
<ClCompile Include="Settings\UISettings.cpp" />
<ClCompile Include="N64System\Debugger\Debugger-Commands.cpp" />
<ClCompile Include="N64System\Debugger\Debugger-Scripts.cpp" />
<ClCompile Include="N64System\Debugger\Debugger-Symbols.cpp" />
<ClCompile Include="N64System\Debugger\Symbols.cpp" />
<ClCompile Include="N64System\Debugger\Debugger-AddBreakpoint.cpp" />
<ClCompile Include="N64System\Debugger\ScriptInstance.cpp" />
<ClCompile Include="N64System\Debugger\ScriptHook.cpp" />
<ClCompile Include="N64System\Debugger\Debugger-DMALogView.cpp" />
<ClCompile Include="N64System\Debugger\Debugger-StackTrace.cpp" />
<ClCompile Include="stdafx.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
@ -85,6 +125,22 @@
<ClCompile Include="UserInterface\WTLControls\PartialGroupBox.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="N64System\Debugger\Debugger-StackView.h" />
<ClInclude Include="N64System\Debugger\Debugger-AddSymbol.h" />
<ClInclude Include="N64System\Debugger\Assembler.h" />
<ClInclude Include="N64System\Debugger\Debugger-RegisterTabs.h" />
<ClInclude Include="N64System\Debugger\Debugger-StackTrace.h" />
<ClInclude Include="N64System\Debugger\Debugger-DMALogView.h" />
<ClInclude Include="N64System\Debugger\DMALog.h" />
<ClInclude Include="N64System\Debugger\OpInfo.h" />
<ClInclude Include="N64System\Debugger\ScriptHook.h" />
<ClInclude Include="N64System\Debugger\ScriptInstance.h" />
<ClInclude Include="N64System\Debugger\Debugger-AddBreakpoint.h" />
<ClInclude Include="N64System\Debugger\Breakpoints.h" />
<ClInclude Include="N64System\Debugger\Symbols.h" />
<ClInclude Include="N64System\Debugger\Debugger-Symbols.h" />
<ClInclude Include="N64System\Debugger\Debugger-Scripts.h" />
<ClInclude Include="N64System\Debugger\Debugger-Commands.h" />
<ClInclude Include="Multilanguage\LanguageSelector.h" />
<ClInclude Include="N64System.h" />
<ClInclude Include="N64System\Debugger\DebugDialog.h" />
@ -94,6 +150,7 @@
<ClInclude Include="N64System\Debugger\Debugger-ViewMemory.h" />
<ClInclude Include="N64System\Debugger\debugger.h" />
<ClInclude Include="N64System\Debugger\DebuggerUI.h" />
<ClInclude Include="N64System\Debugger\ScriptSystem.h" />
<ClInclude Include="Settings\GuiSettings.h" />
<ClInclude Include="Settings\NotificationSettings.h" />
<ClInclude Include="Settings\UISettings.h" />
@ -129,6 +186,7 @@
<ClInclude Include="UserInterface\WTLControls\ModifiedEditBox.h" />
<ClInclude Include="UserInterface\WTLControls\numberctrl.h" />
<ClInclude Include="UserInterface\WTLControls\PartialGroupBox.h" />
<ClInclude Include="UserInterface\WTLControls\TooltipDialog.h" />
<ClInclude Include="WTLApp.h" />
</ItemGroup>
<ItemGroup>
@ -136,6 +194,9 @@
<Project>{3326e128-33af-422c-bb7c-67cc6b915610}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
<ProjectReference Include="..\3rdParty\duktape\duktape.vcxproj">
<Project>{e8d9a652-a354-4374-b6c5-a51ee62749fd}</Project>
</ProjectReference>
<ProjectReference Include="..\3rdParty\zlib\zlib.vcxproj">
<Project>{731bd205-2826-4631-b7af-117658e88dbc}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
@ -151,8 +212,11 @@
<ItemGroup>
<None Include="res\divider.cur" />
<None Include="res\hand.cur" />
<None Include="UserInterface\API.js" />
<None Include="UserInterface\icons\bin00001.bin" />
<None Include="UserInterface\Icons\divider.cur" />
<None Include="UserInterface\Icons\hand.cur" />
<None Include="UserInterface\icons\javascri.bin" />
</ItemGroup>
<ItemGroup>
<Image Include="res\ListItems.bmp" />
@ -169,4 +233,9 @@
<ItemGroup>
<Manifest Include="Project64.exe.manifest" />
</ItemGroup>
<ProjectExtensions>
<VisualStudio>
<UserProperties RESOURCE_FILE="UserInterface\UIResources.rc" />
</VisualStudio>
</ProjectExtensions>
</Project>

View File

@ -162,11 +162,59 @@
<ClCompile Include="Settings\UISettings.cpp">
<Filter>Source Files\Settings Files</Filter>
</ClCompile>
<ClCompile Include="UserInterface\SupportWindow.cpp">
<Filter>Source Files\User Interface Source</Filter>
</ClCompile>
<ClCompile Include="UserInterface\SupportEnterCode.cpp">
<Filter>Source Files\User Interface Source</Filter>
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="UserInterface\SupportWindow.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="N64System\Debugger\Debugger-Commands.cpp">
<Filter>Source Files\User Interface Source\Debugger Source</Filter>
</ClCompile>
<ClCompile Include="N64System\Debugger\Debugger-Scripts.cpp">
<Filter>Source Files\User Interface Source\Debugger Source</Filter>
</ClCompile>
<ClCompile Include="N64System\Debugger\ScriptSystem.cpp">
<Filter>Source Files\User Interface Source\Debugger Source</Filter>
</ClCompile>
<ClCompile Include="N64System\Debugger\Debugger-Symbols.cpp">
<Filter>Source Files\User Interface Source\Debugger Source</Filter>
</ClCompile>
<ClCompile Include="N64System\Debugger\Breakpoints.cpp">
<Filter>Source Files\User Interface Source\Debugger Source</Filter>
</ClCompile>
<ClCompile Include="N64System\Debugger\Debugger-AddBreakpoint.cpp">
<Filter>Source Files\User Interface Source\Debugger Source</Filter>
</ClCompile>
<ClCompile Include="N64System\Debugger\Symbols.cpp">
<Filter>Source Files\User Interface Source\Debugger Source</Filter>
</ClCompile>
<ClCompile Include="N64System\Debugger\ScriptHook.cpp">
<Filter>Source Files\User Interface Source\Debugger Source</Filter>
</ClCompile>
<ClCompile Include="N64System\Debugger\ScriptInstance.cpp">
<Filter>Source Files\User Interface Source\Debugger Source</Filter>
</ClCompile>
<ClCompile Include="N64System\Debugger\Debugger-StackTrace.cpp">
<Filter>Source Files\User Interface Source\Debugger Source</Filter>
</ClCompile>
<ClCompile Include="N64System\Debugger\Assembler.cpp">
<Filter>Source Files\User Interface Source\Debugger Source</Filter>
</ClCompile>
<ClCompile Include="N64System\Debugger\DMALog.cpp">
<Filter>Source Files\User Interface Source\Debugger Source</Filter>
</ClCompile>
<ClCompile Include="N64System\Debugger\Debugger-AddSymbol.cpp">
<Filter>Source Files\User Interface Source\Debugger Source</Filter>
</ClCompile>
<ClCompile Include="N64System\Debugger\Debugger-DMALogView.cpp">
<Filter>Source Files\User Interface Source\Debugger Source</Filter>
</ClCompile>
<ClCompile Include="N64System\Debugger\Debugger-RegisterTabs.cpp">
<Filter>Source Files\User Interface Source\Debugger Source</Filter>
</ClCompile>
<ClCompile Include="N64System\Debugger\Debugger-StackView.cpp">
<Filter>Source Files\User Interface Source\Debugger Source</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
@ -299,11 +347,65 @@
<ClInclude Include="Settings\UISettings.h">
<Filter>Header Files\Settings</Filter>
</ClInclude>
<ClInclude Include="UserInterface\SupportWindow.h">
<Filter>Header Files\User Interface Headers</Filter>
</ClInclude>
<ClInclude Include="UserInterface\SupportEnterCode.h">
<Filter>Header Files\User Interface Headers</Filter>
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="UserInterface\SupportWindow.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="N64System\Debugger\Debugger-Commands.h">
<Filter>Header Files\N64 System Headers\Debugger Headers</Filter>
</ClInclude>
<ClInclude Include="N64System\Debugger\Debugger-Scripts.h">
<Filter>Header Files\N64 System Headers\Debugger Headers</Filter>
</ClInclude>
<ClInclude Include="N64System\Debugger\ScriptSystem.h">
<Filter>Header Files\N64 System Headers\Debugger Headers</Filter>
</ClInclude>
<ClInclude Include="N64System\Debugger\Debugger-Symbols.h">
<Filter>Header Files\N64 System Headers\Debugger Headers</Filter>
</ClInclude>
<ClInclude Include="N64System\Debugger\Breakpoints.h">
<Filter>Header Files\N64 System Headers\Debugger Headers</Filter>
</ClInclude>
<ClInclude Include="N64System\Debugger\Symbols.h">
<Filter>Header Files\N64 System Headers\Debugger Headers</Filter>
</ClInclude>
<ClInclude Include="N64System\Debugger\Debugger-AddBreakpoint.h">
<Filter>Header Files\N64 System Headers\Debugger Headers</Filter>
</ClInclude>
<ClInclude Include="N64System\Debugger\ScriptHook.h">
<Filter>Header Files\N64 System Headers\Debugger Headers</Filter>
</ClInclude>
<ClInclude Include="N64System\Debugger\ScriptInstance.h">
<Filter>Header Files\N64 System Headers\Debugger Headers</Filter>
</ClInclude>
<ClInclude Include="N64System\Debugger\Debugger-StackTrace.h">
<Filter>Header Files\N64 System Headers\Debugger Headers</Filter>
</ClInclude>
<ClInclude Include="N64System\Debugger\Assembler.h">
<Filter>Header Files\N64 System Headers\Debugger Headers</Filter>
</ClInclude>
<ClInclude Include="N64System\Debugger\Debugger-AddSymbol.h">
<Filter>Header Files\N64 System Headers\Debugger Headers</Filter>
</ClInclude>
<ClInclude Include="N64System\Debugger\DMALog.h">
<Filter>Header Files\N64 System Headers\Debugger Headers</Filter>
</ClInclude>
<ClInclude Include="N64System\Debugger\Debugger-DMALogView.h">
<Filter>Header Files\N64 System Headers\Debugger Headers</Filter>
</ClInclude>
<ClInclude Include="N64System\Debugger\Debugger-RegisterTabs.h">
<Filter>Header Files\N64 System Headers\Debugger Headers</Filter>
</ClInclude>
<ClInclude Include="N64System\Debugger\Debugger-StackView.h">
<Filter>Header Files\N64 System Headers\Debugger Headers</Filter>
</ClInclude>
<ClInclude Include="N64System\Debugger\OpInfo.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="UserInterface\WTLControls\TooltipDialog.h">
<Filter>Header Files\User Interface Headers\WTL Controls Headers</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
@ -319,6 +421,13 @@
<None Include="UserInterface\Icons\hand.cur">
<Filter>Resource Files</Filter>
</None>
<None Include="UserInterface\icons\bin00001.bin">
<Filter>Resource Files</Filter>
</None>
<None Include="UserInterface\icons\javascri.bin">
<Filter>Resource Files</Filter>
</None>
<None Include="UserInterface\API.js" />
</ItemGroup>
<ItemGroup>
<Image Include="res\ListItems.bmp">

View File

@ -0,0 +1,705 @@
Number.prototype.hex = function(len)
{
len = (len || 8);
var str = (this >>> 0).toString(16).toUpperCase()
while (str.length < len)
{
str = "0" + str
}
return str
}
const u8 = 'u8', u16 = 'u16', u32 = 'u32',
s8 = 's8', s16 = 's16', s32 = 's32',
float = 'float', double = 'double'
const _typeSizes = {
u8: 1, u16: 2, u32: 4,
s8: 1, s16: 2, s32: 4,
float: 4, double: 8
}
const _regNums = {
r0: 0, at: 1, v0: 2, v1: 3,
a0: 4, a1: 5, a2: 6, a3: 7,
t0: 8, t1: 9, t2: 10, t3: 11,
t4: 12, t5: 13, t6: 14, t7: 15,
s0: 16, s1: 17, s2: 18, s3: 19,
s4: 20, s5: 21, s6: 22, s7: 23,
t8: 24, t9: 25, k0: 26, k1: 27,
gp: 28, sp: 29, fp: 30, ra: 31,
f0: 0, f1: 1, f2: 2, f3: 3,
f4: 4, f5: 5, f6: 6, f7: 7,
f8: 8, f9: 9, f10: 10, f11: 11,
f12: 12, f13: 13, f14: 14, f15: 15,
f16: 16, f17: 17, f18: 18, f19: 19,
f20: 20, f21: 21, f22: 22, f23: 23,
f24: 24, f25: 25, f26: 26, f27: 27,
f28: 28, f29: 29, f30: 30, f31: 31
}
function AddressRange(start, end)
{
this.start = start >>> 0
this.end = end >>> 0
Object.freeze(this)
}
const ADDR_ANY = new AddressRange(0x00000000, 0x100000000)
const ADDR_ANY_KUSEG = new AddressRange(0x00000000, 0x80000000)
const ADDR_ANY_KSEG0 = new AddressRange(0x80000000, 0xA0000000)
const ADDR_ANY_KSEG1 = new AddressRange(0xA0000000, 0xC0000000)
const ADDR_ANY_KSEG2 = new AddressRange(0xC0000000, 0x100000000)
const ADDR_ANY_RDRAM = new AddressRange(0x80000000, 0x80800000)
const ADDR_ANY_RDRAM_UNC = new AddressRange(0xA0000000, 0xA0800000)
const ADDR_ANY_CART_ROM = new AddressRange(0x90000000, 0x96000000)
const ADDR_ANY_CART_ROM_UNC = new AddressRange(0xB0000000, 0xB6000000)
const system = {
pause: function()
{
_native.pause()
},
resume: function()
{
},
reset: function()
{
},
hardreset: function()
{
},
savestate: function()
{
},
loadstate: function()
{
},
setsaveslot: function(slot)
{
},
getsaveslot: function()
{
},
generatebitmap: function()
{
}
}
const debug = {
showmemory: function(address)
{
},
showcommands: function(address)
{
_native.showCommands(address)
},
breakhere: function()
{
debug.showcommands(gpr.pc)
system.pause()
},
disasm: function()
{
}
}
const console = {
print: function(data)
{
_native.consolePrint(data);
},
log: function()
{
for(var i in arguments)
{
console.print(arguments[i].toString())
if(i < arguments.length - 1)
{
console.print(" ")
}
}
console.print("\r\n")
},
clear: function()
{
_native.consoleClear();
}
}
const screen = {
print: function(x, y, text)
{
_native.screenPrint(x, y, text)
}
}
const events = (function()
{
var callbacks = {};
var nextCallbackId = 0;
return {
on: function(hook, callback, param, param2, bOnce)
{
this._stashCallback(callback)
return _native.addCallback(hook, callback, param, param2, bOnce)
},
onexec: function(addr, callback)
{
var param = 0;
var param2 = 0;
if (typeof (addr) == "object")
{
param = addr.start;
param2 = addr.end;
}
else if (typeof (addr) == "number")
{
param = addr;
}
return events.on('exec', callback, param, param2)
},
onread: function(addr, callback)
{
var param = 0;
var param2 = 0;
if (typeof (addr) == "object")
{
param = addr.start;
param2 = addr.end;
}
else if (typeof (addr) == "number")
{
param = addr;
}
return events.on('read', callback, param, param2)
},
onwrite: function(addr, callback)
{
var param = 0;
var param2 = 0;
if (typeof (addr) == "object")
{
param = addr.start;
param2 = addr.end;
}
else if (typeof (addr) == "number")
{
param = addr;
}
return events.on('write', callback, param, param2)
},
ondraw: function(callback)
{
return events.on('draw', callback, 0)
},
remove: function(callbackId)
{
_native.removeCallback(callbackId)
},
clear: function(){},
_stashCallback: function(callback)
{
callbacks[nextCallbackId] = callback
return nextCallbackId++;
},
_unstashCallback: function()
{
},
}
})();
const gpr = new Proxy({},
{
get: function(obj, prop)
{
if (typeof prop == 'number' && prop < 32)
{
return _native.getGPRVal(prop)
}
if (prop in _regNums)
{
return _native.getGPRVal(_regNums[prop])
}
switch(prop)
{
case 'pc': return _native.getPCVal(); break;
case 'hi': return _native.getHIVal(false); break;
case 'lo': return _native.getLOVal(false); break;
}
},
set: function(obj, prop, val)
{
if (typeof prop == 'number' && prop < 32)
{
_native.setGPRVal(prop, false, val)
return
}
if (prop in _regNums)
{
_native.setGPRVal(_regNums[prop], false, val)
return
}
switch(prop)
{
case 'pc': _native.setPCVal(val); break;
case 'hi': _native.setHIVal(false, val); break;
case 'lo': _native.setLOVal(false, val); break;
}
}
})
const ugpr = new Proxy({},
{
get: function (obj, prop)
{
if (typeof prop == 'number' && prop < 32)
{
return _native.getGPRVal(prop, true)
}
if (prop in _regNums)
{
return _native.getGPRVal(_regNums[prop], true)
}
switch(prop)
{
case 'hi': return _native.getHIVal(true); break;
case 'lo': return _native.getLOVal(true); break;
}
},
set: function (obj, prop, val)
{
if (typeof prop == 'number' && prop < 32)
{
_native.setGPRVal(prop, true, val)
return
}
if (prop in _regNums)
{
_native.setGPRVal(_regNums[prop], true, val)
return
}
switch(prop)
{
case 'hi': _native.setHIVal(true, val); break;
case 'lo': _native.setLOVal(true, val); break;
}
}
})
const fpr = new Proxy({},
{
get: function(obj, prop)
{
if (typeof prop == 'number')
{
return _native.getFPRVal(prop)
}
if (prop in _regNums)
{
return _native.getFPRVal(_regNums[prop])
}
},
set: function(obj, prop, val)
{
if (typeof prop == 'number' && prop < 32)
{
_native.setFPRVal(prop, false, val)
return
}
if (prop in _regNums)
{
_native.setFPRVal(_regNums[prop], false, val)
}
}
})
const dfpr = new Proxy({},
{
get: function (obj, prop)
{
if (typeof prop == 'number')
{
return _native.getFPRVal(prop, true)
}
if (prop in _regNums)
{
return _native.getFPRVal(_regNums[prop], true)
}
},
set: function (obj, prop, val)
{
if (typeof prop == 'number' && prop < 32)
{
_native.setFPRVal(prop, true, val)
return
}
if (prop in _regNums)
{
_native.setFPRVal(_regNums[prop], true, val)
}
}
})
const rom = {
u8: new Proxy({},
{
get: function (obj, prop)
{
return _native.getROMInt(prop, 8, false)
}
}),
u16: new Proxy({},
{
get: function (obj, prop)
{
return _native.getROMInt(prop, 16, false)
}
}),
u32: new Proxy({},
{
get: function (obj, prop)
{
return _native.getROMInt(prop, 32, false)
}
}),
s8: new Proxy({},
{
get: function (obj, prop)
{
return _native.getROMInt(prop, 8, true)
}
}),
s16: new Proxy({},
{
get: function (obj, prop)
{
return _native.getROMInt(prop, 16, true)
}
}),
s32: new Proxy({},
{
get: function (obj, prop)
{
return _native.getROMInt(prop, 32, true)
}
}),
'float': new Proxy({},
{
get: function (obj, prop)
{
return _native.getROMFloat(prop)
},
set: function (obj, prop, val)
{
_native.setROMFloat(prop, val)
}
}),
'double': new Proxy({},
{
get: function (obj, prop)
{
return _native.getROMFloat(prop, true)
},
set: function (obj, prop, val)
{
_native.setROMFloat(prop, val, true)
}
}),
getblock: function (address, size)
{
return _native.getROMBlock(address, size)
},
getstring: function(address, maxLen)
{
return _native.getROMString(address, maxLen)
},
}
const mem = {
u8: new Proxy({},
{
get: function(obj, prop)
{
return _native.getRDRAMInt(prop, 8, false)
},
set: function(obj, prop, val)
{
_native.setRDRAMInt(prop, 8, val)
}
}),
u16: new Proxy({},
{
get: function(obj, prop)
{
return _native.getRDRAMInt(prop, 16, false)
},
set: function(obj, prop, val)
{
_native.setRDRAMInt(prop, 16, val)
}
}),
u32: new Proxy({},
{
get: function(obj, prop)
{
return _native.getRDRAMInt(prop, 32, false)
},
set: function(obj, prop, val)
{
_native.setRDRAMInt(prop, 32, val)
}
}),
s8: new Proxy({},
{
get: function(obj, prop)
{
return _native.getRDRAMInt(prop, 8, true)
},
set: function(obj, prop, val)
{
_native.setRDRAMInt(prop, 8, val)
}
}),
s16: new Proxy({},
{
get: function(obj, prop)
{
return _native.getRDRAMInt(prop, 16, true)
},
set: function(obj, prop, val)
{
_native.setRDRAMInt(prop, 16, val)
}
}),
s32: new Proxy({},
{
get: function(obj, prop)
{
return _native.getRDRAMInt(prop, 32, true)
},
set: function(obj, prop, val)
{
_native.setRDRAMInt(prop, 32, val)
}
}),
'float': new Proxy({},
{
get: function(obj, prop)
{
return _native.getRDRAMFloat(prop)
},
set: function(obj, prop, val)
{
_native.setRDRAMFloat(prop, val)
}
}),
'double': new Proxy({},
{
get: function(obj, prop)
{
return _native.getRDRAMFloat(prop, true)
},
set: function(obj, prop, val)
{
_native.setRDRAMFloat(prop, val, true)
}
}),
getblock: function(address, size)
{
return _native.getRDRAMBlock(address, size)
},
getstring: function(address, maxLen)
{
return _native.getRDRAMString(address, maxLen)
},
bindvar: function(obj, baseAddr, name, type)
{
Object.defineProperty(obj, name,
{
get: function()
{
return mem[type][baseAddr]
},
set: function(val)
{
mem[type][baseAddr] = val
}
})
return obj
},
bindvars: function(obj, list)
{
for(var i = 0; i < list.length; i++)
{
mem.bindvar(obj, list[i][0], list[i][1], list[i][2])
}
return obj
},
bindstruct: function(obj, baseAddr, props)
{
for (var name in props)
{
var type = props[name]
var size = _typeSizes[type]
mem.bindvar(obj, baseAddr, name, type)
baseAddr += size
}
return obj
},
typedef: function(props, proto)
{
var size = 0
for (var name in props)
{
size += _typeSizes[props[name]]
}
var StructClass = function(baseAddr)
{
mem.bindstruct(this, baseAddr, props)
}
StructClass.sizeof = function()
{
return size
}
/*if(proto)
{
StructClass.prototype = proto
}*/
return StructClass
}
}
function alert(text, caption){
caption = caption || ""
_native.msgBox(text, caption)
}
function Socket(fd)
{
var connected = false;
var _fd;
if(fd)
{
// assume this was constructed from Server
_fd = fd;
connected = true;
} else {
_fd = _native.sockCreate();
}
var _ondata = function(data){}
var _onclose = function(){}
var _onconnect = function(){}
var _onconnect_base = function(){
connected = 1;
_onconnect();
}
var _bufferSize = 2048
this.write = function(data, callback)
{
_native.write(_fd, data, callback)
}
this.close = function()
{
_native.close(_fd)
}
this.connect = function(settings, callback)
{
if(!connected)
{
_onconnect = callback;
_native.sockConnect(_fd, settings.host || '127.0.0.1', settings.port || 80, _onconnect_base);
}
}
var _read = function(data)
{
if(data == null)
{
connected = false;
_onclose();
return;
}
_native.read(_fd, _bufferSize, _read)
_ondata(data)
}
this.on = function(eventType, callback)
{
switch(eventType)
{
case 'data':
_ondata = callback
_native.read(_fd, _bufferSize, _read)
break;
case 'close':
// note: does nothing if ondata not set
_onclose = callback
break;
}
}
}
function Server(settings)
{
var _this = this;
var _fd = _native.sockCreate()
var _onconnection = function(socket){}
if(settings.port)
{
_native.sockListen(_fd, settings.port || 80)
}
// Intermediate callback
// convert clientFd to Socket and accept next client
var _acceptClient = function(clientFd)
{
_onconnection(new Socket(clientFd))
_native.sockAccept(_fd, _acceptClient)
}
this.listen = function(port)
{
_native.sockListen(_fd, port)
}
this.on = function(eventType, callback)
{
switch(eventType)
{
case 'connection':
_onconnection = callback
_native.sockAccept(_fd, _acceptClient)
break;
}
}
}

View File

@ -2,6 +2,9 @@
#include "RomInformationClass.h"
#include <Project64-core/N64System/N64DiskClass.h>
#include <Project64/N64System/Debugger/Breakpoints.h>
#include <Project64/N64System/Debugger/ScriptSystem.h>
#include <windows.h>
#include <commdlg.h>
@ -51,7 +54,7 @@ CMainMenu::CMainMenu(CMainGui * hMainWindow) :
m_ChangeSettingList.push_back(Debugger_AppLogFlush);
m_ChangeSettingList.push_back(Game_CurrentSaveState);
m_ChangeSettingList.push_back(Setting_CurrentLanguage);
for (UISettingList::const_iterator iter = m_ChangeUISettingList.begin(); iter != m_ChangeUISettingList.end(); iter++)
{
g_Settings->RegisterChangeCB((SettingID)(FirstUISettings + *iter), this, (CSettings::SettingChangedFunc)SettingsChanged);
@ -467,6 +470,7 @@ bool CMainMenu::ProcessMessage(HWND hWnd, DWORD /*FromAccelerator*/, DWORD MenuI
case ID_DEBUG_DISABLE_GAMEFIX:
g_Settings->SaveBool(Debugger_DisableGameFixes, !g_Settings->LoadBool(Debugger_DisableGameFixes));
break;
case ID_DEBUGGER_TRACE_MD5: SetTraceModuleSetttings(Debugger_TraceMD5); break;
case ID_DEBUGGER_TRACE_SETTINGS: SetTraceModuleSetttings(Debugger_TraceSettings); break;
case ID_DEBUGGER_TRACE_UNKNOWN: SetTraceModuleSetttings(Debugger_TraceUnknown); break;
@ -503,7 +507,13 @@ bool CMainMenu::ProcessMessage(HWND hWnd, DWORD /*FromAccelerator*/, DWORD MenuI
case ID_DEBUGGER_INTERRUPT_VI: g_BaseSystem->ExternalEvent(SysEvent_Interrupt_VI); break;
case ID_DEBUGGER_INTERRUPT_PI: g_BaseSystem->ExternalEvent(SysEvent_Interrupt_PI); break;
case ID_DEBUGGER_INTERRUPT_DP: g_BaseSystem->ExternalEvent(SysEvent_Interrupt_DP); break;
case ID_CURRENT_SAVE_DEFAULT:
case ID_DEBUGGER_BREAKPOINTS: m_Gui->Debug_ShowCommandsWindow(); break;
case ID_DEBUGGER_SCRIPTS: m_Gui->Debug_ShowScriptsWindow(); break;
case ID_DEBUGGER_SYMBOLS: m_Gui->Debug_ShowSymbolsWindow(); break;
case ID_DEBUGGER_DMALOG: m_Gui->Debug_ShowDMALogWindow(); break;
case ID_DEBUGGER_STACKTRACE: m_Gui->Debug_ShowStackTrace(); break;
case ID_DEBUGGER_STACKVIEW: m_Gui->Debug_ShowStackWindow(); break;
case ID_CURRENT_SAVE_DEFAULT:
g_Notify->DisplayMessage(3, stdstr_f(GS(MENU_SLOT_SAVE), GetSaveSlotString(MenuID - ID_CURRENT_SAVE_DEFAULT).c_str()).c_str());
g_Settings->SaveDword(Game_CurrentSaveState, (DWORD)(MenuID - ID_CURRENT_SAVE_DEFAULT));
break;
@ -994,12 +1004,15 @@ void CMainMenu::FillOutMenu(HMENU hMenu)
/* Debug - R4300i
*******************/
Item.Reset(ID_DEBUGGER_LOGOPTIONS, EMPTY_STRING, EMPTY_STDSTR, NULL, L"R4300i &Commands...");
Item.SetItemEnabled(false);
DebugR4300Menu.push_back(Item);
Item.Reset(ID_DEBUGGER_R4300REGISTERS, EMPTY_STRING, EMPTY_STDSTR, NULL, L"R4300i &Registers...");
Item.SetItemEnabled(true);
//ID_DEBUGGER_LOGOPTIONS
Item.Reset(ID_DEBUGGER_BREAKPOINTS, EMPTY_STRING, EMPTY_STDSTR, NULL, L"R4300i &Commands...");
Item.SetItemEnabled(CPURunning);
DebugR4300Menu.push_back(Item);
//Item.Reset(ID_DEBUGGER_R4300REGISTERS, EMPTY_STRING, EMPTY_STDSTR, NULL, L"R4300i &Registers...");
//Item.SetItemEnabled(true);
// DebugR4300Menu.push_back(Item);
Item.Reset(ID_DEBUG_DISABLE_GAMEFIX, EMPTY_STRING, EMPTY_STDSTR, NULL, L"Disable Game Fixes");
if (g_Settings->LoadBool(Debugger_DisableGameFixes))
{
@ -1112,9 +1125,39 @@ void CMainMenu::FillOutMenu(HMENU hMenu)
/* Debugger Main Menu
****************/
Item.Reset(ID_DEBUGGER_BREAKPOINTS, EMPTY_STRING, EMPTY_STDSTR, NULL, L"Breakpoint...");
Item.SetItemEnabled(CPURunning);
//Item.SetItemEnabled(CPURunning);
DebugMenu.push_back(Item);
DebugMenu.push_back(MENU_ITEM(SPLITER));
/* Debugger - Symbols
****************/
Item.Reset(ID_DEBUGGER_SYMBOLS, EMPTY_STRING, EMPTY_STDSTR, NULL, L"Symbols...");
//Item.SetItemEnabled(CPURunning);
DebugMenu.push_back(Item);
/* Debug - Scripts
*******************/
Item.Reset(ID_DEBUGGER_SCRIPTS, EMPTY_STRING, EMPTY_STDSTR, NULL, L"Scripts...");
//Item.SetItemEnabled(CPURunning);
DebugMenu.push_back(Item);
/* Debug - DMA Log
*******************/
Item.Reset(ID_DEBUGGER_DMALOG, EMPTY_STRING, EMPTY_STDSTR, NULL, L"DMA Log...");
//Item.SetItemEnabled(CPURunning);
DebugMenu.push_back(Item);
/* Debug - Stack
*******************/
Item.Reset(ID_DEBUGGER_STACKVIEW, EMPTY_STRING, EMPTY_STDSTR, NULL, L"Stack...");
DebugMenu.push_back(Item);
/* Debug - Stack Trace
*******************/
Item.Reset(ID_DEBUGGER_STACKTRACE, EMPTY_STRING, EMPTY_STDSTR, NULL, L"Stack Trace...");
Item.SetItemEnabled(false);
DebugMenu.push_back(Item);
DebugMenu.push_back(MENU_ITEM(SPLITER));
/* Debug - RSP
*******************/

View File

@ -39,7 +39,8 @@ enum MainMenuID
ID_DEBUGGER_LOGOPTIONS, ID_DEBUGGER_GENERATELOG, ID_DEBUGGER_DUMPMEMORY, ID_DEBUGGER_SEARCHMEMORY,
ID_DEBUGGER_TLBENTRIES, ID_DEBUGGER_BREAKPOINTS, ID_DEBUGGER_MEMORY, ID_DEBUGGER_R4300REGISTERS,
ID_DEBUGGER_INTERRUPT_SP, ID_DEBUGGER_INTERRUPT_SI, ID_DEBUGGER_INTERRUPT_AI, ID_DEBUGGER_INTERRUPT_VI,
ID_DEBUGGER_INTERRUPT_PI, ID_DEBUGGER_INTERRUPT_DP,
ID_DEBUGGER_INTERRUPT_PI, ID_DEBUGGER_INTERRUPT_DP, ID_DEBUGGER_SCRIPTS, ID_DEBUGGER_SYMBOLS, ID_DEBUGGER_DMALOG,
ID_DEBUGGER_STACKTRACE, ID_DEBUGGER_STACKVIEW,
// App logging
ID_DEBUGGER_APPLOG_FLUSH, ID_DEBUGGER_TRACE_MD5, ID_DEBUGGER_TRACE_SETTINGS, ID_DEBUGGER_TRACE_UNKNOWN, ID_DEBUGGER_TRACE_APPINIT,

View File

@ -32,6 +32,7 @@ CAdvancedOptionsPage::CAdvancedOptionsPage(HWND hParent, const RECT & rcDispay)
AddModCheckBox(GetDlgItem(IDC_START_ON_ROM_OPEN), Setting_AutoStart);
AddModCheckBox(GetDlgItem(IDC_ZIP), Setting_AutoZipInstantSave);
AddModCheckBox(GetDlgItem(IDC_DEBUGGER), Debugger_Enabled);
AddModCheckBox(GetDlgItem(IDC_INTERPRETER), Setting_ForceInterpreterCPU);
AddModCheckBox(GetDlgItem(IDC_REMEMBER_CHEAT), Setting_RememberCheats);
AddModCheckBox(GetDlgItem(IDC_UNIQUE_SAVE_DIR), Setting_UniqueSaveDir);
AddModCheckBox(GetDlgItem(IDC_CHECK_RUNNING), Setting_CheckEmuRunning);

View File

@ -19,6 +19,7 @@ class CAdvancedOptionsPage :
COMMAND_ID_HANDLER_EX(IDC_START_ON_ROM_OPEN,CheckBoxChanged)
COMMAND_ID_HANDLER_EX(IDC_ZIP,CheckBoxChanged)
COMMAND_ID_HANDLER_EX(IDC_DEBUGGER,CheckBoxChanged)
COMMAND_ID_HANDLER_EX(IDC_INTERPRETER, CheckBoxChanged)
COMMAND_ID_HANDLER_EX(IDC_REMEMBER_CHEAT,CheckBoxChanged)
COMMAND_ID_HANDLER_EX(IDC_CHECK_RUNNING, CheckBoxChanged)
COMMAND_ID_HANDLER_EX(IDC_UNIQUE_SAVE_DIR, CheckBoxChanged)

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,7 @@
// CListCtrl - A WTL list control with Windows Vista style item selection.
//
// Revision: 1.5
// Last modified: 9th April 2006
// Last modified: 2nd November 2016
//
/////////////////////////////////////////////////////////////////////////////
@ -43,6 +43,7 @@ public:
CListImpl()
{
m_bSortEnabled = TRUE; // Added by Rowan 05/12/2006
m_bRightClickSelect = FALSE; // shygoo 2016 Nov 2
m_bShowHeader = TRUE;
m_bSortAscending = TRUE;
m_bButtonDown = FALSE;
@ -97,10 +98,16 @@ public:
~CListImpl()
{
if (m_wndItemEdit.IsWindow())
{
// patch memory window crash
m_wndItemEdit.UnsubclassWindow();
}
}
protected:
BOOL m_bSortEnabled; // Added by Rowan 05/12/2006 to disable sorting
BOOL m_bRightClickSelect; // shygoo 2016 Nov 2
BOOL m_bShowHeader;
BOOL m_bShowSort;
BOOL m_bSortAscending;
@ -330,6 +337,12 @@ public:
m_bSortEnabled = bSortEnabled;
}
// shygoo 2016 Nov 2
void SetRightClickSelect( BOOL bRightClickSelect = TRUE)
{
m_bRightClickSelect = bRightClickSelect;
}
void ShowHeader( BOOL bShowHeader = TRUE )
{
m_bShowHeader = bShowHeader;
@ -2245,7 +2258,7 @@ public:
if (( pT->GetItemFlags( nItem, nIndex ) & ITEM_FLAGS_HIT_NOTIFY ) != 0)
{
NotifyParent( nItem, nSubItem, LCN_HITTEST );
NotifyParent( nItem, nSubItem, LCN_HITTEST );
}
}
}
@ -2336,9 +2349,12 @@ public:
int nItem = NULL_ITEM;
int nSubItem = NULL_SUBITEM;
// only select item if not already selected (de-select in OnLButtonUp)
if ( HitTest( point, nItem, nSubItem ) && !IsSelected( nItem ) )
SelectItem( nItem, nSubItem, nFlags );
if (m_bRightClickSelect)
{
// only select item if not already selected (de-select in OnLButtonUp)
if (HitTest(point, nItem, nSubItem) && !IsSelected(nItem))
SelectItem(nItem, nSubItem, nFlags);
}
}
void OnRButtonUp( UINT /*nFlags*/, CPoint point )
@ -2352,7 +2368,7 @@ public:
// notify parent of right-click item
NotifyParent( nItem, nSubItem, LCN_RIGHTCLICK );
}
void OnMouseMove( UINT nFlags, CPoint point )
{
T* pT = static_cast<T*>(this);
@ -2485,6 +2501,8 @@ public:
m_nHotItem = nItem;
m_nHotSubItem = nSubItem;
NotifyParent(nItem, nSubItem, LCN_HOTITEMCHANGED);
}
int nIndex = GetColumnIndex( m_nHotSubItem );

View File

@ -81,6 +81,7 @@
#define LCN_MODIFIED ( LCN_FIRST - 6 )
#define LCN_HYPERLINK ( LCN_FIRST - 7 )
#define LCN_HITTEST ( LCN_FIRST - 8 )
#define LCN_HOTITEMCHANGED ( LCN_FIRST - 9 )
struct CListNotify
{

View File

@ -0,0 +1,57 @@
#pragma once
#include "stdafx.h"
typedef struct {
WORD ctrlId;
char* text;
} _ToolTipMap;
template <class T>
class CToolTipDialog
{
private:
HWND m_hWndTooltip;
public:
CToolTipDialog()
{
}
void AddToolTip(WORD ctrlId, char* lpszText)
{
T* pT = static_cast<T*>(this);
TOOLINFO toolInfo = { 0 };
toolInfo.cbSize = sizeof(toolInfo);
toolInfo.hwnd = pT->m_hWnd;
toolInfo.uFlags = TTF_IDISHWND | TTF_SUBCLASS;
toolInfo.uId = (UINT_PTR) ::GetDlgItem(pT->m_hWnd, ctrlId);
toolInfo.lpszText = lpszText;
SendMessage(m_hWndTooltip, TTM_ADDTOOL, 0, (LPARAM)&toolInfo);
}
void DlgToolTip_Init()
{
T* pT = static_cast<T*>(this);
m_hWndTooltip = CreateWindowEx(NULL, TOOLTIPS_CLASS, NULL,
WS_POPUP | TTS_ALWAYSTIP,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
pT->m_hWnd, NULL,
NULL, NULL);
const _ToolTipMap* map = pT->_GetToolTipMap();
for (int i = 0; map[i].ctrlId != 0; i++)
{
AddToolTip(map[i].ctrlId, map[i].text);
}
}
};
#define BEGIN_TOOLTIP_MAP() static const _ToolTipMap* _GetToolTipMap() { static const _ToolTipMap map[] = {
#define TOOLTIP(ctrlId, text) { ctrlId, text },
#define END_TOOLTIP_MAP() { 0 } }; return map; }

View File

@ -1,8 +1,12 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by UI Resources.rc
// Used by UIResources.rc
//
#define VERSION_REVISION 0
#define VER_VER_DEBUG 0
#define VERSION_MAJOR 2
#define IDAPPLY 3
#define VERSION_MINOR 3
#define IDI_PJ64_Icon 101
#define IDD_Rom_Information 104
#define IDD_Key_Prompt 108
@ -40,17 +44,44 @@
#define IDD_Settings_Config 149
#define IDD_Support_Project64 150
#define IDD_Support_EnterCode 151
#define IDD_Debugger_Commands 152
#define IDR_POPUP 155
#define IDD_Debugger_RegGPR 158
#define IDR_CHEAT_MENU 160
#define IDD_Debugger_AddBreakpoint 160
#define IDD_Lang_Select 161
#define IDD_Settings_GameRecompiler 162
#define IDD_Settings_GamePlugin 163
#define IDD_Settings_GameStatus 164
#define IDD_Debugger_RegFPR 166
#define IDD_Debugger_Scripts 169
#define IDD_Debugger_RegPI 170
#define IDD_Debugger_Symbols 172
#define IDD_Debugger_AddSymbol 174
#define IDR_MEM_BP_POPUP 177
#define IDR_JSAPI_TEXT 181
#define IDD_Debugger_DMALog 182
#define IDD_Debugger_StackTrace 184
#define IDD_Debugger_RegCOP0 185
#define IDR_MENU1 186
#define IDR_SCRIPT_POPUP 186
#define IDR_OP_POPUP 187
#define IDD_Debugger_Stack 191
#define IDD_Debugger_RegSP 192
#define IDD_Debugger_RegMI 193
#define IDD_Debugger_RegAI 194
#define IDD_Debugger_RegSI 195
#define IDD_Debugger_RegRI 196
#define IDD_Debugger_RegDPC 197
#define IDD_Debugger_RegRDRAM 198
#define IDD_Debugger_RegVI 199
#define IDD_Debugger_RegDD 200
#define IDC_MENU_ITEM_TEXT 1000
#define IDC_CLOSE_BUTTON 1001
#define IDC_LIST2 1003
#define IDC_CURRENT_KEYS 1003
#define RSP_LIST 1004
#define IDC_CURRENT_KEYS2 1004
#define RSP_ABOUT 1006
#define IDC_ASSIGN 1006
#define IDC_BTN_CHOOSE_FILE 1006
@ -59,7 +90,6 @@
#define IDC_BTN_RDRAM 1007
#define IDC_REFRSH_MEM 1007
#define IDC_INFO_ROMNAME 1008
#define IDC_BUTTON3 1008
#define IDC_RESET_PAGE 1008
#define IDC_INFO_CARTID 1009
#define IDC_VIRTUALKEY 1009
@ -93,6 +123,7 @@
#define IDC_SMM_DMA 1013
#define IDC_UNKNOWN_ALIGN 1013
#define IDC_DELAY_DP 1013
#define IDC_INTERPRETER 1013
#define IDC_INFO_CRC1 1014
#define IDC_ASSIGNED_MENU_ITEM 1014
#define IDC_TLB_RULES 1014
@ -225,6 +256,7 @@
#define IDC_ZIP 1092
#define IDC_SETTING_INFO 1092
#define IDC_GOOD_NAME_TEXT 1093
#define IDC_SETTING_INFO2 1093
#define IDC_FUNCFIND_TEXT 1094
#define IDC_REMEMBER 1095
#define IDC_GFX_NAME 1095
@ -237,7 +269,6 @@
#define IDC_AUDIO_NAME 1099
#define IDC_ROM_REGCACHE 1099
#define IDC_COUNTPERBYTE_TEXT 1099
#define IDC_BORDER 1099
#define IDC_CONT_NAME 1100
#define IDC_COUNTPERBYTE 1100
#define ID_SUPPORT_PJ64 1100
@ -255,9 +286,15 @@
#define IDC_DIR_FRAME5 1105
#define IDC_MAXROMS_TXT 1111
#define IDC_ROMSEL_TEXT2 1112
#define IDC_R0_EDIT 1112
#define IDC_MAXROMDIR_TXT 1113
#define IDC_CMD_LIST 1113
#define IDC_ROMSEL_TEXT4 1114
#define IDC_R1_EDIT 1114
#define IDC_GO_BTN 1116
#define IDC_UNMARK 1119
#define IDC_STEP_BTN 1119
#define IDC_ADDSYMBOL_BTN 1119
#define IDC_NOTES 1120
#define IDC_CHEAT_LIST 1121
#define IDC_CHEAT_NAME 1122
@ -269,28 +306,45 @@
#define IDC_USE_ROMBROWSER 1133
#define IDC_USING 1134
#define IDC_AVALIABLE 1135
#define IDC_R2_EDIT 1135
#define IDC_R3_EDIT 1136
#define IDC_REMOVE 1137
#define IDC_R4_EDIT 1137
#define IDC_RECURSION 1138
#define IDC_R5_EDIT 1138
#define IDC_R6_EDIT 1139
#define IDC_R7_EDIT 1140
#define IDC_V64 1141
#define IDC_R8_EDIT 1141
#define IDC_LOAD_FULLSCREEN 1142
#define IDC_Z64 1142
#define IDC_R9_EDIT 1142
#define IDC_ROMSEL_TEXT5 1143
#define IDC_REMEMBER_CHEAT 1143
#define IDC_N64 1143
#define IDC_R10_EDIT 1143
#define IDC_ROMSEL_TEXT6 1144
#define IDC_SCREEN_SAVER 1144
#define IDC_ROM 1144
#define IDC_CHECK_RUNNING 1144
#define IDC_R11_EDIT 1144
#define IDC_BASIC_MODE 1145
#define IDC_JAP 1145
#define IDC_UNIQUE_SAVE_DIR 1145
#define IDC_R12_EDIT 1145
#define IDC_PAL 1146
#define IDC_R13_EDIT 1146
#define IDC_USA 1147
#define IDC_R14_EDIT 1147
#define IDC_R15_EDIT 1148
#define IDC_SHELL_INT_TEXT 1149
#define IDC_RDB_HOME 1150
#define IDC_SHELL_INT_TEXT2 1150
#define IDC_COUNTFACT 1151
#define IDC_CHT_HOME 1151
#define IDC_SHELL_INT_TEXT3 1151
#define IDC_RDX_HOME 1152
#define IDC_SHELL_INT_TEXT4 1152
#define IDC_MEMORY_SIZE_TEXT 1153
#define IDC_SAVE_TYPE_TEXT 1154
#define IDC_LAN 1154
@ -307,15 +361,39 @@
#define IDC_CHT_AUTHOR 1163
#define IDC_CHT_VERSION 1164
#define IDC_CHT_DATE 1165
#define IDC_R16_EDIT 1165
#define IDC_RDX 1166
#define IDC_R17_EDIT 1166
#define IDC_RDX_AUTHOR 1167
#define IDC_R18_EDIT 1167
#define IDC_RDX_VERSION 1168
#define IDC_R19_EDIT 1168
#define IDC_RDX_DATE 1169
#define IDC_R20_EDIT 1169
#define IDC_R21_EDIT 1170
#define IDC_R22_EDIT 1171
#define IDC_NEWCHEAT 1172
#define IDC_R23_EDIT 1172
#define IDC_R24_EDIT 1173
#define IDC_R25_EDIT 1174
#define IDC_R26_EDIT 1175
#define IDC_R27_EDIT 1176
#define IDC_R28_EDIT 1177
#define IDC_INFO_LOCATION 1178
#define IDC_CHEAT_CODES 1178
#define IDC_R29_EDIT 1178
#define IDC_STATE 1179
#define IDC_R30_EDIT 1179
#define IDC_R31_EDIT 1180
#define IDC_HI_EDIT 1183
#define IDC_LO_EDIT 1184
#define IDC_BP_LIST 1185
#define IDC_CTX_INFO_EDIT 1185
#define IDC_ADDBP_BTN 1186
#define IDC_REMOVESYMBOL_BTN 1186
#define IDC_RMBP_BTN 1187
#define IDC_CHEATSFRAME 1188
#define IDC_CLEARBP_BTN 1188
#define IDC_ADDCHEATSFRAME 1189
#define IDC_CHEAT_OPTIONS 1190
#define IDC_ROM_NAME 1191
@ -324,6 +402,7 @@
#define IDC_LABEL_OPTIONS_FORMAT 1192
#define IDC_LOCATION 1193
#define IDC_ROM_SIZE 1194
#define IDC_REG_TABS 1194
#define IDC_CART_ID 1195
#define IDC_MANUFACTURER 1196
#define IDC_COUNTRY 1197
@ -332,16 +411,220 @@
#define IDC_CIC_CHIP 1200
#define IDC_ROM_MD5 1201
#define IDC_NOTESFRAME 1201
#define IDC_CHK_READ 1201
#define IDC_CHK_WRITE 1203
#define IDC_CHK_EXEC 1204
#define IDC_F0_EDIT 1204
#define IDC_NOTE 1205
#define IDC_F1_EDIT 1205
#define IDC_DIGITAL_TEXT 1206
#define IDC_F2_EDIT 1206
#define IDC_VALUE_TEXT 1207
#define IDC_F3_EDIT 1207
#define IDC_NOTES_TEXT 1208
#define IDC_F4_EDIT 1208
#define IDC_F5_EDIT 1209
#define IDC_F6_EDIT 1210
#define IDC_F7_EDIT 1211
#define IDC_F8_EDIT 1212
#define IDC_F9_EDIT 1213
#define IDC_F10_EDIT 1214
#define IDC_F11_EDIT 1215
#define IDC_F12_EDIT 1216
#define IDC_F13_EDIT 1217
#define IDC_F14_EDIT 1218
#define IDC_LANG_SEL 1219
#define IDC_F15_EDIT 1219
#define IDC_IPL_DIR 1220
#define IDC_F16_EDIT 1220
#define IDC_SELECT_IPL_DIR 1221
#define IDC_F17_EDIT 1221
#define IDC_IPLDIR_TXT 1222
#define IDC_F18_EDIT 1222
#define IDC_F19_EDIT 1223
#define IDC_F20_EDIT 1224
#define IDC_F21_EDIT 1225
#define IDC_F22_EDIT 1226
#define IDC_F23_EDIT 1227
#define IDC_F24_EDIT 1228
#define IDC_F25_EDIT 1229
#define IDC_F26_EDIT 1230
#define IDC_F27_EDIT 1231
#define IDC_F28_EDIT 1232
#define IDC_F29_EDIT 1233
#define IDC_F30_EDIT 1234
#define IDC_F31_EDIT 1235
#define IDC_SKIP_BTN 1268
#define IDC_CONSOLE_EDIT 1271
#define IDC_FILTER_EDIT 1271
#define IDC_EVAL_EDIT 1272
#define IDC_PI00_EDIT 1274
#define IDC_PI04_EDIT 1275
#define IDC_PI08_EDIT 1276
#define IDC_PI0C_EDIT 1277
#define IDC_PI10_EDIT 1278
#define IDC_PI14_EDIT 1279
#define IDC_PI18_EDIT 1280
#define IDC_PI1C_EDIT 1281
#define IDC_PI20_EDIT 1282
#define IDC_PI24_EDIT 1283
#define IDC_PI28_EDIT 1284
#define IDC_PI2C_EDIT 1285
#define IDC_PI30_EDIT 1286
#define IDC_STACK_LIST 1288
#define IDC_SYMBOLS_LIST 1290
#define IDC_SYMBOLS_BTN 1291
#define IDC_DESC_EDIT 1292
#define IDC_TYPE_COMBOBOX 1293
#define IDC_OPCODE_BOX 1295
#define IDC_NAME_EDIT 1296
#define IDC_SCRIPT_LIST 1297
#define IDC_DMA_LIST 1300
#define IDC_CLEAR_BTN 1302
#define IDC_DMA_RAM_EDIT 1303
#define IDC_COPY_BTN 1303
#define IDC_BUTTON1 1305
#define IDC_DMA_ROM_EDIT 1306
#define IDC_TRACE_STATIC 1307
#define IDC_RAM_STATIC 1308
#define IDC_ROM_STATIC 1309
#define IDC_STACKTRACE_LIST 1313
#define IDC_OP_EDIT 1314
#define IDC_COP0_0_EDIT 1315
#define IDC_COP0_1_EDIT 1316
#define IDC_COP0_2_EDIT 1317
#define IDC_COP0_3_EDIT 1318
#define IDC_COP0_4_EDIT 1319
#define IDC_COP0_5_EDIT 1320
#define IDC_COP0_6_EDIT 1321
#define IDC_COP0_7_EDIT 1322
#define IDC_COP0_8_EDIT 1323
#define IDC_COP0_9_EDIT 1324
#define IDC_COP0_10_EDIT 1325
#define IDC_COP0_11_EDIT 1326
#define IDC_COP0_12_EDIT 1327
#define IDC_COP0_13_EDIT 1328
#define IDC_COP0_14_EDIT 1329
#define IDC_COP0_15_EDIT 1330
#define IDC_COP0_16_EDIT 1331
#define IDC_COP0_17_EDIT 1332
#define IDC_COP0_18_EDIT 1333
#define IDC_FILTER_STATIC 1339
#define IDC_SYM_INFO 1348
#define IDC_BLOCK_INFO 1350
#define IDC_DMA_INFO 1351
#define IDC_BACK_BTN 1352
#define IDC_FORWARD_BTN 1353
#define IDC_PC_EDIT 1354
#define IDC_VIEWPC_BTN 1355
#define IDC_PC_STATIC 1356
#define IDC_SP_STATIC 1358
#define IDC_MEM_BTN 1359
#define IDC_CAUSE_TIP 1361
#define IDC_EDIT1 1362
#define IDC_FCSR_EDIT 1362
#define IDC_SP00_EDIT 1363
#define IDC_SP04_EDIT 1364
#define IDC_SP08_EDIT 1365
#define IDC_SP0C_EDIT 1366
#define IDC_SP10_EDIT 1367
#define IDC_SP14_EDIT 1368
#define IDC_SP18_EDIT 1369
#define IDC_SP1C_EDIT 1370
#define IDC_SP_PC_EDIT 1371
#define IDC_SI00_EDIT 1372
#define IDC_SI04_EDIT 1373
#define IDC_SI08_EDIT 1374
#define IDC_SI0C_EDIT 1375
#define IDC_AI00_EDIT 1376
#define IDC_AI04_EDIT 1377
#define IDC_AI08_EDIT 1378
#define IDC_AI0C_EDIT 1379
#define IDC_AI10_EDIT 1380
#define IDC_AI14_EDIT 1381
#define IDC_MI00_EDIT 1382
#define IDC_MI04_EDIT 1383
#define IDC_MI08_EDIT 1384
#define IDC_MI0C_EDIT 1385
#define IDC_RI00_EDIT 1386
#define IDC_RI04_EDIT 1387
#define IDC_RI08_EDIT 1388
#define IDC_RI0C_EDIT 1389
#define IDC_RI10_EDIT 1390
#define IDC_RI14_EDIT 1391
#define IDC_RI18_EDIT 1392
#define IDC_RI1C_EDIT 1393
#define IDC_DPC00_EDIT 1394
#define IDC_DPC04_EDIT 1395
#define IDC_DPC08_EDIT 1396
#define IDC_DPC0C_EDIT 1397
#define IDC_DPC10_EDIT 1398
#define IDC_DPC14_EDIT 1399
#define IDC_DPC18_EDIT 1400
#define IDC_DPC1C_EDIT 1401
#define IDC_RDRAM00_EDIT 1402
#define IDC_RDRAM04_EDIT 1403
#define IDC_RDRAM08_EDIT 1404
#define IDC_RDRAM0C_EDIT 1405
#define IDC_RDRAM10_EDIT 1406
#define IDC_RDRAM14_EDIT 1407
#define IDC_RDRAM18_EDIT 1408
#define IDC_RDRAM1C_EDIT 1409
#define IDC_RDRAM20_EDIT 1410
#define IDC_RDRAM24_EDIT 1411
#define IDC_VI00_EDIT 1412
#define IDC_VI04_EDIT 1413
#define IDC_VI08_EDIT 1414
#define IDC_VI0C_EDIT 1415
#define IDC_VI10_EDIT 1416
#define IDC_VI14_EDIT 1417
#define IDC_VI18_EDIT 1418
#define IDC_VI1C_EDIT 1419
#define IDC_VI20_EDIT 1420
#define IDC_VI24_EDIT 1421
#define IDC_VI28_EDIT 1422
#define IDC_VI2C_EDIT 1423
#define IDC_VI30_EDIT 1424
#define IDC_VI34_EDIT 1425
#define IDC_DD00_EDIT 1426
#define IDC_DD04_EDIT 1427
#define IDC_DD08_EDIT 1428
#define IDC_DD0C_EDIT 1429
#define IDC_DD10_EDIT 1430
#define IDC_DD14_EDIT 1431
#define IDC_DD18_EDIT 1432
#define IDC_DD1C_EDIT 1433
#define IDC_DD20_EDIT 1434
#define IDC_DD24_EDIT 1435
#define IDC_DD28_EDIT 1436
#define IDC_DD2C_EDIT 1437
#define IDC_DD30_EDIT 1438
#define IDC_DD34_EDIT 1439
#define IDC_DD38_EDIT 1440
#define IDC_DD3C_EDIT 1441
#define IDC_DD40_EDIT 1442
#define IDC_DD44_EDIT 1443
#define IDC_DD48_EDIT 1444
#define VERSION_BUILD 9999
#define ID_POPUP_SHOWINMEMORYVIEWER 40005
#define ID_POPUPMENU_PLAYGAMEWITHDISK 40008
#define ID_POPUPMENU_ADDSYMBOL 40013
#define ID_POPUPMENU_VIEWDISASM 40017
#define ID_POPUPMENU_CLEARALLBPS 40019
#define ID_POPUPMENU_TOGGLERBP 40020
#define ID_POPUPMENU_TOGGLEWBP 40021
#define ID_POPUP_RUN 40024
#define ID_POPUP_STOP 40025
#define ID_POPUPMENU_INSERTNOP 40026
#define ID_POPUPMENU_RESTORE 40027
#define ID_POPUPMENU_RESTOREALL 40029
#define ID_POPUPMENU_EDIT 40030
#define ID_POPUPMENU_FOLLOWJUMP 40032
#define ID_POPUPMENU_RUNTO 40034
#define ID_Menu 40035
#define ID_POPUPMENU_VIEWMEMORY 40036
#define ID_POPUPMENU_TOGGLEBP 40039
#define ID_POPUPMENU_CLEARBPS 40040
#define ID_POPUPMENU_ROMDIRECTORY 40137
#define ID_POPUPMENU_REFRESHROMLIST 40138
#define ID_POPUPMENU_PLAYGAME 40152
@ -356,9 +639,9 @@
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 153
#define _APS_NEXT_COMMAND_VALUE 40009
#define _APS_NEXT_CONTROL_VALUE 1104
#define _APS_NEXT_SYMED_VALUE 101
#define _APS_NEXT_RESOURCE_VALUE 194
#define _APS_NEXT_COMMAND_VALUE 40041
#define _APS_NEXT_CONTROL_VALUE 1445
#define _APS_NEXT_SYMED_VALUE 102
#endif
#endif

View File

@ -147,8 +147,8 @@ int DisplayRSPCommand (DWORD location, int InsertPos)
RSPCommandLine[InsertPos].Location = location;
RSPCommandLine[InsertPos].status = status;
RSPCommandLine[InsertPos].opcode = OpCode;
sprintf(RSPCommandLine[InsertPos].String," 0x%03X\t%s",location,
RSPOpcodeName ( OpCode, location ));
sprintf(RSPCommandLine[InsertPos].String," 0x%04X\t%s",0x1000 | location,
RSPOpcodeName ( OpCode, 0x1000 | location ));
if ( SendMessage(hList,LB_GETCOUNT,0,0) <= InsertPos)
{
SendMessage(hList,LB_INSERTSTRING,(WPARAM)InsertPos, (LPARAM)location);
@ -471,7 +471,7 @@ void Paint_RSP_Commands (HWND hDlg)
TextOut( ps.hdc, 97,16,"Instruction",11);
TextOut( ps.hdc, 180,16,"Arguments",9);
TextOut( ps.hdc, 354,2," Address ",9);
TextOut( ps.hdc, 358,19,"0x",2);
TextOut( ps.hdc, 358,19,"0x1",3);
SelectObject( ps.hdc,hOldFont );
SetBkMode( ps.hdc, OldBkMode );
@ -1004,18 +1004,18 @@ char * RSPRegimmName ( DWORD OpCode, DWORD PC )
{ /* MIPS pseudo-instruction: BAL (Branch and Link) */
sprintf(
CommandName,
"BAL\t0x%03X",
(PC + ((short)command.offset << 2) + 4) & 0xFFC
"BAL\t0x%04X",
(PC + ((short)command.offset << 2) + 4) & 0x1FFC
);
}
else
{
sprintf(
CommandName,
"%s\t%s, 0x%03X",
"%s\t%s, 0x%04X",
mnemonics_regimm[command.rt],
GPR_Name(command.rs),
(PC + ((short)command.offset << 2) + 4) & 0xFFC
(PC + ((short)command.offset << 2) + 4) & 0x1FFC
);
}
return CommandName;
@ -1210,44 +1210,44 @@ char * RSPOpcodeName ( DWORD OpCode, DWORD PC )
break;
case RSP_J:
case RSP_JAL:
sprintf(CommandName, "%s\t0x%03X",
sprintf(CommandName, "%s\t0x%04X",
mnemonics_primary[command.op],
(command.target << 2) & 0xFFC
(command.target << 2) & 0x1FFC
);
break;
case RSP_BEQ:
if (command.rs == 0 && command.rt == 0)
{
sprintf(CommandName, "%s\t0x%03X",
sprintf(CommandName, "%s\t0x%04X",
"B",
(PC + ((short)command.offset << 2) + 4) & 0xFFC
(PC + ((short)command.offset << 2) + 4) & 0x1FFC
);
break;
}
else if (command.rs == 0 || command.rt == 0)
{
sprintf(CommandName, "%s\t%s, 0x%03X",
sprintf(CommandName, "%s\t%s, 0x%04X",
"BEQZ",
GPR_Name(command.rs == 0 ? command.rt : command.rs),
(PC + ((short)command.offset << 2) + 4) & 0xFFC
(PC + ((short)command.offset << 2) + 4) & 0x1FFC
);
break;
}
/* else { fall through to show the full BEQ } */
case RSP_BNE:
sprintf(CommandName, "%s\t%s, %s, 0x%03X",
sprintf(CommandName, "%s\t%s, %s, 0x%04X",
mnemonics_primary[command.op],
GPR_Name(command.rs),
GPR_Name(command.rt),
(PC + ((short)command.offset << 2) + 4) & 0xFFC
(PC + ((short)command.offset << 2) + 4) & 0x1FFC
);
break;
case RSP_BLEZ:
case RSP_BGTZ:
sprintf(CommandName, "%s\t%s, 0x%03X",
sprintf(CommandName, "%s\t%s, 0x%04X",
mnemonics_primary[command.op],
GPR_Name(command.rs),
(PC + ((short)command.offset << 2) + 4) & 0xFFC
(PC + ((short)command.offset << 2) + 4) & 0x1FFC
);
break;
case RSP_ADDI:

View File

@ -368,13 +368,11 @@ LRESULT CALLBACK RefreshRSP_RegProc ( HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
PaintRSP_Vector2_Panel (hWnd);
break;
}
}
break;
default:
return( (*RefreshProc)(hWnd, uMsg, wParam, lParam) );
}
return( FALSE );
return CallWindowProc(RefreshProc, hWnd, uMsg, wParam, lParam);
}
LRESULT CALLBACK RSP_Registers_Proc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {

691
apidoc.htm Normal file
View File

@ -0,0 +1,691 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Project64d JS API</title>
<link href='https://fonts.googleapis.com/css?family=Open+Sans:400,400italic,700,700italic' rel='stylesheet' type='text/css'>
<style>
body {
font-family: "Open Sans", segoe ui, tahoma, sans;
font-size: 14px;
background-color: #EEE;
}
a {
color: #494;
text-decoration: none;
font-weight: bold;
}
div.inline-content {
display: inline-block;
vertical-align: top;
}
div.panel {
background-color: #FFF;
padding: 10px;
border-top: 4px solid #FFAAAA;
margin-bottom: 10px;
box-shadow: -5px 5px 5px #DDD;
}
div.classname {
font-weight: bold;
font-size: 18px;
}
div.propertyname {
font-weight: bold;
}
div.property {
padding: 10px;
}
div.propertydesc {
padding: 10px;
}
pre.example {
background-color: #EFE;
border: 1px solid #BCB;
padding: 5px;
font-family: consolas, courier new, monospace;
white-space: pre;
margin: 10px;
font-size: 12px;
color: #020;
}
pre.example::before {
content: "Example";
float: right;
opacity: 0.5;
font-size: 11px;
font-family: "Open Sans", segoe ui, tahoma, sans;
}
span.snip {
background-color: #EFE;
border: 1px solid #BCB;
padding: 0px 2px;
font-size: 13px;
color: #020;
font-family: consolas, courier new, monospace;
border-radius: 3px;
}
span.tag {
float: right;
margin-left: 2px;
border: 2px solid #885;
border-radius: 5px;
background-color: #FFE;
color: #885;
font-weight: bold;
padding: 0px 2px;
font-size: 12px;
}
span.tag2 {
float: right;
margin-left: 2px;
border: 2px solid #588;
border-radius: 5px;
background-color: #EFF;
color: #588;
font-weight: bold;
padding: 0px 2px;
font-size: 12px;
}
</style>
</head>
<body>
<div style="margin: 10px; font-size: 24px;">Project64d Javascript API</div>
<div class="inline-content" style="width: 150px; min-width: 150px; margin-left: 10px;">
<div class="panel" id="sidebar" style="width: 120px; position: absolute;">
<a href="#mem">mem</a><br>
<a href="#rom">rom</a><br>
<a href="#events">events</a><br>
<a href="#debug">debug</a><br>
<a href="#console">console</a><br>
<a href="#alert">alert</a><br>
<a href="#screen">screen</a><br>
<a href="#gpr">gpr</a><br>
<a href="#ugpr">ugpr</a><br>
<a href="#fpr">fpr</a><br>
<a href="#dfpr">dfpr</a><br>
<a href="#Server">Server</a><br>
<a href="#Socket">Socket</a><br>
<a href="#AddressRange">AddressRange</a><br>
<a href="#Number">Number</a><br>
</div>
</div>
<div class="inline-content" style="max-width: 700px;">
<div class="panel" id="mem">
<div class="classname">mem</div>
<div class="property">
<div class="propertyname">mem.u8|u16|u32|s8|s16|s32|float|double</div>
<div class="propertydesc">
Arrays for reading and modifying values in virtual memory.
Virtual addresses are always used for indeces regardless of type size.
<pre class="example">
var addr_power = 0x8033B21E
if(mem.u8[addr_power] &lt; 1)
{
mem.u8[addr_power] = 8
}
</pre>
</div>
</div>
<div class="property">
<div class="propertyname">mem.getblock(baseAddr, size)</div>
<div class="propertydesc">
Returns a Buffer object from a block of data of <span class="snip">size</span> bytes at <span class="snip">baseAddr</span> in virtual memory.
</div>
</div>
<div class="property">
<div class="propertyname">mem.getstring(baseAddr[, maxLen])</div>
<div class="propertydesc">
Returns a string from a zero-terminated ASCII string at <span class="snip">baseAddr</span> in virtual memory.
</div>
</div>
<div class="property">
<div class="propertyname">mem.bindvar(obj, baseAddr, name, type)</div>
<div class="propertydesc">
Adds property <span class="snip">name</span> to <span class="snip">obj</span> and "binds" it to the virtual address specified by <span class="snip">baseAddr</span>.
Valid types are: <span class="snip">u8</span>, <span class="snip">u16</span>, <span class="snip">u32</span>, <span class="snip">s8</span>, <span class="snip">s16</span>, <span class="snip">s32</span>, <span class="snip">float</span>, and <span class="snip">double</span>.
<pre class="example">
mem.bindvar(this, 0x8033B21E, 'power', u8)
if(power &lt; 1)
{
power = 8
}
</pre>
</div>
</div>
<div class="property">
<div class="propertyname">mem.bindvars(obj, vars)</div>
<div class="propertydesc">
Adds multiple virtual memory-bound properties to <span class="snip">obj</span>.
Returns <span class="snip">obj</span>.
<pre class="example">
var mario = mem.bindvars({},
[
[0x8033B1B0, 'y', float],
[0x8033B21E, 'power', u8]
])
mario.power = 5
mario.y = 500.00
</pre>
</div>
</div>
<div class="property">
<div class="propertyname">mem.bindstruct(obj, baseAddr, props)</div>
<div class="propertydesc">
Adds multiple virtual memory-bound properties to <span class="snip">obj</span>.
Addresses are determined by type sizes.
Returns <span class="snip">obj</span>.
<pre class="example">
var marioPos = mem.bindstruct(this, 0x8033B1AC,
{
x: float,
y: float,
z: float
})
</pre>
</div>
</div>
<div class="property">
<div class="propertyname">mem.typedef(props)</div>
<div class="propertydesc">
Returns a "struct" class that may be constructed using the address of a real struct in virtual memory.
<pre class="example">
const Player = mem.typedef(
{
health: u32,
x: float,
y: float,
z: float
})
Player.prototype.move = function(x, y, z)
{
this.x = x
this.y = y
this.z = z
}
Player.prototype.heal = function()
{
this.health = 100;
}
var player = new Player(0x8033B1AC)
player.move(100, 200, 300)
player.heal()
</pre>
</div>
</div>
</div>
<div class="panel" id="rom">
<div class="classname">rom</div>
<div class="property">
<div class="propertyname">rom.u8|u16|u32|s8|s16|s32|float|double</div>
<div class="propertydesc">
Arrays for reading values in cartridge ROM. Indexing works in a similar manner to <a href="#mem">mem</a>'s.
<pre class="example">
var crc1 = rom.u32[0x00000010]
var crc2 = rom.u32[0x00000014]
</pre>
</div>
</div>
<div class="property">
<div class="propertyname">rom.getblock(baseAddr, size)</div>
<div class="propertydesc">
Returns a Buffer object from a block of data of size bytes at <span class="snip">baseAddr</span> in cartridge ROM.
</div>
</div>
<div class="property">
<div class="propertyname">rom.getstring(baseAddr[, maxLen])</div>
<div class="propertydesc">
Returns a string from a zero-terminated ASCII string at <span class="snip">baseAddr</span> in cartridge ROM.
<pre class="example">
var romName = rom.getstring(0x00000020)
console.log('Internal ROM name: ' + romName)</div>
</div>
</div>
<div class="panel" id="events">
<div class="classname">events</div>
<!--
<div class="property">
<div class="propertyname">events.on(hook, callback, tag)</div>
<div class="propertydesc">
<pre class="example"></pre>
</div>
</div>-->
<div class="property">
<span class="tag2">emulation thread</span>
<span class="tag">interpreter mode</span>
<div class="propertyname">events.onexec(address, callback)</div>
<div class="propertydesc">
Adds a CPU execution callback for a virtual address or <a href="AddressRange">AddressRange</a> and returns a callback ID.
<span class="snip">callback</span> will be invoked at the beginning of a CPU step if the program counter is at <span class="snip">address</span>.
<span class="snip">callback</span> receives the program counter address at which the event is fired.
<pre class="example">
events.onexec(0x802CB1C0, function()
{
console.log('CPU is calling 0x802CB1C0')
})
</pre>
<pre class="example">
events.onexec(ADDR_ANY, function(addr))
{
// Log every step!
console.log('CPU is executing ' + addr.hex())
})
</pre>
</div>
</div>
<div class="property">
<span class="tag2">emulation thread</span>
<span class="tag">interpreter mode</span>
<div class="propertyname">events.onread(address, callback)</div>
<div class="propertydesc">
Adds a CPU read callback for a virtual address or <a href="AddressRange">AddressRange</a> and returns a callback ID.
<span class="snip">callback</span> will be invoked at the beginning of a CPU step if the current instruction is going to read from <span class="snip">address</span>.
<span class="snip">callback</span> receives the virtual address that the CPU is going to read.
<pre class="example">
events.onread(0x8033B1B0, function()
{
console.log('CPU is reading 8033B1B0')
})
</pre>
<pre class="example">
const addr_range_rom = {start: 0xB0000000, end: 0xB6000000}
events.onread(addr_range_rom, function(addr)
{
console.log('CPU is reading ROM ' + addr)
})
</pre>
</div>
</div>
<div class="property">
<span class="tag2">emulation thread</span>
<span class="tag">interpreter mode</span>
<div class="propertyname">events.onwrite(address, callback)</div>
<div class="propertydesc">
Adds a CPU write callback for a virtual address or <a href="AddressRange">AddressRange</a> and returns a callback ID.
<span class="snip">callback</span> will be invoked at the beginning of a CPU step if the current instruction is going to write to <span class="snip">address</span>.
<span class="snip">callback</span> receives the virtual address that the CPU is going to write to.
<pre class="example">
events.onwrite(0x8033B1B0, function()
{
console.log('CPU is modifying 8033B1B0')
})
</pre>
<pre class="example">
events.onwrite({0xB0000000, 0x90000000}, function(addr)
{
console.log(gpr.pc.hex() + ': wrote to cartridge ' + addr.hex());
})
</pre>
</div>
</div>
<div class="property">
<span class="tag2">emulation thread</span>
<div class="propertyname">events.ondraw(callback)</div>
<div class="propertydesc">
Adds a callback which will be invoked immediately after Project64 requests a screen update from the graphics plugin.
Returns a callback ID.
<pre class="example">
events.ondraw(function()
{
console.log('Frame drawn')
})
</pre>
</div>
</div>
<div class="property">
<div class="propertyname">events.remove(callbackId)</div>
<div class="propertydesc">
Removes a registered callback by its ID.
<pre class="example">
var callbackId = events.onexec(0x80000180, function()
{
// Only invoked once
console.log('Interrupt fired')
events.remove(callbackId)
})
</pre>
</div>
</div>
<!-- template
<div class="property">
<div class="propertyname"></div>
<div class="propertydesc">
<pre class="example"></pre>
</div>
</div>
-->
</div>
<div class="panel" id="debug">
<div class="classname">debug</div>
<div class="property">
<div class="propertyname">debug.breakhere()</div>
<div class="propertydesc">
Pauses emulation and opens the debugger window. Useful for creating conditional breakpoints.
<pre class="example">
events.onexec(0x802CB1C0, function()
{
if(gpr.a0 == 0)
{
console.log('0 passed to 0x802CB1C0, breaking')
debug.breakhere()
}
})
</pre>
</div>
</div>
</div>
<div class="panel" id="console">
<div class="classname">console</div>
<div class="property">
<div class="propertyname">console.print(text)</div>
<div class="propertydesc">
Prints text to the script console.
<pre class="example">console.print('Hello world\n')</pre>
</div>
</div>
<div class="property">
<div class="propertyname">console.log(text[, text2, ...])</div>
<div class="propertydesc">
Concatenates all provided text arguments with spaces and prints the result to the script console with a trailing newline.
<pre class="example">console.log('Hello', 'world')</pre>
</div>
</div>
<div class="property">
<div class="propertyname">console.clear()</div>
<div class="propertydesc">
Clears all previously printed text from the script console.
</div>
</div>
</div>
<div class="panel" id="alert">
<div class="classname">alert</div>
<div class="property">
<div class="propertyname">alert(message[, caption])</div>
<div class="propertydesc">
Shows a message box with an optional caption.
The calling thread will be blocked until the message box is dismissed.
<pre class="example">
alert('Hello world') // Blocks the script's thread
events.onexec(0x80000180, function()
{
alert('Interrupt fired!') // Blocks the emulation thread
})</pre>
</div>
</div>
</div>
<div class="panel" id="screen">
<div class="classname">screen</div>
<div class="property">
<div class="propertyname">screen.print(x, y, text)</div>
<div class="propertydesc">
Prints <span class="snip">text</span> to the screen at the provided <span class="snip">x</span> and <span class="snip">y</span> coordinates.
Should be called from an <span class="snip">events.ondraw</span> callback.
<b>(Unstable!)</b>
<pre class="example">
events.ondraw(function()
{
screen.print(20, 20, "power: ' + mem.u8[0x8033B21E])
})</pre>
</div>
</div>
</div>
<div class="panel" id="gpr">
<div class="classname">gpr</div>
<div class="property">
<div class="propertyname">gpr.r0|at|v0|v1|a0 ...</div>
<div class="propertyname">gpr[0|1|2 ...]</div>
<div class="propertydesc">
Variables representing the lower 32 bits of each general purpose register.
<pre class="example">
events.onexec(0x802CB1C0, function()
{
if(gpr.a0 == 2)
{
gpr.a0 = 3
}
})
</pre>
</div>
</div>
<div class="property">
<div class="propertyname">gpr.pc</div>
<div class="propertydesc">
Variable representing the CPU's program counter.
</div>
</div>
<div class="property">
<div class="propertyname">gpr.hi</div>
<div class="propertydesc">
Variable representing the lower 32 bits of the HI register.
</div>
</div>
<div class="property">
<div class="propertyname">gpr.lo</div>
<div class="propertydesc">
Variable representing the lower 32 bits of the LO register.
</div>
</div>
</div>
<div class="panel" id="ugpr">
<div class="classname">ugpr</div>
<div class="property">
<div class="propertyname">ugpr.r0|at|v0|v1|a0 ...</div>
<div class="propertyname">ugpr[0|1|2 ...]</div>
<div class="propertydesc">
Variables representing the upper 32 bits of each general purpose register.
</div>
</div>
<div class="property">
<div class="propertyname">ugpr.hi</div>
<div class="propertydesc">
Variable representing the upper 32 bits of the HI register.
</div>
</div>
<div class="property">
<div class="propertyname">ugpr.lo</div>
<div class="propertydesc">
Variable representing the upper 32 bits of the LO register.
</div>
</div>
</div>
<div class="panel" id="fpr">
<div class="classname">fpr</div>
<div class="property">
<div class="propertyname">fpr.f0|f1|f2|f3|f4 ...</div>
<div class="propertyname">fpr[0|1|2 ...]</div>
<div class="propertydesc">
Variables representing the 32-bit floating point registers.
<pre class="example">
events.onexec(0x802CB1C0, function()
{
if(gpr.f0 == 2.0)
{
gpr.f0 = 3.0
}
})
</pre>
</div>
</div>
</div>
<div class="panel" id="dfpr">
<div class="classname">dfpr</div>
<div class="property">
<div class="propertyname">dfpr.f0|f2|f4|f6 ...</div>
<div class="propertyname">dfpr[0|2|4 ...]</div>
<div class="propertydesc">
Variables representing the 64-bit floating point registers.
</div>
</div>
</div>
<div class="panel" id="Server">
<div class="classname">Server</div>
<div class="property">
<div class="propertyname">new Server(settings)</div>
<div class="propertydesc">
Creates a new server socket.
If <span class="snip">port</span> is provided in <span class="snip">settings</span>, the server will start listening immediately.
<pre class="example">var server = new Server({port: 80})</pre>
</div>
</div>
<div class="property">
<div class="propertyname">server.listen(port)</div>
<div class="propertydesc">
Binds the server socket to a port and starts listening.
</div>
</div>
<div class="property">
<div class="propertyname">server.on('connection', callback)</div>
<div class="propertydesc">
Starts accepting clients.
When a client is accepted, a Socket object for it is created and passed to <span class="snip">callback</span>.
<pre class="example">
server.on('connection', function(socket)
{
socket.on('data', function(data)
{
socket.write('hello')
})
})</pre>
</div>
</div>
<!--
server.listen(port)
server.on(evt, callback)
'connection' -> callback(socket)-->
</div>
<div class="panel" id="Socket">
<div class="classname">Socket</div>
<div class="property">
<div class="propertyname">new Socket([fd])</div>
<div class="propertydesc">
Creates a new socket object.
</div>
</div>
<div class="property">
<div class="propertyname">socket.connect(settings[, callback])</div>
<div class="propertydesc">
Connects the socket to the <span class="snip">host</span> and <span class="snip">port</span> specified by the <span class="snip">settings</span> object.
The default values for the host and port are <span class="snip">"127.0.0.1"</span> and <span class="snip">80</span> respectively.
</div>
</div>
<div class="property">
<div class="propertyname">socket.write(data[, callback])</div>
<div class="propertydesc">
Writes <span class="snip">data</span> to the socket.
</div>
</div>
<div class="property">
<div class="propertyname">socket.on('data', callback)</div>
<div class="propertydesc">
Starts reading data from the socket asynchronously. When data arrives, it is passed to <span class="snip">callback</span> as a Buffer object.
<!--<pre class="example"></pre>-->
</div>
</div>
<div class="property">
<div class="propertyname">socket.on('close', callback)</div>
<div class="propertydesc">
</div>
</div>
</div>
<div class="panel" id="AddressRange">
<div class="classname">AddressRange</div>
<div class="property">
<div class="propertyname">new AddressRange(start, end)</div>
<div class="propertydesc">
Creates an immutable object with <span class="snip">start</span> and <span class="snip">end</span> address properties.<br>
The following <b>AddressRange</b> objects are defined globally:
<pre>
<b>ADDR_ANY</b> 0x00000000 : 0x100000000 Any 32-bit address
<b>ADDR_ANY_KUSEG</b> 0x00000000 : 0x80000000 MIPS user mode TLB mapped segment
<b>ADDR_ANY_KSEG0</b> 0x80000000 : 0xA0000000 MIPS cached unmapped segment
<b>ADDR_ANY_KSEG1</b> 0xA0000000 : 0xC0000000 MIPS uncached unmapped segment
<b>ADDR_ANY_KSEG2</b> 0xC0000000 : 0x100000000 MIPS kernel mode TLB mapped segment
<b>ADDR_ANY_RDRAM</b> 0x80000000 : 0x80800000 Cached RDRAM
<b>ADDR_ANY_RDRAM_UNC</b> 0xA0000000 : 0xA0800000 Uncached RDRAM
<b>ADDR_ANY_CART_ROM</b> 0x90000000 : 0x96000000 Cached cartridge ROM
<b>ADDR_ANY_CART_ROM_UNC</b> 0xB0000000 : 0xB6000000 Uncached cartridge ROM
</pre>
</div>
</div>
</div>
<div class="panel" id="Number">
<div class="classname">Number</div>
<div class="property">
<div class="propertyname">number.hex([nChars])</div>
<div class="propertydesc">
Returns a hexadecimal string representation of the number object. The resulting string is prepended with zeroes until its character length meets <span class="snip">nChars</span> or 8 by default.
<pre class="example">
var sm64EntryPC = rom.u32[0x00000008]
console.log("Entry: " + sm64EntryPC.hex()) // "Entry: 80246000"</pre>
</div>
</div>
</div>
<!--
<div class="panel">
alert(message)<br>
_native<br>
_native.addCallback(hook, callback, tag)<br>
_native.setGPRVal(regnum, val)<br>
_native.getGPRVal(regnum)<br>
_native.getRDRAMInt(address, bitWidth)<br>
_native.setRDRAMInt(address, bitWidth, val)<br>
_native.getRDRAMFloat(address[, bDouble])<br>
_native.setRDRAMFloat(address, val[, bDouble])<br>
_native.sockCreate(port)<br>
_native.sockListen(fd)<br>
_native.sockAccept(fd)<br>
_native.sockRead(fd, callback)<br>
_native.sockWrite(fd, data, callback)<br>
_native.msgBox(message[, caption])<br>
</div>
-->
</div>
<script>
(function(){
var domSidebar = document.getElementById('sidebar');
var baseTop = domSidebar.getBoundingClientRect().top + window.scrollY;
document.onscroll = function(){
if(window.scrollY > baseTop) {
domSidebar.style.position = "fixed";
domSidebar.style.top = '0px';
} else {
domSidebar.style.position = "absolute";
domSidebar.style.top = baseTop + 'px';
}
}
})();
</script>
</body>
</html>