503 lines
37 KiB
HTML
503 lines
37 KiB
HTML
|
|
|
|
<!DOCTYPE html>
|
|
<html lang="en">
|
|
|
|
<head>
|
|
|
|
<meta charset="utf-8" />
|
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
|
<meta name="generator" content="HelpNDoc Personal Edition 7.3.0.348">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
<link rel="icon" href="favicon.ico"/>
|
|
|
|
<title>Debugger</title>
|
|
<meta name="description" content="" />
|
|
<meta name="keywords" content="Debugger,Inline Assembler,Symbolic Debugging">
|
|
|
|
|
|
|
|
|
|
|
|
<!-- Twitter Card data -->
|
|
<meta name="twitter:card" content="summary">
|
|
<meta name="twitter:title" content="Debugger">
|
|
<meta name="twitter:description" content="">
|
|
|
|
<!-- Open Graph data -->
|
|
<meta property="og:title" content="Debugger" />
|
|
<meta property="og:type" content="article" />
|
|
<meta property="og:description" content="" />
|
|
<meta property="og:site_name" content="FCEUX Help" />
|
|
|
|
<!-- Bootstrap core CSS -->
|
|
<link href="vendors/bootstrap-3.4.1/css/bootstrap.min.css" rel="stylesheet"/>
|
|
|
|
<!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
|
|
<link href="vendors/bootstrap-3.4.1/css/ie10-viewport-bug-workaround.css" rel="stylesheet"/>
|
|
|
|
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
|
<!--[if lt IE 9]>
|
|
<script src="vendors/html5shiv-3.7.3/html5shiv.min.js"></script>
|
|
<script src="vendors/respond-1.4.2/respond.min.js"></script>
|
|
<![endif]-->
|
|
|
|
<!-- JsTree styles -->
|
|
<link href="vendors/jstree-3.3.10/themes/default/style.min.css" rel="stylesheet"/>
|
|
|
|
<!-- Hnd styles -->
|
|
<link href="css/layout.min.css" rel="stylesheet" />
|
|
<link href="css/effects.min.css" rel="stylesheet" />
|
|
<link href="css/theme-light-blue.min.css" rel="stylesheet" />
|
|
<link href="css/print.min.css" rel="stylesheet" media="print" />
|
|
<style type="text/css">nav { width: 250px} @media screen and (min-width:769px) { body.md-nav-expanded div#main { margin-left: 250px} body.md-nav-expanded header { padding-left: 264px} }</style>
|
|
|
|
<!-- Content style -->
|
|
<link href="css/hnd.content.css" rel="stylesheet" />
|
|
|
|
|
|
|
|
|
|
|
|
</head>
|
|
|
|
<body class="md-nav-expanded">
|
|
|
|
|
|
|
|
<div id="skip-link">
|
|
<a href="#main-content" class="element-invisible">Skip to main content</a>
|
|
</div>
|
|
|
|
<header class="headroom">
|
|
<button class="hnd-toggle btn btn-default">
|
|
<span class="sr-only">Toggle navigation</span>
|
|
<span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span>
|
|
</button>
|
|
<h1>FCEUX Help</h1>
|
|
|
|
</header>
|
|
|
|
<nav id="panel-left" class="md-nav-expanded">
|
|
<!-- Nav tabs -->
|
|
<ul class="tab-tabs nav nav-tabs" role="tablist">
|
|
<li id="nav-close">
|
|
<button class="hnd-toggle btn btn-default">
|
|
<span class="glyphicon glyphicon-remove" aria-hidden="true"></span>
|
|
</button>
|
|
</li>
|
|
|
|
|
|
<li role="presentation" class="tab active">
|
|
<a href="#contents" id="tab-contents" aria-controls="contents" role="tab" data-toggle="tab">
|
|
<i class="glyphicon glyphicon-list"></i>
|
|
Contents
|
|
</a>
|
|
</li>
|
|
|
|
<li role="presentation" class="tab">
|
|
<a href="#index" id="tab-index" aria-controls="index" role="tab" data-toggle="tab">
|
|
<i class="glyphicon glyphicon-asterisk"></i>
|
|
Index
|
|
</a>
|
|
</li>
|
|
|
|
<li role="presentation" class="tab">
|
|
<a href="#search" id="tab-search" aria-controls="search" role="tab" data-toggle="tab">
|
|
<i class="glyphicon glyphicon-search"></i>
|
|
Search
|
|
</a>
|
|
</li>
|
|
|
|
</ul> <!-- /Nav tabs -->
|
|
|
|
<!-- Tab panes -->
|
|
<div class="tab-content">
|
|
|
|
<div role="tabpanel" class="tab-pane active" id="contents">
|
|
<div id="toc" class="tree-container unselectable"
|
|
data-url="_toc.json"
|
|
data-openlvl="1"
|
|
>
|
|
|
|
</div>
|
|
</div> <!-- /contents-->
|
|
|
|
<div role="tabpanel" class="tab-pane" id="index">
|
|
<div id="keywords" class="tree-container unselectable"
|
|
data-url="_keywords.json"
|
|
data-openlvl="1"
|
|
>
|
|
|
|
</div>
|
|
</div> <!-- /index-->
|
|
|
|
<div role="tabpanel" class="tab-pane" id="search">
|
|
<div class="search-content">
|
|
<div class="search-input">
|
|
<form id="search-form">
|
|
<div class="form-group">
|
|
<div class="input-group">
|
|
<input type="text" class="form-control" id="input-search" name="input-search" placeholder="Search..." />
|
|
<span class="input-group-btn">
|
|
<button class="btn btn-default" type="submit">
|
|
<span class="glyphicon glyphicon-search" aria-hidden="true"></span>
|
|
</button>
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div> <!-- /search-input -->
|
|
<div class="search-result">
|
|
<div id="search-info"></div>
|
|
<div class="tree-container unselectable" id="search-tree"></div>
|
|
</div> <!-- /search-result -->
|
|
</div> <!-- /search-content -->
|
|
</div> <!-- /search-->
|
|
|
|
</div> <!-- /Tab panes -->
|
|
|
|
</nav>
|
|
|
|
<div id="main">
|
|
|
|
<article>
|
|
<div id="topic-content" class="container-fluid"
|
|
data-hnd-id="Debugger"
|
|
data-hnd-context="14"
|
|
data-hnd-title="Debugger"
|
|
>
|
|
|
|
<div class="navigation">
|
|
<ol class="breadcrumb">
|
|
<li><a href="Debug.html">Debug</a></li>
|
|
</ol>
|
|
<div class="nav-arrows">
|
|
<div class="btn-group btn-group" role="group"><a class="btn btn-default" href="Debug.html" title="Debug" role="button"><span class="glyphicon glyphicon-menu-up" aria-hidden="true"></span></a><a class="btn btn-default" href="Debug.html" title="Debug" role="button"><span class="glyphicon glyphicon-menu-left" aria-hidden="true"></span></a><a class="btn btn-default" href="PPUViewer.html" title="PPU Viewer" role="button"><span class="glyphicon glyphicon-menu-right" aria-hidden="true"></span></a></div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<a id="main-content"></a>
|
|
|
|
<h2>Debugger</h2>
|
|
|
|
<div class="main-content">
|
|
|
|
<p class="rvps2"><span class="rvts22">Debugger</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts17">Introduction</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6">The debugger is a tool for inspecting and manipulating machine instructions and their execution. The debugger window has several components:</span></p>
|
|
<ul style="text-indent: 0px; padding: 0; margin: 0 0 0 24px; list-style-position: outside; list-style-type: disc;">
|
|
<li class="rvps2"><span class="rvts6">Execution - a small set of controls for controlling the execution of code.</span></li>
|
|
<li class="rvps2"><span class="rvts6">CPU State - display of registers, flags, the stack, cycles and instructions counters, and also the PPU state.</span></li>
|
|
<li class="rvps2"><span class="rvts6">Memory disassembly - displays a disassembly of the bytes currently accessible by the CPU data bus.</span></li>
|
|
<li class="rvps2"><span class="rvts6">Breakpoints - a list of breakpoints for debugging.</span></li>
|
|
<li class="rvps2"><span class="rvts6">Bookmarks - a list of bookmarked addresses for quick navigation.</span></li>
|
|
<li class="rvps2"><span class="rvts6">Other - buttons for controlling symbolic debugging, rom patching, etc.</span></li>
|
|
</ul>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts17">Execution and CPU State</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6">Execution is controlled by the set of buttons at the top-middle of the window. These allow you to break (pause) execution and inspect the current state of the NES.</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6">When an NES ROM is opened, it will be normally be running right away (unless you manually pause the emulator before loading). Most of the debugger window does not update while the game is running. To begin debugging you may click one of the buttons that will break (pause) execution, such as "Step Into".</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<ul style="text-indent: 0px; padding: 0; margin: 0 0 0 24px; list-style-position: outside; list-style-type: disc;">
|
|
<li class="rvps2"><span class="rvts6">Run - runs the program continuously until the next breakpoint is hit, or the emulator is paused manually. The same effect can be achieved by pressing the Pause hotkey which will unpause emulator when it's paused.</span></li>
|
|
<li class="rvps2"><span class="rvts6">Step Into - runs one instruction and then breaks.</span></li>
|
|
<li class="rvps2"><span class="rvts6">Step Out - attempt to run until the current subroutine ends with an RTS; in some cases will behave the same as Run.</span></li>
|
|
<li class="rvps2"><span class="rvts6">Step Over - runs one instruction, unless it is a JSR instruction, which will run until its RTS.</span></li>
|
|
<li class="rvps2"><span class="rvts6">Run Line - runs one scanline before breaking.</span></li>
|
|
<li class="rvps2"><span class="rvts6">128 Lines - runs 128 scanlines before breaking.</span></li>
|
|
</ul>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6">The Pause hotkey will break execution or resume it. The Frame Advance hotkey will run the emulator for one frame and then break.</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6">When execution is paused, the disassembly view will begin with the memory near the current program counter location (PC). The ">" mark shows the line which will be executed next. You can scroll the disassembly up or down (using scrollbar or mouse wheel) to observe the code. Then you can click "Seek PC" to return to the program counter at any time.</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6">You can also use "Seek To" button that will navigate to the specified address. Either type a hexadecimal address to the text field or simply left-click on any address in the Disassembly window.</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<div class="rvps2">
|
|
<table width="100%" border="1" cellpadding="6" cellspacing="2" style="border-color: #000000; border-style: solid; border-spacing: 2px;">
|
|
<tr valign="top">
|
|
<td width="305" height="46" style="border-color: #000000; border-style: solid; padding: 6px;">
|
|
<p class="rvps2"><span class="rvts78">HINT: When entering the address manually, these convenient strings may be used instead of the hexadecimal memory address:</span></p>
|
|
<p class="rvps2"><span class="rvts78">NES special addresses:</span></p>
|
|
<ul style="text-indent: 0px; padding: 0; margin: 0 0 0 24px; list-style-position: outside; list-style-type: disc;">
|
|
<li class="rvps2"><span class="rvts78">NMI/VBL - non-maskable interrupt vector (at FFFA)</span></li>
|
|
<li class="rvps2"><span class="rvts78">RST - reset vector (at FFFC)</span></li>
|
|
<li class="rvps2"><span class="rvts78">IRQ - interrupt vector (at FFFE)</span></li>
|
|
</ul>
|
|
<p class="rvps2"><span class="rvts78">FDS special addresses:</span></p>
|
|
<ul style="text-indent: 0px; padding: 0; margin: 0 0 0 24px; list-style-position: outside; list-style-type: disc;">
|
|
<li class="rvps2"><span class="rvts78">NMI1 - non-maskable interrupt vector (at DFF6)</span></li>
|
|
<li class="rvps2"><span class="rvts78">NMI2 - non-maskable interrupt vector (at DFF8)</span></li>
|
|
<li class="rvps2"><span class="rvts78">NMI3 - non-maskable interrupt vector (at DFFA)</span></li>
|
|
<li class="rvps2"><span class="rvts78">RST - reset vector (at DFFC)</span></li>
|
|
<li class="rvps2"><span class="rvts78">IRQ - interrupt vector (at DFFE)</span></li>
|
|
</ul>
|
|
<p class="rvps2"><span class="rvts78">NSF special addresses:</span></p>
|
|
<ul style="text-indent: 0px; padding: 0; margin: 0 0 0 24px; list-style-position: outside; list-style-type: disc;">
|
|
<li class="rvps2"><span class="rvts78">LOAD - NSF LOAD address</span></li>
|
|
<li class="rvps2"><span class="rvts78">INIT - NSF INIT address</span></li>
|
|
<li class="rvps2"><span class="rvts78">PLAY - NSF PLAY address</span></li>
|
|
</ul>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
<p class="rvps2"><span class="rvts58"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6">While execution is broken (emulation is paused), the program counter (PC) can be edited, as well as the three registers A/X/Y, and the status flags. Normally they should be left as-is, but changing them at runtime can be useful for more advanced debugging.</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6">The contents of memory starting at the stack pointer (somewhere in the range $0100-01FF) is displayed in the Stack frame below the A/X/Y registers.</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6">The current PPU memory address, sprite memory address, scanline, and rendering pixel are displayed below the stack and status flags. </span><span class="rvts20">Examples of Scanline number:</span><span class="rvts6"> -1 means Prerender time, 240 is Idle scanline, 0-239 are visible scanlines, 241-260/310 are VBlank scanlines.</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6">To the right from the PPU section there's Cycles counter and Instructions counter that keep counting while the game is running. You can use the information for keeping statistics, for code profiling or writing PPU-synchronized code (e.g. raster effects). You can also make the debugger break automatically based on the counters values. The "Reset counters" button resets both counters to 0. You can also access the counters via </span><a class="rvts76" href="LuaFunctionsList.html">Lua</a><span class="rvts6">.</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts17">Disassembly</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6">This large frame takes up the left side of the debugger window. It displays the current contents of memory accessible by the CPU with an automatic disassembly of that data into assembly instructions. The following memory ranges may contain useful data for inspection:</span></p>
|
|
<ul style="text-indent: 0px; padding: 0; margin: 0 0 0 24px; list-style-position: outside; list-style-type: disc;">
|
|
<li class="rvps2"><span class="rvts6">0000-00FF - zero page (RAM)</span></li>
|
|
<li class="rvps2"><span class="rvts6">0100-01FF - stack (RAM)</span></li>
|
|
<li class="rvps2"><span class="rvts6">0200-07FF - RAM</span></li>
|
|
<li class="rvps2"><span class="rvts6">4018-FFFF - mapper controlled (ROM or RAM, may be bankswitched)</span></li>
|
|
</ul>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6">Memory contents are displayed in this form:</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts77">0F:C0A8:24 1F BIT $001F = #$80</span></p>
|
|
<p class="rvps2"><span class="rvts77">bb:mmmm:dd dd dd iiiiiiiiiiiii...</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<ul style="text-indent: 0px; padding: 0; margin: 0 0 0 24px; list-style-position: outside; list-style-type: disc;">
|
|
<li class="rvps2"><span class="rvts6">bb - 16k iNES bank, designates which 16k bank from the iNES file is mapped here. Note that the number may be not the same as the actual hardware bank of the mapper.</span></li>
|
|
<li class="rvps2"><span class="rvts6">mmmm - physical address on the NES CPU data bus.</span></li>
|
|
<li class="rvps2"><span class="rvts6">dd - data bytes belonging to the instruction beginning at this address.</span></li>
|
|
<li class="rvps2"><span class="rvts6">iiii - assembly description of the instruction, possibly with symbolic decoration.</span></li>
|
|
</ul>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6">When debugging an NSF program, the bank designation will be a 4k NSF bank instead of the 16k iNES bank.</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6">A single instruction may be one to three bytes, and will all appear on the line before the assembly code description of that instruction. An instruction with "= #$xx" at the end conveniently indicates the value currently in memory at the address referenced by the instruction.</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6">Hovering the mouse over the disassembly will display at the bottom of the window more detailed information about the location of this code in the iNES file.</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6">There is narrow column to the left of the Disassembly window. Left clicking on this column will open the </span><span class="rvts49">Inline Assembler</span><span class="rvts6">, which allows you to patch the ROM at runtime. Right clicking on this column will open the </span><a class="rvts76" href="HexEditor.html">Hex Editor</a><span class="rvts6">, which allows you to directly edit the ROM. Middle-clicking on this column will bring up the </span><a class="rvts76" href="GameGenieEncoderDecoder.html">Game Genie Encoder</a><span class="rvts6"> at that address, so you can easily make Game Genie codes.</span></p>
|
|
<p class="rvps2"><span class="rvts6">Also, when </span><a class="rvts76" href="CodeDataLogger.html">Code/Data Logger</a><span class="rvts6"> is running, this small column displays whether the respective line of the disassembled memory was executed ("c") or it was read as Data ("d"), or it wasn't logged yet (empty space). This way you can easily distinguish which branches of the game code were executed and which weren't.</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts17">Symbolic Debugging</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6">FCEUX allows you to label any address of RAM or ROM with a human-readable symbolic name.</span></p>
|
|
<p class="rvps2"><span class="rvts6">For example, when you've figured out that at the address $C022 there's a subroutine which refills player HP, you can right-click the address and type a name like "AddHealthpoints". You can also add a comment, which will be seen while browsing the code near this address. From now on, the address will be substituted by the name everywhere - in all instructions referencing this address, in Hex Editor window, in the log produced by Trace Logger. E.g., JSR $C022 will look like JSR AddHealthpoints.</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6">You can also label a series of adresses as an array by specifiying the array size, every address label in range will be followed with an array index. For example, if you label $C000 with name "ArrayName", and set the size to 0xF, then $C000 is named "ArrayName[0]", $C001 is "ArrayName[1]"... and so on, the last labeled address is $C00E with name "ArrayName[E]". The start index number can be manually set to a value other than zero.</span></p>
|
|
<p class="rvps2"><span class="rvts6">A name must be specified in array labeling, or the debugger only show the comment of the addresses.</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6">When entering the name, you can use any symbols except #. It's also recommended to avoid whitespaces in names.</span></p>
|
|
<p class="rvps2"><span class="rvts6">To rename an address, just right-click the name.</span></p>
|
|
<p class="rvps2"><span class="rvts6">Note that each label is individual, when you rename one of the labels in an array, the other label won't change simutaneously. To change all the names in an array, you should edit the name of the first element in the array, specify the array size and check "Overwrite names in array body".</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6">To delete a label, check the "Delete" checkbox and click OK.</span></p>
|
|
<p class="rvps2"><span class="rvts6">The array size specified in delete mode indicates labels of how many bytes will be deleted. If you select $C000 and set array size to 0xF, all the labels form $C000 to $C00E are deleted. </span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6">The data for Symbolic Debugging is stored in </span><a class="rvts76" href="NLFilesFormat.html">NL files</a><span class="rvts6"> in the same folder as the ROM. You can edit the files in any text editor (to reload all NL files of the currently active ROM file press the "Reload Symbols" button), but it's more convenient to use right-clicks.</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6">You can enable and disable symbolic debugging by clicking the checkbox "Symbolic debug" in the lower right corner. In general, there's no need to disable this feature. If you need to see the actual address which got substituted by a name, you can simply left-click the name and watch its address in the "Seek To" text field. This also works when clicking a name in the Trace Logger window.</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts17">Breakpoints</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6">Breakpoints will automatically break execution when chosen conditions are met. To create a breakpoint, click the Add button in the Breakpoints frame in the upper right corner of the debugger.</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6">Each breakpoint has an address range to watch. Use only the left address field if you wish to watch a single byte address. When entering the address of a breakpoint, you can also use the aforementioned convenient strings (such as IRQ) instead of hexadecimal memory addresses.</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6">Check one or more of the options to watch for Read, Write, or Execute at the given address. Note that fetching of code from an address will not break as a Read; so use the Execute box for this case. Breakpoints can be given a name that will appear in the breakpoints list. The condition field can be used to break only on particular conditions; see "Conditional Breakpoints" below.</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6">Double click on a breakpoint in the Breakpoints list to quickly disable or enable this breakpoint. So you don't have to delete breakpoints to stop them from causing the debugger to halt the game.</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6">A special kind of breakpoints with the "Forbid" option will prevent any breakpoints from occurring within the specified memory address range. This can be enabled and disabled like other breakpoints.</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6">A quicker way to add PC breakpoints is to double click on any address in the Disassembly when you want to set the breakpoint to that address. </span><span class="rvts20">Example:</span><span class="rvts6"> when you need to quickly advance emulation to a given line of code, double-click on the address part of the line, and the "Add Execute breakpoint here" dialog will appear, just click "OK" and then hit "Run", Debugger will break at this line of code.</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6">There is also an option to Break on Bad Opcodes, which will halt execution if a bad instruction opcode is reached.</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6">Finally, you can make the debugger break after executing a certain number of instructions or CPU cycles.</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6">More advanced breakpoints conditions and full automation may be achieved through Lua script breakpoints. See the </span><a class="rvts76" href="LuaFunctionsList.html#LuaBreakpoints">Lua reference</a><span class="rvts6"> for more information.</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6">Breakpoints are listed in the following form:</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts77">aaaa EmRWXF nnnn cccc</span></p>
|
|
<p class="rvps2"><span class="rvts77">or</span></p>
|
|
<p class="rvps2"><span class="rvts77">aaaa-aaaa EmRWXF nnnn cccc</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<ul style="text-indent: 0px; padding: 0; margin: 0 0 0 24px; list-style-position: outside; list-style-type: disc;">
|
|
<li class="rvps2"><span class="rvts6">aaaa - address of breakpoint</span></li>
|
|
<li class="rvps2"><span class="rvts6">E - enabled</span></li>
|
|
<li class="rvps2"><span class="rvts6">m - memory area: C = CPU, P = PPU, S = sprite</span></li>
|
|
<li class="rvps2"><span class="rvts6">R - read</span></li>
|
|
<li class="rvps2"><span class="rvts6">W - write</span></li>
|
|
<li class="rvps2"><span class="rvts6">X - execute</span></li>
|
|
<li class="rvps2"><span class="rvts6">F - Forbid</span></li>
|
|
<li class="rvps2"><span class="rvts6">nnnn - (optional) name of breakpoint</span></li>
|
|
<li class="rvps2"><span class="rvts6">nnnn - (optional) condition of breakpoint</span></li>
|
|
</ul>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts17">Conditional Breakpoints</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6">Breakpoints may also have a conditional statement that causes them to execute only if that statement evaluates to true. The conditional breakpoint grammar has this form:</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<ul style="text-indent: 0px; padding: 0; margin: 0 0 0 24px; list-style-position: outside; list-style-type: disc;">
|
|
<li class="rvps2"><span class="rvts6">Connect -> Compare { ('||' | '&&') Compare }</span></li>
|
|
<li class="rvps2"><span class="rvts6">Compare -> Sum { ('==' | '!=' | '<=' | '>=' | '<' | '>') Sum }</span></li>
|
|
<li class="rvps2"><span class="rvts6">Sum -> Product { ('+' | '-') Product }</span></li>
|
|
<li class="rvps2"><span class="rvts6">Product -> Primitive { ('*' | '/') Primitive }</span></li>
|
|
<li class="rvps2"><span class="rvts6">Primitive -> Number | Address | Register | Flag | PC Bank | Data Bank | '(' Connect ')'</span></li>
|
|
<li class="rvps2"><span class="rvts6">Number -> '#' [0123456789ABCDEF]*</span></li>
|
|
<li class="rvps2"><span class="rvts6">Address -> '$' [0123456789ABCDEF]* | '$' '[' Connect ']'</span></li>
|
|
<li class="rvps2"><span class="rvts6">Register -> 'A' | 'X' | 'Y' | 'P'</span></li>
|
|
<li class="rvps2"><span class="rvts6">Flag -> 'N' | 'C' | 'Z' | 'I' | 'B' | 'V' </span><span class="rvts79">| 'D' | 'U'</span></li>
|
|
<li class="rvps2"><span class="rvts6">PC Bank -> 'K'</span></li>
|
|
<li class="rvps2"><span class="rvts6">Data Bank -> 'T'</span></li>
|
|
<li class="rvps2"><span class="rvts79">Read/Write Value</span><span class="rvts6"> -> </span><span class="rvts79">'R' | 'W'</span></li>
|
|
</ul>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6">The parser is very strict. All numbers are hexadecimal. Always prefix a number with # for an immediate value, or $ for a memory address. If a memory address needs to be calculated use $[] with the calculation inside the brackets.</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6">Registers A/X/Y are 8-bit unsigned values. Register P is the 16-bit program counter.</span></p>
|
|
<p class="rvps2"><span class="rvts6">Flags evaluate to 1 if set, 0 if clear. (U is the unused bit of the status register, and D is the unused decimal flag.)</span></p>
|
|
<p class="rvps2"><span class="rvts6">For instructions that read or write a single byte (e.g. LDA, STY, PHA, ASL abs), condition R evaluates to the value that will be read by the instruction, and condition W evaluates to the value that will be written.</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6">Connecting operators || or && combine boolean terms. Parentheses dictate order of operations.</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts20">Example conditions:</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6">Break only if register A is less than value at memory address $0005:</span></p>
|
|
<p class="rvps2"><span class="rvts77">A < $0005</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6">Break only if the value at the indirect address is not equal to FF:</span></p>
|
|
<p class="rvps2"><span class="rvts77">#FF != $[$10+($11*#100)]</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6">Break only if flag N is clear or A is not equal to 00:</span></p>
|
|
<p class="rvps2"><span class="rvts77">(N==#0 || A!=#0)</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6">Break only when accessing a data from bank 2 (the condiition is relevant when using with Read/Write-type breakpoints):</span></p>
|
|
<p class="rvps2"><span class="rvts77">T==#2</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts17">Bookmarks</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6">A list of bookmarked addresses can be kept in the Address Bookmarks frame to make memory navigation easier. Simply type a hexadecimal address (or a convenient string, such as "NMI") and click "Add" to add it to your bookmarks. Alternatively, just left-click any address in the Disassembly window, and the address will appear in the Bookmark Add field, so you don't have to type it.</span></p>
|
|
<p class="rvps2"><span class="rvts6">Next time you wish to go to this address just double click on the bookmark.</span></p>
|
|
<p class="rvps2"><span class="rvts6">You can also name bookmarks.</span></p>
|
|
<p class="rvps2"><span class="rvts6">When you exit the emulator, bookmarks are saved in a .deb file named after the ROM of the debugged game. Next time you return to debugging the game, the list of bookmarks will be automatically loaded from the file.</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts17">Inline Assembler</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6">Open the inline assembler by left-clicking in the empty column to the left of the memory view.</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6">The starting memory address is displayed in the PC field at the top of the inline assembler window. Type a line of assembly to add in the empty field just below this, and hit enter. The assembled code of your patch will appear below as you enter each line.</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6">Click Apply to apply your patch to the ROM in memory. Click Undo to remove the last assembled line. After applying a patch, clicking Save will allow you to save this patch directly to the ROM file.</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts17">Other</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6">If the ".DEB files" checkbox in the lower right corner of the debugger window is checked, the emulator will automatically save debug settings such as breakpoints and bookmarks in a .deb file alongside the NES ROM, and load these settings next time you open the ROM.</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6">There is a "Rom Patcher" button that may be used to apply a small patch to a ROM, although </span><a class="rvts76" href="HexEditor.html">Hex Editor</a><span class="rvts6"> is more convenient in general.</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6">The "ROM offsets" option will display ROM offsets instead of CPU addresses in the Disassembly window.</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6">The "Restore Original Window Size" button will restore the original size of the debugger window if you resized it manually.</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6">The "Auto-open" checkbox causes the debugger window to open automatically whenever an NES ROM is opened.</span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6"><br/></span></p>
|
|
<p class="rvps2"><span class="rvts6"></span><span class="rvts6"></span></p>
|
|
<p class="rvps4" style="clear: both;"><span class="rvts18">Created with the Personal Edition of HelpNDoc: </span><a class="rvts19" href="https://www.helpndoc.com/feature-tour">Easily create HTML Help documents</a></p>
|
|
|
|
</div>
|
|
|
|
<div id="topic_footer"><div id="topic_footer_content">2020</div></div>
|
|
</div> <!-- /#topic-content -->
|
|
</article>
|
|
|
|
<footer></footer>
|
|
|
|
</div> <!-- /#main -->
|
|
|
|
<div class="mask" data-toggle="sm-nav-expanded"></div>
|
|
|
|
<!-- Modal -->
|
|
<div class="modal fade" id="hndModal" tabindex="-1" role="dialog" aria-labelledby="hndModalLabel">
|
|
<div class="modal-dialog" role="document">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
|
<h4 class="modal-title" id="hndModalLabel"></h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-primary modal-btn-close" data-dismiss="modal">Close</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Splitter -->
|
|
<div id="hnd-splitter" style="left: 250px"></div>
|
|
|
|
<!-- Scripts -->
|
|
<script src="vendors/jquery-3.5.1/jquery.min.js"></script>
|
|
<script src="vendors/bootstrap-3.4.1/js/bootstrap.min.js"></script>
|
|
<script src="vendors/bootstrap-3.4.1/js/ie10-viewport-bug-workaround.js"></script>
|
|
<script src="vendors/markjs-8.11.1/jquery.mark.min.js"></script>
|
|
<script src="vendors/uri-1.19.2/uri.min.js"></script>
|
|
<script src="vendors/imageMapResizer-1.0.10/imageMapResizer.min.js"></script>
|
|
<script src="vendors/headroom-0.11.0/headroom.min.js"></script>
|
|
<script src="vendors/jstree-3.3.10/jstree.min.js"></script>
|
|
<script src="vendors/interactjs-1.9.22/interact.min.js"></script>
|
|
|
|
<!-- HelpNDoc scripts -->
|
|
<script src="js/polyfill.object.min.js"></script>
|
|
<script src="_translations.js"></script>
|
|
<script src="js/hndsd.min.js"></script>
|
|
<script src="js/hndse.min.js"></script>
|
|
<script src="js/app.min.js"></script>
|
|
|
|
<!-- Init script -->
|
|
<script>
|
|
$(function() {
|
|
// Create the app
|
|
var app = new Hnd.App();
|
|
// Update translations
|
|
hnd_ut(app);
|
|
// Instanciate imageMapResizer
|
|
imageMapResize();
|
|
// Custom JS
|
|
|
|
// Boot the app
|
|
app.Boot();
|
|
});
|
|
</script>
|
|
|
|
|
|
|
|
</body>
|
|
|
|
</html>
|
|
|