Merge branch 'master' into feature/lodefmode-moviecart
13
Changes.txt
|
@ -12,6 +12,17 @@
|
||||||
Release History
|
Release History
|
||||||
===========================================================================
|
===========================================================================
|
||||||
|
|
||||||
|
6.5.3 to 6.6 (??? ??, 202?)
|
||||||
|
|
||||||
|
* Added web links for many games
|
||||||
|
|
||||||
|
* Debugger: added optional logging of breaks and traps
|
||||||
|
|
||||||
|
* Debugger: enhanced prompt's auto complete and history
|
||||||
|
|
||||||
|
-Have fun!
|
||||||
|
|
||||||
|
|
||||||
6.5.2 to 6.5.3 (April 20, 2021)
|
6.5.2 to 6.5.3 (April 20, 2021)
|
||||||
|
|
||||||
* Added context-sensitive help.
|
* Added context-sensitive help.
|
||||||
|
@ -26,8 +37,6 @@
|
||||||
|
|
||||||
* Fixed immediate disassembling when switching options in debugger.
|
* Fixed immediate disassembling when switching options in debugger.
|
||||||
|
|
||||||
-Have fun!
|
|
||||||
|
|
||||||
|
|
||||||
6.5.1 to 6.5.2 (February 25, 2021)
|
6.5.1 to 6.5.2 (February 25, 2021)
|
||||||
|
|
||||||
|
|
|
@ -102,10 +102,10 @@ feature that no other 2600 debugger has; it's <b>completely</b> cross-platform.<
|
||||||
breakpoints as you want.</li>
|
breakpoints as you want.</li>
|
||||||
|
|
||||||
<li>Conditional breakpoints - Break running program when some arbitrary
|
<li>Conditional breakpoints - Break running program when some arbitrary
|
||||||
condition is true (e.g. "breakif {a == $7f && c}" will break when the Accumulator value is $7f and the Carry flag is true, no matter where
|
condition is true (e.g. "breakIf {a == $7f && c}" will break when the Accumulator value is $7f and the Carry flag is true, no matter where
|
||||||
in the program this happens). Unlike the cond breaks in PCAE, Stella's
|
in the program this happens). Unlike the cond breaks in PCAE, Stella's
|
||||||
are *fast*: the emulation will run at full speed unless you use lots
|
are *fast*: the emulation will run at full speed unless you use lots
|
||||||
of breakif's at the same time, or have a slow CPU.</li>
|
of breakIf's at the same time, or have a slow CPU.</li>
|
||||||
|
|
||||||
<li>Watches - View contents of a location/register before every
|
<li>Watches - View contents of a location/register before every
|
||||||
debugger prompt.</li>
|
debugger prompt.</li>
|
||||||
|
@ -172,7 +172,7 @@ feature that no other 2600 debugger has; it's <b>completely</b> cross-platform.<
|
||||||
<li>Data sources for the CPU SP/A/X/Y registers, showing the resolved/source
|
<li>Data sources for the CPU SP/A/X/Y registers, showing the resolved/source
|
||||||
address of of load operands.</li>
|
address of of load operands.</li>
|
||||||
<li>Scanline advance (like frame advance, break at beginning
|
<li>Scanline advance (like frame advance, break at beginning
|
||||||
of next scanline).</li>
|
of next scanLine).</li>
|
||||||
<li>TIA display is updated during step/trace, so we can see our
|
<li>TIA display is updated during step/trace, so we can see our
|
||||||
scanlines being drawn as it happens. This isn't 100% perfect: unlike
|
scanlines being drawn as it happens. This isn't 100% perfect: unlike
|
||||||
a real TIA, the one in Stella only updates when it's written to.</li>
|
a real TIA, the one in Stella only updates when it's written to.</li>
|
||||||
|
@ -183,7 +183,7 @@ feature that no other 2600 debugger has; it's <b>completely</b> cross-platform.<
|
||||||
named after the ROM image.</li>
|
named after the ROM image.</li>
|
||||||
<li>Saving the current debugger state to a script file (including
|
<li>Saving the current debugger state to a script file (including
|
||||||
breakpoints, traps, etc).</li>
|
breakpoints, traps, etc).</li>
|
||||||
<li>Built-in functions for use with "breakif", to support common conditions
|
<li>Built-in functions for use with "breakIf", to support common conditions
|
||||||
(such as breaking when the user presses Game Select...)</li>
|
(such as breaking when the user presses Game Select...)</li>
|
||||||
<li>Patching ROM in-place.</li>
|
<li>Patching ROM in-place.</li>
|
||||||
<li>Save patched ROM</li>
|
<li>Save patched ROM</li>
|
||||||
|
@ -251,9 +251,9 @@ command on the command line, or alternatively within the ROM launcher in
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>Using the ` key will always enter the debugger at the end of
|
<p>Using the ` key will always enter the debugger at the end of
|
||||||
the frame (for NTSC games usually scanline 262). This is because Stella only checks
|
the frame (for NTSC games usually scanLine 262). This is because Stella only checks
|
||||||
for keystrokes once per frame. Once in the debugger, you can control
|
for keystrokes once per frame. Once in the debugger, you can control
|
||||||
execution by stepping one instruction, scanline, or frame at a time
|
execution by stepping one instruction, scanLine, or frame at a time
|
||||||
(or more than one at a time, using commands in the prompt). You can
|
(or more than one at a time, using commands in the prompt). You can
|
||||||
also set breakpoints or traps, which will cause the emulator to enter
|
also set breakpoints or traps, which will cause the emulator to enter
|
||||||
the debugger when they are triggered, even if it happens in mid-frame.</p>
|
the debugger when they are triggered, even if it happens in mid-frame.</p>
|
||||||
|
@ -345,52 +345,52 @@ size can be configured e.g. in the
|
||||||
<p>
|
<p>
|
||||||
<table BORDER=1 cellpadding=4>
|
<table BORDER=1 cellpadding=4>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Key</th>
|
|
||||||
<th>Function</th>
|
<th>Function</th>
|
||||||
|
<th>Key</th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Control + S</td>
|
|
||||||
<td>Step</td>
|
<td>Step</td>
|
||||||
|
<td>Control + S</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Control + T</td>
|
|
||||||
<td>Trace</td>
|
<td>Trace</td>
|
||||||
|
<td>Control + T</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Control + L</td>
|
|
||||||
<td>Scan +1</td>
|
<td>Scan +1</td>
|
||||||
|
<td>Control + L</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Control + F</td>
|
|
||||||
<td>Frame +1</td>
|
<td>Frame +1</td>
|
||||||
|
<td>Control + F</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Alt + Left arrow</td>
|
|
||||||
<td>Rewind 1</td>
|
<td>Rewind 1</td>
|
||||||
|
<td>Alt + Left arrow</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Shift-Alt + Left arrow</td>
|
|
||||||
<td>Rewind 10</td>
|
<td>Rewind 10</td>
|
||||||
|
<td>Shift-Alt + Left arrow</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Alt + Down arrow</td>
|
|
||||||
<td>Rewind all</td>
|
<td>Rewind all</td>
|
||||||
|
<td>Alt + Down arrow</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Alt + Right arrow</td>
|
|
||||||
<td>Unwind 1</td>
|
<td>Unwind 1</td>
|
||||||
|
<td>Alt + Right arrow</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Shift-Alt + Right arrow</td>
|
|
||||||
<td>Unwind 10</td>
|
<td>Unwind 10</td>
|
||||||
|
<td>Shift-Alt + Right arrow</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Alt + Up arrow</td>
|
|
||||||
<td>Unwind all</td>
|
<td>Unwind all</td>
|
||||||
|
<td>Alt + Up arrow</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Backquote (`)</td>
|
|
||||||
<td>Run, exits debugger</td>
|
<td>Run, exits debugger</td>
|
||||||
|
<td>Backquote (`)</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</p>
|
</p>
|
||||||
|
@ -408,7 +408,7 @@ in detail in the <a href="index.html">User's Guide</a>.</p>
|
||||||
|
|
||||||
<p>The debugger tracks changes to the CPU, TIA and RIOT registers and RAM by
|
<p>The debugger tracks changes to the CPU, TIA and RIOT registers and RAM by
|
||||||
displaying changed locations or registers with a red background after each step,
|
displaying changed locations or registers with a red background after each step,
|
||||||
trace, scanline, or frame advance. This sounds simple, and it is, but
|
trace, scanLine, or frame advance. This sounds simple, and it is, but
|
||||||
it's also amazingly useful.</p>
|
it's also amazingly useful.</p>
|
||||||
|
|
||||||
<p>One clarification about the change tracking: it only tracks when values
|
<p>One clarification about the change tracking: it only tracks when values
|
||||||
|
@ -428,25 +428,28 @@ or Supermon for the C=64.</p>
|
||||||
Bash-style commands are also supported:</p>
|
Bash-style commands are also supported:</p>
|
||||||
|
|
||||||
<table border="1" cellpadding=4>
|
<table border="1" cellpadding=4>
|
||||||
<tr><th>Key</th><th>Function</th></tr>
|
<tr><th>Function</th><th>Key</th></tr>
|
||||||
<tr><td>Home</td><td>Move cursor to beginning of line</td></tr>
|
<tr><td>Move cursor to beginning of line</td><td>Home</td></tr>
|
||||||
<tr><td>End</td><td>Move cursor to end of line</td></tr>
|
<tr><td>Move cursor to end of line</td><td>End</td></tr>
|
||||||
<tr><td>Delete</td><td>Remove character to right of cursor</td></tr>
|
<tr><td>Remove character to right of cursor</td><td>Delete</td></tr>
|
||||||
<tr><td>Backspace</td><td>Remove character to left of cursor</td></tr>
|
<tr><td>Remove character to left of cursor</td><td>Backspace</td></tr>
|
||||||
<tr><td>Control + A</td><td>Same function as 'Home'</td></tr>
|
<tr><td>Same function as 'Home'</td><td>Control + A</td></tr>
|
||||||
<tr><td>Control + E</td><td>Same function as 'End'</td></tr>
|
<tr><td>Same function as 'End'</td><td>Control + E</td></tr>
|
||||||
<tr><td>Control + D</td><td>Same function as 'Delete'</td></tr>
|
<tr><td>Same function as 'Delete'</td><td>Control + D</td></tr>
|
||||||
<tr><td>Control + K</td><td>Remove all characters from cursor to end of line</td></tr>
|
<tr><td>Remove all characters from cursor to end of line</td><td>Control + K</td></tr>
|
||||||
<tr><td>Control + U</td><td>Remove all characters from cursor to beginning of line</td></tr>
|
<tr><td>Remove all characters from cursor to beginning of line</td><td>Control + U</td></tr>
|
||||||
<tr><td>Control + W</td><td>Remove entire word to left of cursor</td></tr>
|
<tr><td>Remove entire word to left of cursor</td><td>Control + W</td></tr>
|
||||||
<tr><td>Shift + PgUp</td><td>Scroll up through previous commands one screen/page</td></tr>
|
<tr><td>Copy current line</td><td>Control + C</td></tr>
|
||||||
<tr><td>Shift + PgDown</td><td>Scroll down through previous commands one screen/page</td></tr>
|
<tr><td>Cut current line</td><td>Control + X</td></tr>
|
||||||
<tr><td>Shift + Up</td><td>Scroll up through previous commands one line</td></tr>
|
<tr><td>Paste over current line</td><td>Control + V</td></tr>
|
||||||
<tr><td>Shift + Down</td><td>Scroll down through previous commands one line</td></tr>
|
<tr><td>Scroll up through previous commands one screen/page</td><td>Shift + PgUp</td></tr>
|
||||||
<tr><td>Shift + Home</td><td>Scroll to beginning of commands</td></tr>
|
<tr><td>Scroll down through previous commands one screen/page</td><td>Shift + PgDown</td></tr>
|
||||||
<tr><td>Shift + End</td><td>Scroll to end of commands</td></tr>
|
<tr><td>Scroll up through previous commands one line</td><td>Shift + Up</td></tr>
|
||||||
|
<tr><td>Scroll down through previous commands one line</td><td>Shift + Down</td></tr>
|
||||||
|
<tr><td>Scroll to beginning of commands</td><td>Shift + Home</td></tr>
|
||||||
|
<tr><td>Scroll to end of commands</td><td>Shift + End</td></tr>
|
||||||
</table>
|
</table>
|
||||||
<p>You can also scroll with the mouse. Copy and paste is not yet supported.</p>
|
<p>You can also scroll with the mouse. Copy and paste is currently only supported for a complete line.</p>
|
||||||
|
|
||||||
<p>To see the available commands, enter "help". For extended help, type "help cmd",
|
<p>To see the available commands, enter "help". For extended help, type "help cmd",
|
||||||
where 'cmd' is the command you wish to know about. The available commands are listed
|
where 'cmd' is the command you wish to know about. The available commands are listed
|
||||||
|
@ -467,16 +470,16 @@ just by re-running the relevant commands in the prompt.</p>
|
||||||
<h3><a name="TabCompletion">Tab Key Auto-Complete</a></h3>
|
<h3><a name="TabCompletion">Tab Key Auto-Complete</a></h3>
|
||||||
|
|
||||||
<p>While entering a command, label or function, you can type a partial name and
|
<p>While entering a command, label or function, you can type a partial name and
|
||||||
press the Tab key to attempt to auto-complete it. If you've ever used
|
press the (Shift +) Tab key to attempt to auto-complete it. If you've ever used
|
||||||
"bash", this will be immediately familiar. If not, try it: load up
|
"bash", this will be immediately familiar. If not, try it: load up
|
||||||
a ROM, go to the debugger, type "g" (but don't press Enter),
|
a ROM, go to the debugger, type "g" (but don't press Enter),
|
||||||
then hit Tab. The "g" will change to "gfx" (since this is the only
|
then hit Tab. The "g" will change to "gfx" (since this is the only
|
||||||
built-in command starting with a "g"). If there are multiple possible
|
built-in command starting with a "g"). If there are multiple possible
|
||||||
completions (try with "tr" instead of "g"), you'll see a list of them,
|
completions (try with "tr" instead of "g"), you can tab through them.
|
||||||
and your partial name will be completed as far as possible.
|
|
||||||
After the first character, the autocompletion considers all
|
After the first character, the autocompletion considers all
|
||||||
characters in the right order as a match (e.g. "twf" will be completed to
|
characters in the right order as a match (e.g. "twf" will be completed to
|
||||||
"trapwriteif").</p>
|
"trapWriteIf"). Alternatively you can make use of the camel case names and type
|
||||||
|
e.g. "tWI" ("trapWriteIf") or "lAS" ("LoadAllStates").</p>
|
||||||
|
|
||||||
<p>Tab completion works on all labels: built-in, loaded from a symbol file,
|
<p>Tab completion works on all labels: built-in, loaded from a symbol file,
|
||||||
or set during debugging with the "define" command. It also works with
|
or set during debugging with the "define" command. It also works with
|
||||||
|
@ -609,7 +612,7 @@ command that takes arguments.</p>
|
||||||
<h4><a name="Breakpoints">Breakpoints</a></h4>
|
<h4><a name="Breakpoints">Breakpoints</a></h4>
|
||||||
|
|
||||||
<p>A breakpoint is a "hotspot" in your program that causes the emulator
|
<p>A breakpoint is a "hotspot" in your program that causes the emulator
|
||||||
to stop emulating and jump into the debugger. You can set as many
|
to stop emulating and jump into the debugger ¹. You can set as many
|
||||||
breakpoints as you like. The command is "break xx yy" where xx is any
|
breakpoints as you like. The command is "break xx yy" where xx is any
|
||||||
expression and yy a bank number. Both arguments are optional. If you have
|
expression and yy a bank number. Both arguments are optional. If you have
|
||||||
created a symbol file, you can use labels for the expression.</p>
|
created a symbol file, you can use labels for the expression.</p>
|
||||||
|
@ -630,8 +633,11 @@ set it. In the example, "break kernel" will remove the breakpoint.
|
||||||
The "break" command can be thought of as a *toggle*: it turns the
|
The "break" command can be thought of as a *toggle*: it turns the
|
||||||
breakpoint on & off, like a light switch.</p>
|
breakpoint on & off, like a light switch.</p>
|
||||||
|
|
||||||
<p>You could also use "clearbreaks" to remove all the breakpoints. Also,
|
<p>You could also use "clearBreaks" to remove all the breakpoints. Also,
|
||||||
there is a "listbreaks" command that will list them all.</p>
|
there is a "listBreaks" command that will list them all.</p>
|
||||||
|
|
||||||
|
<p>¹ By enabling "logBreaks" you can log the current state into
|
||||||
|
the System Log and continue emulation instead.</p>
|
||||||
|
|
||||||
<h4><a name="ConditionalBreaks">Conditional Breaks</a></h4>
|
<h4><a name="ConditionalBreaks">Conditional Breaks</a></h4>
|
||||||
|
|
||||||
|
@ -661,10 +667,10 @@ is the "!" operator): !(*SWCHB&1). The parentheses are necessary as
|
||||||
we want to apply the ! to the result of the &, not just the first term
|
we want to apply the ! to the result of the &, not just the first term
|
||||||
(the "*SWCHB").</p>
|
(the "*SWCHB").</p>
|
||||||
|
|
||||||
<p>"breakif !(*SWCHB&1)" will do the job for us. However, it's an ugly mess
|
<p>"breakIf !(*SWCHB&1)" will do the job for us. However, it's an ugly mess
|
||||||
of letters, numbers, and punctuation. We can do a little better:</p>
|
of letters, numbers, and punctuation. We can do a little better:</p>
|
||||||
|
|
||||||
<p>"breakif { !(*SWCHB & 1 ) }" is a lot more readable, isn't it? If
|
<p>"breakIf { !(*SWCHB & 1 ) }" is a lot more readable, isn't it? If
|
||||||
you're going to use readable expressions with spaces in them,
|
you're going to use readable expressions with spaces in them,
|
||||||
enclose the entire expression in curly braces.</p>
|
enclose the entire expression in curly braces.</p>
|
||||||
|
|
||||||
|
@ -673,9 +679,9 @@ condition that depends on input (like SWCHB) will always happen at the
|
||||||
end of a frame. This is different from how a real 2600 works, but most
|
end of a frame. This is different from how a real 2600 works, but most
|
||||||
ROMs only check for input once per frame anyway.</p>
|
ROMs only check for input once per frame anyway.</p>
|
||||||
|
|
||||||
<p>Conditional breaks appear in "listbreaks", numbered starting from
|
<p>Conditional breaks appear in "listBreaks", numbered starting from
|
||||||
zero. You can remove a cond-break with "delbreakif number", where
|
zero. You can remove a cond-break with "delBreakIf number", where
|
||||||
the number comes from "listbreaks" or by entering the same conditional break again.</p>
|
the number comes from "listBreaks" or by entering the same conditional break again.</p>
|
||||||
|
|
||||||
<p>Any time the debugger is entered due to a trap, breakpoint, or
|
<p>Any time the debugger is entered due to a trap, breakpoint, or
|
||||||
conditional break, the reason will be displayed in the
|
conditional break, the reason will be displayed in the
|
||||||
|
@ -684,16 +690,16 @@ conditional break, the reason will be displayed in the
|
||||||
<h4><a name="Functions">Functions</a></h4>
|
<h4><a name="Functions">Functions</a></h4>
|
||||||
|
|
||||||
<p>There is one annoyance about complex expressions: once we
|
<p>There is one annoyance about complex expressions: once we
|
||||||
remove the conditional break with "delbreakif" or "clearbreaks",
|
remove the conditional break with "delBreakIf" or "clearBreaks",
|
||||||
we'd have to retype it (or search backwards with the up-arrow key)
|
we'd have to retype it (or search backwards with the up-arrow key)
|
||||||
if we wanted to use it again.</p>
|
if we wanted to use it again.</p>
|
||||||
|
|
||||||
<p>We can avoid this by defining the expression as a function, then using
|
<p>We can avoid this by defining the expression as a function, then using
|
||||||
"breakif function_name":</p>
|
"breakIf function_name":</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
function gameReset { !(*SWCHB & 1 ) }
|
function gameReset { !(*SWCHB & 1 ) }
|
||||||
breakif gameReset
|
breakIf gameReset
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>Now we have a meaningful name for the condition, so we can use it again.
|
<p>Now we have a meaningful name for the condition, so we can use it again.
|
||||||
|
@ -703,16 +709,16 @@ if the Game Select switch is pressed. We want to break when the user
|
||||||
presses both Select and Reset:</p>
|
presses both Select and Reset:</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
breakif { gameReset && gameSelect }
|
breakIf { gameReset && gameSelect }
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>User-defined functions appear in "listfunctions", which shows the label
|
<p>User-defined functions appear in "listFunctions", which shows the label
|
||||||
and expression for each function. Functions can be removed with
|
and expression for each function. Functions can be removed with
|
||||||
"delfunction label", where the labels come from "listfunctions".</p>
|
"delFunction label", where the labels come from "listFunctions".</p>
|
||||||
|
|
||||||
<h4><a name="BuiltInFunctions">Built-in Functions</a></h4>
|
<h4><a name="BuiltInFunctions">Built-in Functions</a></h4>
|
||||||
|
|
||||||
<p>Stella has some pre-defined functions for use with the "breakif"
|
<p>Stella has some pre-defined functions for use with the "breakIf"
|
||||||
command. These allow you to break and enter the debugger on various
|
command. These allow you to break and enter the debugger on various
|
||||||
conditions without having to define the conditions yourself.</p>
|
conditions without having to define the conditions yourself.</p>
|
||||||
|
|
||||||
|
@ -723,24 +729,24 @@ Stella debugger.</p>
|
||||||
|
|
||||||
<table border="1" cellpadding=4>
|
<table border="1" cellpadding=4>
|
||||||
<tr><th>Function</th><th>Definition</th><th>Description</th></tr>
|
<tr><th>Function</th><th>Definition</th><th>Description</th></tr>
|
||||||
<tr><td> _joy0left</td><td> !(*SWCHA & $40)</td><td> Left joystick moved left</td></tr>
|
<tr><td> _joy0Left</td><td> !(*SWCHA & $40)</td><td> Left joystick moved left</td></tr>
|
||||||
<tr><td> _joy0right</td><td> !(*SWCHA & $80)</td><td> Left joystick moved right</td></tr>
|
<tr><td> _joy0Right</td><td> !(*SWCHA & $80)</td><td> Left joystick moved right</td></tr>
|
||||||
<tr><td> _joy0up</td><td> !(*SWCHA & $10)</td><td> Left joystick moved up</td></tr>
|
<tr><td> _joy0Up</td><td> !(*SWCHA & $10)</td><td> Left joystick moved up</td></tr>
|
||||||
<tr><td> _joy0down</td><td> !(*SWCHA & $20)</td><td> Left joystick moved down</td></tr>
|
<tr><td> _joy0Down</td><td> !(*SWCHA & $20)</td><td> Left joystick moved down</td></tr>
|
||||||
<tr><td> _joy0button</td><td> !(*INPT4 & $80)</td><td> Left joystick button pressed</td></tr>
|
<tr><td> _joy0Fire</td><td> !(*INPT4 & $80)</td><td> Left joystick fire button pressed</td></tr>
|
||||||
<tr><td> _joy1left</td><td> !(*SWCHA & $04)</td><td> Right joystick moved left</td></tr>
|
<tr><td> _joy1Left</td><td> !(*SWCHA & $04)</td><td> Right joystick moved left</td></tr>
|
||||||
<tr><td> _joy1right</td><td> !(*SWCHA & $08)</td><td> Right joystick moved right</td></tr>
|
<tr><td> _joy1Right</td><td> !(*SWCHA & $08)</td><td> Right joystick moved right</td></tr>
|
||||||
<tr><td> _joy1up</td><td> !(*SWCHA & $01)</td><td> Right joystick moved up</td></tr>
|
<tr><td> _joy1Up</td><td> !(*SWCHA & $01)</td><td> Right joystick moved up</td></tr>
|
||||||
<tr><td> _joy1down</td><td> !(*SWCHA & $02)</td><td> Right joystick moved down</td></tr>
|
<tr><td> _joy1Down</td><td> !(*SWCHA & $02)</td><td> Right joystick moved down</td></tr>
|
||||||
<tr><td> _joy1button</td><td> !(*INPT5 & $80)</td><td> Right joystick button pressed</td></tr>
|
<tr><td> _joy1Fire</td><td> !(*INPT5 & $80)</td><td> Right joystick fire button pressed</td></tr>
|
||||||
<tr><td> _select</td><td> !(*SWCHB & $02)</td><td> Game Select pressed</td></tr>
|
<tr><td> _select</td><td> !(*SWCHB & $02)</td><td> Game Select pressed</td></tr>
|
||||||
<tr><td> _reset</td><td> !(*SWCHB & $01)</td><td> Game Reset pressed</td></tr>
|
<tr><td> _reset</td><td> !(*SWCHB & $01)</td><td> Game Reset pressed</td></tr>
|
||||||
<tr><td> _color</td><td> *SWCHB & $08</td><td> Color/BW set to Color</td></tr>
|
<tr><td> _color</td><td> *SWCHB & $08</td><td> Color/BW set to Color</td></tr>
|
||||||
<tr><td> _bw</td><td> !(*SWCHB & $08)</td><td> Color/BW set to BW</td></tr>
|
<tr><td> _bw</td><td> !(*SWCHB & $08)</td><td> Color/BW set to BW</td></tr>
|
||||||
<tr><td> _diff0b</td><td> !(*SWCHB & $40)</td><td> Left difficulty set to B (easy)</td></tr>
|
<tr><td> _diff0B</td><td> !(*SWCHB & $40)</td><td> Left difficulty set to B (easy)</td></tr>
|
||||||
<tr><td> _diff0a</td><td> *SWCHB & $40</td><td> Left difficulty set to A (hard)</td></tr>
|
<tr><td> _diff0A</td><td> *SWCHB & $40</td><td> Left difficulty set to A (hard)</td></tr>
|
||||||
<tr><td> _diff1b</td><td> !(*SWCHB & $80)</td><td> Right difficulty set to B (easy)</td></tr>
|
<tr><td> _diff1B</td><td> !(*SWCHB & $80)</td><td> Right difficulty set to B (easy)</td></tr>
|
||||||
<tr><td> _diff1a</td><td> *SWCHB & $80</td><td> Right difficulty set to A (hard)</td></tr>
|
<tr><td> _diff1A</td><td> *SWCHB & $80</td><td> Right difficulty set to A (hard)</td></tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<p>Don't worry about memorizing them all: the Prompt "help" command
|
<p>Don't worry about memorizing them all: the Prompt "help" command
|
||||||
|
@ -756,36 +762,36 @@ that holds 'number of scanlines' on an actual console).</p>
|
||||||
<table border="1" cellpadding=4>
|
<table border="1" cellpadding=4>
|
||||||
<tr><th>Function</th><th>Description</th></tr>
|
<tr><th>Function</th><th>Description</th></tr>
|
||||||
<tr><td> _bank</td><td> Currently selected bank</td></tr>
|
<tr><td> _bank</td><td> Currently selected bank</td></tr>
|
||||||
<tr><td> _cclocks</td><td> Color clocks on a scanline</td></tr>
|
<tr><td> _cClocks</td><td> Color clocks on a scanLine</td></tr>
|
||||||
<tr><td> _cycleshi</td><td> Higher 32 bits of number of cycles since emulation started</td></tr>
|
<tr><td> _cyclesHi</td><td> Higher 32 bits of number of cycles since emulation started</td></tr>
|
||||||
<tr><td> _cycleslo</td><td> Lower 32 bits of number of cycles since emulation started</td></tr>
|
<tr><td> _cyclesLo</td><td> Lower 32 bits of number of cycles since emulation started</td></tr>
|
||||||
<tr><td> _fcount</td><td> Number of frames since emulation started</td></tr>
|
<tr><td> _fCount</td><td> Number of frames since emulation started</td></tr>
|
||||||
<tr><td> _fcycles</td><td> Number of cycles since frame started</td></tr>
|
<tr><td> _fCycles</td><td> Number of cycles since frame started</td></tr>
|
||||||
<tr><td> _ftimreadcycles</td><td>Number of cycles used by timer reads since frame started</td></tr>
|
<tr><td> _fTimReadCycles</td><td>Number of cycles used by timer reads since frame started</td></tr>
|
||||||
<tr><td> _fwsynccycles</td><td>Number of cycles skipped by WSYNC since frame started</td></tr>
|
<tr><td> _fWsyncCycles</td><td>Number of cycles skipped by WSYNC since frame started</td></tr>
|
||||||
<tr><td> _icycles</td><td> Number of cycles of last instruction</td></tr>
|
<tr><td> _iCycles</td><td> Number of cycles of last instruction</td></tr>
|
||||||
<tr><td> _scan</td><td> Current scanline count</td></tr>
|
<tr><td> _scan</td><td> Current scanLine count</td></tr>
|
||||||
<tr><td> _scanend</td><td> Scanline count at end of last frame</td></tr>
|
<tr><td> _scanEnd</td><td> Scanline count at end of last frame</td></tr>
|
||||||
<tr><td> _scycles</td><td> Number of cycles in current scanline</td></tr>
|
<tr><td> _sCycles</td><td> Number of cycles in current scanLine</td></tr>
|
||||||
<tr><td> _timwrapread</td><td> Timer read wrapped on this cycle</td></tr>
|
<tr><td> _timWrapRead</td><td> Timer read wrapped on this cycle</td></tr>
|
||||||
<tr><td> _timwrapwrite</td><td> Timer write wrapped on this cycle</td></tr>
|
<tr><td> _timWrapWrite</td><td> Timer write wrapped on this cycle</td></tr>
|
||||||
<tr><td> _vblank</td><td> Whether vertical blank is enabled (1 or 0)</td></tr>
|
<tr><td> _vBlank</td><td> Whether vertical blank is enabled (1 or 0)</td></tr>
|
||||||
<tr><td> _vsync</td><td> Whether vertical sync is enabled (1 or 0)</td></tr>
|
<tr><td> _vSync</td><td> Whether vertical sync is enabled (1 or 0)</td></tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<p><b>_scan</b> always contains the current scanline count. You can use
|
<p><b>_scan</b> always contains the current scanLine count. You can use
|
||||||
this to break your program in the middle of your kernel. Example:</p>
|
this to break your program in the middle of your kernel. Example:</p>
|
||||||
<pre>
|
<pre>
|
||||||
breakif _scan==#64
|
breakIf _scan==#64
|
||||||
</pre>
|
</pre>
|
||||||
<p>This will cause Stella to enter the debugger when the TIA reaches the
|
<p>This will cause Stella to enter the debugger when the TIA reaches the
|
||||||
beginning of the 64th scanline.</p>
|
beginning of the 64th scanLine.</p>
|
||||||
|
|
||||||
<p><b>_bank</b> always contains the currently selected bank. For 2K or 4K
|
<p><b>_bank</b> always contains the currently selected bank. For 2K or 4K
|
||||||
(non-bankswitched) ROMs, it will always contain 0. One useful use is:</p>
|
(non-bankswitched) ROMs, it will always contain 0. One useful use is:</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
breakif { pc==myLabel && _bank==1 }
|
breakIf { pc==myLabel && _bank==1 }
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>This is similar to setting a regular breakpoint, but it will only trigger
|
<p>This is similar to setting a regular breakpoint, but it will only trigger
|
||||||
|
@ -804,8 +810,8 @@ pointed to by the Y register, even if the Y register changes.</p>
|
||||||
|
|
||||||
<p>The watches are numbered. The numbers are printed along with the
|
<p>The watches are numbered. The numbers are printed along with the
|
||||||
watches, so you can tell which is which. To delete a watch use the
|
watches, so you can tell which is which. To delete a watch use the
|
||||||
"delwatch" command with the watch number (1 to whatever). You can
|
"delWatch" command with the watch number (1 to whatever). You can
|
||||||
also delete them all with the "clearwatches" command.</p>
|
also delete them all with the "clearWatches" command.</p>
|
||||||
|
|
||||||
<p>Note that there's no real point in watching a label or CPU register
|
<p>Note that there's no real point in watching a label or CPU register
|
||||||
without dereferencing it: Labels are constants, and CPU registers
|
without dereferencing it: Labels are constants, and CPU registers
|
||||||
|
@ -818,7 +824,7 @@ accesses to a memory address, rather than specific location in the
|
||||||
program. They're useful for finding code that modifies TIA registers
|
program. They're useful for finding code that modifies TIA registers
|
||||||
or memory.</p>
|
or memory.</p>
|
||||||
|
|
||||||
<p>Traps can also combined with a condition ("trapif"). If an access
|
<p>Traps can also combined with a condition ("trapIf"). If an access
|
||||||
to a memory address is caught, the condition is evaluated additionally.
|
to a memory address is caught, the condition is evaluated additionally.
|
||||||
Only if the condition is true too, the emulations stops. For details
|
Only if the condition is true too, the emulations stops. For details
|
||||||
about conditions see <a href="#ConditionalBreaks"><b>Conditional Breaks</b></a> described above.</p>
|
about conditions see <a href="#ConditionalBreaks"><b>Conditional Breaks</b></a> described above.</p>
|
||||||
|
@ -842,12 +848,12 @@ so the best we can do is stop before the next instruction runs.</p>
|
||||||
<p>Traps come in two varieties: read access traps and write access traps.
|
<p>Traps come in two varieties: read access traps and write access traps.
|
||||||
It is possible to set both types of trap on the same address (that's
|
It is possible to set both types of trap on the same address (that's
|
||||||
what the plain "trap" command does). To set a read or write only trap,
|
what the plain "trap" command does). To set a read or write only trap,
|
||||||
use "trapread(if)" or "trapwrite(if)".
|
use "trapRead(if)" or "trapWrite(if)".
|
||||||
|
|
||||||
<p>All traps appear in "listtraps", numbered starting from zero. You
|
<p>All traps appear in "listTraps", numbered starting from zero. You
|
||||||
can remove a trap with "deltrap number", where the number comes from
|
can remove a trap with "delTrap number", where the number comes from
|
||||||
"listtraps" or by entering the identical trap again. You can get rid of
|
"listTraps" or by entering the identical trap again. You can get rid of
|
||||||
all traps at once with the "cleartraps" command.</p></p>
|
all traps at once with the "clearTraps" command.</p></p>
|
||||||
|
|
||||||
</br>
|
</br>
|
||||||
<h3><a name="SaveWork">Save your work!</a></h3>
|
<h3><a name="SaveWork">Save your work!</a></h3>
|
||||||
|
@ -856,58 +862,61 @@ later re-use.</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<b><a name="savecmd">save</a></b>: If you've defined a lot of complex functions, you probably will
|
<b><a name="savecmd">save</a></b>: If you've defined a lot of complex
|
||||||
want to re-use them in future runs of the debugger. You can save all
|
functions, you probably will want to re-use them in future runs of the
|
||||||
your functions, breakpoints, conditional breaks, traps and watches with the
|
debugger. You can save all your functions, breakpoints, conditional breaks,
|
||||||
"save" command. If you name your saved file the same as the ROM filename
|
traps and watches with the "save" command. By default it is saved in the
|
||||||
and place it in the ROM directory, it will be auto-loaded next time you
|
user directory with the same as the ROM filename. In this case it will be
|
||||||
load the same ROM in Stella. The saved file is just a plain text file
|
auto-loaded next time you load the same ROM in Stella. The saved file is
|
||||||
called "<rom_filename>.script", so you can edit it and add new functions, etc.
|
just a plain text file called "<rom_filename>.script", so you can
|
||||||
|
edit it and add more functions, etc.
|
||||||
|
<p>Use "autoSave" to automatically execute the "save" command when
|
||||||
|
exiting the debugger.</p>
|
||||||
<p>Note: While "save" is ROM specific, you can also create a file called
|
<p>Note: While "save" is ROM specific, you can also create a file called
|
||||||
"autoexec.script" which will be loaded when the debugger starts, no matter
|
"autoexec.script" which will be loaded when the debugger starts, no matter
|
||||||
what ROM you have loaded.<p>
|
what ROM you have loaded.<p>
|
||||||
See <a href="#Startup"><b>Startup</b></a> for details.
|
See <a href="#Startup"><b>Startup</b></a> for details.
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<b>saveconfig</b>: The "saveconfig" command creates a
|
<b>saveConfig</b>: The "saveConfig" command creates a
|
||||||
<a href="#DistellaConfiguration"><b>DiStella Configuration File</b></a> which is
|
<a href="#DistellaConfiguration"><b>DiStella Configuration File</b></a> which is
|
||||||
based on Stella's dynamic and static analysis of the current ROM.
|
based on Stella's dynamic and static analysis of the current ROM.
|
||||||
<p>This will be automatically loaded the next time your start the debugger.
|
<p>This will be automatically loaded the next time your start the debugger.
|
||||||
From there on, you can continue analyzing the ROM and then use "saveconfig"
|
From there on, you can continue analyzing the ROM and then use "saveConfig"
|
||||||
again to update the configuration. You can also use "loadconfig" to load it
|
again to update the configuration. You can also use "loadConfig" to load it
|
||||||
manually.
|
manually.
|
||||||
<p>Note that this is not tested for multi-banked ROMs.</p>
|
<p>Note that this is not tested for multi-banked ROMs.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<b>savedis</b>:
|
<b>saveDis</b>:
|
||||||
While your are playing or debugging a game, Stella will gather dynamic
|
While your are playing or debugging a game, Stella will gather dynamic
|
||||||
information about the ROM. It can then use that information together with
|
information about the ROM. It can then use that information together with
|
||||||
a static analysis of the ROM and therefore create a better disassembly
|
a static analysis of the ROM and therefore create a better disassembly
|
||||||
than DiStella alone. "savedis" allows you to save that disassembly as the
|
than DiStella alone. "saveDis" allows you to save that disassembly as the
|
||||||
result of this combined analysis.
|
result of this combined analysis.
|
||||||
<p>Note that this currently only works for single banked ROMs. For larger
|
<p>Note that this currently only works for single banked ROMs. For larger
|
||||||
ROMs, the created disassembly is incomplete.</p>
|
ROMs, the created disassembly is incomplete.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p><b>saverom</b>:
|
<p><b>saveRom</b>:
|
||||||
If you have manipulated a ROM, you can save it with "saverom". The file is
|
If you have manipulated a ROM, you can save it with "saveRom". The file is
|
||||||
named "<rom_filename>.a26".</p>
|
named "<rom_filename>.a26".</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p><b>saveses</b>:
|
<p><b>saveSes</b>:
|
||||||
The "saveses" command dumps the whole prompt session into a file named
|
The "saveSes" command dumps the whole prompt session into a file named
|
||||||
"<YYYY-MM-DD_HH-mm-ss>.txt". So you can later lookup what you did exactly
|
"<YYYY-MM-DD_HH-mm-ss>.txt". So you can later lookup what you did exactly
|
||||||
when you were debugging at that time.</p>
|
when you were debugging at that time.</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p><b>saveallstates</b>:
|
<p><b>saveAllStates</b>:
|
||||||
This command works identical to the save all states hotkey (Alt + F9) during emulation.
|
This command works identical to the save all states hotkey (Alt + F9) during emulation.
|
||||||
The saved states can be loaded with "loadallstates".</p>
|
The saved states can be loaded with "loadAllStates".</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p><b>savestate</b>:
|
<p><b>saveState</b>:
|
||||||
This command works identical to the save state hotkey (F9) during emulation.
|
This command works identical to the save state hotkey (F9) during emulation.
|
||||||
Any previously saved state can be loaded with "loadstate" plus the slot
|
Any previously saved state can be loaded with "loadState" plus the slot
|
||||||
number (0-9).</p>
|
number (0-9).</p>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -921,63 +930,66 @@ Type "help 'cmd'" to see extended information about the given command.</p>
|
||||||
<pre>
|
<pre>
|
||||||
a - Set Accumulator to <value>
|
a - Set Accumulator to <value>
|
||||||
aud - Mark 'AUD' range in disassembly
|
aud - Mark 'AUD' range in disassembly
|
||||||
|
autoSave - Automatically execute "save" when exiting the debugger
|
||||||
base - Set default number base to <base> (bin, dec, hex)
|
base - Set default number base to <base> (bin, dec, hex)
|
||||||
bcol - Mark 'BCOL' range in disassembly
|
bCol - Mark 'BCOL' range in disassembly
|
||||||
break - Set/clear breakpoint at <address> and <bank>
|
break - Set/clear breakpoint at <address> and <bank>
|
||||||
breakif - Set/clear breakpoint on <condition>
|
breakIf - Set/clear breakpoint on <condition>
|
||||||
breaklabel - Set/clear breakpoint on <address> (no mirrors, all banks)
|
breakLabel - Set/clear breakpoint on <address> (no mirrors, all banks)
|
||||||
c - Carry Flag: set (0 or 1), or toggle (no arg)
|
c - Carry Flag: set (0 or 1), or toggle (no arg)
|
||||||
cheat - Use a cheat code (see manual for cheat types)
|
cheat - Use a cheat code (see manual for cheat types)
|
||||||
clearbreaks - Clear all breakpoints
|
clearBreaks - Clear all breakpoints
|
||||||
clearconfig - Clear DiStella config directives [bank xx]
|
clearConfig - Clear DiStella config directives [bank xx]
|
||||||
clearsavestateifs - Clear all savestate points
|
clearHistory - Clear the prompt history
|
||||||
cleartraps - Clear all traps
|
clearSaveStateIfs - Clear all saveState points
|
||||||
clearwatches - Clear all watches
|
clearTraps - Clear all traps
|
||||||
|
clearWatches - Clear all watches
|
||||||
cls - Clear prompt area of text
|
cls - Clear prompt area of text
|
||||||
code - Mark 'CODE' range in disassembly
|
code - Mark 'CODE' range in disassembly
|
||||||
col - Mark 'COL' range in disassembly
|
col - Mark 'COL' range in disassembly
|
||||||
colortest - Show value xx as TIA color
|
colorTest - Show value xx as TIA color
|
||||||
d - Decimal Mode Flag: set (0 or 1), or toggle (no arg)
|
d - Decimal Mode Flag: set (0 or 1), or toggle (no arg)
|
||||||
data - Mark 'DATA' range in disassembly
|
data - Mark 'DATA' range in disassembly
|
||||||
debugcolors - Show Fixed Debug Colors information
|
debugColors - Show Fixed Debug Colors information
|
||||||
define - Define label xx for address yy
|
define - Define label xx for address yy
|
||||||
delbreakif - Delete conditional breakif <xx>
|
delBreakIf - Delete conditional breakIf <xx>
|
||||||
delfunction - Delete function with label xx
|
delFunction - Delete function with label xx
|
||||||
delsavestateif - Delete conditional savestate point <xx>
|
delSaveStateIf - Delete conditional saveState point <xx>
|
||||||
deltrap - Delete trap <xx>
|
delTrap - Delete trap <xx>
|
||||||
delwatch - Delete watch <xx>
|
delWatch - Delete watch <xx>
|
||||||
disasm - Disassemble address xx [yy lines] (default=PC)
|
disAsm - Disassemble address xx [yy lines] (default=PC)
|
||||||
dump - Dump data at address <xx> [to yy] [1: memory; 2: CPU state; 4: input regs] [?]
|
dump - Dump data at address <xx> [to yy] [1: memory; 2: CPU state; 4: input regs] [?]
|
||||||
exec - Execute script file <xx> [prefix]
|
exec - Execute script file <xx> [prefix]
|
||||||
exitrom - Exit emulator, return to ROM launcher
|
exitRom - Exit emulator, return to ROM launcher
|
||||||
frame - Advance emulation by <xx> frames (default=1)
|
frame - Advance emulation by <xx> frames (default=1)
|
||||||
function - Define function name xx for expression yy
|
function - Define function name xx for expression yy
|
||||||
gfx - Mark 'GFX' range in disassembly
|
gfx - Mark 'GFX' range in disassembly
|
||||||
help - help <command>
|
help - help <command>
|
||||||
joy0up - Set joystick 0 up direction to value <x> (0 or 1), or toggle (no arg)
|
joy0Up - Set joystick 0 up direction to value <x> (0 or 1), or toggle (no arg)
|
||||||
joy0down - Set joystick 0 down direction to value <x> (0 or 1), or toggle (no arg)
|
joy0Down - Set joystick 0 down direction to value <x> (0 or 1), or toggle (no arg)
|
||||||
joy0left - Set joystick 0 left direction to value <x> (0 or 1), or toggle (no arg)
|
joy0Left - Set joystick 0 left direction to value <x> (0 or 1), or toggle (no arg)
|
||||||
joy0right - Set joystick 0 right direction to value <x> (0 or 1), or toggle (no arg)
|
joy0Right - Set joystick 0 right direction to value <x> (0 or 1), or toggle (no arg)
|
||||||
joy0fire - Set joystick 0 fire button to value <x> (0 or 1), or toggle (no arg)
|
joy0Fire - Set joystick 0 fire button to value <x> (0 or 1), or toggle (no arg)
|
||||||
joy1up - Set joystick 1 up direction to value <x> (0 or 1), or toggle (no arg)
|
joy1Up - Set joystick 1 up direction to value <x> (0 or 1), or toggle (no arg)
|
||||||
joy1down - Set joystick 1 down direction to value <x> (0 or 1), or toggle (no arg)
|
joy1Down - Set joystick 1 down direction to value <x> (0 or 1), or toggle (no arg)
|
||||||
joy1left - Set joystick 1 left direction to value <x> (0 or 1), or toggle (no arg)
|
joy1Left - Set joystick 1 left direction to value <x> (0 or 1), or toggle (no arg)
|
||||||
joy1right - Set joystick 1 right direction to value <x> (0 or 1), or toggle (no arg)
|
joy1Right - Set joystick 1 right direction to value <x> (0 or 1), or toggle (no arg)
|
||||||
joy1fire - Set joystick 1 fire button to value <x> (0 or 1), or toggle (no arg)
|
joy1Fire - Set joystick 1 fire button to value <x> (0 or 1), or toggle (no arg)
|
||||||
jump - Scroll disassembly to address xx
|
jump - Scroll disassembly to address xx
|
||||||
listbreaks - List breakpoints
|
listBreaks - List breakpoints
|
||||||
listconfig - List DiStella config directives [bank xx]
|
listConfig - List DiStella config directives [bank xx]
|
||||||
listfunctions - List user-defined functions
|
listFunctions - List user-defined functions
|
||||||
listsavestateifs - List savestate points
|
listSaveStateIfs - List saveState points
|
||||||
listtraps - List traps
|
listTraps - List traps
|
||||||
loadconfig - Load DiStella config file
|
loadConfig - Load DiStella config file
|
||||||
loadallstates - Load all emulator states
|
loadAllStates - Load all emulator states
|
||||||
loadstate - Load emulator state xx (0-9)
|
loadState - Load emulator state xx (0-9)
|
||||||
|
logBreaks - Logs breaks and traps and continues emulation
|
||||||
n - Negative Flag: set (0 or 1), or toggle (no arg)
|
n - Negative Flag: set (0 or 1), or toggle (no arg)
|
||||||
palette - Show current TIA palette
|
palette - Show current TIA palette
|
||||||
pc - Set Program Counter to address xx
|
pc - Set Program Counter to address xx
|
||||||
pcol - Mark 'PCOL' range in disassembly
|
pCol - Mark 'PCOL' range in disassembly
|
||||||
pgfx - Mark 'PGFX' range in disassembly
|
pGfx - Mark 'PGFX' range in disassembly
|
||||||
print - Evaluate/print expression xx in hex/dec/binary
|
print - Evaluate/print expression xx in hex/dec/binary
|
||||||
ram - Show ZP RAM, or set address xx to yy1 [yy2 ...]
|
ram - Show ZP RAM, or set address xx to yy1 [yy2 ...]
|
||||||
reset - Reset system to power-on state
|
reset - Reset system to power-on state
|
||||||
|
@ -986,32 +998,32 @@ clearsavestateifs - Clear all savestate points
|
||||||
rom - Set ROM address xx to yy1 [yy2 ...]
|
rom - Set ROM address xx to yy1 [yy2 ...]
|
||||||
row - Mark 'ROW' range in disassembly
|
row - Mark 'ROW' range in disassembly
|
||||||
run - Exit debugger, return to emulator
|
run - Exit debugger, return to emulator
|
||||||
runto - Run until string xx in disassembly
|
runTo - Run until string xx in disassembly
|
||||||
runtopc - Run until PC is set to value xx
|
runToPc - Run until PC is set to value xx
|
||||||
s - Set Stack Pointer to value xx
|
s - Set Stack Pointer to value xx
|
||||||
save - Save breaks, watches, traps and functions to file <xx or ?>
|
save - Save breaks, watches, traps and functions to file [xx or ?]
|
||||||
saveaccess - Save access counters to CSV file [?]
|
saveAccess - Save access counters to CSV file [?]
|
||||||
saveconfig - Save DiStella config file (with default name)
|
saveConfig - Save DiStella config file (with default name)
|
||||||
savedis - Save DiStella disassembly to file [?]
|
saveDis - Save DiStella disassembly to file [?]
|
||||||
saverom - Save (possibly patched) ROM to file [?]
|
saveRom - Save (possibly patched) ROM to file [?]
|
||||||
saveses - Save console session to file [?]
|
saveSes - Save console session to file [?]
|
||||||
savesnap - Save current TIA image to PNG file
|
saveSnap - Save current TIA image to PNG file
|
||||||
saveallstates - Save all emulator states
|
saveAllStates - Save all emulator states
|
||||||
savestate - Save emulator state xx (valid args 0-9)
|
saveState - Save emulator state xx (valid args 0-9)
|
||||||
savestateif - Create savestate on <condition>
|
saveStateIf - Create saveState on <condition>
|
||||||
scanline - Advance emulation by <xx> scanlines (default=1)
|
scanLine - Advance emulation by <xx> scanlines (default=1)
|
||||||
step - Single step CPU [with count xx]
|
step - Single step CPU [with count xx]
|
||||||
stepwhile - Single step CPU while <condition> is true
|
stepWhile - Single step CPU while <condition> is true
|
||||||
tia - Show TIA state
|
tia - Show TIA state
|
||||||
trace - Single step CPU over subroutines [with count xx]
|
trace - Single step CPU over subroutines [with count xx]
|
||||||
trap - Trap read/write access to address(es) xx [yy]
|
trap - Trap read/write access to address(es) xx [yy]
|
||||||
trapif - On <condition> trap R/W access to address(es) xx [yy]
|
trapIf - On <condition> trap R/W access to address(es) xx [yy]
|
||||||
trapread - Trap read access to address(es) xx [yy]
|
trapRead - Trap read access to address(es) xx [yy]
|
||||||
trapreadif - On <condition> trap read access to address(es) xx [yy]
|
trapReadIf - On <condition> trap read access to address(es) xx [yy]
|
||||||
trapwrite - Trap write access to address(es) xx [yy]
|
trapWrite - Trap write access to address(es) xx [yy]
|
||||||
trapwriteif - On <condition> trap write access to address(es) xx [yy]
|
trapWriteIf - On <condition> trap write access to address(es) xx [yy]
|
||||||
type - Show disassembly type for address xx [yy]
|
type - Show disassembly type for address xx [yy]
|
||||||
uhex - Toggle upper/lowercase HEX display
|
uHex - Toggle upper/lowercase HEX display
|
||||||
undef - Undefine label xx (if defined)
|
undef - Undefine label xx (if defined)
|
||||||
unwind - Unwind state state by one or [xx] steps/traces/scanlines/frames...
|
unwind - Unwind state state by one or [xx] steps/traces/scanlines/frames...
|
||||||
v - Overflow Flag: set (0 or 1), or toggle (no arg)
|
v - Overflow Flag: set (0 or 1), or toggle (no arg)
|
||||||
|
@ -1111,12 +1123,12 @@ volume resulting from the two channel volumes.</p>
|
||||||
<p>In the upper left of the debugger, you'll see the current frame of
|
<p>In the upper left of the debugger, you'll see the current frame of
|
||||||
video as generated by the TIA. If a complete frame hasn't been drawn,
|
video as generated by the TIA. If a complete frame hasn't been drawn,
|
||||||
the partial contents of the current frame will be displayed up to the
|
the partial contents of the current frame will be displayed up to the
|
||||||
current scanline, with the contents of the old frame (in black &
|
current scanLine, with the contents of the old frame (in black &
|
||||||
white) filling the rest of the display. Note that if 'phosphor mode'
|
white) filling the rest of the display. Note that if 'phosphor mode'
|
||||||
or TV effects are enabled, you won't see the effects here; this shows the
|
or TV effects are enabled, you won't see the effects here; this shows the
|
||||||
<b>raw</b> TIA image only.</p>
|
<b>raw</b> TIA image only.</p>
|
||||||
|
|
||||||
<p>To e.g. watch the TIA draw the frame one scanline at a time, you can
|
<p>To e.g. watch the TIA draw the frame one scanLine at a time, you can
|
||||||
use the 'Scan+1' button, the prompt "scan" command or the Control-L key.</p>
|
use the 'Scan+1' button, the prompt "scan" command or the Control-L key.</p>
|
||||||
|
|
||||||
<p>You can also right-click anywhere in this window to show a context menu,
|
<p>You can also right-click anywhere in this window to show a context menu,
|
||||||
|
@ -1124,10 +1136,10 @@ as illustrated:</p>
|
||||||
<p><img src="graphics/debugger_tiaoutcmenu.png"></p>
|
<p><img src="graphics/debugger_tiaoutcmenu.png"></p>
|
||||||
<p>The options are as follows:</p>
|
<p>The options are as follows:</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li><b>Fill to scanline</b>: This option will draw all scanlines up to the
|
<li><b>Fill to scanLine</b>: This option will draw all scanlines up to the
|
||||||
vertical position where the mouse was clicked (see also <a href="#TIAZoom"><b>TIA Zoom</b></a>).</li>
|
vertical position where the mouse was clicked (see also <a href="#TIAZoom"><b>TIA Zoom</b></a>).</li>
|
||||||
<li><b>Toggle breakpoint</b>: Will toggle a conditional breakpoint at the
|
<li><b>Toggle breakpoint</b>: Will toggle a conditional breakpoint at the
|
||||||
scanline where the mouse was clicked. You can also use a left-click or
|
scanLine where the mouse was clicked. You can also use a left-click or
|
||||||
the Prompt Tab commands to list and turn off the breakpoint
|
the Prompt Tab commands to list and turn off the breakpoint
|
||||||
(see also <a href="#TIAZoom"><b>TIA Zoom</b></a>).</li>
|
(see also <a href="#TIAZoom"><b>TIA Zoom</b></a>).</li>
|
||||||
<li><b>Set zoom position</b>: Influences what is shown in the TIA
|
<li><b>Set zoom position</b>: Influences what is shown in the TIA
|
||||||
|
@ -1148,27 +1160,27 @@ as illustrated:</p>
|
||||||
<p>The indicators are as follows (note that all these are read-only):</p>
|
<p>The indicators are as follows (note that all these are read-only):</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li><b>Frame Cycls</b>: The number of CPU cycles that have been executed this frame since
|
<li><b>Frame Cycls</b>: The number of CPU cycles that have been executed this frame since
|
||||||
VSYNC was cleared at scanline 0.</li>
|
VSYNC was cleared at scanLine 0.</li>
|
||||||
<li><b>WSync Cycls</b>: The number of CPU cycles that have been skipped by WSYNC this frame since
|
<li><b>WSync Cycls</b>: The number of CPU cycles that have been skipped by WSYNC this frame since
|
||||||
VSYNC was cleared at scanline 0.</li>
|
VSYNC was cleared at scanLine 0.</li>
|
||||||
<li><b>Timer Cycls</b>: The number of CPU cycles (approximately) that have been used by timer read loops since
|
<li><b>Timer Cycls</b>: The number of CPU cycles (approximately) that have been used by timer read loops since
|
||||||
VSYNC was cleared at scanline 0.</li>
|
VSYNC was cleared at scanLine 0.</li>
|
||||||
<li><b>Total</b>: The total number of CPU cycles since this ROM was loaded or reset.</li>
|
<li><b>Total</b>: The total number of CPU cycles since this ROM was loaded or reset.</li>
|
||||||
<li><b>Delta</b>: The number of CPU cycles that have been executed since the last debugger
|
<li><b>Delta</b>: The number of CPU cycles that have been executed since the last debugger
|
||||||
interrupt.</li>
|
interrupt.</li>
|
||||||
<li><b>Frame Cnt.</b>: The number of frames since this ROM was loaded or reset.</li>
|
<li><b>Frame Cnt.</b>: The number of frames since this ROM was loaded or reset.</li>
|
||||||
<li><b>Scanline</b>: The scanline that's currently being drawn, and the count from the
|
<li><b>Scanline</b>: The scanLine that's currently being drawn, and the count from the
|
||||||
previous frame. Scanline 0 is the one on which VSYNC is cleared (after being set for
|
previous frame. Scanline 0 is the one on which VSYNC is cleared (after being set for
|
||||||
3 scanlines, as per the Stella Programmer's Guide).</li>
|
3 scanlines, as per the Stella Programmer's Guide).</li>
|
||||||
<li><b>Scan Cycle</b>: The number of CPU cycles that have been executed since the beginning
|
<li><b>Scan Cycle</b>: The number of CPU cycles that have been executed since the beginning
|
||||||
of the current scanline.</li>
|
of the current scanLine.</li>
|
||||||
<li><b>Pixel Pos</b>: The current number of visible color clocks that have been displayed on
|
<li><b>Pixel Pos</b>: The current number of visible color clocks that have been displayed on
|
||||||
the current scanline, starting from the beginning of the Horizontal Blank period.
|
the current scanLine, starting from the beginning of the Horizontal Blank period.
|
||||||
During HBLANK, this value will be negative (representing the number of clocks
|
During HBLANK, this value will be negative (representing the number of clocks
|
||||||
until the first visible one). Since there are 68 color clocks per HBLANK and
|
until the first visible one). Since there are 68 color clocks per HBLANK and
|
||||||
160 visible clocks per scanline, the Pixel Position will range from -68 to 159.</li>
|
160 visible clocks per scanLine, the Pixel Position will range from -68 to 159.</li>
|
||||||
<li><b>Color Clock</b>: The current number of total color clocks since the beginning of this
|
<li><b>Color Clock</b>: The current number of total color clocks since the beginning of this
|
||||||
scanline's HBLANK. This counter starts at zero, but otherwise displays the same
|
scanLine's HBLANK. This counter starts at zero, but otherwise displays the same
|
||||||
information as the Pixel Position (so Color Clock will always be 68 more than Pixel
|
information as the Pixel Position (so Color Clock will always be 68 more than Pixel
|
||||||
Position, and will range from 0 to 228).</li>
|
Position, and will range from 0 to 228).</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -1186,10 +1198,10 @@ as illustrated:</p>
|
||||||
<p><img src="graphics/debugger_tiazoomcmenu.png"></p>
|
<p><img src="graphics/debugger_tiazoomcmenu.png"></p>
|
||||||
<p>These options allow you to:</p>
|
<p>These options allow you to:</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li><b>Fill to scanline</b>: This option will draw all scanlines up to the
|
<li><b>Fill to scanLine</b>: This option will draw all scanlines up to the
|
||||||
vertical position where the mouse was clicked.</li>
|
vertical position where the mouse was clicked.</li>
|
||||||
<li><b>Toggle breakpoint</b>: Will toggle a conditional breakpoint at the
|
<li><b>Toggle breakpoint</b>: Will toggle a conditional breakpoint at the
|
||||||
scanline where the mouse was clicked. You can also
|
scanLine where the mouse was clicked. You can also
|
||||||
the Prompt Tab commands to list and turn off the breakpoint.</li>
|
the Prompt Tab commands to list and turn off the breakpoint.</li>
|
||||||
<li><b>2x|4x|8x zoom</b>: Zoom in on the image for even greater detail.</li>
|
<li><b>2x|4x|8x zoom</b>: Zoom in on the image for even greater detail.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -1375,7 +1387,7 @@ labels. Normally there will be nothing there: this indicates that there's
|
||||||
no breakpoint set at that address. You can set and clear breakpoints by
|
no breakpoint set at that address. You can set and clear breakpoints by
|
||||||
clicking in this area. When a breakpoint is set, there will be a
|
clicking in this area. When a breakpoint is set, there will be a
|
||||||
red circle in this area. These are the same breakpoints as used
|
red circle in this area. These are the same breakpoints as used
|
||||||
by the <a href="#Breakpoints">break</a> command, <b>not</b> the conditional "breakif" breakpoints
|
by the <a href="#Breakpoints">break</a> command, <b>not</b> the conditional "breakIf" breakpoints
|
||||||
(which makes sense: conditional breaks can break on any condition, the Program
|
(which makes sense: conditional breaks can break on any condition, the Program
|
||||||
Counter isn't necessarily involved).</li>
|
Counter isn't necessarily involved).</li>
|
||||||
<li><b>Labels</b>: Any labels assigned to the given address, either generated
|
<li><b>Labels</b>: Any labels assigned to the given address, either generated
|
||||||
|
@ -1473,7 +1485,7 @@ or lowercase for "illegal" 6502 instructions (like "dcp"). If automatic resolvin
|
||||||
of code sections has been disabled for any reason, you'll likely see a lot
|
of code sections has been disabled for any reason, you'll likely see a lot
|
||||||
of illegal opcodes if you scroll to a data table in ROM. This can also
|
of illegal opcodes if you scroll to a data table in ROM. This can also
|
||||||
occur if the disassembler hasn't yet encountered addresses in the PC.
|
occur if the disassembler hasn't yet encountered addresses in the PC.
|
||||||
If you step/trace/scanline/frame advance into such an area, the disassembler
|
If you step/trace/scanLine/frame advance into such an area, the disassembler
|
||||||
will make note of it, and disassemble it correctly from that point on.</p>
|
will make note of it, and disassemble it correctly from that point on.</p>
|
||||||
|
|
||||||
<!-- TODO - is this true any longer?
|
<!-- TODO - is this true any longer?
|
||||||
|
@ -1541,7 +1553,7 @@ Note: The code will continue to run fine, but the ROM image will be altered.</li
|
||||||
<li>The ROM Widget only works on ROM or zero-page RAM separately. If your game runs
|
<li>The ROM Widget only works on ROM or zero-page RAM separately. If your game runs
|
||||||
code from zero-page RAM, the disassembly will show addresses $80 to $FF (zero-page
|
code from zero-page RAM, the disassembly will show addresses $80 to $FF (zero-page
|
||||||
RAM address space) only. Once your RAM routine returns, the ROM Widget will switch
|
RAM address space) only. Once your RAM routine returns, the ROM Widget will switch
|
||||||
back to ROM space ($1000 - $1FFF and mirrors). The same is true of the "disasm"
|
back to ROM space ($1000 - $1FFF and mirrors). The same is true of the "disAsm"
|
||||||
command; it will show either ROM or RAM space, not both at the same time.</li>
|
command; it will show either ROM or RAM space, not both at the same time.</li>
|
||||||
|
|
||||||
<li>The standard VCS memory map has the cartridge port at locations
|
<li>The standard VCS memory map has the cartridge port at locations
|
||||||
|
@ -1610,13 +1622,13 @@ space with the appropriate directive, there are times when it will fail. There a
|
||||||
several options in this case:</p>
|
several options in this case:</p>
|
||||||
<ol>
|
<ol>
|
||||||
<li><b>Manually set the directives</b>: Directives can be set in the debugger
|
<li><b>Manually set the directives</b>: Directives can be set in the debugger
|
||||||
prompt with the aud/code/col/bcol/gfx/pcol/pgfx/data/row commands. These accept an address range
|
prompt with the aud/code/col/bcol/gfx/pCol/pGfx/data/row commands. These accept an address range
|
||||||
for the given directive type. Setting a range with the same type a second time
|
for the given directive type. Setting a range with the same type a second time
|
||||||
will remove that directive from the range.</li>
|
will remove that directive from the range.</li>
|
||||||
<li><b>Use configuration files</b>: Configuration files can be used to automatically
|
<li><b>Use configuration files</b>: Configuration files can be used to automatically
|
||||||
load a list of directives when a ROM is loaded. These files can be generated with the
|
load a list of directives when a ROM is loaded. These files can be generated with the
|
||||||
'saveconfig' command, and loaded with the 'loadconfig' command. There are also
|
'saveConfig' command, and loaded with the 'loadConfig' command. There are also
|
||||||
'listconfig' and 'clearconfig' commands to show and erase (respectively) the current
|
'listConfig' and 'clearConfig' commands to show and erase (respectively) the current
|
||||||
directive listing. Upon opening the debugger for the first time, Stella attempts
|
directive listing. Upon opening the debugger for the first time, Stella attempts
|
||||||
to load a configuration file from the folder containing the ROM. Assuming a ROM named "rr.a26" exists, the config file must be named <i>rr.cfg</i>.
|
to load a configuration file from the folder containing the ROM. Assuming a ROM named "rr.a26" exists, the config file must be named <i>rr.cfg</i>.
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -1689,7 +1701,7 @@ but it helps to know at least a little about 6502 programming.</p>
|
||||||
(for that, we have to disable the collision checking code, which means
|
(for that, we have to disable the collision checking code, which means
|
||||||
we have to find and understand it first!)</li>
|
we have to find and understand it first!)</li>
|
||||||
|
|
||||||
<li>Set a Write Trap on the lives counter address: "trapwrite $ba"
|
<li>Set a Write Trap on the lives counter address: "trapWrite $ba"
|
||||||
in the Prompt. Exit the debugger and play until you get killed. When
|
in the Prompt. Exit the debugger and play until you get killed. When
|
||||||
you die, the trap will cause the emulator to enter the debugger with the
|
you die, the trap will cause the emulator to enter the debugger with the
|
||||||
Program Counter pointing to the instruction *after* the one that wrote
|
Program Counter pointing to the instruction *after* the one that wrote
|
||||||
|
@ -1737,7 +1749,7 @@ but it helps to know at least a little about 6502 programming.</p>
|
||||||
will *still* see 3 lives: Success! We've hacked Battlezone to give us
|
will *still* see 3 lives: Success! We've hacked Battlezone to give us
|
||||||
infinite lives.</li>
|
infinite lives.</li>
|
||||||
|
|
||||||
<li>Save your work. In the prompt: "saverom". You now
|
<li>Save your work. In the prompt: "saveRom". You now
|
||||||
have your very own infinite-lives version of Battlezone. The file will
|
have your very own infinite-lives version of Battlezone. The file will
|
||||||
be saved in your HOME directory (NOT your ROM directory), so you might
|
be saved in your HOME directory (NOT your ROM directory), so you might
|
||||||
want to move it to your ROM directory if it isn't the current directory.
|
want to move it to your ROM directory if it isn't the current directory.
|
||||||
|
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 9.6 KiB After Width: | Height: | Size: 9.1 KiB |
143
docs/index.html
|
@ -629,7 +629,7 @@
|
||||||
The tables below show the default settings.<br/><br/>
|
The tables below show the default settings.<br/><br/>
|
||||||
|
|
||||||
Note: All key names are based on the US QWERTY <a href="https://en.wikipedia.org/wiki/Keyboard_layout">
|
Note: All key names are based on the US QWERTY <a href="https://en.wikipedia.org/wiki/Keyboard_layout">
|
||||||
keyboard layout.</a>. If you use a different layout some keys may differ. You can use the
|
keyboard layout</a>. If you use a different layout some keys may differ. You can use the
|
||||||
following layout image as reference where to find the US keys on your keyboard.
|
following layout image as reference where to find the US keys on your keyboard.
|
||||||
</p>
|
</p>
|
||||||
<p><img src="graphics/qwertz.png"></p>
|
<p><img src="graphics/qwertz.png"></p>
|
||||||
|
@ -785,8 +785,8 @@
|
||||||
|
|
||||||
<table BORDER=2>
|
<table BORDER=2>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Left Joystick (Joy0)</th>
|
<th>Left Joystick</th>
|
||||||
<th>Right Joystick (Joy1)</th>
|
<th>Right Joystick</th>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -898,32 +898,32 @@
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Pad Up</td>
|
<td>Pad Up</td>
|
||||||
<td>Same as 'Joy0 Up'</td>
|
<td>Same as Left Joystick 'Up'</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Pad Down</td>
|
<td>Pad Down</td>
|
||||||
<td>Same as 'Joy0 Down'</td>
|
<td>Same as Left Joystick 'Down'</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Pad Left</td>
|
<td>Pad Left</td>
|
||||||
<td>Same as 'Joy0 Left'</td>
|
<td>Same as Left Joystick 'Left'</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Pad Right</td>
|
<td>Pad Right</td>
|
||||||
<td>Same as 'Joy0 Right'</td>
|
<td>Same as Left Joystick 'Right'</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Button 'B'</td>
|
<td>Button 'B'</td>
|
||||||
<td>Same as 'Joy0 Fire'</td>
|
<td>Same as Left Joystick 'Fire'</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Button 'C'</td>
|
<td>Button 'C'</td>
|
||||||
<td>Same as 'Joy0 Top Booster Button'</td>
|
<td>Same as Left Joystick 'Top Booster Button'</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</td>
|
</td>
|
||||||
|
@ -937,32 +937,32 @@
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Pad Up</td>
|
<td>Pad Up</td>
|
||||||
<td>Same as 'Joy1 Up'</td>
|
<td>Same as Right Joystick 'Up'</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Pad Down</td>
|
<td>Pad Down</td>
|
||||||
<td>Same as 'Joy1 Down'</td>
|
<td>Same as Right Joystick 'Down'</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Pad Left</td>
|
<td>Pad Left</td>
|
||||||
<td>Same as 'Joy1 Left'</td>
|
<td>Same as Right Joystick 'Left'</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Pad Right</td>
|
<td>Pad Right</td>
|
||||||
<td>Same as 'Joy1 Right'</td>
|
<td>Same as Right Joystick 'Right'</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Button 'B'</td>
|
<td>Button 'B'</td>
|
||||||
<td>Same as 'Joy1 Fire'</td>
|
<td>Same as Right Joystick 'Fire'</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Button 'C'</td>
|
<td>Button 'C'</td>
|
||||||
<td>Same as 'Joy1 Top Booster Button'</td>
|
<td>Same as Right Joystick 'Top Booster Button'</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</td>
|
</td>
|
||||||
|
@ -987,17 +987,17 @@
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Left Direction</td>
|
<td>Left Direction</td>
|
||||||
<td>Same as 'Joy0 Left'</td>
|
<td>Same as Left Joystick 'Left'</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Right Direction</td>
|
<td>Right Direction</td>
|
||||||
<td>Same as 'Joy0 Right'</td>
|
<td>Same as Left Joystick 'Right'</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Fire Button</td>
|
<td>Fire Button</td>
|
||||||
<td>Same as 'Joy0 Fire'</td>
|
<td>Same as Left Joystick 'Fire'</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</td>
|
</td>
|
||||||
|
@ -1011,17 +1011,17 @@
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Left Direction</td>
|
<td>Left Direction</td>
|
||||||
<td>Same as 'Joy1 Left'</td>
|
<td>Same as Right Joystick 'Left'</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Right Direction</td>
|
<td>Right Direction</td>
|
||||||
<td>Same as 'Joy1 Right'</td>
|
<td>Same as Right Joystick 'Right'</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Fire Button</td>
|
<td>Fire Button</td>
|
||||||
<td>Same as 'Joy1 Fire'</td>
|
<td>Same as Right Joystick 'Fire'</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</td>
|
</td>
|
||||||
|
@ -1043,7 +1043,7 @@
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Fire Button</td>
|
<td>Fire Button</td>
|
||||||
<td>Same as 'Joy0 Fire'</td>
|
<td>Same as Left Joystick 'Fire'</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</td>
|
</td>
|
||||||
|
@ -1065,7 +1065,7 @@
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Fire Button</td>
|
<td>Fire Button</td>
|
||||||
<td>Same as 'Joy0 Fire'</td>
|
<td>Same as Left Joystick 'Fire'</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</td>
|
</td>
|
||||||
|
@ -1089,32 +1089,32 @@
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Paddle 0 Turn Left</td>
|
<td>Paddle A Turn Left</td>
|
||||||
<td>Left arrow</td>
|
<td>Left arrow</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Paddle 0 Turn Right</td>
|
<td>Paddle A Turn Right</td>
|
||||||
<td>Right arrow</td>
|
<td>Right arrow</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Paddle 0 Fire</td>
|
<td>Paddle A Fire</td>
|
||||||
<td>Left Control, Space</td>
|
<td>Left Control, Space</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Paddle 1 Turn Left</td>
|
<td>Paddle B Turn Left</td>
|
||||||
<td>Up arrow</td>
|
<td>Up arrow</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Paddle 1 Turn Right</td>
|
<td>Paddle B Turn Right</td>
|
||||||
<td>Down arrow</td>
|
<td>Down arrow</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Paddle 1 Fire</td>
|
<td>Paddle B Fire</td>
|
||||||
<td>4</td>
|
<td>4</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
@ -1128,32 +1128,32 @@
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Paddle 2 Turn Left</td>
|
<td>Paddle A Turn Left</td>
|
||||||
<td>G</td>
|
<td>G</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Paddle 2 Turn Right</td>
|
<td>Paddle A Turn Right</td>
|
||||||
<td>J</td>
|
<td>J</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Paddle 2 Fire</td>
|
<td>Paddle A Fire</td>
|
||||||
<td>F</td>
|
<td>F</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Paddle 3 Turn Left</td>
|
<td>Paddle B Turn Left</td>
|
||||||
<td>Y</td>
|
<td>Y</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Paddle 3 Turn Right</td>
|
<td>Paddle B Turn Right</td>
|
||||||
<td>H</td>
|
<td>H</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Paddle 3 Fire</td>
|
<td>Paddle B Fire</td>
|
||||||
<td>6</td>
|
<td>6</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
@ -1161,12 +1161,12 @@
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<p><b>Keypad Controller (can be remapped)</b></p>
|
<p><b>Keyboard Controller (can be remapped)</b></p>
|
||||||
|
|
||||||
<table BORDER=2>
|
<table BORDER=2>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Left Keypad</th>
|
<th>Left Keyboard</th>
|
||||||
<th>Right Keypad</th>
|
<th>Right Keyboard</th>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -3541,6 +3541,25 @@
|
||||||
fatal errors are simply logged, and emulation continues. Do not use this
|
fatal errors are simply logged, and emulation continues. Do not use this
|
||||||
unless you know exactly what you're doing, as it changes the behaviour as
|
unless you know exactly what you're doing, as it changes the behaviour as
|
||||||
compared to real hardware.</td>
|
compared to real hardware.</td>
|
||||||
|
</tr><tr>
|
||||||
|
<td><pre>-dev.thumb.incycles <1|0></pre></td>
|
||||||
|
<td>When enabled, ARM emulation cycles are added to 6507 system cycles. This
|
||||||
|
allows detecting timer overruns, but will also distort audio.</br>
|
||||||
|
Note: The ARM emulation cycles are only a coarse approximation.
|
||||||
|
</td>
|
||||||
|
</tr><tr>
|
||||||
|
<td><pre>-dev.thumb.cyclefactor <float></pre></td>
|
||||||
|
<td>Defines the ARM cycle count correction factor (default = 0.95).</td>
|
||||||
|
</tr><tr>
|
||||||
|
<td><pre>-dev.thumb.chiptype <0|1></pre></td>
|
||||||
|
<td>Selects the emulated chip type (0 = LPC2103, 1 = LPC2104 family). This
|
||||||
|
setting affects the CPU clock, the Flash memory access clock cycles and
|
||||||
|
the number of Flash banks.</td>
|
||||||
|
</tr><tr>
|
||||||
|
<td><pre>-dev.thumb.mammode <0..3></pre></td>
|
||||||
|
<td>Selects the Memory Accelerator Module (MAM) mode.</br>
|
||||||
|
Note: Mode X (3) is for testing only. It reduces Flash memory access
|
||||||
|
clock cycles to always 1.</td>
|
||||||
</tr><tr>
|
</tr><tr>
|
||||||
<td><pre>-<plr.|dev.>eepromaccess <1|0></pre></td>
|
<td><pre>-<plr.|dev.>eepromaccess <1|0></pre></td>
|
||||||
<td>When enabled, each read or write access to the AtariVox/SaveKey EEPROM is
|
<td>When enabled, each read or write access to the AtariVox/SaveKey EEPROM is
|
||||||
|
@ -3654,8 +3673,7 @@
|
||||||
<table border="1" cellpadding="4">
|
<table border="1" cellpadding="4">
|
||||||
<tr><th>Item</th><th>Brief description</th><th>For more information,<br>see <a href="#CommandLine">Command Line</a></th></tr>
|
<tr><th>Item</th><th>Brief description</th><th>For more information,<br>see <a href="#CommandLine">Command Line</a></th></tr>
|
||||||
<tr><td>Palette</td><td>Palette used for emulation mode</td><td>-palette</td></tr>
|
<tr><td>Palette</td><td>Palette used for emulation mode</td><td>-palette</td></tr>
|
||||||
<tr><td>NTSC phase</td><td>Adjust phase shift of 'Custom' NTSC palette</td><td>-pal.phase_ntsc</td></tr>
|
<tr><td>NTSC/PAL phase</td><td>Adjust phase shift of 'Custom' NTSC or PAL (depends on game) palette. </td><td>-pal.phase_ntsc, -pal.phase_pal</td></tr>
|
||||||
<tr><td>PAL phase</td><td>Adjust phase shift of 'Custom' PAL palette</td><td>-pal.phase_pal</td></tr>
|
|
||||||
<tr><td>R</td><td>Adjust red scale and shift of 'Custom' palette</td><td>-pal.red_scale, -pal.red_shift</td></tr>
|
<tr><td>R</td><td>Adjust red scale and shift of 'Custom' palette</td><td>-pal.red_scale, -pal.red_shift</td></tr>
|
||||||
<tr><td>G</td><td>Adjust green scale and shift of 'Custom' palette</td><td>-pal.green_scale, -pal.green_shift</td></tr>
|
<tr><td>G</td><td>Adjust green scale and shift of 'Custom' palette</td><td>-pal.green_scale, -pal.green_shift</td></tr>
|
||||||
<tr><td>B</td><td>Adjust blue scale and shift of 'Custom' palette</td><td>-pal.blue_scale, -pal.blue_shift</td></tr>
|
<tr><td>B</td><td>Adjust blue scale and shift of 'Custom' palette</td><td>-pal.blue_scale, -pal.blue_shift</td></tr>
|
||||||
|
@ -3899,16 +3917,13 @@
|
||||||
while in emulation mode, the left arrow could mean 'joystick 0 left', while in UI
|
while in emulation mode, the left arrow could mean 'joystick 0 left', while in UI
|
||||||
mode it could mean 'move cursor left'. Emulation mode occurs whenever you're
|
mode it could mean 'move cursor left'. Emulation mode occurs whenever you're
|
||||||
actually playing a game. UI mode occurs whenever a user interface is present
|
actually playing a game. UI mode occurs whenever a user interface is present
|
||||||
(ROM launcher, debugger, settings menu, etc.). Because of these different modes,
|
(ROM launcher, debugger, settings menu, etc.).
|
||||||
there are two separate mapping areas.
|
|
||||||
|
|
||||||
<p>To remap an event:
|
<p>To remap an event:
|
||||||
<ol>
|
<ol>
|
||||||
<li>Enter <b>Options Menu</b> and click the <b>Input Settings</b> button.</li>
|
<li>Enter <b>Options Menu</b> and click the <b>Input Settings</b> button.</li>
|
||||||
<li>If you wish to remap emulation events, click the 'Emulation Events' tab. Here
|
<li>Click the 'Event Mappings' tab. Here you can also filter the list of events by type.
|
||||||
you can also filter for the type of events.
|
<li>Select the event you want to remap and click the 'Map' button.</li>
|
||||||
Otherwise, click the 'UI Events' tab for user interface events.</li>
|
|
||||||
<li>Select event you want to remap and click the 'Map' button.</li>
|
|
||||||
<li>Now define the input:
|
<li>Now define the input:
|
||||||
<ul>
|
<ul>
|
||||||
<li>Either press a key, a modifier key (Control, Shift...) or a modifier+key combination.</li>
|
<li>Either press a key, a modifier key (Control, Shift...) or a modifier+key combination.</li>
|
||||||
|
@ -3917,7 +3932,7 @@
|
||||||
Notes:<ul>
|
Notes:<ul>
|
||||||
<li>If nothing seems to happen, either Stella can't see the input device, or the
|
<li>If nothing seems to happen, either Stella can't see the input device, or the
|
||||||
selected event doesn't support being remapped to the input device.</li>
|
selected event doesn't support being remapped to the input device.</li>
|
||||||
<li>The same input can be used for multiple controller types (e.g. 'Right' for 'P0 Joystick Right' and 'Paddle 0 Turn Right').</li>
|
<li>The same input can be used for multiple controller types (e.g. 'Right' for 'Left Joystick Right' and 'Left Paddle A Turn Right').</li>
|
||||||
<li>If the same input is used again for the same controller type, the old mapping will be removed.</li>
|
<li>If the same input is used again for the same controller type, the old mapping will be removed.</li>
|
||||||
<li>Events which are available in both event modes can be remapped individually.</li>
|
<li>Events which are available in both event modes can be remapped individually.</li>
|
||||||
<li>Left and right modifiers are mapped separately when used alone.</li>
|
<li>Left and right modifiers are mapped separately when used alone.</li>
|
||||||
|
@ -3965,7 +3980,7 @@
|
||||||
<tr><td>Allow all 4 directions ...</td><td>Allow all 4 joystick directions to be pressed simultaneously</td><td>-joyallow4</td></tr>
|
<tr><td>Allow all 4 directions ...</td><td>Allow all 4 joystick directions to be pressed simultaneously</td><td>-joyallow4</td></tr>
|
||||||
<tr><td>Use modifier key combos</td><td>Enable using modifier keys in keyboard actions</td><td>-modcombo</td></tr>
|
<tr><td>Use modifier key combos</td><td>Enable using modifier keys in keyboard actions</td><td>-modcombo</td></tr>
|
||||||
<tr><td>Swap Stelladaptor ports</td><td>Swap the order of the detected Stelladaptors/2600-daptors (see <b>Advanced Configuration - <a href="#Adaptor">Stelladaptor/2600-daptor Support</a></b>)</td><td>-saport</td></tr>
|
<tr><td>Swap Stelladaptor ports</td><td>Swap the order of the detected Stelladaptors/2600-daptors (see <b>Advanced Configuration - <a href="#Adaptor">Stelladaptor/2600-daptor Support</a></b>)</td><td>-saport</td></tr>
|
||||||
<tr><td>Joystick Database</td><td>Show all joysticks that Stella knows about, with the option to remove them</td><td> </td></tr>
|
<tr><td>Controller Database</td><td>Show all controllers that Stella knows about, with the option to remove them</td><td> </td></tr>
|
||||||
<tr><td>Erase EEPROM</td><td>Erase the whole AtariVox/SaveKey flash memory</td><td> </td></tr>
|
<tr><td>Erase EEPROM</td><td>Erase the whole AtariVox/SaveKey flash memory</td><td> </td></tr>
|
||||||
<tr><td>AtariVox serial port</td><td>Described in further detail in <b>Advanced Configuration - <a href="#AtariVox">AtariVox/SaveKey Support</a></b> </td><td>-avoxport</td></tr>
|
<tr><td>AtariVox serial port</td><td>Described in further detail in <b>Advanced Configuration - <a href="#AtariVox">AtariVox/SaveKey Support</a></b> </td><td>-avoxport</td></tr>
|
||||||
</table>
|
</table>
|
||||||
|
@ -4140,7 +4155,7 @@
|
||||||
|
|
||||||
<h2><b><a name="Adaptor">Stelladaptor/2600-daptor Support</a></b></h2>
|
<h2><b><a name="Adaptor">Stelladaptor/2600-daptor Support</a></b></h2>
|
||||||
|
|
||||||
<blockquote> H
|
<blockquote>
|
||||||
<p>Stella supports real Atari 2600 joysticks, paddles, driving controllers
|
<p>Stella supports real Atari 2600 joysticks, paddles, driving controllers
|
||||||
and trackballs (CX22/CX80 'Trak-Ball', Atari and Amiga mouse) using the
|
and trackballs (CX22/CX80 'Trak-Ball', Atari and Amiga mouse) using the
|
||||||
<a href="http://www.grandideastudio.com/stelladaptor-2600">Stelladaptor</a> and
|
<a href="http://www.grandideastudio.com/stelladaptor-2600">Stelladaptor</a> and
|
||||||
|
@ -4156,13 +4171,13 @@
|
||||||
<ul>
|
<ul>
|
||||||
<li>The first device found will act as the <b>left game port</b>
|
<li>The first device found will act as the <b>left game port</b>
|
||||||
on a real Atari. Depending on the device, Stella will detect it as
|
on a real Atari. Depending on the device, Stella will detect it as
|
||||||
either the left joystick, paddles 0 & 1, the left driving controller,
|
either the left joystick, left paddles A & B, the left driving controller,
|
||||||
left keypad, etc.</li>
|
left keyboard, etc.</li>
|
||||||
|
|
||||||
<li>The second device found will act as the <b>right game port</b>
|
<li>The second device found will act as the <b>right game port</b>
|
||||||
on a real Atari. Depending on the device, Stella will detect it as
|
on a real Atari. Depending on the device, Stella will detect it as
|
||||||
either the right joystick, paddles 2 & 3, the right driving controller,
|
either the right joystick, right paddles A & B, the right driving controller,
|
||||||
right keypad, etc.</li>
|
right keyboard, etc.</li>
|
||||||
|
|
||||||
<li>Any other devices will be ignored.</li>
|
<li>Any other devices will be ignored.</li>
|
||||||
|
|
||||||
|
@ -4874,7 +4889,7 @@ Ms Pac-Man (Stella extended codes):
|
||||||
<td VALIGN="TOP"><i>Console.SwapPorts</i></td>
|
<td VALIGN="TOP"><i>Console.SwapPorts</i></td>
|
||||||
<td>Indicates that the left and right ports should be
|
<td>Indicates that the left and right ports should be
|
||||||
swapped internally. This is used for ROMs like 'Raiders of the Lost Ark' where the
|
swapped internally. This is used for ROMs like 'Raiders of the Lost Ark' where the
|
||||||
Player 0 joystick is plugged into the right joystick port.
|
1st player's joystick is plugged into the right joystick port.
|
||||||
The value must be <b>Yes</b> or <b>No</b>.</td>
|
The value must be <b>Yes</b> or <b>No</b>.</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
@ -4882,8 +4897,8 @@ Ms Pac-Man (Stella extended codes):
|
||||||
<td VALIGN="TOP"><i>Controller.SwapPaddles</i></td>
|
<td VALIGN="TOP"><i>Controller.SwapPaddles</i></td>
|
||||||
<td>Indicates that the left and right paddles in
|
<td>Indicates that the left and right paddles in
|
||||||
a particular port should be swapped. This is used for ROMs like
|
a particular port should be swapped. This is used for ROMs like
|
||||||
'Demons to Diamonds' where the default paddle is paddle 1, not
|
'Demons to Diamonds' where the default paddle is left paddle B, not
|
||||||
paddle 0. Other ROMs such as 'Tac-Scan' default to paddle 3,
|
left paddle A. Other ROMs such as 'Tac-Scan' default to right paddle B,
|
||||||
which can be set using both 'Controller.SwapPaddles' and
|
which can be set using both 'Controller.SwapPaddles' and
|
||||||
'Console.SwapPorts'. The value must be <b>Yes</b> or <b>No</b>.</td>
|
'Console.SwapPorts'. The value must be <b>Yes</b> or <b>No</b>.</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -4907,14 +4922,14 @@ Ms Pac-Man (Stella extended codes):
|
||||||
Y-axis and right button. The value must be <b>Auto</b> or <b>XY</b>, as follows:
|
Y-axis and right button. The value must be <b>Auto</b> or <b>XY</b>, as follows:
|
||||||
<table cellpadding="2" border="1">
|
<table cellpadding="2" border="1">
|
||||||
<tr><th> Id </th><th>Controller</th></tr>
|
<tr><th> Id </th><th>Controller</th></tr>
|
||||||
<tr><td>0 </td><td>Paddle 0</td></tr>
|
<tr><td>0 </td><td>Left Paddle A</td></tr>
|
||||||
<tr><td>1 </td><td>Paddle 1</td></tr>
|
<tr><td>1 </td><td>Left Paddle B</td></tr>
|
||||||
<tr><td>2 </td><td>Paddle 2</td></tr>
|
<tr><td>2 </td><td>Right Paddle A</td></tr>
|
||||||
<tr><td>3 </td><td>Paddle 3</td></tr>
|
<tr><td>3 </td><td>Right Paddle B</td></tr>
|
||||||
<tr><td>4 </td><td>Driving 0</td></tr>
|
<tr><td>4 </td><td>Left Driving</td></tr>
|
||||||
<tr><td>5 </td><td>Driving 1</td></tr>
|
<tr><td>5 </td><td>Right Driving</td></tr>
|
||||||
<tr><td>6 </td><td>MindLink 0</td></tr>
|
<tr><td>6 </td><td>Left MindLink</td></tr>
|
||||||
<tr><td>7 </td><td>MindLink 1</td></tr>
|
<tr><td>7 </td><td>Right MindLink</td></tr>
|
||||||
</table>
|
</table>
|
||||||
An <I>optional</I> second parameter (default of 100) indicates how much
|
An <I>optional</I> second parameter (default of 100) indicates how much
|
||||||
of the paddle range the mouse should emulate.
|
of the paddle range the mouse should emulate.
|
||||||
|
|
|
@ -71,6 +71,8 @@ FBBackendSDL2::~FBBackendSDL2()
|
||||||
myWindow = nullptr;
|
myWindow = nullptr;
|
||||||
}
|
}
|
||||||
SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_TIMER);
|
SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_TIMER);
|
||||||
|
|
||||||
|
cerr << "~FBBackendSDL2()" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -40,6 +40,8 @@ namespace {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int REF_COUNT = 0;
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
FBSurfaceSDL2::FBSurfaceSDL2(FBBackendSDL2& backend,
|
FBSurfaceSDL2::FBSurfaceSDL2(FBBackendSDL2& backend,
|
||||||
uInt32 width, uInt32 height,
|
uInt32 width, uInt32 height,
|
||||||
|
@ -48,6 +50,7 @@ FBSurfaceSDL2::FBSurfaceSDL2(FBBackendSDL2& backend,
|
||||||
: myBackend{backend},
|
: myBackend{backend},
|
||||||
myInterpolationMode{inter}
|
myInterpolationMode{inter}
|
||||||
{
|
{
|
||||||
|
REF_COUNT++;
|
||||||
createSurface(width, height, staticData);
|
createSurface(width, height, staticData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,6 +61,8 @@ FBSurfaceSDL2::~FBSurfaceSDL2()
|
||||||
|
|
||||||
if(mySurface)
|
if(mySurface)
|
||||||
{
|
{
|
||||||
|
REF_COUNT--;
|
||||||
|
cerr << " ~FBSurfaceSDL2(): " << this << " " << REF_COUNT << endl;
|
||||||
SDL_FreeSurface(mySurface);
|
SDL_FreeSurface(mySurface);
|
||||||
mySurface = nullptr;
|
mySurface = nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -218,7 +218,7 @@ json JoyMap::saveMapping(const EventMode mode) const
|
||||||
json eventMappings = json::array();
|
json eventMappings = json::array();
|
||||||
|
|
||||||
for (const auto& [_mapping, _event]: sortedMap) {
|
for (const auto& [_mapping, _event]: sortedMap) {
|
||||||
if (_mapping.mode != mode) continue;
|
if(_mapping.mode != mode || _event == Event::NoType) continue;
|
||||||
|
|
||||||
json eventMapping = json::object();
|
json eventMapping = json::object();
|
||||||
|
|
||||||
|
@ -255,6 +255,10 @@ int JoyMap::loadMapping(const json& eventMappings, const EventMode mode)
|
||||||
JoyHatDir hatDirection = eventMapping.contains("hat") ? eventMapping.at("hatDirection").get<JoyHatDir>() : JoyHatDir::CENTER;
|
JoyHatDir hatDirection = eventMapping.contains("hat") ? eventMapping.at("hatDirection").get<JoyHatDir>() : JoyHatDir::CENTER;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// avoid blocking mappings for NoType events
|
||||||
|
if(eventMapping.at("event").get<Event::Type>() == Event::NoType)
|
||||||
|
continue;
|
||||||
|
|
||||||
add(
|
add(
|
||||||
eventMapping.at("event").get<Event::Type>(),
|
eventMapping.at("event").get<Event::Type>(),
|
||||||
mode,
|
mode,
|
||||||
|
|
|
@ -241,7 +241,7 @@ json KeyMap::saveMapping(const EventMode mode) const
|
||||||
json mappings = json::array();
|
json mappings = json::array();
|
||||||
|
|
||||||
for (const auto& [_mapping, _event]: sortedMap) {
|
for (const auto& [_mapping, _event]: sortedMap) {
|
||||||
if (_mapping.mode != mode) continue;
|
if (_mapping.mode != mode || _event == Event::NoType) continue;
|
||||||
|
|
||||||
json mapping = json::object();
|
json mapping = json::object();
|
||||||
|
|
||||||
|
@ -264,6 +264,10 @@ int KeyMap::loadMapping(const json& mappings, const EventMode mode) {
|
||||||
for(const json& mapping : mappings)
|
for(const json& mapping : mappings)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
// avoid blocking mappings for NoType events
|
||||||
|
if(mapping.at("event").get<Event::Type>() == Event::NoType)
|
||||||
|
continue;
|
||||||
|
|
||||||
add(
|
add(
|
||||||
mapping.at("event").get<Event::Type>(),
|
mapping.at("event").get<Event::Type>(),
|
||||||
mode,
|
mode,
|
||||||
|
|
|
@ -56,7 +56,8 @@ void Logger::logMessage(const string& message, Level level)
|
||||||
cout << message << endl << std::flush;
|
cout << message << endl << std::flush;
|
||||||
myLogMessages += message + "\n";
|
myLogMessages += message + "\n";
|
||||||
}
|
}
|
||||||
else if(static_cast<int>(level) <= myLogLevel)
|
else if(static_cast<int>(level) <= myLogLevel ||
|
||||||
|
level == Logger::Level::ALWAYS)
|
||||||
{
|
{
|
||||||
if(myLogToConsole)
|
if(myLogToConsole)
|
||||||
cout << message << endl << std::flush;
|
cout << message << endl << std::flush;
|
||||||
|
|
|
@ -30,6 +30,7 @@ class Logger {
|
||||||
ERR = 0, // cannot use ERROR???
|
ERR = 0, // cannot use ERROR???
|
||||||
INFO = 1,
|
INFO = 1,
|
||||||
DEBUG = 2,
|
DEBUG = 2,
|
||||||
|
ALWAYS = 3,
|
||||||
MIN = ERR,
|
MIN = ERR,
|
||||||
MAX = DEBUG
|
MAX = DEBUG
|
||||||
};
|
};
|
||||||
|
@ -38,7 +39,7 @@ class Logger {
|
||||||
|
|
||||||
static Logger& instance();
|
static Logger& instance();
|
||||||
|
|
||||||
static void log(const string& message, Level level);
|
static void log(const string& message, Level level = Level::ALWAYS);
|
||||||
|
|
||||||
static void error(const string& message);
|
static void error(const string& message);
|
||||||
|
|
||||||
|
|
|
@ -54,45 +54,45 @@ MouseControl::MouseControl(Console& console, const string& mode)
|
||||||
case MouseControl::Type::NoControl:
|
case MouseControl::Type::NoControl:
|
||||||
msg << "not used";
|
msg << "not used";
|
||||||
break;
|
break;
|
||||||
case MouseControl::Type::Paddle0:
|
case MouseControl::Type::LeftPaddleA:
|
||||||
type = Controller::Type::Paddles;
|
type = Controller::Type::Paddles;
|
||||||
id = 0;
|
id = 0;
|
||||||
msg << "Paddle 0";
|
msg << "Left Paddle A";
|
||||||
break;
|
break;
|
||||||
case MouseControl::Type::Paddle1:
|
case MouseControl::Type::LeftPaddleB:
|
||||||
type = Controller::Type::Paddles;
|
type = Controller::Type::Paddles;
|
||||||
id = 1;
|
id = 1;
|
||||||
msg << "Paddle 1";
|
msg << "Left Paddle B";
|
||||||
break;
|
break;
|
||||||
case MouseControl::Type::Paddle2:
|
case MouseControl::Type::RightPaddleA:
|
||||||
type = Controller::Type::Paddles;
|
type = Controller::Type::Paddles;
|
||||||
id = 2;
|
id = 2;
|
||||||
msg << "Paddle 2";
|
msg << "Right Paddle A";
|
||||||
break;
|
break;
|
||||||
case MouseControl::Type::Paddle3:
|
case MouseControl::Type::RightPaddleB:
|
||||||
type = Controller::Type::Paddles;
|
type = Controller::Type::Paddles;
|
||||||
id = 3;
|
id = 3;
|
||||||
msg << "Paddle 3";
|
msg << "Right Paddle B";
|
||||||
break;
|
break;
|
||||||
case MouseControl::Type::Driving0:
|
case MouseControl::Type::LeftDriving:
|
||||||
type = Controller::Type::Driving;
|
type = Controller::Type::Driving;
|
||||||
id = 0;
|
id = 0;
|
||||||
msg << "Driving 0";
|
msg << "Left Driving";
|
||||||
break;
|
break;
|
||||||
case MouseControl::Type::Driving1:
|
case MouseControl::Type::RightDriving:
|
||||||
type = Controller::Type::Driving;
|
type = Controller::Type::Driving;
|
||||||
id = 1;
|
id = 1;
|
||||||
msg << "Driving 1";
|
msg << "Right Driving";
|
||||||
break;
|
break;
|
||||||
case MouseControl::Type::MindLink0:
|
case MouseControl::Type::LeftMindLink:
|
||||||
type = Controller::Type::MindLink;
|
type = Controller::Type::MindLink;
|
||||||
id = 0;
|
id = 0;
|
||||||
msg << "MindLink 0";
|
msg << "Left MindLink";
|
||||||
break;
|
break;
|
||||||
case MouseControl::Type::MindLink1:
|
case MouseControl::Type::RightMindLink:
|
||||||
type = Controller::Type::MindLink;
|
type = Controller::Type::MindLink;
|
||||||
id = 1;
|
id = 1;
|
||||||
msg << "MindLink 1";
|
msg << "Right MindLink";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -43,8 +43,8 @@ class MouseControl
|
||||||
*/
|
*/
|
||||||
enum class Type
|
enum class Type
|
||||||
{
|
{
|
||||||
Paddle0 = 0, Paddle1, Paddle2, Paddle3,
|
LeftPaddleA = 0, LeftPaddleB, RightPaddleA, RightPaddleB,
|
||||||
Driving0, Driving1, MindLink0, MindLink1,
|
LeftDriving, RightDriving, LeftMindLink, RightMindLink,
|
||||||
NoControl
|
NoControl
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -98,27 +98,12 @@ int PhysicalJoystickHandler::add(const PhysicalJoystickPtr& stick)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
// Figure out what type of joystick this is
|
// Figure out what type of joystick this is
|
||||||
bool specialAdaptor = false;
|
bool isAdaptor = false;
|
||||||
|
|
||||||
if(BSPF::containsIgnoreCase(stick->name, "2600-daptor"))
|
if(BSPF::containsIgnoreCase(stick->name, "Stelladaptor")
|
||||||
|
|| BSPF::containsIgnoreCase(stick->name, "2600-daptor"))
|
||||||
{
|
{
|
||||||
specialAdaptor = true;
|
isAdaptor = true;
|
||||||
if(stick->numAxes == 4)
|
|
||||||
{
|
|
||||||
// TODO - detect controller type based on z-axis
|
|
||||||
stick->name = "2600-daptor D9";
|
|
||||||
}
|
|
||||||
else if(stick->numAxes == 3)
|
|
||||||
{
|
|
||||||
stick->name = "2600-daptor II";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
stick->name = "2600-daptor";
|
|
||||||
}
|
|
||||||
else if(BSPF::containsIgnoreCase(stick->name, "Stelladaptor"))
|
|
||||||
{
|
|
||||||
stick->name = "Stelladaptor";
|
|
||||||
specialAdaptor = true;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -141,11 +126,40 @@ int PhysicalJoystickHandler::add(const PhysicalJoystickPtr& stick)
|
||||||
// The stick *must* be inserted here, since it may be used below
|
// The stick *must* be inserted here, since it may be used below
|
||||||
mySticks[stick->ID] = stick;
|
mySticks[stick->ID] = stick;
|
||||||
|
|
||||||
// Map the stelladaptors we've found according to the specified ports
|
bool erased = false;
|
||||||
// The 'type' is also set there
|
if(isAdaptor)
|
||||||
if(specialAdaptor)
|
{
|
||||||
mapStelladaptors(myOSystem.settings().getString("saport"));
|
// Map the Stelladaptors we've found according to the specified ports
|
||||||
|
// The 'type' is also set there
|
||||||
|
erased = mapStelladaptors(myOSystem.settings().getString("saport"), stick->ID);
|
||||||
|
|
||||||
|
}
|
||||||
|
if(erased)
|
||||||
|
// We have to add all Stelladaptors again, because they have changed
|
||||||
|
// name due to being reordered when mapping them
|
||||||
|
for(auto& [_id, _stick] : mySticks)
|
||||||
|
{
|
||||||
|
if(_stick->name.find(" (emulates ") != std::string::npos)
|
||||||
|
addToDatabase(_stick);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
addToDatabase(stick);
|
||||||
|
|
||||||
|
// We're potentially swapping out an input device behind the back of
|
||||||
|
// the Event system, so we make sure all Stelladaptor-generated events
|
||||||
|
// are reset
|
||||||
|
for(int port = 0; port < NUM_PORTS; ++port)
|
||||||
|
{
|
||||||
|
for(int axis = 0; axis < NUM_SA_AXIS; ++axis)
|
||||||
|
myEvent.set(SA_Axis[port][axis], 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return stick->ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void PhysicalJoystickHandler::addToDatabase(const PhysicalJoystickPtr& stick)
|
||||||
|
{
|
||||||
// Add stick to database
|
// Add stick to database
|
||||||
auto it = myDatabase.find(stick->name);
|
auto it = myDatabase.find(stick->name);
|
||||||
if(it != myDatabase.end()) // already present
|
if(it != myDatabase.end()) // already present
|
||||||
|
@ -162,16 +176,10 @@ int PhysicalJoystickHandler::add(const PhysicalJoystickPtr& stick)
|
||||||
setStickDefaultMapping(stick->ID, Event::NoType, EventMode::kMenuMode);
|
setStickDefaultMapping(stick->ID, Event::NoType, EventMode::kMenuMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We're potentially swapping out an input device behind the back of
|
ostringstream buf;
|
||||||
// the Event system, so we make sure all Stelladaptor-generated events
|
buf << "Added joystick " << stick->ID << ":" << endl
|
||||||
// are reset
|
<< " " << stick->about() << endl;
|
||||||
for(int port = 0; port < NUM_PORTS; ++port)
|
Logger::info(buf.str());
|
||||||
{
|
|
||||||
for(int axis = 0; axis < NUM_SA_AXIS; ++axis)
|
|
||||||
myEvent.set(SA_Axis[port][axis], 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return stick->ID;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -223,8 +231,9 @@ bool PhysicalJoystickHandler::remove(const string& name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void PhysicalJoystickHandler::mapStelladaptors(const string& saport)
|
bool PhysicalJoystickHandler::mapStelladaptors(const string& saport, int ID)
|
||||||
{
|
{
|
||||||
|
bool erased = false;
|
||||||
// saport will have two values:
|
// saport will have two values:
|
||||||
// 'lr' means treat first valid adaptor as left port, second as right port
|
// 'lr' means treat first valid adaptor as left port, second as right port
|
||||||
// 'rl' means treat first valid adaptor as right port, second as left port
|
// 'rl' means treat first valid adaptor as right port, second as left port
|
||||||
|
@ -238,44 +247,55 @@ void PhysicalJoystickHandler::mapStelladaptors(const string& saport)
|
||||||
saOrder[0] = 2; saOrder[1] = 1;
|
saOrder[0] = 2; saOrder[1] = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(auto& [_id, _joyptr]: mySticks)
|
for(auto& [_id, _stick]: mySticks)
|
||||||
{
|
{
|
||||||
bool found = false;
|
bool found = false;
|
||||||
// remove previously added emulated ports
|
size_t pos = _stick->name.find(" (emulates ");
|
||||||
size_t pos = _joyptr->name.find(" (emulates ");
|
|
||||||
|
|
||||||
if(pos != std::string::npos)
|
if(pos != std::string::npos && ID != -1 && ID < _stick->ID)
|
||||||
_joyptr->name.erase(pos);
|
{
|
||||||
|
// Erase a previously added Stelladapter with a higher ID
|
||||||
|
ostringstream buf;
|
||||||
|
buf << "Erased joystick " << _stick->ID << ":" << endl
|
||||||
|
<< " " << _stick->about() << endl;
|
||||||
|
Logger::info(buf.str());
|
||||||
|
|
||||||
if(BSPF::startsWithIgnoreCase(_joyptr->name, "Stelladaptor"))
|
_stick->name.erase(pos);
|
||||||
|
erased = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//if(BSPF::startsWithIgnoreCase(_stick->name, "Stelladaptor"))
|
||||||
|
if(BSPF::containsIgnoreCase(_stick->name, "Stelladaptor"))
|
||||||
{
|
{
|
||||||
if(saOrder[saCount] == 1)
|
if(saOrder[saCount] == 1)
|
||||||
_joyptr->type = PhysicalJoystick::Type::LEFT_STELLADAPTOR;
|
_stick->type = PhysicalJoystick::Type::LEFT_STELLADAPTOR;
|
||||||
else if(saOrder[saCount] == 2)
|
else if(saOrder[saCount] == 2)
|
||||||
_joyptr->type = PhysicalJoystick::Type::RIGHT_STELLADAPTOR;
|
_stick->type = PhysicalJoystick::Type::RIGHT_STELLADAPTOR;
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
else if(BSPF::startsWithIgnoreCase(_joyptr->name, "2600-daptor"))
|
else //if(BSPF::startsWithIgnoreCase(_stick->name, "2600-daptor"))
|
||||||
|
if(BSPF::containsIgnoreCase(_stick->name, "2600-daptor"))
|
||||||
{
|
{
|
||||||
if(saOrder[saCount] == 1)
|
if(saOrder[saCount] == 1)
|
||||||
_joyptr->type = PhysicalJoystick::Type::LEFT_2600DAPTOR;
|
_stick->type = PhysicalJoystick::Type::LEFT_2600DAPTOR;
|
||||||
else if(saOrder[saCount] == 2)
|
else if(saOrder[saCount] == 2)
|
||||||
_joyptr->type = PhysicalJoystick::Type::RIGHT_2600DAPTOR;
|
_stick->type = PhysicalJoystick::Type::RIGHT_2600DAPTOR;
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
if(found)
|
if(found)
|
||||||
{
|
{
|
||||||
if(saOrder[saCount] == 1)
|
if(saOrder[saCount] == 1)
|
||||||
_joyptr->name += " (emulates left joystick port)";
|
_stick->name += " (emulates left joystick port)";
|
||||||
else if(saOrder[saCount] == 2)
|
else if(saOrder[saCount] == 2)
|
||||||
_joyptr->name += " (emulates right joystick port)";
|
_stick->name += " (emulates right joystick port)";
|
||||||
|
|
||||||
saCount++;
|
saCount++;
|
||||||
// always map Stelladaptor/2600-daptor to emulation mode defaults
|
// always map Stelladaptor/2600-daptor to emulation mode defaults
|
||||||
setStickDefaultMapping(_joyptr->ID, Event::NoType, EventMode::kEmulationMode);
|
setStickDefaultMapping(_stick->ID, Event::NoType, EventMode::kEmulationMode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
myOSystem.settings().setValue("saport", saport);
|
myOSystem.settings().setValue("saport", saport);
|
||||||
|
return erased;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -361,8 +381,8 @@ void PhysicalJoystickHandler::setStickDefaultMapping(int stick, Event::Type even
|
||||||
setDefaultAction(stick, item, event, EventMode::kJoystickMode, updateDefaults);
|
setDefaultAction(stick, item, event, EventMode::kJoystickMode, updateDefaults);
|
||||||
for (const auto& item : DefaultLeftPaddlesMapping)
|
for (const auto& item : DefaultLeftPaddlesMapping)
|
||||||
setDefaultAction(stick, item, event, EventMode::kPaddlesMode, updateDefaults);
|
setDefaultAction(stick, item, event, EventMode::kPaddlesMode, updateDefaults);
|
||||||
for (const auto& item : DefaultLeftKeypadMapping)
|
for (const auto& item : DefaultLeftKeyboardMapping)
|
||||||
setDefaultAction(stick, item, event, EventMode::kKeypadMode, updateDefaults);
|
setDefaultAction(stick, item, event, EventMode::kKeyboardMode, updateDefaults);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -371,8 +391,8 @@ void PhysicalJoystickHandler::setStickDefaultMapping(int stick, Event::Type even
|
||||||
setDefaultAction(stick, item, event, EventMode::kJoystickMode, updateDefaults);
|
setDefaultAction(stick, item, event, EventMode::kJoystickMode, updateDefaults);
|
||||||
for (const auto& item : DefaultRightPaddlesMapping)
|
for (const auto& item : DefaultRightPaddlesMapping)
|
||||||
setDefaultAction(stick, item, event, EventMode::kPaddlesMode, updateDefaults);
|
setDefaultAction(stick, item, event, EventMode::kPaddlesMode, updateDefaults);
|
||||||
for (const auto& item : DefaultRightKeypadMapping)
|
for (const auto& item : DefaultRightKeyboardMapping)
|
||||||
setDefaultAction(stick, item, event, EventMode::kKeypadMode, updateDefaults);
|
setDefaultAction(stick, item, event, EventMode::kKeyboardMode, updateDefaults);
|
||||||
}
|
}
|
||||||
for(const auto& item : DefaultCommonMapping)
|
for(const auto& item : DefaultCommonMapping)
|
||||||
setDefaultAction(stick, item, event, EventMode::kCommonMode, updateDefaults);
|
setDefaultAction(stick, item, event, EventMode::kCommonMode, updateDefaults);
|
||||||
|
@ -409,9 +429,9 @@ void PhysicalJoystickHandler::defineControllerMappings(const Controller::Type ty
|
||||||
case Controller::Type::Keyboard:
|
case Controller::Type::Keyboard:
|
||||||
case Controller::Type::KidVid:
|
case Controller::Type::KidVid:
|
||||||
if(port == Controller::Jack::Left)
|
if(port == Controller::Jack::Left)
|
||||||
myLeftMode = EventMode::kKeypadMode;
|
myLeftMode = EventMode::kKeyboardMode;
|
||||||
else
|
else
|
||||||
myRightMode = EventMode::kKeypadMode;
|
myRightMode = EventMode::kKeyboardMode;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Controller::Type::Paddles:
|
case Controller::Type::Paddles:
|
||||||
|
@ -456,8 +476,8 @@ void PhysicalJoystickHandler::enableEmulationMappings()
|
||||||
enableMappings(RightPaddlesEvents, EventMode::kPaddlesMode);
|
enableMappings(RightPaddlesEvents, EventMode::kPaddlesMode);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EventMode::kKeypadMode:
|
case EventMode::kKeyboardMode:
|
||||||
enableMappings(RightKeypadEvents, EventMode::kKeypadMode);
|
enableMappings(RightKeyboardEvents, EventMode::kKeyboardMode);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -471,8 +491,8 @@ void PhysicalJoystickHandler::enableEmulationMappings()
|
||||||
enableMappings(LeftPaddlesEvents, EventMode::kPaddlesMode);
|
enableMappings(LeftPaddlesEvents, EventMode::kPaddlesMode);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EventMode::kKeypadMode:
|
case EventMode::kKeyboardMode:
|
||||||
enableMappings(LeftKeypadEvents, EventMode::kKeypadMode);
|
enableMappings(LeftKeyboardEvents, EventMode::kKeyboardMode);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -527,8 +547,8 @@ EventMode PhysicalJoystickHandler::getEventMode(const Event::Type event, const E
|
||||||
if(isPaddleEvent(event))
|
if(isPaddleEvent(event))
|
||||||
return EventMode::kPaddlesMode;
|
return EventMode::kPaddlesMode;
|
||||||
|
|
||||||
if(isKeypadEvent(event))
|
if(isKeyboardEvent(event))
|
||||||
return EventMode::kKeypadMode;
|
return EventMode::kKeyboardMode;
|
||||||
|
|
||||||
if(isCommonEvent(event))
|
if(isCommonEvent(event))
|
||||||
return EventMode::kCommonMode;
|
return EventMode::kCommonMode;
|
||||||
|
@ -552,16 +572,16 @@ bool PhysicalJoystickHandler::isPaddleEvent(const Event::Type event) const
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool PhysicalJoystickHandler::isKeypadEvent(const Event::Type event) const
|
bool PhysicalJoystickHandler::isKeyboardEvent(const Event::Type event) const
|
||||||
{
|
{
|
||||||
return LeftKeypadEvents.find(event) != LeftKeypadEvents.end()
|
return LeftKeyboardEvents.find(event) != LeftKeyboardEvents.end()
|
||||||
|| RightKeypadEvents.find(event) != RightKeypadEvents.end();
|
|| RightKeyboardEvents.find(event) != RightKeyboardEvents.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool PhysicalJoystickHandler::isCommonEvent(const Event::Type event) const
|
bool PhysicalJoystickHandler::isCommonEvent(const Event::Type event) const
|
||||||
{
|
{
|
||||||
return !(isJoystickEvent(event) || isPaddleEvent(event) || isKeypadEvent(event));
|
return !(isJoystickEvent(event) || isPaddleEvent(event) || isKeyboardEvent(event));
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -579,7 +599,7 @@ void PhysicalJoystickHandler::eraseMapping(Event::Type event, EventMode mode)
|
||||||
_joyptr->eraseMap(EventMode::kCommonMode);
|
_joyptr->eraseMap(EventMode::kCommonMode);
|
||||||
_joyptr->eraseMap(EventMode::kJoystickMode);
|
_joyptr->eraseMap(EventMode::kJoystickMode);
|
||||||
_joyptr->eraseMap(EventMode::kPaddlesMode);
|
_joyptr->eraseMap(EventMode::kPaddlesMode);
|
||||||
_joyptr->eraseMap(EventMode::kKeypadMode);
|
_joyptr->eraseMap(EventMode::kKeyboardMode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -656,7 +676,7 @@ bool PhysicalJoystickHandler::addJoyMapping(Event::Type event, EventMode mode, i
|
||||||
// erase identical mappings for all controller modes
|
// erase identical mappings for all controller modes
|
||||||
j->joyMap.erase(EventMode::kJoystickMode, button, axis, adir);
|
j->joyMap.erase(EventMode::kJoystickMode, button, axis, adir);
|
||||||
j->joyMap.erase(EventMode::kPaddlesMode, button, axis, adir);
|
j->joyMap.erase(EventMode::kPaddlesMode, button, axis, adir);
|
||||||
j->joyMap.erase(EventMode::kKeypadMode, button, axis, adir);
|
//j->joyMap.erase(EventMode::kKeyboardMode, button, axis, adir); // no common buttons in keyboard mode!
|
||||||
j->joyMap.erase(EventMode::kCompuMateMode, button, axis, adir);
|
j->joyMap.erase(EventMode::kCompuMateMode, button, axis, adir);
|
||||||
}
|
}
|
||||||
else if (evMode != EventMode::kMenuMode)
|
else if (evMode != EventMode::kMenuMode)
|
||||||
|
@ -691,7 +711,7 @@ bool PhysicalJoystickHandler::addJoyHatMapping(Event::Type event, EventMode mode
|
||||||
// erase identical mappings for all controller modes
|
// erase identical mappings for all controller modes
|
||||||
j->joyMap.erase(EventMode::kJoystickMode, button, hat, hdir);
|
j->joyMap.erase(EventMode::kJoystickMode, button, hat, hdir);
|
||||||
j->joyMap.erase(EventMode::kPaddlesMode, button, hat, hdir);
|
j->joyMap.erase(EventMode::kPaddlesMode, button, hat, hdir);
|
||||||
j->joyMap.erase(EventMode::kKeypadMode, button, hat, hdir);
|
j->joyMap.erase(EventMode::kKeyboardMode, button, hat, hdir);
|
||||||
j->joyMap.erase(EventMode::kCompuMateMode, button, hat, hdir);
|
j->joyMap.erase(EventMode::kCompuMateMode, button, hat, hdir);
|
||||||
}
|
}
|
||||||
else if (evMode != EventMode::kMenuMode)
|
else if (evMode != EventMode::kMenuMode)
|
||||||
|
@ -1068,113 +1088,113 @@ void PhysicalJoystickHandler::changeDrivingSensitivity(int direction)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
PhysicalJoystickHandler::EventMappingArray PhysicalJoystickHandler::DefaultLeftJoystickMapping = {
|
PhysicalJoystickHandler::EventMappingArray PhysicalJoystickHandler::DefaultLeftJoystickMapping = {
|
||||||
// Left joystick (assume buttons zero..two)
|
// Left joystick (assume buttons zero..two)
|
||||||
{Event::JoystickZeroFire, 0},
|
{Event::LeftJoystickFire, 0},
|
||||||
{Event::JoystickZeroFire5, 1},
|
{Event::LeftJoystickFire5, 1},
|
||||||
{Event::JoystickZeroFire9, 2},
|
{Event::LeftJoystickFire9, 2},
|
||||||
// Left joystick left/right directions
|
// Left joystick left/right directions
|
||||||
{Event::JoystickZeroLeft, JOY_CTRL_NONE, JoyAxis::X, JoyDir::NEG},
|
{Event::LeftJoystickLeft, JOY_CTRL_NONE, JoyAxis::X, JoyDir::NEG},
|
||||||
{Event::JoystickZeroRight, JOY_CTRL_NONE, JoyAxis::X, JoyDir::POS},
|
{Event::LeftJoystickRight, JOY_CTRL_NONE, JoyAxis::X, JoyDir::POS},
|
||||||
// Left joystick up/down directions
|
// Left joystick up/down directions
|
||||||
{Event::JoystickZeroUp, JOY_CTRL_NONE, JoyAxis::Y, JoyDir::NEG},
|
{Event::LeftJoystickUp, JOY_CTRL_NONE, JoyAxis::Y, JoyDir::NEG},
|
||||||
{Event::JoystickZeroDown, JOY_CTRL_NONE, JoyAxis::Y, JoyDir::POS},
|
{Event::LeftJoystickDown, JOY_CTRL_NONE, JoyAxis::Y, JoyDir::POS},
|
||||||
// Left joystick left/right directions (assume hat 0)
|
// Left joystick left/right directions (assume hat 0)
|
||||||
{Event::JoystickZeroLeft, JOY_CTRL_NONE, JoyAxis::NONE, JoyDir::NONE, 0, JoyHatDir::LEFT},
|
{Event::LeftJoystickLeft, JOY_CTRL_NONE, JoyAxis::NONE, JoyDir::NONE, 0, JoyHatDir::LEFT},
|
||||||
{Event::JoystickZeroRight, JOY_CTRL_NONE, JoyAxis::NONE, JoyDir::NONE, 0, JoyHatDir::RIGHT},
|
{Event::LeftJoystickRight, JOY_CTRL_NONE, JoyAxis::NONE, JoyDir::NONE, 0, JoyHatDir::RIGHT},
|
||||||
// Left joystick up/down directions (assume hat 0)
|
// Left joystick up/down directions (assume hat 0)
|
||||||
{Event::JoystickZeroUp, JOY_CTRL_NONE, JoyAxis::NONE, JoyDir::NONE, 0, JoyHatDir::UP},
|
{Event::LeftJoystickUp, JOY_CTRL_NONE, JoyAxis::NONE, JoyDir::NONE, 0, JoyHatDir::UP},
|
||||||
{Event::JoystickZeroDown, JOY_CTRL_NONE, JoyAxis::NONE, JoyDir::NONE, 0, JoyHatDir::DOWN},
|
{Event::LeftJoystickDown, JOY_CTRL_NONE, JoyAxis::NONE, JoyDir::NONE, 0, JoyHatDir::DOWN},
|
||||||
};
|
};
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
PhysicalJoystickHandler::EventMappingArray PhysicalJoystickHandler::DefaultRightJoystickMapping = {
|
PhysicalJoystickHandler::EventMappingArray PhysicalJoystickHandler::DefaultRightJoystickMapping = {
|
||||||
// Right joystick (assume buttons zero..two)
|
// Right joystick (assume buttons zero..two)
|
||||||
{Event::JoystickOneFire, 0},
|
{Event::RightJoystickFire, 0},
|
||||||
{Event::JoystickOneFire5, 1},
|
{Event::RightJoystickFire5, 1},
|
||||||
{Event::JoystickOneFire9, 2},
|
{Event::RightJoystickFire9, 2},
|
||||||
// Right joystick left/right directions
|
// Right joystick left/right directions
|
||||||
{Event::JoystickOneLeft, JOY_CTRL_NONE, JoyAxis::X, JoyDir::NEG},
|
{Event::RightJoystickLeft, JOY_CTRL_NONE, JoyAxis::X, JoyDir::NEG},
|
||||||
{Event::JoystickOneRight, JOY_CTRL_NONE, JoyAxis::X, JoyDir::POS},
|
{Event::RightJoystickRight, JOY_CTRL_NONE, JoyAxis::X, JoyDir::POS},
|
||||||
// Right joystick up/down directions
|
// Right joystick up/down directions
|
||||||
{Event::JoystickOneUp, JOY_CTRL_NONE, JoyAxis::Y, JoyDir::NEG},
|
{Event::RightJoystickUp, JOY_CTRL_NONE, JoyAxis::Y, JoyDir::NEG},
|
||||||
{Event::JoystickOneDown, JOY_CTRL_NONE, JoyAxis::Y, JoyDir::POS},
|
{Event::RightJoystickDown, JOY_CTRL_NONE, JoyAxis::Y, JoyDir::POS},
|
||||||
// Right joystick left/right directions (assume hat 0)
|
// Right joystick left/right directions (assume hat 0)
|
||||||
{Event::JoystickOneLeft, JOY_CTRL_NONE, JoyAxis::NONE, JoyDir::NONE, 0, JoyHatDir::LEFT},
|
{Event::RightJoystickLeft, JOY_CTRL_NONE, JoyAxis::NONE, JoyDir::NONE, 0, JoyHatDir::LEFT},
|
||||||
{Event::JoystickOneRight, JOY_CTRL_NONE, JoyAxis::NONE, JoyDir::NONE, 0, JoyHatDir::RIGHT},
|
{Event::RightJoystickRight, JOY_CTRL_NONE, JoyAxis::NONE, JoyDir::NONE, 0, JoyHatDir::RIGHT},
|
||||||
// Right joystick up/down directions (assume hat 0)
|
// Right joystick up/down directions (assume hat 0)
|
||||||
{Event::JoystickOneUp, JOY_CTRL_NONE, JoyAxis::NONE, JoyDir::NONE, 0, JoyHatDir::UP},
|
{Event::RightJoystickUp, JOY_CTRL_NONE, JoyAxis::NONE, JoyDir::NONE, 0, JoyHatDir::UP},
|
||||||
{Event::JoystickOneDown, JOY_CTRL_NONE, JoyAxis::NONE, JoyDir::NONE, 0, JoyHatDir::DOWN},
|
{Event::RightJoystickDown, JOY_CTRL_NONE, JoyAxis::NONE, JoyDir::NONE, 0, JoyHatDir::DOWN},
|
||||||
};
|
};
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
PhysicalJoystickHandler::EventMappingArray PhysicalJoystickHandler::DefaultLeftPaddlesMapping = {
|
PhysicalJoystickHandler::EventMappingArray PhysicalJoystickHandler::DefaultLeftPaddlesMapping = {
|
||||||
{Event::PaddleZeroAnalog, JOY_CTRL_NONE, JoyAxis::X, JoyDir::ANALOG},
|
{Event::LeftPaddleAAnalog, JOY_CTRL_NONE, JoyAxis::X, JoyDir::ANALOG},
|
||||||
#if defined(RETRON77)
|
#if defined(RETRON77)
|
||||||
{Event::PaddleZeroAnalog, JOY_CTRL_NONE, JoyAxis::Z, JoyDir::ANALOG},
|
{Event::LeftPaddleAAnalog, JOY_CTRL_NONE, JoyAxis::Z, JoyDir::ANALOG},
|
||||||
#endif
|
#endif
|
||||||
// Current code does NOT allow digital and anlog events on the same axis at the same time
|
// Current code does NOT allow digital and anlog events on the same axis at the same time
|
||||||
//{Event::PaddleZeroDecrease, JOY_CTRL_NONE, JoyAxis::X, JoyDir::POS},
|
//{Event::LeftPaddleADecrease, JOY_CTRL_NONE, JoyAxis::X, JoyDir::POS},
|
||||||
//{Event::PaddleZeroIncrease, JOY_CTRL_NONE, JoyAxis::X, JoyDir::NEG},
|
//{Event::LeftPaddleAIncrease, JOY_CTRL_NONE, JoyAxis::X, JoyDir::NEG},
|
||||||
{Event::PaddleZeroFire, 0},
|
{Event::LeftPaddleAFire, 0},
|
||||||
{Event::PaddleOneAnalog, JOY_CTRL_NONE, JoyAxis::Y, JoyDir::ANALOG},
|
{Event::LeftPaddleBAnalog, JOY_CTRL_NONE, JoyAxis::Y, JoyDir::ANALOG},
|
||||||
#if defined(RETRON77)
|
#if defined(RETRON77)
|
||||||
{Event::PaddleOneAnalog, JOY_CTRL_NONE, JoyAxis::A3, JoyDir::ANALOG},
|
{Event::LeftPaddleBAnalog, JOY_CTRL_NONE, JoyAxis::A3, JoyDir::ANALOG},
|
||||||
#endif
|
#endif
|
||||||
// Current code does NOT allow digital and anlog events on the same axis at the same
|
// Current code does NOT allow digital and anlog events on the same axis at the same
|
||||||
//{Event::PaddleOneDecrease, JOY_CTRL_NONE, JoyAxis::Y, JoyDir::POS},
|
//{Event::LeftPaddleBDecrease, JOY_CTRL_NONE, JoyAxis::Y, JoyDir::POS},
|
||||||
//{Event::PaddleOneIncrease, JOY_CTRL_NONE, JoyAxis::Y, JoyDir::NEG},
|
//{Event::LeftPaddleBIncrease, JOY_CTRL_NONE, JoyAxis::Y, JoyDir::NEG},
|
||||||
{Event::PaddleOneFire, 1},
|
{Event::LeftPaddleBFire, 1},
|
||||||
};
|
};
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
PhysicalJoystickHandler::EventMappingArray PhysicalJoystickHandler::DefaultRightPaddlesMapping = {
|
PhysicalJoystickHandler::EventMappingArray PhysicalJoystickHandler::DefaultRightPaddlesMapping = {
|
||||||
{Event::PaddleTwoAnalog, JOY_CTRL_NONE, JoyAxis::X, JoyDir::ANALOG},
|
{Event::RightPaddleAAnalog, JOY_CTRL_NONE, JoyAxis::X, JoyDir::ANALOG},
|
||||||
#if defined(RETRON77)
|
#if defined(RETRON77)
|
||||||
{Event::PaddleTwoAnalog, JOY_CTRL_NONE, JoyAxis::Z, JoyDir::ANALOG},
|
{Event::RightPaddleAAnalog, JOY_CTRL_NONE, JoyAxis::Z, JoyDir::ANALOG},
|
||||||
#endif
|
#endif
|
||||||
// Current code does NOT allow digital and anlog events on the same axis at the same
|
// Current code does NOT allow digital and anlog events on the same axis at the same
|
||||||
//{Event::PaddleTwoDecrease, JOY_CTRL_NONE, JoyAxis::X, JoyDir::POS},
|
//{Event::RightPaddleADecrease, JOY_CTRL_NONE, JoyAxis::X, JoyDir::POS},
|
||||||
//{Event::PaddleTwoIncrease, JOY_CTRL_NONE, JoyAxis::X, JoyDir::NEG},
|
//{Event::RightPaddleAIncrease, JOY_CTRL_NONE, JoyAxis::X, JoyDir::NEG},
|
||||||
{Event::PaddleTwoFire, 0},
|
{Event::RightPaddleAFire, 0},
|
||||||
{Event::PaddleThreeAnalog, JOY_CTRL_NONE, JoyAxis::Y, JoyDir::ANALOG},
|
{Event::RightPaddleBAnalog, JOY_CTRL_NONE, JoyAxis::Y, JoyDir::ANALOG},
|
||||||
#if defined(RETRON77)
|
#if defined(RETRON77)
|
||||||
{Event::PaddleThreeAnalog, JOY_CTRL_NONE, JoyAxis::A3, JoyDir::ANALOG},
|
{Event::RightPaddleBAnalog, JOY_CTRL_NONE, JoyAxis::A3, JoyDir::ANALOG},
|
||||||
#endif
|
#endif
|
||||||
// Current code does NOT allow digital and anlog events on the same axis at the same
|
// Current code does NOT allow digital and anlog events on the same axis at the same
|
||||||
//{Event::PaddleThreeDecrease,JOY_CTRL_NONE, JoyAxis::Y, JoyDir::POS},
|
//{Event::RightPaddleBDecrease,JOY_CTRL_NONE, JoyAxis::Y, JoyDir::POS},
|
||||||
//{Event::PaddleThreeIncrease,JOY_CTRL_NONE, JoyAxis::Y, JoyDir::NEG},
|
//{Event::RightPaddleBIncrease,JOY_CTRL_NONE, JoyAxis::Y, JoyDir::NEG},
|
||||||
{Event::PaddleThreeFire, 1},
|
{Event::RightPaddleBFire, 1},
|
||||||
};
|
};
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
PhysicalJoystickHandler::EventMappingArray PhysicalJoystickHandler::DefaultLeftKeypadMapping = {
|
PhysicalJoystickHandler::EventMappingArray PhysicalJoystickHandler::DefaultLeftKeyboardMapping = {
|
||||||
{Event::KeyboardZero1, 0},
|
{Event::LeftKeyboard1, 0},
|
||||||
{Event::KeyboardZero2, 1},
|
{Event::LeftKeyboard2, 1},
|
||||||
{Event::KeyboardZero3, 2},
|
{Event::LeftKeyboard3, 2},
|
||||||
{Event::KeyboardZero4, 3},
|
{Event::LeftKeyboard4, 3},
|
||||||
{Event::KeyboardZero5, 4},
|
{Event::LeftKeyboard5, 4},
|
||||||
{Event::KeyboardZero6, 5},
|
{Event::LeftKeyboard6, 5},
|
||||||
{Event::KeyboardZero7, 6},
|
{Event::LeftKeyboard7, 6},
|
||||||
{Event::KeyboardZero8, 7},
|
{Event::LeftKeyboard8, 7},
|
||||||
{Event::KeyboardZero9, 8},
|
{Event::LeftKeyboard9, 8},
|
||||||
{Event::KeyboardZeroStar, 9},
|
{Event::LeftKeyboardStar, 9},
|
||||||
{Event::KeyboardZero0, 10},
|
{Event::LeftKeyboard0, 10},
|
||||||
{Event::KeyboardZeroPound, 11},
|
{Event::LeftKeyboardPound, 11},
|
||||||
};
|
};
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
PhysicalJoystickHandler::EventMappingArray PhysicalJoystickHandler::DefaultRightKeypadMapping = {
|
PhysicalJoystickHandler::EventMappingArray PhysicalJoystickHandler::DefaultRightKeyboardMapping = {
|
||||||
{Event::KeyboardOne1, 0},
|
{Event::RightKeyboard1, 0},
|
||||||
{Event::KeyboardOne2, 1},
|
{Event::RightKeyboard2, 1},
|
||||||
{Event::KeyboardOne3, 2},
|
{Event::RightKeyboard3, 2},
|
||||||
{Event::KeyboardOne4, 3},
|
{Event::RightKeyboard4, 3},
|
||||||
{Event::KeyboardOne5, 4},
|
{Event::RightKeyboard5, 4},
|
||||||
{Event::KeyboardOne6, 5},
|
{Event::RightKeyboard6, 5},
|
||||||
{Event::KeyboardOne7, 6},
|
{Event::RightKeyboard7, 6},
|
||||||
{Event::KeyboardOne8, 7},
|
{Event::RightKeyboard8, 7},
|
||||||
{Event::KeyboardOne9, 8},
|
{Event::RightKeyboard9, 8},
|
||||||
{Event::KeyboardOneStar, 9},
|
{Event::RightKeyboardStar, 9},
|
||||||
{Event::KeyboardOne0, 10},
|
{Event::RightKeyboard0, 10},
|
||||||
{Event::KeyboardOnePound, 11},
|
{Event::RightKeyboardPound, 11},
|
||||||
};
|
};
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -70,7 +70,7 @@ class PhysicalJoystickHandler
|
||||||
int add(const PhysicalJoystickPtr& stick);
|
int add(const PhysicalJoystickPtr& stick);
|
||||||
bool remove(int id);
|
bool remove(int id);
|
||||||
bool remove(const string& name);
|
bool remove(const string& name);
|
||||||
void mapStelladaptors(const string& saport);
|
bool mapStelladaptors(const string& saport, int ID = -1);
|
||||||
bool hasStelladaptors() const;
|
bool hasStelladaptors() const;
|
||||||
void setDefaultMapping(Event::Type type, EventMode mode);
|
void setDefaultMapping(Event::Type type, EventMode mode);
|
||||||
|
|
||||||
|
@ -140,6 +140,9 @@ class PhysicalJoystickHandler
|
||||||
return i != mySticks.cend() ? i->second : nullptr;
|
return i != mySticks.cend() ? i->second : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add stick to stick database
|
||||||
|
void addToDatabase(const PhysicalJoystickPtr& stick);
|
||||||
|
|
||||||
// Set default mapping for given joystick when no mappings already exist
|
// Set default mapping for given joystick when no mappings already exist
|
||||||
void setStickDefaultMapping(int stick, Event::Type type, EventMode mode,
|
void setStickDefaultMapping(int stick, Event::Type type, EventMode mode,
|
||||||
bool updateDefaults = false);
|
bool updateDefaults = false);
|
||||||
|
@ -175,7 +178,7 @@ class PhysicalJoystickHandler
|
||||||
/** Checks event type. */
|
/** Checks event type. */
|
||||||
bool isJoystickEvent(const Event::Type event) const;
|
bool isJoystickEvent(const Event::Type event) const;
|
||||||
bool isPaddleEvent(const Event::Type event) const;
|
bool isPaddleEvent(const Event::Type event) const;
|
||||||
bool isKeypadEvent(const Event::Type event) const;
|
bool isKeyboardEvent(const Event::Type event) const;
|
||||||
bool isCommonEvent(const Event::Type event) const;
|
bool isCommonEvent(const Event::Type event) const;
|
||||||
|
|
||||||
void enableCommonMappings();
|
void enableCommonMappings();
|
||||||
|
@ -195,8 +198,8 @@ class PhysicalJoystickHandler
|
||||||
static EventMappingArray DefaultRightJoystickMapping;
|
static EventMappingArray DefaultRightJoystickMapping;
|
||||||
static EventMappingArray DefaultLeftPaddlesMapping;
|
static EventMappingArray DefaultLeftPaddlesMapping;
|
||||||
static EventMappingArray DefaultRightPaddlesMapping;
|
static EventMappingArray DefaultRightPaddlesMapping;
|
||||||
static EventMappingArray DefaultLeftKeypadMapping;
|
static EventMappingArray DefaultLeftKeyboardMapping;
|
||||||
static EventMappingArray DefaultRightKeypadMapping;
|
static EventMappingArray DefaultRightKeyboardMapping;
|
||||||
|
|
||||||
static constexpr int NUM_PORTS = 2;
|
static constexpr int NUM_PORTS = 2;
|
||||||
static constexpr int NUM_SA_AXIS = 2;
|
static constexpr int NUM_SA_AXIS = 2;
|
||||||
|
|
|
@ -53,7 +53,7 @@ PhysicalKeyboardHandler::PhysicalKeyboardHandler(OSystem& system, EventHandler&
|
||||||
loadSerializedMappings(myOSystem.settings().getString("keymap_emu"), EventMode::kCommonMode);
|
loadSerializedMappings(myOSystem.settings().getString("keymap_emu"), EventMode::kCommonMode);
|
||||||
loadSerializedMappings(myOSystem.settings().getString("keymap_joy"), EventMode::kJoystickMode);
|
loadSerializedMappings(myOSystem.settings().getString("keymap_joy"), EventMode::kJoystickMode);
|
||||||
loadSerializedMappings(myOSystem.settings().getString("keymap_pad"), EventMode::kPaddlesMode);
|
loadSerializedMappings(myOSystem.settings().getString("keymap_pad"), EventMode::kPaddlesMode);
|
||||||
loadSerializedMappings(myOSystem.settings().getString("keymap_key"), EventMode::kKeypadMode);
|
loadSerializedMappings(myOSystem.settings().getString("keymap_key"), EventMode::kKeyboardMode);
|
||||||
loadSerializedMappings(myOSystem.settings().getString("keymap_ui"), EventMode::kMenuMode);
|
loadSerializedMappings(myOSystem.settings().getString("keymap_ui"), EventMode::kMenuMode);
|
||||||
|
|
||||||
updateDefaults = true;
|
updateDefaults = true;
|
||||||
|
@ -65,7 +65,10 @@ PhysicalKeyboardHandler::PhysicalKeyboardHandler(OSystem& system, EventHandler&
|
||||||
setDefaultMapping(Event::NoType, EventMode::kMenuMode, updateDefaults);
|
setDefaultMapping(Event::NoType, EventMode::kMenuMode, updateDefaults);
|
||||||
#ifdef GUI_SUPPORT
|
#ifdef GUI_SUPPORT
|
||||||
setDefaultMapping(Event::NoType, EventMode::kEditMode, updateDefaults);
|
setDefaultMapping(Event::NoType, EventMode::kEditMode, updateDefaults);
|
||||||
#endif // DEBUG
|
#endif
|
||||||
|
#ifdef DEBUGGER_SUPPORT
|
||||||
|
setDefaultMapping(Event::NoType, EventMode::kPromptMode, updateDefaults);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -109,7 +112,7 @@ bool PhysicalKeyboardHandler::isMappingUsed(EventMode mode, const EventMapping&
|
||||||
return myKeyMap.check(EventMode::kCommonMode, map.key, map.mod)
|
return myKeyMap.check(EventMode::kCommonMode, map.key, map.mod)
|
||||||
|| myKeyMap.check(EventMode::kJoystickMode, map.key, map.mod)
|
|| myKeyMap.check(EventMode::kJoystickMode, map.key, map.mod)
|
||||||
|| myKeyMap.check(EventMode::kPaddlesMode, map.key, map.mod)
|
|| myKeyMap.check(EventMode::kPaddlesMode, map.key, map.mod)
|
||||||
|| myKeyMap.check(EventMode::kKeypadMode, map.key, map.mod)
|
|| myKeyMap.check(EventMode::kKeyboardMode, map.key, map.mod)
|
||||||
|| myKeyMap.check(EventMode::kCompuMateMode, map.key, map.mod);
|
|| myKeyMap.check(EventMode::kCompuMateMode, map.key, map.mod);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,8 +180,8 @@ void PhysicalKeyboardHandler::setDefaultMapping(Event::Type event, EventMode mod
|
||||||
setDefaultKey(item, event, EventMode::kJoystickMode, updateDefaults);
|
setDefaultKey(item, event, EventMode::kJoystickMode, updateDefaults);
|
||||||
for (const auto& item: DefaultPaddleMapping)
|
for (const auto& item: DefaultPaddleMapping)
|
||||||
setDefaultKey(item, event, EventMode::kPaddlesMode, updateDefaults);
|
setDefaultKey(item, event, EventMode::kPaddlesMode, updateDefaults);
|
||||||
for (const auto& item: DefaultKeypadMapping)
|
for (const auto& item: DefaultKeyboardMapping)
|
||||||
setDefaultKey(item, event, EventMode::kKeypadMode, updateDefaults);
|
setDefaultKey(item, event, EventMode::kKeyboardMode, updateDefaults);
|
||||||
for (const auto& item : CompuMateMapping)
|
for (const auto& item : CompuMateMapping)
|
||||||
setDefaultKey(item, event, EventMode::kCompuMateMode, updateDefaults);
|
setDefaultKey(item, event, EventMode::kCompuMateMode, updateDefaults);
|
||||||
break;
|
break;
|
||||||
|
@ -195,6 +198,13 @@ void PhysicalKeyboardHandler::setDefaultMapping(Event::Type event, EventMode mod
|
||||||
setDefaultKey(item, event, EventMode::kEditMode);
|
setDefaultKey(item, event, EventMode::kEditMode);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef DEBUGGER_SUPPORT
|
||||||
|
case EventMode::kPromptMode:
|
||||||
|
// Edit mode events are always set because they are not saved
|
||||||
|
for(const auto& item : FixedPromptMapping)
|
||||||
|
setDefaultKey(item, event, EventMode::kPromptMode);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -254,7 +264,7 @@ EventMode PhysicalKeyboardHandler::getMode(const Controller::Type type)
|
||||||
{
|
{
|
||||||
case Controller::Type::Keyboard:
|
case Controller::Type::Keyboard:
|
||||||
case Controller::Type::KidVid:
|
case Controller::Type::KidVid:
|
||||||
return EventMode::kKeypadMode;
|
return EventMode::kKeyboardMode;
|
||||||
|
|
||||||
case Controller::Type::Paddles:
|
case Controller::Type::Paddles:
|
||||||
case Controller::Type::PaddlesIAxDr:
|
case Controller::Type::PaddlesIAxDr:
|
||||||
|
@ -282,28 +292,28 @@ void PhysicalKeyboardHandler::enableEmulationMappings()
|
||||||
switch(myRight2ndMode)
|
switch(myRight2ndMode)
|
||||||
{
|
{
|
||||||
case EventMode::kPaddlesMode:
|
case EventMode::kPaddlesMode:
|
||||||
enableMappings(Right2PaddlesEvents, EventMode::kPaddlesMode);
|
enableMappings(QTPaddles4Events, EventMode::kPaddlesMode);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EventMode::kEmulationMode: // no QuadTari
|
case EventMode::kEmulationMode: // no QuadTari
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
enableMappings(Right2JoystickEvents, EventMode::kJoystickMode);
|
enableMappings(QTJoystick4Events, EventMode::kJoystickMode);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(myLeft2ndMode)
|
switch(myLeft2ndMode)
|
||||||
{
|
{
|
||||||
case EventMode::kPaddlesMode:
|
case EventMode::kPaddlesMode:
|
||||||
enableMappings(Left2PaddlesEvents, EventMode::kPaddlesMode);
|
enableMappings(QTPaddles3Events, EventMode::kPaddlesMode);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EventMode::kEmulationMode: // no QuadTari
|
case EventMode::kEmulationMode: // no QuadTari
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
enableMappings(Left2JoystickEvents, EventMode::kJoystickMode);
|
enableMappings(QTJoystick3Events, EventMode::kJoystickMode);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -313,8 +323,8 @@ void PhysicalKeyboardHandler::enableEmulationMappings()
|
||||||
enableMappings(RightPaddlesEvents, EventMode::kPaddlesMode);
|
enableMappings(RightPaddlesEvents, EventMode::kPaddlesMode);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EventMode::kKeypadMode:
|
case EventMode::kKeyboardMode:
|
||||||
enableMappings(RightKeypadEvents, EventMode::kKeypadMode);
|
enableMappings(RightKeyboardEvents, EventMode::kKeyboardMode);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EventMode::kCompuMateMode:
|
case EventMode::kCompuMateMode:
|
||||||
|
@ -332,8 +342,8 @@ void PhysicalKeyboardHandler::enableEmulationMappings()
|
||||||
enableMappings(LeftPaddlesEvents, EventMode::kPaddlesMode);
|
enableMappings(LeftPaddlesEvents, EventMode::kPaddlesMode);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EventMode::kKeypadMode:
|
case EventMode::kKeyboardMode:
|
||||||
enableMappings(LeftKeypadEvents, EventMode::kKeypadMode);
|
enableMappings(LeftKeyboardEvents, EventMode::kKeyboardMode);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EventMode::kCompuMateMode:
|
case EventMode::kCompuMateMode:
|
||||||
|
@ -390,8 +400,8 @@ EventMode PhysicalKeyboardHandler::getEventMode(const Event::Type event,
|
||||||
if (isPaddleEvent(event))
|
if (isPaddleEvent(event))
|
||||||
return EventMode::kPaddlesMode;
|
return EventMode::kPaddlesMode;
|
||||||
|
|
||||||
if (isKeypadEvent(event))
|
if (isKeyboardEvent(event))
|
||||||
return EventMode::kKeypadMode;
|
return EventMode::kKeyboardMode;
|
||||||
|
|
||||||
if (isCommonEvent(event))
|
if (isCommonEvent(event))
|
||||||
return EventMode::kCommonMode;
|
return EventMode::kCommonMode;
|
||||||
|
@ -404,31 +414,31 @@ EventMode PhysicalKeyboardHandler::getEventMode(const Event::Type event,
|
||||||
bool PhysicalKeyboardHandler::isJoystickEvent(const Event::Type event) const
|
bool PhysicalKeyboardHandler::isJoystickEvent(const Event::Type event) const
|
||||||
{
|
{
|
||||||
return LeftJoystickEvents.find(event) != LeftJoystickEvents.end()
|
return LeftJoystickEvents.find(event) != LeftJoystickEvents.end()
|
||||||
|| Left2JoystickEvents.find(event) != Left2JoystickEvents.end()
|
|| QTJoystick3Events.find(event) != QTJoystick3Events.end()
|
||||||
|| RightJoystickEvents.find(event) != RightJoystickEvents.end()
|
|| RightJoystickEvents.find(event) != RightJoystickEvents.end()
|
||||||
|| Right2JoystickEvents.find(event) != Right2JoystickEvents.end();
|
|| QTJoystick4Events.find(event) != QTJoystick4Events.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool PhysicalKeyboardHandler::isPaddleEvent(const Event::Type event) const
|
bool PhysicalKeyboardHandler::isPaddleEvent(const Event::Type event) const
|
||||||
{
|
{
|
||||||
return LeftPaddlesEvents.find(event) != LeftPaddlesEvents.end()
|
return LeftPaddlesEvents.find(event) != LeftPaddlesEvents.end()
|
||||||
|| Left2PaddlesEvents.find(event) != Left2PaddlesEvents.end()
|
|| QTPaddles3Events.find(event) != QTPaddles3Events.end()
|
||||||
|| RightPaddlesEvents.find(event) != RightPaddlesEvents.end()
|
|| RightPaddlesEvents.find(event) != RightPaddlesEvents.end()
|
||||||
|| Right2PaddlesEvents.find(event) != Right2PaddlesEvents.end();
|
|| QTPaddles4Events.find(event) != QTPaddles4Events.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool PhysicalKeyboardHandler::isKeypadEvent(const Event::Type event) const
|
bool PhysicalKeyboardHandler::isKeyboardEvent(const Event::Type event) const
|
||||||
{
|
{
|
||||||
return LeftKeypadEvents.find(event) != LeftKeypadEvents.end()
|
return LeftKeyboardEvents.find(event) != LeftKeyboardEvents.end()
|
||||||
|| RightKeypadEvents.find(event) != RightKeypadEvents.end();
|
|| RightKeyboardEvents.find(event) != RightKeyboardEvents.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool PhysicalKeyboardHandler::isCommonEvent(const Event::Type event) const
|
bool PhysicalKeyboardHandler::isCommonEvent(const Event::Type event) const
|
||||||
{
|
{
|
||||||
return !(isJoystickEvent(event) || isPaddleEvent(event) || isKeypadEvent(event));
|
return !(isJoystickEvent(event) || isPaddleEvent(event) || isKeyboardEvent(event));
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -445,7 +455,7 @@ void PhysicalKeyboardHandler::saveMapping()
|
||||||
myOSystem.settings().setValue("keymap_emu", myKeyMap.saveMapping(EventMode::kCommonMode).dump(2));
|
myOSystem.settings().setValue("keymap_emu", myKeyMap.saveMapping(EventMode::kCommonMode).dump(2));
|
||||||
myOSystem.settings().setValue("keymap_joy", myKeyMap.saveMapping(EventMode::kJoystickMode).dump(2));
|
myOSystem.settings().setValue("keymap_joy", myKeyMap.saveMapping(EventMode::kJoystickMode).dump(2));
|
||||||
myOSystem.settings().setValue("keymap_pad", myKeyMap.saveMapping(EventMode::kPaddlesMode).dump(2));
|
myOSystem.settings().setValue("keymap_pad", myKeyMap.saveMapping(EventMode::kPaddlesMode).dump(2));
|
||||||
myOSystem.settings().setValue("keymap_key", myKeyMap.saveMapping(EventMode::kKeypadMode).dump(2));
|
myOSystem.settings().setValue("keymap_key", myKeyMap.saveMapping(EventMode::kKeyboardMode).dump(2));
|
||||||
myOSystem.settings().setValue("keymap_ui", myKeyMap.saveMapping(EventMode::kMenuMode).dump(2));
|
myOSystem.settings().setValue("keymap_ui", myKeyMap.saveMapping(EventMode::kMenuMode).dump(2));
|
||||||
enableEmulationMappings();
|
enableEmulationMappings();
|
||||||
}
|
}
|
||||||
|
@ -467,10 +477,12 @@ bool PhysicalKeyboardHandler::addMapping(Event::Type event, EventMode mode,
|
||||||
// erase identical mappings for all controller modes
|
// erase identical mappings for all controller modes
|
||||||
myKeyMap.erase(EventMode::kJoystickMode, key, mod);
|
myKeyMap.erase(EventMode::kJoystickMode, key, mod);
|
||||||
myKeyMap.erase(EventMode::kPaddlesMode, key, mod);
|
myKeyMap.erase(EventMode::kPaddlesMode, key, mod);
|
||||||
myKeyMap.erase(EventMode::kKeypadMode, key, mod);
|
myKeyMap.erase(EventMode::kKeyboardMode, key, mod);
|
||||||
myKeyMap.erase(EventMode::kCompuMateMode, key, mod);
|
myKeyMap.erase(EventMode::kCompuMateMode, key, mod);
|
||||||
}
|
}
|
||||||
else if(evMode != EventMode::kMenuMode && evMode != EventMode::kEditMode)
|
else if(evMode != EventMode::kMenuMode
|
||||||
|
&& evMode != EventMode::kEditMode
|
||||||
|
&& evMode != EventMode::kPromptMode)
|
||||||
{
|
{
|
||||||
// erase identical mapping for kCommonMode
|
// erase identical mapping for kCommonMode
|
||||||
myKeyMap.erase(EventMode::kCommonMode, key, mod);
|
myKeyMap.erase(EventMode::kCommonMode, key, mod);
|
||||||
|
@ -899,111 +911,132 @@ PhysicalKeyboardHandler::FixedEditMapping = {
|
||||||
{Event::EndEdit, KBDK_KP_ENTER},
|
{Event::EndEdit, KBDK_KP_ENTER},
|
||||||
{Event::AbortEdit, KBDK_ESCAPE},
|
{Event::AbortEdit, KBDK_ESCAPE},
|
||||||
};
|
};
|
||||||
#endif
|
#endif // GUI_SUPPORT
|
||||||
|
|
||||||
|
#ifdef DEBUGGER_SUPPORT
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
PhysicalKeyboardHandler::EventMappingArray
|
||||||
|
PhysicalKeyboardHandler::FixedPromptMapping = {
|
||||||
|
{Event::UINavNext, KBDK_TAB},
|
||||||
|
{Event::UINavPrev, KBDK_TAB, KBDM_SHIFT},
|
||||||
|
{Event::UIPgUp, KBDK_PAGEUP},
|
||||||
|
{Event::UIPgUp, KBDK_PAGEUP, KBDM_SHIFT},
|
||||||
|
{Event::UIPgDown, KBDK_PAGEDOWN},
|
||||||
|
{Event::UIPgDown, KBDK_PAGEDOWN, KBDM_SHIFT},
|
||||||
|
{Event::UIHome, KBDK_HOME, KBDM_SHIFT},
|
||||||
|
{Event::UIEnd, KBDK_END, KBDM_SHIFT},
|
||||||
|
{Event::UIUp, KBDK_UP, KBDM_SHIFT},
|
||||||
|
{Event::UIDown, KBDK_DOWN, KBDM_SHIFT},
|
||||||
|
{Event::UILeft, KBDK_DOWN},
|
||||||
|
{Event::UIRight, KBDK_UP},
|
||||||
|
|
||||||
|
};
|
||||||
|
#endif // DEBUGGER_SUPPORT
|
||||||
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultJoystickMapping = {
|
PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultJoystickMapping = {
|
||||||
{Event::JoystickZeroUp, KBDK_UP},
|
{Event::LeftJoystickUp, KBDK_UP},
|
||||||
{Event::JoystickZeroDown, KBDK_DOWN},
|
{Event::LeftJoystickDown, KBDK_DOWN},
|
||||||
{Event::JoystickZeroLeft, KBDK_LEFT},
|
{Event::LeftJoystickLeft, KBDK_LEFT},
|
||||||
{Event::JoystickZeroRight, KBDK_RIGHT},
|
{Event::LeftJoystickRight, KBDK_RIGHT},
|
||||||
{Event::JoystickZeroUp, KBDK_KP_8},
|
{Event::LeftJoystickUp, KBDK_KP_8},
|
||||||
{Event::JoystickZeroDown, KBDK_KP_2},
|
{Event::LeftJoystickDown, KBDK_KP_2},
|
||||||
{Event::JoystickZeroLeft, KBDK_KP_4},
|
{Event::LeftJoystickLeft, KBDK_KP_4},
|
||||||
{Event::JoystickZeroRight, KBDK_KP_6},
|
{Event::LeftJoystickRight, KBDK_KP_6},
|
||||||
{Event::JoystickZeroFire, KBDK_SPACE},
|
{Event::LeftJoystickFire, KBDK_SPACE},
|
||||||
{Event::JoystickZeroFire, KBDK_LCTRL},
|
{Event::LeftJoystickFire, KBDK_LCTRL},
|
||||||
{Event::JoystickZeroFire, KBDK_KP_5},
|
{Event::LeftJoystickFire, KBDK_KP_5},
|
||||||
{Event::JoystickZeroFire5, KBDK_4},
|
{Event::LeftJoystickFire5, KBDK_4},
|
||||||
{Event::JoystickZeroFire5, KBDK_RSHIFT},
|
{Event::LeftJoystickFire5, KBDK_RSHIFT},
|
||||||
{Event::JoystickZeroFire5, KBDK_KP_9},
|
{Event::LeftJoystickFire5, KBDK_KP_9},
|
||||||
{Event::JoystickZeroFire9, KBDK_5},
|
{Event::LeftJoystickFire9, KBDK_5},
|
||||||
{Event::JoystickZeroFire9, KBDK_RCTRL},
|
{Event::LeftJoystickFire9, KBDK_RCTRL},
|
||||||
{Event::JoystickZeroFire9, KBDK_KP_3},
|
{Event::LeftJoystickFire9, KBDK_KP_3},
|
||||||
|
|
||||||
{Event::JoystickOneUp, KBDK_Y},
|
{Event::RightJoystickUp, KBDK_Y},
|
||||||
{Event::JoystickOneDown, KBDK_H},
|
{Event::RightJoystickDown, KBDK_H},
|
||||||
{Event::JoystickOneLeft, KBDK_G},
|
{Event::RightJoystickLeft, KBDK_G},
|
||||||
{Event::JoystickOneRight, KBDK_J},
|
{Event::RightJoystickRight, KBDK_J},
|
||||||
{Event::JoystickOneFire, KBDK_F},
|
{Event::RightJoystickFire, KBDK_F},
|
||||||
{Event::JoystickOneFire5, KBDK_6},
|
{Event::RightJoystickFire5, KBDK_6},
|
||||||
{Event::JoystickOneFire9, KBDK_7},
|
{Event::RightJoystickFire9, KBDK_7},
|
||||||
|
|
||||||
// Same as Joysticks Zero & One + SHIFT
|
// Same as Joysticks Zero & One + SHIFT
|
||||||
{Event::JoystickTwoUp, KBDK_UP, KBDM_SHIFT},
|
{Event::QTJoystickThreeUp, KBDK_UP, KBDM_SHIFT},
|
||||||
{Event::JoystickTwoDown, KBDK_DOWN, KBDM_SHIFT},
|
{Event::QTJoystickThreeDown, KBDK_DOWN, KBDM_SHIFT},
|
||||||
{Event::JoystickTwoLeft, KBDK_LEFT, KBDM_SHIFT},
|
{Event::QTJoystickThreeLeft, KBDK_LEFT, KBDM_SHIFT},
|
||||||
{Event::JoystickTwoRight, KBDK_RIGHT, KBDM_SHIFT},
|
{Event::QTJoystickThreeRight, KBDK_RIGHT, KBDM_SHIFT},
|
||||||
{Event::JoystickTwoUp, KBDK_KP_8, KBDM_SHIFT},
|
{Event::QTJoystickThreeUp, KBDK_KP_8, KBDM_SHIFT},
|
||||||
{Event::JoystickTwoDown, KBDK_KP_2, KBDM_SHIFT},
|
{Event::QTJoystickThreeDown, KBDK_KP_2, KBDM_SHIFT},
|
||||||
{Event::JoystickTwoLeft, KBDK_KP_4, KBDM_SHIFT},
|
{Event::QTJoystickThreeLeft, KBDK_KP_4, KBDM_SHIFT},
|
||||||
{Event::JoystickTwoRight, KBDK_KP_6, KBDM_SHIFT},
|
{Event::QTJoystickThreeRight, KBDK_KP_6, KBDM_SHIFT},
|
||||||
{Event::JoystickTwoFire, KBDK_SPACE, KBDM_SHIFT},
|
{Event::QTJoystickThreeFire, KBDK_SPACE, KBDM_SHIFT},
|
||||||
|
|
||||||
{Event::JoystickThreeUp, KBDK_Y, KBDM_SHIFT},
|
{Event::QTJoystickFourUp, KBDK_Y, KBDM_SHIFT},
|
||||||
{Event::JoystickThreeDown, KBDK_H, KBDM_SHIFT},
|
{Event::QTJoystickFourDown, KBDK_H, KBDM_SHIFT},
|
||||||
{Event::JoystickThreeLeft, KBDK_G, KBDM_SHIFT},
|
{Event::QTJoystickFourLeft, KBDK_G, KBDM_SHIFT},
|
||||||
{Event::JoystickThreeRight, KBDK_J, KBDM_SHIFT},
|
{Event::QTJoystickFourRight, KBDK_J, KBDM_SHIFT},
|
||||||
{Event::JoystickThreeFire, KBDK_F, KBDM_SHIFT},
|
{Event::QTJoystickFourFire, KBDK_F, KBDM_SHIFT},
|
||||||
};
|
};
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
PhysicalKeyboardHandler::EventMappingArray
|
PhysicalKeyboardHandler::EventMappingArray
|
||||||
PhysicalKeyboardHandler::DefaultPaddleMapping = {
|
PhysicalKeyboardHandler::DefaultPaddleMapping = {
|
||||||
{Event::PaddleZeroDecrease, KBDK_RIGHT},
|
{Event::LeftPaddleADecrease, KBDK_RIGHT},
|
||||||
{Event::PaddleZeroIncrease, KBDK_LEFT},
|
{Event::LeftPaddleAIncrease, KBDK_LEFT},
|
||||||
{Event::PaddleZeroFire, KBDK_SPACE},
|
{Event::LeftPaddleAFire, KBDK_SPACE},
|
||||||
{Event::PaddleZeroFire, KBDK_LCTRL},
|
{Event::LeftPaddleAFire, KBDK_LCTRL},
|
||||||
{Event::PaddleZeroFire, KBDK_KP_5},
|
{Event::LeftPaddleAFire, KBDK_KP_5},
|
||||||
|
|
||||||
{Event::PaddleOneDecrease, KBDK_DOWN},
|
{Event::LeftPaddleBDecrease, KBDK_DOWN},
|
||||||
{Event::PaddleOneIncrease, KBDK_UP},
|
{Event::LeftPaddleBIncrease, KBDK_UP},
|
||||||
{Event::PaddleOneFire, KBDK_4},
|
{Event::LeftPaddleBFire, KBDK_4},
|
||||||
{Event::PaddleOneFire, KBDK_RCTRL},
|
{Event::LeftPaddleBFire, KBDK_RCTRL},
|
||||||
|
|
||||||
{Event::PaddleTwoDecrease, KBDK_J},
|
{Event::RightPaddleADecrease, KBDK_J},
|
||||||
{Event::PaddleTwoIncrease, KBDK_G},
|
{Event::RightPaddleAIncrease, KBDK_G},
|
||||||
{Event::PaddleTwoFire, KBDK_F},
|
{Event::RightPaddleAFire, KBDK_F},
|
||||||
|
|
||||||
{Event::PaddleThreeDecrease, KBDK_H},
|
{Event::RightPaddleBDecrease, KBDK_H},
|
||||||
{Event::PaddleThreeIncrease, KBDK_Y},
|
{Event::RightPaddleBIncrease, KBDK_Y},
|
||||||
{Event::PaddleThreeFire, KBDK_6},
|
{Event::RightPaddleBFire, KBDK_6},
|
||||||
|
|
||||||
// Same as Paddles Zero..Three Fire + SHIFT
|
// Same as Paddles Zero..Three Fire + SHIFT
|
||||||
{Event::PaddleFourFire, KBDK_SPACE, KBDM_SHIFT},
|
{Event::QTPaddle3AFire, KBDK_SPACE, KBDM_SHIFT},
|
||||||
{Event::PaddleFiveFire, KBDK_4, KBDM_SHIFT},
|
{Event::QTPaddle3BFire, KBDK_4, KBDM_SHIFT},
|
||||||
{Event::PaddleSixFire, KBDK_F, KBDM_SHIFT},
|
{Event::QTPaddle4AFire, KBDK_F, KBDM_SHIFT},
|
||||||
{Event::PaddleSevenFire, KBDK_6, KBDM_SHIFT},
|
{Event::QTPaddle4BFire, KBDK_6, KBDM_SHIFT},
|
||||||
};
|
};
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
PhysicalKeyboardHandler::EventMappingArray
|
PhysicalKeyboardHandler::EventMappingArray
|
||||||
PhysicalKeyboardHandler::DefaultKeypadMapping = {
|
PhysicalKeyboardHandler::DefaultKeyboardMapping = {
|
||||||
{Event::KeyboardZero1, KBDK_1},
|
{Event::LeftKeyboard1, KBDK_1},
|
||||||
{Event::KeyboardZero2, KBDK_2},
|
{Event::LeftKeyboard2, KBDK_2},
|
||||||
{Event::KeyboardZero3, KBDK_3},
|
{Event::LeftKeyboard3, KBDK_3},
|
||||||
{Event::KeyboardZero4, KBDK_Q},
|
{Event::LeftKeyboard4, KBDK_Q},
|
||||||
{Event::KeyboardZero5, KBDK_W},
|
{Event::LeftKeyboard5, KBDK_W},
|
||||||
{Event::KeyboardZero6, KBDK_E},
|
{Event::LeftKeyboard6, KBDK_E},
|
||||||
{Event::KeyboardZero7, KBDK_A},
|
{Event::LeftKeyboard7, KBDK_A},
|
||||||
{Event::KeyboardZero8, KBDK_S},
|
{Event::LeftKeyboard8, KBDK_S},
|
||||||
{Event::KeyboardZero9, KBDK_D},
|
{Event::LeftKeyboard9, KBDK_D},
|
||||||
{Event::KeyboardZeroStar, KBDK_Z},
|
{Event::LeftKeyboardStar, KBDK_Z},
|
||||||
{Event::KeyboardZero0, KBDK_X},
|
{Event::LeftKeyboard0, KBDK_X},
|
||||||
{Event::KeyboardZeroPound, KBDK_C},
|
{Event::LeftKeyboardPound, KBDK_C},
|
||||||
|
|
||||||
{Event::KeyboardOne1, KBDK_8},
|
{Event::RightKeyboard1, KBDK_8},
|
||||||
{Event::KeyboardOne2, KBDK_9},
|
{Event::RightKeyboard2, KBDK_9},
|
||||||
{Event::KeyboardOne3, KBDK_0},
|
{Event::RightKeyboard3, KBDK_0},
|
||||||
{Event::KeyboardOne4, KBDK_I},
|
{Event::RightKeyboard4, KBDK_I},
|
||||||
{Event::KeyboardOne5, KBDK_O},
|
{Event::RightKeyboard5, KBDK_O},
|
||||||
{Event::KeyboardOne6, KBDK_P},
|
{Event::RightKeyboard6, KBDK_P},
|
||||||
{Event::KeyboardOne7, KBDK_K},
|
{Event::RightKeyboard7, KBDK_K},
|
||||||
{Event::KeyboardOne8, KBDK_L},
|
{Event::RightKeyboard8, KBDK_L},
|
||||||
{Event::KeyboardOne9, KBDK_SEMICOLON},
|
{Event::RightKeyboard9, KBDK_SEMICOLON},
|
||||||
{Event::KeyboardOneStar, KBDK_COMMA},
|
{Event::RightKeyboardStar, KBDK_COMMA},
|
||||||
{Event::KeyboardOne0, KBDK_PERIOD},
|
{Event::RightKeyboard0, KBDK_PERIOD},
|
||||||
{Event::KeyboardOnePound, KBDK_SLASH},
|
{Event::RightKeyboardPound, KBDK_SLASH},
|
||||||
};
|
};
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -104,7 +104,7 @@ class PhysicalKeyboardHandler
|
||||||
/** Checks event type. */
|
/** Checks event type. */
|
||||||
bool isJoystickEvent(const Event::Type event) const;
|
bool isJoystickEvent(const Event::Type event) const;
|
||||||
bool isPaddleEvent(const Event::Type event) const;
|
bool isPaddleEvent(const Event::Type event) const;
|
||||||
bool isKeypadEvent(const Event::Type event) const;
|
bool isKeyboardEvent(const Event::Type event) const;
|
||||||
bool isCommonEvent(const Event::Type event) const;
|
bool isCommonEvent(const Event::Type event) const;
|
||||||
|
|
||||||
void enableCommonMappings();
|
void enableCommonMappings();
|
||||||
|
@ -149,12 +149,15 @@ class PhysicalKeyboardHandler
|
||||||
static EventMappingArray DefaultMenuMapping;
|
static EventMappingArray DefaultMenuMapping;
|
||||||
#ifdef GUI_SUPPORT
|
#ifdef GUI_SUPPORT
|
||||||
static EventMappingArray FixedEditMapping;
|
static EventMappingArray FixedEditMapping;
|
||||||
|
#endif
|
||||||
|
#ifdef DEBUGGER_SUPPORT
|
||||||
|
static EventMappingArray FixedPromptMapping;
|
||||||
#endif
|
#endif
|
||||||
static EventMappingArray DefaultCommonMapping;
|
static EventMappingArray DefaultCommonMapping;
|
||||||
// Controller specific mappings
|
// Controller specific mappings
|
||||||
static EventMappingArray DefaultJoystickMapping;
|
static EventMappingArray DefaultJoystickMapping;
|
||||||
static EventMappingArray DefaultPaddleMapping;
|
static EventMappingArray DefaultPaddleMapping;
|
||||||
static EventMappingArray DefaultKeypadMapping;
|
static EventMappingArray DefaultKeyboardMapping;
|
||||||
static EventMappingArray CompuMateMapping;
|
static EventMappingArray CompuMateMapping;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -26,8 +26,6 @@
|
||||||
PaletteHandler::PaletteHandler(OSystem& system)
|
PaletteHandler::PaletteHandler(OSystem& system)
|
||||||
: myOSystem{system}
|
: myOSystem{system}
|
||||||
{
|
{
|
||||||
// Load user-defined palette for this ROM
|
|
||||||
loadUserPalette();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -315,6 +313,10 @@ void PaletteHandler::setPalette()
|
||||||
{
|
{
|
||||||
const string& name = myOSystem.settings().getString("palette");
|
const string& name = myOSystem.settings().getString("palette");
|
||||||
|
|
||||||
|
// Load user-defined palette for this ROM
|
||||||
|
if(name == SETTING_USER)
|
||||||
|
loadUserPalette();
|
||||||
|
|
||||||
// Look at all the palettes, since we don't know which one is
|
// Look at all the palettes, since we don't know which one is
|
||||||
// currently active
|
// currently active
|
||||||
static constexpr BSPF::array2D<const PaletteArray*, PaletteType::NumTypes, int(ConsoleTiming::numTimings)> palettes = {{
|
static constexpr BSPF::array2D<const PaletteArray*, PaletteType::NumTypes, int(ConsoleTiming::numTimings)> palettes = {{
|
||||||
|
|
|
@ -58,7 +58,7 @@ void PhysicalJoystick::initialize(int index, const string& desc,
|
||||||
eraseMap(EventMode::kMenuMode);
|
eraseMap(EventMode::kMenuMode);
|
||||||
eraseMap(EventMode::kJoystickMode);
|
eraseMap(EventMode::kJoystickMode);
|
||||||
eraseMap(EventMode::kPaddlesMode);
|
eraseMap(EventMode::kPaddlesMode);
|
||||||
eraseMap(EventMode::kKeypadMode);
|
eraseMap(EventMode::kKeyboardMode);
|
||||||
eraseMap(EventMode::kCommonMode);
|
eraseMap(EventMode::kCommonMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ json PhysicalJoystick::getMap() const
|
||||||
mapping["name"] = name;
|
mapping["name"] = name;
|
||||||
|
|
||||||
for (auto& mode: {
|
for (auto& mode: {
|
||||||
EventMode::kMenuMode, EventMode::kJoystickMode, EventMode::kPaddlesMode, EventMode::kKeypadMode, EventMode::kCommonMode
|
EventMode::kMenuMode, EventMode::kJoystickMode, EventMode::kPaddlesMode, EventMode::kKeyboardMode, EventMode::kCommonMode
|
||||||
})
|
})
|
||||||
mapping[jsonName(mode)] = joyMap.saveMapping(mode);
|
mapping[jsonName(mode)] = joyMap.saveMapping(mode);
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
|
#pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
|
||||||
#pragma clang diagnostic ignored "-Wimplicit-fallthrough"
|
#pragma clang diagnostic ignored "-Wimplicit-fallthrough"
|
||||||
#pragma clang diagnostic ignored "-Wreserved-id-macro"
|
#pragma clang diagnostic ignored "-Wreserved-id-macro"
|
||||||
|
#pragma clang diagnostic ignored "-Wold-style-cast"
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
#pragma clang diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -284,7 +284,7 @@ void ZipHandler::ZipFile::readEcd()
|
||||||
|
|
||||||
// Find the ECD signature
|
// Find the ECD signature
|
||||||
Int32 offset;
|
Int32 offset;
|
||||||
for(offset = Int32(buflen - EcdReader::minimumLength()); offset >= 0; --offset)
|
for(offset = Int32(buflen - EcdReader::minimumLength()); offset >= 0; --offset)
|
||||||
{
|
{
|
||||||
EcdReader reader(buffer.get() + offset);
|
EcdReader reader(buffer.get() + offset);
|
||||||
if(reader.signatureCorrect() && ((reader.totalLength() + offset) <= buflen))
|
if(reader.signatureCorrect() && ((reader.totalLength() + offset) <= buflen))
|
||||||
|
@ -445,13 +445,13 @@ void ZipHandler::ZipFile::decompressDataType8(
|
||||||
uInt64 input_remaining = myHeader.compressedLength;
|
uInt64 input_remaining = myHeader.compressedLength;
|
||||||
|
|
||||||
// Reset the stream
|
// Reset the stream
|
||||||
z_stream stream;
|
z_stream stream;
|
||||||
stream.zalloc = Z_NULL;
|
stream.zalloc = Z_NULL;
|
||||||
stream.zfree = Z_NULL;
|
stream.zfree = Z_NULL;
|
||||||
stream.opaque = Z_NULL;
|
stream.opaque = Z_NULL;
|
||||||
stream.avail_in = 0;
|
stream.avail_in = 0;
|
||||||
stream.next_out = reinterpret_cast<Bytef *>(out.get());
|
stream.next_out = reinterpret_cast<Bytef *>(out.get());
|
||||||
stream.avail_out = uInt32(length); // TODO - use zip64
|
stream.avail_out = uInt32(length); // TODO - use zip64
|
||||||
|
|
||||||
// Initialize the decompressor
|
// Initialize the decompressor
|
||||||
int zerr = inflateInit2(&stream, -MAX_WBITS);
|
int zerr = inflateInit2(&stream, -MAX_WBITS);
|
||||||
|
|
|
@ -260,7 +260,7 @@ namespace BSPF
|
||||||
// Test whether the first string matches the second one (case insensitive)
|
// Test whether the first string matches the second one (case insensitive)
|
||||||
// - the first character must match
|
// - the first character must match
|
||||||
// - the following characters must appear in the order of the first string
|
// - the following characters must appear in the order of the first string
|
||||||
inline bool matches(string_view s1, string_view s2)
|
inline bool matchesIgnoreCase(string_view s1, string_view s2)
|
||||||
{
|
{
|
||||||
if(startsWithIgnoreCase(s1, s2.substr(0, 1)))
|
if(startsWithIgnoreCase(s1, s2.substr(0, 1)))
|
||||||
{
|
{
|
||||||
|
@ -277,6 +277,50 @@ namespace BSPF
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test whether the first string matches the second one
|
||||||
|
// (case sensitive for upper case characters in second string, except first one)
|
||||||
|
// - the first character must match
|
||||||
|
// - the following characters must appear in the order of the first string
|
||||||
|
inline bool matchesCamelCase(const string_view s1, const string_view s2)
|
||||||
|
{
|
||||||
|
// skip leading '_' for matching
|
||||||
|
uInt32 ofs = (s1[0] == '_' && s2[0] == '_') ? 1 : 0;
|
||||||
|
|
||||||
|
if(startsWithIgnoreCase(s1.substr(ofs), s2.substr(ofs, 1)))
|
||||||
|
{
|
||||||
|
size_t lastUpper = ofs, pos = 1;
|
||||||
|
|
||||||
|
for(uInt32 j = 1 + ofs; j < s2.size(); ++j)
|
||||||
|
{
|
||||||
|
if(std::isupper(s2[j]))
|
||||||
|
{
|
||||||
|
size_t found = s1.find_first_of(s2[j], pos + ofs);
|
||||||
|
|
||||||
|
if(found == string::npos)
|
||||||
|
return false;
|
||||||
|
// make sure no upper case characters are skipped
|
||||||
|
for(size_t k = lastUpper + 1; k < found; ++k)
|
||||||
|
if(isupper(s1[k]))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
pos = found + 1;
|
||||||
|
lastUpper = found;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
size_t found = findIgnoreCase(s1, s2.substr(j, 1), pos + ofs);
|
||||||
|
|
||||||
|
if(found == string::npos)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
pos += found + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Modify 'str', replacing all occurrences of 'from' with 'to'
|
// Modify 'str', replacing all occurrences of 'from' with 'to'
|
||||||
inline void replaceAll(string& str, const string& from, const string& to)
|
inline void replaceAll(string& str, const string& from, const string& to)
|
||||||
{
|
{
|
||||||
|
|
|
@ -48,11 +48,12 @@ NLOHMANN_JSON_SERIALIZE_ENUM(JoyHatDir, {
|
||||||
|
|
||||||
NLOHMANN_JSON_SERIALIZE_ENUM(EventMode, {
|
NLOHMANN_JSON_SERIALIZE_ENUM(EventMode, {
|
||||||
{EventMode::kEditMode, "kEditMode"},
|
{EventMode::kEditMode, "kEditMode"},
|
||||||
|
{EventMode::kPromptMode, "kPromptMode"},
|
||||||
{EventMode::kMenuMode, "kMenuMode"},
|
{EventMode::kMenuMode, "kMenuMode"},
|
||||||
{EventMode::kEmulationMode, "kEmulationMode"},
|
{EventMode::kEmulationMode, "kEmulationMode"},
|
||||||
{EventMode::kJoystickMode, "kJoystickMode"},
|
{EventMode::kJoystickMode, "kJoystickMode"},
|
||||||
{EventMode::kPaddlesMode, "kPaddlesMode"},
|
{EventMode::kPaddlesMode, "kPaddlesMode"},
|
||||||
{EventMode::kKeypadMode, "kKeypadMode"},
|
{EventMode::kKeyboardMode, "kKeyboardMode"},
|
||||||
{EventMode::kCompuMateMode, "kCompuMateMode"},
|
{EventMode::kCompuMateMode, "kCompuMateMode"},
|
||||||
{EventMode::kCommonMode, "kCommonMode"},
|
{EventMode::kCommonMode, "kCommonMode"},
|
||||||
{EventMode::kNumModes, "kNumModes"},
|
{EventMode::kNumModes, "kNumModes"},
|
||||||
|
@ -72,74 +73,74 @@ NLOHMANN_JSON_SERIALIZE_ENUM(Event::Type, {
|
||||||
{Event::ConsoleRightDiffToggle, "ConsoleRightDiffToggle"},
|
{Event::ConsoleRightDiffToggle, "ConsoleRightDiffToggle"},
|
||||||
{Event::ConsoleSelect, "ConsoleSelect"},
|
{Event::ConsoleSelect, "ConsoleSelect"},
|
||||||
{Event::ConsoleReset, "ConsoleReset"},
|
{Event::ConsoleReset, "ConsoleReset"},
|
||||||
{Event::JoystickZeroUp, "JoystickZeroUp"},
|
{Event::LeftJoystickUp, "LeftJoystickUp"},
|
||||||
{Event::JoystickZeroDown, "JoystickZeroDown"},
|
{Event::LeftJoystickDown, "LeftJoystickDown"},
|
||||||
{Event::JoystickZeroLeft, "JoystickZeroLeft"},
|
{Event::LeftJoystickLeft, "LeftJoystickLeft"},
|
||||||
{Event::JoystickZeroRight, "JoystickZeroRight"},
|
{Event::LeftJoystickRight, "LeftJoystickRight"},
|
||||||
{Event::JoystickZeroFire, "JoystickZeroFire"},
|
{Event::LeftJoystickFire, "LeftJoystickFire"},
|
||||||
{Event::JoystickZeroFire5, "JoystickZeroFire5"},
|
{Event::LeftJoystickFire5, "LeftJoystickFire5"},
|
||||||
{Event::JoystickZeroFire9, "JoystickZeroFire9"},
|
{Event::LeftJoystickFire9, "LeftJoystickFire9"},
|
||||||
{Event::JoystickOneUp, "JoystickOneUp"},
|
{Event::RightJoystickUp, "RightJoystickUp"},
|
||||||
{Event::JoystickOneDown, "JoystickOneDown"},
|
{Event::RightJoystickDown, "RightJoystickDown"},
|
||||||
{Event::JoystickOneLeft, "JoystickOneLeft"},
|
{Event::RightJoystickLeft, "RightJoystickLeft"},
|
||||||
{Event::JoystickOneRight, "JoystickOneRight"},
|
{Event::RightJoystickRight, "RightJoystickRight"},
|
||||||
{Event::JoystickOneFire, "JoystickOneFire"},
|
{Event::RightJoystickFire, "RightJoystickFire"},
|
||||||
{Event::JoystickOneFire5, "JoystickOneFire5"},
|
{Event::RightJoystickFire5, "RightJoystickFire5"},
|
||||||
{Event::JoystickOneFire9, "JoystickOneFire9"},
|
{Event::RightJoystickFire9, "RightJoystickFire9"},
|
||||||
{Event::JoystickTwoUp, "JoystickTwoUp"},
|
{Event::QTJoystickThreeUp, "QTJoystickThreeUp"},
|
||||||
{Event::JoystickTwoDown, "JoystickTwoDown"},
|
{Event::QTJoystickThreeDown, "QTJoystickThreeDown"},
|
||||||
{Event::JoystickTwoLeft, "JoystickTwoLeft"},
|
{Event::QTJoystickThreeLeft, "QTJoystickThreeLeft"},
|
||||||
{Event::JoystickTwoRight, "JoystickTwoRight"},
|
{Event::QTJoystickThreeRight, "QTJoystickThreeRight"},
|
||||||
{Event::JoystickTwoFire, "JoystickTwoFire"},
|
{Event::QTJoystickThreeFire, "QTJoystickThreeFire"},
|
||||||
{Event::JoystickThreeUp, "JoystickThreeUp"},
|
{Event::QTJoystickFourUp, "QTJoystickFourUp"},
|
||||||
{Event::JoystickThreeDown, "JoystickThreeDown"},
|
{Event::QTJoystickFourDown, "QTJoystickFourDown"},
|
||||||
{Event::JoystickThreeLeft, "JoystickThreeLeft"},
|
{Event::QTJoystickFourLeft, "QTJoystickFourLeft"},
|
||||||
{Event::JoystickThreeRight, "JoystickThreeRight"},
|
{Event::QTJoystickFourRight, "QTJoystickFourRight"},
|
||||||
{Event::JoystickThreeFire, "JoystickThreeFire"},
|
{Event::QTJoystickFourFire, "QTJoystickFourFire"},
|
||||||
{Event::PaddleZeroDecrease, "PaddleZeroDecrease"},
|
{Event::LeftPaddleADecrease, "LeftPaddleADecrease"},
|
||||||
{Event::PaddleZeroIncrease, "PaddleZeroIncrease"},
|
{Event::LeftPaddleAIncrease, "LeftPaddleAIncrease"},
|
||||||
{Event::PaddleZeroAnalog, "PaddleZeroAnalog"},
|
{Event::LeftPaddleAAnalog, "LeftPaddleAAnalog"},
|
||||||
{Event::PaddleZeroFire, "PaddleZeroFire"},
|
{Event::LeftPaddleAFire, "LeftPaddleAFire"},
|
||||||
{Event::PaddleOneDecrease, "PaddleOneDecrease"},
|
{Event::LeftPaddleBDecrease, "LeftPaddleBDecrease"},
|
||||||
{Event::PaddleOneIncrease, "PaddleOneIncrease"},
|
{Event::LeftPaddleBIncrease, "LeftPaddleBIncrease"},
|
||||||
{Event::PaddleOneAnalog, "PaddleOneAnalog"},
|
{Event::LeftPaddleBAnalog, "LeftPaddleBAnalog"},
|
||||||
{Event::PaddleOneFire, "PaddleOneFire"},
|
{Event::LeftPaddleBFire, "LeftPaddleBFire"},
|
||||||
{Event::PaddleTwoDecrease, "PaddleTwoDecrease"},
|
{Event::RightPaddleADecrease, "RightPaddleADecrease"},
|
||||||
{Event::PaddleTwoIncrease, "PaddleTwoIncrease"},
|
{Event::RightPaddleAIncrease, "RightPaddleAIncrease"},
|
||||||
{Event::PaddleTwoAnalog, "PaddleTwoAnalog"},
|
{Event::RightPaddleAAnalog, "RightPaddleAAnalog"},
|
||||||
{Event::PaddleTwoFire, "PaddleTwoFire"},
|
{Event::RightPaddleAFire, "RightPaddleAFire"},
|
||||||
{Event::PaddleThreeDecrease, "PaddleThreeDecrease"},
|
{Event::RightPaddleBDecrease, "RightPaddleBDecrease"},
|
||||||
{Event::PaddleThreeIncrease, "PaddleThreeIncrease"},
|
{Event::RightPaddleBIncrease, "RightPaddleBIncrease"},
|
||||||
{Event::PaddleThreeAnalog, "PaddleThreeAnalog"},
|
{Event::RightPaddleBAnalog, "RightPaddleBAnalog"},
|
||||||
{Event::PaddleThreeFire, "PaddleThreeFire"},
|
{Event::RightPaddleBFire, "RightPaddleBFire"},
|
||||||
{Event::PaddleFourFire, "PaddleFourFire"},
|
{Event::QTPaddle3AFire, "QTPaddle3AFire"},
|
||||||
{Event::PaddleFiveFire, "PaddleFiveFire"},
|
{Event::QTPaddle3BFire, "QTPaddle3BFire"},
|
||||||
{Event::PaddleSixFire, "PaddleSixFire"},
|
{Event::QTPaddle4AFire, "QTPaddle4AFire"},
|
||||||
{Event::PaddleSevenFire, "PaddleSevenFire"},
|
{Event::QTPaddle4BFire, "QTPaddle4BFire"},
|
||||||
{Event::KeyboardZero1, "KeyboardZero1"},
|
{Event::LeftKeyboard1, "LeftKeyboard1"},
|
||||||
{Event::KeyboardZero2, "KeyboardZero2"},
|
{Event::LeftKeyboard2, "LeftKeyboard2"},
|
||||||
{Event::KeyboardZero3, "KeyboardZero3"},
|
{Event::LeftKeyboard3, "LeftKeyboard3"},
|
||||||
{Event::KeyboardZero4, "KeyboardZero4"},
|
{Event::LeftKeyboard4, "LeftKeyboard4"},
|
||||||
{Event::KeyboardZero5, "KeyboardZero5"},
|
{Event::LeftKeyboard5, "LeftKeyboard5"},
|
||||||
{Event::KeyboardZero6, "KeyboardZero6"},
|
{Event::LeftKeyboard6, "LeftKeyboard6"},
|
||||||
{Event::KeyboardZero7, "KeyboardZero7"},
|
{Event::LeftKeyboard7, "LeftKeyboard7"},
|
||||||
{Event::KeyboardZero8, "KeyboardZero8"},
|
{Event::LeftKeyboard8, "LeftKeyboard8"},
|
||||||
{Event::KeyboardZero9, "KeyboardZero9"},
|
{Event::LeftKeyboard9, "LeftKeyboard9"},
|
||||||
{Event::KeyboardZeroStar, "KeyboardZeroStar"},
|
{Event::LeftKeyboardStar, "LeftKeyboardStar"},
|
||||||
{Event::KeyboardZero0, "KeyboardZero0"},
|
{Event::LeftKeyboard0, "LeftKeyboard0"},
|
||||||
{Event::KeyboardZeroPound, "KeyboardZeroPound"},
|
{Event::LeftKeyboardPound, "LeftKeyboardPound"},
|
||||||
{Event::KeyboardOne1, "KeyboardOne1"},
|
{Event::RightKeyboard1, "RightKeyboard1"},
|
||||||
{Event::KeyboardOne2, "KeyboardOne2"},
|
{Event::RightKeyboard2, "RightKeyboard2"},
|
||||||
{Event::KeyboardOne3, "KeyboardOne3"},
|
{Event::RightKeyboard3, "RightKeyboard3"},
|
||||||
{Event::KeyboardOne4, "KeyboardOne4"},
|
{Event::RightKeyboard4, "RightKeyboard4"},
|
||||||
{Event::KeyboardOne5, "KeyboardOne5"},
|
{Event::RightKeyboard5, "RightKeyboard5"},
|
||||||
{Event::KeyboardOne6, "KeyboardOne6"},
|
{Event::RightKeyboard6, "RightKeyboard6"},
|
||||||
{Event::KeyboardOne7, "KeyboardOne7"},
|
{Event::RightKeyboard7, "RightKeyboard7"},
|
||||||
{Event::KeyboardOne8, "KeyboardOne8"},
|
{Event::RightKeyboard8, "RightKeyboard8"},
|
||||||
{Event::KeyboardOne9, "KeyboardOne9"},
|
{Event::RightKeyboard9, "RightKeyboard9"},
|
||||||
{Event::KeyboardOneStar, "KeyboardOneStar"},
|
{Event::RightKeyboardStar, "RightKeyboardStar"},
|
||||||
{Event::KeyboardOne0, "KeyboardOne0"},
|
{Event::RightKeyboard0, "RightKeyboard0"},
|
||||||
{Event::KeyboardOnePound, "KeyboardOnePound"},
|
{Event::RightKeyboardPound, "RightKeyboardPound"},
|
||||||
{Event::CompuMateFunc, "CompuMateFunc"},
|
{Event::CompuMateFunc, "CompuMateFunc"},
|
||||||
{Event::CompuMateShift, "CompuMateShift"},
|
{Event::CompuMateShift, "CompuMateShift"},
|
||||||
{Event::CompuMate0, "CompuMate0"},
|
{Event::CompuMate0, "CompuMate0"},
|
||||||
|
|
|
@ -206,7 +206,7 @@ int main(int ac, char* av[])
|
||||||
|
|
||||||
// Create the full OSystem after the settings, since settings are
|
// Create the full OSystem after the settings, since settings are
|
||||||
// probably needed for defaults
|
// probably needed for defaults
|
||||||
Logger::debug("Creating the OSystem ...");
|
Logger::log("Creating the OSystem ...");
|
||||||
if(!theOSystem->initialize(globalOpts))
|
if(!theOSystem->initialize(globalOpts))
|
||||||
{
|
{
|
||||||
Logger::error("ERROR: Couldn't create OSystem");
|
Logger::error("ERROR: Couldn't create OSystem");
|
||||||
|
|
|
@ -1493,23 +1493,23 @@ void CartDebug::getCompletions(const char* in, StringList& completions) const
|
||||||
{
|
{
|
||||||
// First scan system equates
|
// First scan system equates
|
||||||
for(uInt16 addr = 0x00; addr <= 0x0F; ++addr)
|
for(uInt16 addr = 0x00; addr <= 0x0F; ++addr)
|
||||||
if(ourTIAMnemonicR[addr] && BSPF::matches(ourTIAMnemonicR[addr], in))
|
if(ourTIAMnemonicR[addr] && BSPF::matchesIgnoreCase(ourTIAMnemonicR[addr], in))
|
||||||
completions.push_back(ourTIAMnemonicR[addr]);
|
completions.push_back(ourTIAMnemonicR[addr]);
|
||||||
for(uInt16 addr = 0x00; addr <= 0x3F; ++addr)
|
for(uInt16 addr = 0x00; addr <= 0x3F; ++addr)
|
||||||
if(ourTIAMnemonicW[addr] && BSPF::matches(ourTIAMnemonicW[addr], in))
|
if(ourTIAMnemonicW[addr] && BSPF::matchesIgnoreCase(ourTIAMnemonicW[addr], in))
|
||||||
completions.push_back(ourTIAMnemonicW[addr]);
|
completions.push_back(ourTIAMnemonicW[addr]);
|
||||||
for(uInt16 addr = 0; addr <= 0x297-0x280; ++addr)
|
for(uInt16 addr = 0; addr <= 0x297-0x280; ++addr)
|
||||||
if(ourIOMnemonic[addr] && BSPF::matches(ourIOMnemonic[addr], in))
|
if(ourIOMnemonic[addr] && BSPF::matchesIgnoreCase(ourIOMnemonic[addr], in))
|
||||||
completions.push_back(ourIOMnemonic[addr]);
|
completions.push_back(ourIOMnemonic[addr]);
|
||||||
for(uInt16 addr = 0; addr <= 0x7F; ++addr)
|
for(uInt16 addr = 0; addr <= 0x7F; ++addr)
|
||||||
if(ourZPMnemonic[addr] && BSPF::matches(ourZPMnemonic[addr], in))
|
if(ourZPMnemonic[addr] && BSPF::matchesIgnoreCase(ourZPMnemonic[addr], in))
|
||||||
completions.push_back(ourZPMnemonic[addr]);
|
completions.push_back(ourZPMnemonic[addr]);
|
||||||
|
|
||||||
// Now scan user-defined labels
|
// Now scan user-defined labels
|
||||||
for(const auto& iter: myUserAddresses)
|
for(const auto& iter: myUserAddresses)
|
||||||
{
|
{
|
||||||
const char* l = iter.first.c_str();
|
const char* l = iter.first.c_str();
|
||||||
if(BSPF::matches(l, in))
|
if(BSPF::matchesCamelCase(l, in))
|
||||||
completions.push_back(l);
|
completions.push_back(l);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "FSNode.hxx"
|
#include "FSNode.hxx"
|
||||||
#include "Settings.hxx"
|
#include "Settings.hxx"
|
||||||
#include "DebuggerDialog.hxx"
|
#include "DebuggerDialog.hxx"
|
||||||
|
#include "PromptWidget.hxx"
|
||||||
#include "DebuggerParser.hxx"
|
#include "DebuggerParser.hxx"
|
||||||
#include "StateManager.hxx"
|
#include "StateManager.hxx"
|
||||||
#include "RewindManager.hxx"
|
#include "RewindManager.hxx"
|
||||||
|
@ -123,6 +124,7 @@ bool Debugger::start(const string& message, int address, bool read,
|
||||||
{
|
{
|
||||||
if(myOSystem.eventHandler().enterDebugMode())
|
if(myOSystem.eventHandler().enterDebugMode())
|
||||||
{
|
{
|
||||||
|
myFirstLog = true;
|
||||||
// This must be done *after* we enter debug mode,
|
// This must be done *after* we enter debug mode,
|
||||||
// so the message isn't erased
|
// so the message isn't erased
|
||||||
ostringstream buf;
|
ostringstream buf;
|
||||||
|
@ -150,7 +152,15 @@ bool Debugger::startWithFatalError(const string& message)
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Debugger::quit(bool exitrom)
|
void Debugger::quit()
|
||||||
|
{
|
||||||
|
if(myOSystem.settings().getBool("dbg.autosave")
|
||||||
|
&& myDialog->prompt().isLoaded())
|
||||||
|
myParser->run("save");
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void Debugger::exit(bool exitrom)
|
||||||
{
|
{
|
||||||
if(exitrom)
|
if(exitrom)
|
||||||
myOSystem.eventHandler().handleEvent(Event::ExitGame);
|
myOSystem.eventHandler().handleEvent(Event::ExitGame);
|
||||||
|
@ -172,7 +182,8 @@ string Debugger::autoExec(StringList* history)
|
||||||
<< myParser->exec(autoexec, history) << endl;
|
<< myParser->exec(autoexec, history) << endl;
|
||||||
|
|
||||||
// Also, "romname.script" if present
|
// Also, "romname.script" if present
|
||||||
FilesystemNode romname(myOSystem.romFile().getPathWithExt(".script"));
|
const string path = myOSystem.userDir().getPath() + myOSystem.romFile().getNameWithExt(".script");
|
||||||
|
FilesystemNode romname(path);
|
||||||
buf << myParser->exec(romname, history) << endl;
|
buf << myParser->exec(romname, history) << endl;
|
||||||
|
|
||||||
// Init builtins
|
// Init builtins
|
||||||
|
@ -442,6 +453,82 @@ bool Debugger::writeTrap(uInt16 t)
|
||||||
return writeTraps().isInitialized() && writeTraps().isSet(t);
|
return writeTraps().isInitialized() && writeTraps().isSet(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void Debugger::log(const string& triggerMsg)
|
||||||
|
{
|
||||||
|
const CartDebug::Disassembly& disasm = myCartDebug->disassembly();
|
||||||
|
int pc = myCpuDebug->pc();
|
||||||
|
|
||||||
|
if(myFirstLog)
|
||||||
|
{
|
||||||
|
ostringstream msg;
|
||||||
|
|
||||||
|
msg << "Trigger: Frame Scn Cy Pxl | PS A X Y SP | ";
|
||||||
|
if(myCartDebug->romBankCount() > 1)
|
||||||
|
{
|
||||||
|
if(myCartDebug->romBankCount() > 9)
|
||||||
|
msg << "Bk/";
|
||||||
|
else
|
||||||
|
msg << "B/";
|
||||||
|
}
|
||||||
|
msg << "Addr Code Disam";
|
||||||
|
Logger::log(msg.str());
|
||||||
|
myFirstLog = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// First find the lines in the range, and determine the longest string
|
||||||
|
uInt16 start = pc & 0xFFF;
|
||||||
|
uInt32 list_size = uInt32(disasm.list.size());
|
||||||
|
uInt32 pos;
|
||||||
|
|
||||||
|
for(pos = 0; pos < list_size; ++pos)
|
||||||
|
{
|
||||||
|
const CartDebug::DisassemblyTag& tag = disasm.list[pos];
|
||||||
|
|
||||||
|
if((tag.address & 0xfff) >= start)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CartDebug::DisassemblyTag& tag = disasm.list[pos];
|
||||||
|
ostringstream msg;
|
||||||
|
|
||||||
|
msg << std::left << std::setw(10) << std::setfill(' ') << triggerMsg;
|
||||||
|
msg << Base::toString(myTiaDebug->frameCount(), Base::Fmt::_10_5) << " "
|
||||||
|
<< Base::toString(myTiaDebug->scanlines(), Base::Fmt::_10_3) << " "
|
||||||
|
<< Base::toString(myTiaDebug->clocksThisLine() / 3, Base::Fmt::_10_02) << " "
|
||||||
|
<< Base::toString(myTiaDebug->clocksThisLine() - 68, Base::Fmt::_10_3) << " | ";
|
||||||
|
msg << (myCpuDebug->n() ? "N" : "n")
|
||||||
|
<< (myCpuDebug->v() ? "V" : "v") << "-"
|
||||||
|
<< (myCpuDebug->b() ? "B" : "b")
|
||||||
|
<< (myCpuDebug->d() ? "D" : "d")
|
||||||
|
<< (myCpuDebug->i() ? "I" : "i")
|
||||||
|
<< (myCpuDebug->z() ? "Z" : "z")
|
||||||
|
<< (myCpuDebug->c() ? "C" : "c") << " "
|
||||||
|
<< Base::HEX2 << myCpuDebug->a() << " "
|
||||||
|
<< Base::HEX2 << myCpuDebug->x() << " "
|
||||||
|
<< Base::HEX2 << myCpuDebug->y() << " "
|
||||||
|
<< Base::HEX2 << myCpuDebug->sp() << " |";
|
||||||
|
|
||||||
|
if(myCartDebug->romBankCount() > 1)
|
||||||
|
{
|
||||||
|
if(myCartDebug->romBankCount() > 9)
|
||||||
|
msg << Base::toString(myCartDebug->getBank(pc), Base::Fmt::_10) << "/";
|
||||||
|
else
|
||||||
|
msg << " " << myCartDebug->getBank(pc) << "/";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
msg << " ";
|
||||||
|
|
||||||
|
msg << Base::HEX4 << pc << " "
|
||||||
|
<< std::left << std::setw(8) << std::setfill(' ') << tag.bytes << " "
|
||||||
|
<< tag.disasm.substr(0, 7);
|
||||||
|
|
||||||
|
if(tag.disasm.length() > 8)
|
||||||
|
msg << tag.disasm.substr(8);
|
||||||
|
|
||||||
|
Logger::log(msg.str());
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
uInt8 Debugger::peek(uInt16 addr, Device::AccessFlags flags)
|
uInt8 Debugger::peek(uInt16 addr, Device::AccessFlags flags)
|
||||||
{
|
{
|
||||||
|
@ -816,12 +903,12 @@ void Debugger::getCompletions(const char* in, StringList& list) const
|
||||||
for(const auto& iter : myFunctions)
|
for(const auto& iter : myFunctions)
|
||||||
{
|
{
|
||||||
const char* l = iter.first.c_str();
|
const char* l = iter.first.c_str();
|
||||||
if(BSPF::matches(l, in))
|
if(BSPF::matchesCamelCase(l, in))
|
||||||
list.push_back(l);
|
list.push_back(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(const auto& reg: ourPseudoRegisters)
|
for(const auto& reg: ourPseudoRegisters)
|
||||||
if(BSPF::matches(reg.name, in))
|
if(BSPF::matchesCamelCase(reg.name, in))
|
||||||
list.push_back(reg.name);
|
list.push_back(reg.name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -849,28 +936,28 @@ bool Debugger::canExit() const
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
std::array<Debugger::BuiltinFunction, 18> Debugger::ourBuiltinFunctions = { {
|
std::array<Debugger::BuiltinFunction, 18> Debugger::ourBuiltinFunctions = { {
|
||||||
// left joystick:
|
// left joystick:
|
||||||
{ "_joy0left", "!(*SWCHA & $40)", "Left joystick moved left" },
|
{ "_joy0Left", "!(*SWCHA & $40)", "Left joystick moved left" },
|
||||||
{ "_joy0right", "!(*SWCHA & $80)", "Left joystick moved right" },
|
{ "_joy0Right", "!(*SWCHA & $80)", "Left joystick moved right" },
|
||||||
{ "_joy0up", "!(*SWCHA & $10)", "Left joystick moved up" },
|
{ "_joy0Up", "!(*SWCHA & $10)", "Left joystick moved up" },
|
||||||
{ "_joy0down", "!(*SWCHA & $20)", "Left joystick moved down" },
|
{ "_joy0Down", "!(*SWCHA & $20)", "Left joystick moved down" },
|
||||||
{ "_joy0button", "!(*INPT4 & $80)", "Left joystick button pressed" },
|
{ "_joy0Fire", "!(*INPT4 & $80)", "Left joystick fire button pressed" },
|
||||||
|
|
||||||
// right joystick:
|
// right joystick:
|
||||||
{ "_joy1left", "!(*SWCHA & $04)", "Right joystick moved left" },
|
{ "_joy1Left", "!(*SWCHA & $04)", "Right joystick moved left" },
|
||||||
{ "_joy1right", "!(*SWCHA & $08)", "Right joystick moved right" },
|
{ "_joy1Right", "!(*SWCHA & $08)", "Right joystick moved right" },
|
||||||
{ "_joy1up", "!(*SWCHA & $01)", "Right joystick moved up" },
|
{ "_joy1Up", "!(*SWCHA & $01)", "Right joystick moved up" },
|
||||||
{ "_joy1down", "!(*SWCHA & $02)", "Right joystick moved down" },
|
{ "_joy1Down", "!(*SWCHA & $02)", "Right joystick moved down" },
|
||||||
{ "_joy1button", "!(*INPT5 & $80)", "Right joystick button pressed" },
|
{ "_joy1Fire", "!(*INPT5 & $80)", "Right joystick fire button pressed" },
|
||||||
|
|
||||||
// console switches:
|
// console switches:
|
||||||
{ "_select", "!(*SWCHB & $02)", "Game Select pressed" },
|
{ "_select", "!(*SWCHB & $02)", "Game Select pressed" },
|
||||||
{ "_reset", "!(*SWCHB & $01)", "Game Reset pressed" },
|
{ "_reset", "!(*SWCHB & $01)", "Game Reset pressed" },
|
||||||
{ "_color", "*SWCHB & $08", "Color/BW set to Color" },
|
{ "_color", "*SWCHB & $08", "Color/BW set to Color" },
|
||||||
{ "_bw", "!(*SWCHB & $08)", "Color/BW set to BW" },
|
{ "_bw", "!(*SWCHB & $08)", "Color/BW set to BW" },
|
||||||
{ "_diff0b", "!(*SWCHB & $40)", "Left diff. set to B (easy)" },
|
{ "_diff0B", "!(*SWCHB & $40)", "Left diff. set to B (easy)" },
|
||||||
{ "_diff0a", "*SWCHB & $40", "Left diff. set to A (hard)" },
|
{ "_diff0A", "*SWCHB & $40", "Left diff. set to A (hard)" },
|
||||||
{ "_diff1b", "!(*SWCHB & $80)", "Right diff. set to B (easy)" },
|
{ "_diff1B", "!(*SWCHB & $80)", "Right diff. set to B (easy)" },
|
||||||
{ "_diff1a", "*SWCHB & $80", "Right diff. set to A (hard)" }
|
{ "_diff1A", "*SWCHB & $80", "Right diff. set to A (hard)" }
|
||||||
} };
|
} };
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -878,25 +965,25 @@ std::array<Debugger::BuiltinFunction, 18> Debugger::ourBuiltinFunctions = { {
|
||||||
std::array<Debugger::PseudoRegister, 16> Debugger::ourPseudoRegisters = { {
|
std::array<Debugger::PseudoRegister, 16> Debugger::ourPseudoRegisters = { {
|
||||||
// Debugger::PseudoRegister Debugger::ourPseudoRegisters[NUM_PSEUDO_REGS] = {
|
// Debugger::PseudoRegister Debugger::ourPseudoRegisters[NUM_PSEUDO_REGS] = {
|
||||||
{ "_bank", "Currently selected bank" },
|
{ "_bank", "Currently selected bank" },
|
||||||
{ "_cclocks", "Color clocks on current scanline" },
|
{ "_cClocks", "Color clocks on current scanline" },
|
||||||
{ "_cycleshi", "Higher 32 bits of number of cycles since emulation started" },
|
{ "_cyclesHi", "Higher 32 bits of number of cycles since emulation started" },
|
||||||
{ "_cycleslo", "Lower 32 bits of number of cycles since emulation started" },
|
{ "_cyclesLo", "Lower 32 bits of number of cycles since emulation started" },
|
||||||
{ "_fcount", "Number of frames since emulation started" },
|
{ "_fCount", "Number of frames since emulation started" },
|
||||||
{ "_fcycles", "Number of cycles since frame started" },
|
{ "_fCycles", "Number of cycles since frame started" },
|
||||||
{ "_ftimreadcycles","Number of cycles used by timer reads since frame started" },
|
{ "_fTimReadCycles","Number of cycles used by timer reads since frame started" },
|
||||||
{ "_fwsynccycles", "Number of cycles skipped by WSYNC since frame started" },
|
{ "_fWsyncCycles", "Number of cycles skipped by WSYNC since frame started" },
|
||||||
{ "_icycles", "Number of cycles of last instruction" },
|
{ "_iCycles", "Number of cycles of last instruction" },
|
||||||
{ "_scan", "Current scanline count" },
|
{ "_scan", "Current scanline count" },
|
||||||
{ "_scanend", "Scanline count at end of last frame" },
|
{ "_scanEnd", "Scanline count at end of last frame" },
|
||||||
{ "_scycles", "Number of cycles in current scanline" },
|
{ "_sCycles", "Number of cycles in current scanline" },
|
||||||
{ "_timwrapread", "Timer read wrapped on this cycle" },
|
{ "_timWrapRead", "Timer read wrapped on this cycle" },
|
||||||
{ "_timwrapwrite", "Timer write wrapped on this cycle" },
|
{ "_timWrapWrite", "Timer write wrapped on this cycle" },
|
||||||
{ "_vblank", "Whether vertical blank is enabled (1 or 0)" },
|
{ "_vBlank", "Whether vertical blank is enabled (1 or 0)" },
|
||||||
{ "_vsync", "Whether vertical sync is enabled (1 or 0)" }
|
{ "_vSync", "Whether vertical sync is enabled (1 or 0)" }
|
||||||
// CPU address access functions:
|
// CPU address access functions:
|
||||||
/*{ "_lastread", "last CPU read address" },
|
/*{ "_lastRead", "last CPU read address" },
|
||||||
{ "_lastwrite", "last CPU write address" },
|
{ "_lastWrite", "last CPU write address" },
|
||||||
{ "__lastbaseread", "last CPU read base address" },
|
{ "__lastBaseRead", "last CPU read base address" },
|
||||||
{ "__lastbasewrite", "last CPU write base address" }*/
|
{ "__lastBaseWrite", "last CPU write base address" }*/
|
||||||
} };
|
} };
|
||||||
//
|
//
|
||||||
|
|
|
@ -102,7 +102,12 @@ class Debugger : public DialogContainer
|
||||||
Wrapper method for EventHandler::leaveDebugMode() for those classes
|
Wrapper method for EventHandler::leaveDebugMode() for those classes
|
||||||
that don't have access to EventHandler.
|
that don't have access to EventHandler.
|
||||||
*/
|
*/
|
||||||
void quit(bool exitrom);
|
void exit(bool exitrom);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Executed when debugger is quit.
|
||||||
|
*/
|
||||||
|
void quit();
|
||||||
|
|
||||||
bool addFunction(const string& name, const string& def,
|
bool addFunction(const string& name, const string& def,
|
||||||
Expression* exp, bool builtin = false);
|
Expression* exp, bool builtin = false);
|
||||||
|
@ -321,6 +326,7 @@ class Debugger : public DialogContainer
|
||||||
bool readTrap(uInt16 t);
|
bool readTrap(uInt16 t);
|
||||||
bool writeTrap(uInt16 t);
|
bool writeTrap(uInt16 t);
|
||||||
void clearAllTraps();
|
void clearAllTraps();
|
||||||
|
void log(const string& triggerMsg);
|
||||||
|
|
||||||
// Set a bunch of RAM locations at once
|
// Set a bunch of RAM locations at once
|
||||||
string setRAM(IntArray& args);
|
string setRAM(IntArray& args);
|
||||||
|
@ -363,6 +369,7 @@ class Debugger : public DialogContainer
|
||||||
static std::array<PseudoRegister, 16> ourPseudoRegisters;
|
static std::array<PseudoRegister, 16> ourPseudoRegisters;
|
||||||
|
|
||||||
static constexpr Int8 ANY_BANK = -1;
|
static constexpr Int8 ANY_BANK = -1;
|
||||||
|
bool myFirstLog{true};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// rewind/unwind n states
|
// rewind/unwind n states
|
||||||
|
|
|
@ -101,7 +101,8 @@ class DebuggerParser
|
||||||
std::array<Parameters, 10> parms;
|
std::array<Parameters, 10> parms;
|
||||||
std::function<void (DebuggerParser*)> executor;
|
std::function<void (DebuggerParser*)> executor;
|
||||||
};
|
};
|
||||||
static std::array<Command, 100> commands;
|
using CommandArray = std::array<Command, 103>;
|
||||||
|
static CommandArray commands;
|
||||||
|
|
||||||
struct Trap
|
struct Trap
|
||||||
{
|
{
|
||||||
|
@ -149,32 +150,34 @@ class DebuggerParser
|
||||||
// List of available command methods
|
// List of available command methods
|
||||||
void executeA();
|
void executeA();
|
||||||
void executeAud();
|
void executeAud();
|
||||||
|
void executeAutoSave();
|
||||||
void executeBase();
|
void executeBase();
|
||||||
void executeBCol();
|
void executeBCol();
|
||||||
void executeBreak();
|
void executeBreak();
|
||||||
void executeBreakif();
|
void executeBreakIf();
|
||||||
void executeBreaklabel();
|
void executeBreakLabel();
|
||||||
void executeC();
|
void executeC();
|
||||||
void executeCheat();
|
void executeCheat();
|
||||||
void executeClearbreaks();
|
void executeClearBreaks();
|
||||||
void executeClearconfig();
|
void executeClearConfig();
|
||||||
void executeClearsavestateifs();
|
void executeClearHistory();
|
||||||
void executeCleartraps();
|
void executeClearSaveStateIfs();
|
||||||
void executeClearwatches();
|
void executeClearTraps();
|
||||||
|
void executeClearWatches();
|
||||||
void executeCls();
|
void executeCls();
|
||||||
void executeCode();
|
void executeCode();
|
||||||
void executeCol();
|
void executeCol();
|
||||||
void executeColortest();
|
void executeColorTest();
|
||||||
void executeD();
|
void executeD();
|
||||||
void executeData();
|
void executeData();
|
||||||
void executeDebugColors();
|
void executeDebugColors();
|
||||||
void executeDefine();
|
void executeDefine();
|
||||||
void executeDelbreakif();
|
void executeDelBreakIf();
|
||||||
void executeDelfunction();
|
void executeDelFunction();
|
||||||
void executeDelsavestateif();
|
void executeDelSaveStateIf();
|
||||||
void executeDeltrap();
|
void executeDelTrap();
|
||||||
void executeDelwatch();
|
void executeDelWatch();
|
||||||
void executeDisasm();
|
void executeDisAsm();
|
||||||
void executeDump();
|
void executeDump();
|
||||||
void executeExec();
|
void executeExec();
|
||||||
void executeExitRom();
|
void executeExitRom();
|
||||||
|
@ -193,14 +196,15 @@ class DebuggerParser
|
||||||
void executeJoy1Right();
|
void executeJoy1Right();
|
||||||
void executeJoy1Fire();
|
void executeJoy1Fire();
|
||||||
void executeJump();
|
void executeJump();
|
||||||
void executeListbreaks();
|
void executeListBreaks();
|
||||||
void executeListconfig();
|
void executeListConfig();
|
||||||
void executeListfunctions();
|
void executeListFunctions();
|
||||||
void executeListsavestateifs();
|
void executeListSaveStateIfs();
|
||||||
void executeListtraps();
|
void executeListTraps();
|
||||||
void executeLoadallstates();
|
void executeLoadAllStates();
|
||||||
void executeLoadconfig();
|
void executeLoadConfig();
|
||||||
void executeLoadstate();
|
void executeLoadState();
|
||||||
|
void executeLogBreaks();
|
||||||
void executeN();
|
void executeN();
|
||||||
void executePalette();
|
void executePalette();
|
||||||
void executePc();
|
void executePc();
|
||||||
|
@ -219,25 +223,25 @@ class DebuggerParser
|
||||||
void executeS();
|
void executeS();
|
||||||
void executeSave();
|
void executeSave();
|
||||||
void executeSaveAccess();
|
void executeSaveAccess();
|
||||||
void executeSaveallstates();
|
void executeSaveAllStates();
|
||||||
void executeSaveconfig();
|
void executeSaveConfig();
|
||||||
void executeSavedisassembly();
|
void executeSaveDisassembly();
|
||||||
void executeSaverom();
|
void executeSaveRom();
|
||||||
void executeSaveses();
|
void executeSaveSes();
|
||||||
void executeSavesnap();
|
void executeSaveSnap();
|
||||||
void executeSavestate();
|
void executeSaveState();
|
||||||
void executeSavestateif();
|
void executeSaveStateIf();
|
||||||
void executeScanline();
|
void executeScanLine();
|
||||||
void executeStep();
|
void executeStep();
|
||||||
void executeStepwhile();
|
void executeStepWhile();
|
||||||
void executeTia();
|
void executeTia();
|
||||||
void executeTrace();
|
void executeTrace();
|
||||||
void executeTrap();
|
void executeTrap();
|
||||||
void executeTrapif();
|
void executeTrapIf();
|
||||||
void executeTrapread();
|
void executeTrapRead();
|
||||||
void executeTrapreadif();
|
void executeTrapReadIf();
|
||||||
void executeTrapwrite();
|
void executeTrapWrite();
|
||||||
void executeTrapwriteif();
|
void executeTrapWriteIf();
|
||||||
void executeTraps(bool read, bool write, const string& command, bool cond = false);
|
void executeTraps(bool read, bool write, const string& command, bool cond = false);
|
||||||
void executeTrapRW(uInt32 addr, bool read, bool write, bool add = true); // not exposed by debugger
|
void executeTrapRW(uInt32 addr, bool read, bool write, bool add = true); // not exposed by debugger
|
||||||
void executeType();
|
void executeType();
|
||||||
|
|
|
@ -0,0 +1,286 @@
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// SSSS tt lll lll
|
||||||
|
// SS SS tt ll ll
|
||||||
|
// SS tttttt eeee ll ll aaaa
|
||||||
|
// SSSS tt ee ee ll ll aa
|
||||||
|
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
|
||||||
|
// SS SS tt ee ll ll aa aa
|
||||||
|
// SSSS ttt eeeee llll llll aaaaa
|
||||||
|
//
|
||||||
|
// Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony
|
||||||
|
// and the Stella Team
|
||||||
|
//
|
||||||
|
// See the file "License.txt" for information on usage and redistribution of
|
||||||
|
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
#include "OSystem.hxx"
|
||||||
|
//#include "EditTextWidget.hxx"
|
||||||
|
#include "PopUpWidget.hxx"
|
||||||
|
#include "DataGridWidget.hxx"
|
||||||
|
#include "CartARMWidget.hxx"
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
CartridgeARMWidget::CartridgeARMWidget(
|
||||||
|
GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont,
|
||||||
|
int x, int y, int w, int h, CartridgeARM& cart)
|
||||||
|
: CartDebugWidget(boss, lfont, nfont, x, y, w, h),
|
||||||
|
myCart{cart}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void CartridgeARMWidget::addCycleWidgets(int xpos, int ypos)
|
||||||
|
{
|
||||||
|
const int INDENT = 20;
|
||||||
|
const int VGAP = 4;
|
||||||
|
VariantList items;
|
||||||
|
|
||||||
|
new StaticTextWidget(_boss, _font, xpos, ypos + 1, "ARM emulation cycles:");
|
||||||
|
xpos += INDENT; ypos += myLineHeight + VGAP;
|
||||||
|
myIncCycles = new CheckboxWidget(_boss, _font, xpos, ypos + 1, "Increase 6507 cycles",
|
||||||
|
kIncCyclesChanged);
|
||||||
|
myIncCycles->setToolTip("Increase 6507 cycles with approximated ARM cycles.");
|
||||||
|
myIncCycles->setTarget(this);
|
||||||
|
|
||||||
|
myCycleFactor = new SliderWidget(_boss, _font, myIncCycles->getRight() + _fontWidth * 2, ypos - 1,
|
||||||
|
_fontWidth * 10, _lineHeight, "Cycle factor", _fontWidth * 14,
|
||||||
|
kFactorChanged, _fontWidth * 4, "%");
|
||||||
|
myCycleFactor->setMinValue(90); myCycleFactor->setMaxValue(110);
|
||||||
|
myCycleFactor->setTickmarkIntervals(4);
|
||||||
|
myCycleFactor->setToolTip("Correct approximated ARM cycles by factor.");
|
||||||
|
myCycleFactor->setTarget(this);
|
||||||
|
|
||||||
|
ypos += (myLineHeight + VGAP) * 2;
|
||||||
|
myCyclesLabel = new StaticTextWidget(_boss, _font, xpos, ypos + 1, "Cycles #");
|
||||||
|
|
||||||
|
myPrevThumbCycles = new DataGridWidget(_boss, _font, myCyclesLabel->getRight(), ypos - 1,
|
||||||
|
1, 1, 6, 32, Common::Base::Fmt::_10_6);
|
||||||
|
myPrevThumbCycles->setEditable(false);
|
||||||
|
myPrevThumbCycles->setToolTip("Approximated CPU cycles of last but one ARM run.\n");
|
||||||
|
|
||||||
|
myThumbCycles = new DataGridWidget(_boss, _font,
|
||||||
|
myPrevThumbCycles->getRight() + _fontWidth / 2, ypos - 1,
|
||||||
|
1, 1, 6, 32, Common::Base::Fmt::_10_6);
|
||||||
|
|
||||||
|
myThumbCycles->setEditable(false);
|
||||||
|
myThumbCycles->setToolTip("Approximated CPU cycles of last ARM run.\n");
|
||||||
|
|
||||||
|
StaticTextWidget* s = new StaticTextWidget(_boss, _font, myCycleFactor->getLeft(), ypos + 1,
|
||||||
|
"Instructions #");
|
||||||
|
|
||||||
|
myPrevThumbInstructions = new DataGridWidget(_boss, _font, s->getRight(), ypos - 1,
|
||||||
|
1, 1, 6, 32, Common::Base::Fmt::_10_6);
|
||||||
|
myPrevThumbInstructions->setEditable(false);
|
||||||
|
myPrevThumbInstructions->setToolTip("Instructions of last but one ARM run.\n");
|
||||||
|
|
||||||
|
myThumbInstructions = new DataGridWidget(_boss, _font,
|
||||||
|
myPrevThumbInstructions->getRight() + _fontWidth / 2, ypos - 1,
|
||||||
|
1, 1, 6, 32, Common::Base::Fmt::_10_6);
|
||||||
|
myThumbInstructions->setEditable(false);
|
||||||
|
myThumbInstructions->setToolTip("Instructions of last ARM run.\n");
|
||||||
|
|
||||||
|
// add later to allow aligning
|
||||||
|
ypos -= myLineHeight + VGAP;
|
||||||
|
int pwidth = myThumbCycles->getRight() - myPrevThumbCycles->getLeft()
|
||||||
|
- PopUpWidget::dropDownWidth(_font);
|
||||||
|
|
||||||
|
items.clear();
|
||||||
|
VarList::push_back(items, "LPC2101" + ELLIPSIS + "3", static_cast<uInt32>(Thumbulator::ChipType::LPC2101));
|
||||||
|
VarList::push_back(items, "LPC2104" + ELLIPSIS + "6 OC", static_cast<uInt32>(Thumbulator::ChipType::LPC2104_OC));
|
||||||
|
VarList::push_back(items, "LPC2104" + ELLIPSIS + "6", static_cast<uInt32>(Thumbulator::ChipType::LPC2104));
|
||||||
|
VarList::push_back(items, "LPC213x", static_cast<uInt32>(Thumbulator::ChipType::LPC213x));
|
||||||
|
myChipType = new PopUpWidget(_boss, _font, xpos, ypos, pwidth, myLineHeight, items,
|
||||||
|
"Chip ", 0, kChipChanged);
|
||||||
|
myChipType->setToolTip("Select emulated ARM chip.");
|
||||||
|
myChipType->setTarget(this);
|
||||||
|
|
||||||
|
myLockMamMode = new CheckboxWidget(_boss, _font, myCycleFactor->getLeft(), ypos + 1, "MAM Mode",
|
||||||
|
kMamLockChanged);
|
||||||
|
myLockMamMode->setToolTip("Check to lock Memory Accelerator Module (MAM) mode.");
|
||||||
|
myLockMamMode->setTarget(this);
|
||||||
|
|
||||||
|
pwidth = myThumbInstructions->getRight() - myPrevThumbInstructions->getLeft()
|
||||||
|
- PopUpWidget::dropDownWidth(_font);
|
||||||
|
items.clear();
|
||||||
|
VarList::push_back(items, "Off (0)", static_cast<uInt32>(Thumbulator::MamModeType::mode0));
|
||||||
|
VarList::push_back(items, "Partial (1)", static_cast<uInt32>(Thumbulator::MamModeType::mode1));
|
||||||
|
VarList::push_back(items, "Full (2)", static_cast<uInt32>(Thumbulator::MamModeType::mode2));
|
||||||
|
VarList::push_back(items, "1 Cycle (X)", static_cast<uInt32>(Thumbulator::MamModeType::modeX));
|
||||||
|
myMamMode = new PopUpWidget(_boss, _font, myPrevThumbInstructions->getLeft(), ypos,
|
||||||
|
pwidth, myLineHeight, items, "", 0, kMamModeChanged);
|
||||||
|
myMamMode->setToolTip("Select emulated Memory Accelerator Module (MAM) mode.");
|
||||||
|
myMamMode->setTarget(this);
|
||||||
|
|
||||||
|
// define the tab order
|
||||||
|
addFocusWidget(myIncCycles);
|
||||||
|
addFocusWidget(myCycleFactor);
|
||||||
|
addFocusWidget(myChipType);
|
||||||
|
addFocusWidget(myLockMamMode);
|
||||||
|
addFocusWidget(myMamMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void CartridgeARMWidget::saveOldState()
|
||||||
|
{
|
||||||
|
myOldState.armPrevRun.clear();
|
||||||
|
myOldState.armRun.clear();
|
||||||
|
|
||||||
|
myOldState.mamMode = static_cast<uInt32>(myCart.mamMode());
|
||||||
|
|
||||||
|
myOldState.armPrevRun.push_back(myCart.prevCycles());
|
||||||
|
myOldState.armPrevRun.push_back(myCart.prevStats().instructions);
|
||||||
|
|
||||||
|
myOldState.armRun.push_back(myCart.cycles());
|
||||||
|
myOldState.armRun.push_back(myCart.stats().instructions);
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void CartridgeARMWidget::loadConfig()
|
||||||
|
{
|
||||||
|
bool isChanged;
|
||||||
|
bool devSettings = instance().settings().getBool("dev.settings");
|
||||||
|
IntArray alist;
|
||||||
|
IntArray vlist;
|
||||||
|
BoolArray changed;
|
||||||
|
|
||||||
|
myChipType->setSelectedIndex(static_cast<uInt32>(instance().settings().getInt("dev.thumb.chiptype")));
|
||||||
|
handleChipType();
|
||||||
|
|
||||||
|
isChanged = static_cast<uInt32>(myCart.mamMode()) != myOldState.mamMode;
|
||||||
|
myMamMode->setSelectedIndex(static_cast<uInt32>(myCart.mamMode()), isChanged);
|
||||||
|
myMamMode->setEnabled(devSettings && myLockMamMode->getState());
|
||||||
|
myLockMamMode->setEnabled(devSettings);
|
||||||
|
|
||||||
|
// ARM cycles
|
||||||
|
myIncCycles->setState(instance().settings().getBool("dev.thumb.inccycles"));
|
||||||
|
myCycleFactor->setValue(std::round(instance().settings().getFloat("dev.thumb.cyclefactor") * 100.F));
|
||||||
|
handleArmCycles();
|
||||||
|
|
||||||
|
alist.clear(); vlist.clear(); changed.clear();
|
||||||
|
alist.push_back(0); vlist.push_back(myCart.prevCycles());
|
||||||
|
changed.push_back(myCart.prevCycles() != uInt32(myOldState.armPrevRun[0]));
|
||||||
|
myPrevThumbCycles->setList(alist, vlist, changed);
|
||||||
|
|
||||||
|
alist.clear(); vlist.clear(); changed.clear();
|
||||||
|
alist.push_back(0); vlist.push_back(myCart.prevStats().instructions);
|
||||||
|
changed.push_back(myCart.prevStats().instructions != uInt32(myOldState.armPrevRun[1]));
|
||||||
|
myPrevThumbInstructions->setList(alist, vlist, changed);
|
||||||
|
|
||||||
|
alist.clear(); vlist.clear(); changed.clear();
|
||||||
|
alist.push_back(0); vlist.push_back(myCart.cycles());
|
||||||
|
changed.push_back(myCart.cycles() != uInt32(myOldState.armRun[0]));
|
||||||
|
myThumbCycles->setList(alist, vlist, changed);
|
||||||
|
|
||||||
|
|
||||||
|
alist.clear(); vlist.clear(); changed.clear();
|
||||||
|
alist.push_back(0); vlist.push_back(myCart.stats().instructions);
|
||||||
|
changed.push_back(myCart.stats().instructions != uInt32(myOldState.armRun[1]));
|
||||||
|
myThumbInstructions->setList(alist, vlist, changed);
|
||||||
|
|
||||||
|
CartDebugWidget::loadConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void CartridgeARMWidget::handleCommand(CommandSender* sender,
|
||||||
|
int cmd, int data, int id)
|
||||||
|
{
|
||||||
|
switch(cmd)
|
||||||
|
{
|
||||||
|
case kChipChanged:
|
||||||
|
handleChipType();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kMamLockChanged:
|
||||||
|
handleMamLock();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kMamModeChanged:
|
||||||
|
handleMamMode();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kIncCyclesChanged:
|
||||||
|
case kFactorChanged:
|
||||||
|
handleArmCycles();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void CartridgeARMWidget::handleChipType()
|
||||||
|
{
|
||||||
|
bool devSettings = instance().settings().getBool("dev.settings");
|
||||||
|
|
||||||
|
if(devSettings)
|
||||||
|
{
|
||||||
|
instance().settings().setValue("dev.thumb.chiptype", myChipType->getSelectedTag().toInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
myChipType->setEnabled(devSettings);
|
||||||
|
Thumbulator::ChipPropsType chipProps = myCart.setChipType(static_cast<Thumbulator::ChipType>(myChipType->getSelectedTag().toInt()));
|
||||||
|
|
||||||
|
// update tooltip with currently selecte chip's properties
|
||||||
|
string tip = myChipType->getToolTip(Common::Point(0, 0));
|
||||||
|
ostringstream buf;
|
||||||
|
tip = tip.substr(0, 25);
|
||||||
|
|
||||||
|
buf << tip << "\nCurrent:\n"
|
||||||
|
<< chipProps.MHz << " MHz, "
|
||||||
|
<< chipProps.flashBanks << " flash bank"
|
||||||
|
<< (chipProps.flashBanks > 1 ? "s" : "") << ", "
|
||||||
|
<< chipProps.flashCycles - 1 << " wait states";
|
||||||
|
myChipType->setToolTip(buf.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void CartridgeARMWidget::handleMamLock()
|
||||||
|
{
|
||||||
|
bool checked = myLockMamMode->getState();
|
||||||
|
|
||||||
|
myMamMode->setEnabled(checked);
|
||||||
|
myCart.lockMamMode(checked);
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void CartridgeARMWidget::handleMamMode()
|
||||||
|
{
|
||||||
|
// override MAM mode set by ROM
|
||||||
|
Int32 mode = myMamMode->getSelected();
|
||||||
|
|
||||||
|
string name = myMamMode->getSelectedName();
|
||||||
|
myMamMode->setSelectedName(name + "XXX");
|
||||||
|
|
||||||
|
|
||||||
|
instance().settings().setValue("dev.thumb.mammode", mode);
|
||||||
|
myCart.setMamMode(static_cast<Thumbulator::MamModeType>(mode));
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void CartridgeARMWidget::handleArmCycles()
|
||||||
|
{
|
||||||
|
bool devSettings = instance().settings().getBool("dev.settings");
|
||||||
|
bool enable = myIncCycles->getState();
|
||||||
|
double factor = static_cast<double>(myCycleFactor->getValue()) / 100.0;
|
||||||
|
|
||||||
|
if(devSettings)
|
||||||
|
{
|
||||||
|
instance().settings().setValue("dev.thumb.inccycles", enable);
|
||||||
|
instance().settings().setValue("dev.thumb.cyclefactor", factor);
|
||||||
|
}
|
||||||
|
|
||||||
|
myIncCycles->setEnabled(devSettings);
|
||||||
|
myCycleFactor->setEnabled(devSettings);
|
||||||
|
myCyclesLabel->setEnabled(devSettings);
|
||||||
|
myThumbCycles->setEnabled(devSettings);
|
||||||
|
myPrevThumbCycles->setEnabled(devSettings);
|
||||||
|
|
||||||
|
myCart.incCycles(devSettings && enable);
|
||||||
|
myCart.cycleFactor(factor);
|
||||||
|
myCart.enableCycleCount(devSettings);
|
||||||
|
}
|
|
@ -0,0 +1,96 @@
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// SSSS tt lll lll
|
||||||
|
// SS SS tt ll ll
|
||||||
|
// SS tttttt eeee ll ll aaaa
|
||||||
|
// SSSS tt ee ee ll ll aa
|
||||||
|
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
|
||||||
|
// SS SS tt ee ll ll aa aa
|
||||||
|
// SSSS ttt eeeee llll llll aaaaa
|
||||||
|
//
|
||||||
|
// Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony
|
||||||
|
// and the Stella Team
|
||||||
|
//
|
||||||
|
// See the file "License.txt" for information on usage and redistribution of
|
||||||
|
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
#ifndef CARTRIDGE_ARM_WIDGET_HXX
|
||||||
|
#define CARTRIDGE_ARM_WIDGET_HXX
|
||||||
|
|
||||||
|
#include "CartARM.hxx"
|
||||||
|
#include "CartDebugWidget.hxx"
|
||||||
|
|
||||||
|
class CheckboxWidget;
|
||||||
|
class SliderWidget;
|
||||||
|
class PopUpWidget;
|
||||||
|
class DataGridWidget;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Abstract base class for ARM cart widgets.
|
||||||
|
|
||||||
|
@author Thomas Jentzsch
|
||||||
|
*/
|
||||||
|
class CartridgeARMWidget : public CartDebugWidget
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CartridgeARMWidget(GuiObject* boss, const GUI::Font& lfont,
|
||||||
|
const GUI::Font& nfont,
|
||||||
|
int x, int y, int w, int h,
|
||||||
|
CartridgeARM& cart);
|
||||||
|
~CartridgeARMWidget() override = default;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void addCycleWidgets(int xpos, int ypos);
|
||||||
|
|
||||||
|
void saveOldState() override;
|
||||||
|
void loadConfig() override;
|
||||||
|
|
||||||
|
void handleCommand(CommandSender* sender, int cmd, int data, int id) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void handleChipType();
|
||||||
|
void handleMamLock();
|
||||||
|
void handleMamMode();
|
||||||
|
void handleArmCycles();
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct CartState {
|
||||||
|
uInt32 mamMode{0};
|
||||||
|
uIntArray armRun;
|
||||||
|
uIntArray armPrevRun;
|
||||||
|
};
|
||||||
|
|
||||||
|
CartridgeARM& myCart;
|
||||||
|
|
||||||
|
CheckboxWidget* myIncCycles{nullptr};
|
||||||
|
SliderWidget* myCycleFactor{nullptr};
|
||||||
|
PopUpWidget* myChipType{nullptr};
|
||||||
|
CheckboxWidget* myLockMamMode{nullptr};
|
||||||
|
PopUpWidget* myMamMode{nullptr};
|
||||||
|
StaticTextWidget* myCyclesLabel{nullptr};
|
||||||
|
DataGridWidget* myPrevThumbCycles{nullptr};
|
||||||
|
DataGridWidget* myPrevThumbInstructions{nullptr};
|
||||||
|
DataGridWidget* myThumbCycles{nullptr};
|
||||||
|
DataGridWidget* myThumbInstructions{nullptr};
|
||||||
|
|
||||||
|
CartState myOldState;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
kChipChanged = 'chCh',
|
||||||
|
kMamLockChanged = 'mlCh',
|
||||||
|
kMamModeChanged = 'mmCh',
|
||||||
|
kIncCyclesChanged = 'inCH',
|
||||||
|
kFactorChanged = 'fcCH'
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Following constructors and assignment operators not supported
|
||||||
|
CartridgeARMWidget() = delete;
|
||||||
|
CartridgeARMWidget(const CartridgeARMWidget&) = delete;
|
||||||
|
CartridgeARMWidget(CartridgeARMWidget&&) = delete;
|
||||||
|
CartridgeARMWidget& operator=(const CartridgeARMWidget&) = delete;
|
||||||
|
CartridgeARMWidget& operator=(CartridgeARMWidget&&) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -25,7 +25,7 @@
|
||||||
CartridgeBUSWidget::CartridgeBUSWidget(
|
CartridgeBUSWidget::CartridgeBUSWidget(
|
||||||
GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont,
|
GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont,
|
||||||
int x, int y, int w, int h, CartridgeBUS& cart)
|
int x, int y, int w, int h, CartridgeBUS& cart)
|
||||||
: CartDebugWidget(boss, lfont, nfont, x, y, w, h),
|
: CartridgeARMWidget(boss, lfont, nfont, x, y, w, h, cart),
|
||||||
myCart{cart}
|
myCart{cart}
|
||||||
{
|
{
|
||||||
uInt16 size = 8 * 4096;
|
uInt16 size = 8 * 4096;
|
||||||
|
@ -186,32 +186,7 @@ CartridgeBUSWidget::CartridgeBUSWidget(
|
||||||
myDigitalSample->setEditable(false);
|
myDigitalSample->setEditable(false);
|
||||||
|
|
||||||
xpos = 10; ypos += myLineHeight + 4 * 2;
|
xpos = 10; ypos += myLineHeight + 4 * 2;
|
||||||
new StaticTextWidget(boss, _font, xpos, ypos + 1, "Last ARM run stats:");
|
addCycleWidgets(xpos, ypos);
|
||||||
xpos = 10 + _font.getMaxCharWidth() * 2; ypos += myLineHeight + 4;
|
|
||||||
StaticTextWidget* s = new StaticTextWidget(boss, _font, xpos, ypos + 1, "Mem. cycles ");
|
|
||||||
myThumbMemCycles = new EditTextWidget(boss, _font, s->getRight(), ypos - 1,
|
|
||||||
EditTextWidget::calcWidth(_font, 6), myLineHeight, "");
|
|
||||||
myThumbMemCycles->setEditable(false);
|
|
||||||
myThumbMemCycles->setToolTip("Number of memory cycles of last ARM run.");
|
|
||||||
|
|
||||||
s = new StaticTextWidget(boss, _font, myThumbMemCycles->getRight() + _fontWidth * 2, ypos + 1, "Fetches ");
|
|
||||||
myThumbFetches = new EditTextWidget(boss, _font, s->getRight(), ypos - 1,
|
|
||||||
EditTextWidget::calcWidth(_font, 6), myLineHeight, "");
|
|
||||||
myThumbFetches->setEditable(false);
|
|
||||||
myThumbFetches->setToolTip("Number of fetches/instructions of last ARM run.");
|
|
||||||
|
|
||||||
ypos += myLineHeight + 4;
|
|
||||||
s = new StaticTextWidget(boss, _font, xpos, ypos + 1, "Reads ");
|
|
||||||
myThumbReads = new EditTextWidget(boss, _font, myThumbMemCycles->getLeft(), ypos - 1,
|
|
||||||
EditTextWidget::calcWidth(_font, 6), myLineHeight, "");
|
|
||||||
myThumbReads->setEditable(false);
|
|
||||||
myThumbReads->setToolTip("Number of reads of last ARM run.");
|
|
||||||
|
|
||||||
s = new StaticTextWidget(boss, _font, myThumbReads->getRight() + _fontWidth * 2, ypos + 1, "Writes ");
|
|
||||||
myThumbWrites = new EditTextWidget(boss, _font, myThumbFetches->getLeft(), ypos - 1,
|
|
||||||
EditTextWidget::calcWidth(_font, 6), myLineHeight, "");
|
|
||||||
myThumbWrites->setEditable(false);
|
|
||||||
myThumbWrites->setToolTip("Number of write of last ARM run.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -268,6 +243,8 @@ void CartridgeBUSWidget::saveOldState()
|
||||||
myOldState.internalram.push_back(myCart.myRAM[i]);
|
myOldState.internalram.push_back(myCart.myRAM[i]);
|
||||||
|
|
||||||
myOldState.samplepointer.push_back(myCart.getSample());
|
myOldState.samplepointer.push_back(myCart.getSample());
|
||||||
|
|
||||||
|
CartridgeARMWidget::saveOldState();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -394,17 +371,7 @@ void CartridgeBUSWidget::loadConfig()
|
||||||
mySamplePointer->setCrossed(true);
|
mySamplePointer->setCrossed(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
myThumbMemCycles->setText(Common::Base::toString(myCart.stats().fetches
|
CartridgeARMWidget::loadConfig();
|
||||||
+ myCart.stats().reads + myCart.stats().writes,
|
|
||||||
Common::Base::Fmt::_10_6));
|
|
||||||
myThumbFetches->setText(Common::Base::toString(myCart.stats().fetches,
|
|
||||||
Common::Base::Fmt::_10_6));
|
|
||||||
myThumbReads->setText(Common::Base::toString(myCart.stats().reads,
|
|
||||||
Common::Base::Fmt::_10_6));
|
|
||||||
myThumbWrites->setText(Common::Base::toString(myCart.stats().writes,
|
|
||||||
Common::Base::Fmt::_10_6));
|
|
||||||
|
|
||||||
CartDebugWidget::loadConfig();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -418,6 +385,8 @@ void CartridgeBUSWidget::handleCommand(CommandSender* sender,
|
||||||
myCart.lockBank();
|
myCart.lockBank();
|
||||||
invalidate();
|
invalidate();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
CartridgeARMWidget::handleCommand(sender, cmd, data, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -24,9 +24,9 @@ class CheckboxWidget;
|
||||||
class DataGridWidget;
|
class DataGridWidget;
|
||||||
class EditTextWidget;
|
class EditTextWidget;
|
||||||
|
|
||||||
#include "CartDebugWidget.hxx"
|
#include "CartARMWidget.hxx"
|
||||||
|
|
||||||
class CartridgeBUSWidget : public CartDebugWidget
|
class CartridgeBUSWidget : public CartridgeARMWidget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CartridgeBUSWidget(GuiObject* boss, const GUI::Font& lfont,
|
CartridgeBUSWidget(GuiObject* boss, const GUI::Font& lfont,
|
||||||
|
@ -66,10 +66,6 @@ class CartridgeBUSWidget : public CartDebugWidget
|
||||||
DataGridWidget* mySamplePointer{nullptr};
|
DataGridWidget* mySamplePointer{nullptr};
|
||||||
CheckboxWidget* myBusOverdrive{nullptr};
|
CheckboxWidget* myBusOverdrive{nullptr};
|
||||||
CheckboxWidget* myDigitalSample{nullptr};
|
CheckboxWidget* myDigitalSample{nullptr};
|
||||||
EditTextWidget* myThumbMemCycles{nullptr};
|
|
||||||
EditTextWidget* myThumbFetches{nullptr};
|
|
||||||
EditTextWidget* myThumbReads{nullptr};
|
|
||||||
EditTextWidget* myThumbWrites{nullptr};
|
|
||||||
std::array<StaticTextWidget*, 6> myDatastreamLabels{nullptr};
|
std::array<StaticTextWidget*, 6> myDatastreamLabels{nullptr};
|
||||||
CartState myOldState;
|
CartState myOldState;
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
|
#include "OSystem.hxx"
|
||||||
#include "DataGridWidget.hxx"
|
#include "DataGridWidget.hxx"
|
||||||
#include "PopUpWidget.hxx"
|
#include "PopUpWidget.hxx"
|
||||||
#include "EditTextWidget.hxx"
|
#include "EditTextWidget.hxx"
|
||||||
|
@ -24,7 +25,7 @@
|
||||||
CartridgeCDFWidget::CartridgeCDFWidget(
|
CartridgeCDFWidget::CartridgeCDFWidget(
|
||||||
GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont,
|
GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont,
|
||||||
int x, int y, int w, int h, CartridgeCDF& cart)
|
int x, int y, int w, int h, CartridgeCDF& cart)
|
||||||
: CartDebugWidget(boss, lfont, nfont, x, y, w, h),
|
: CartridgeARMWidget(boss, lfont, nfont, x, y, w, h, cart),
|
||||||
myCart{cart}
|
myCart{cart}
|
||||||
{
|
{
|
||||||
const int VBORDER = 8;
|
const int VBORDER = 8;
|
||||||
|
@ -56,7 +57,7 @@ CartridgeCDFWidget::CartridgeCDFWidget(
|
||||||
myLineHeight, items,
|
myLineHeight, items,
|
||||||
"Set bank ", 0, kBankChanged);
|
"Set bank ", 0, kBankChanged);
|
||||||
myBank->setTarget(this);
|
myBank->setTarget(this);
|
||||||
//addFocusWidget(myBank);
|
addFocusWidget(myBank);
|
||||||
|
|
||||||
// Fast Fetch flag
|
// Fast Fetch flag
|
||||||
myFastFetch = new CheckboxWidget(boss, _font, myBank->getRight() + 24, ypos + 1,
|
myFastFetch = new CheckboxWidget(boss, _font, myBank->getRight() + 24, ypos + 1,
|
||||||
|
@ -69,7 +70,7 @@ CartridgeCDFWidget::CartridgeCDFWidget(
|
||||||
// Datastream Pointers
|
// Datastream Pointers
|
||||||
#define DS_X (HBORDER + _font.getStringWidth("xx "))
|
#define DS_X (HBORDER + _font.getStringWidth("xx "))
|
||||||
xpos = DS_X;
|
xpos = DS_X;
|
||||||
ypos += myLineHeight + VGAP * 3;
|
ypos += myLineHeight + VGAP * 2;
|
||||||
new StaticTextWidget(boss, _font, xpos, ypos, "Datastream Pointers");
|
new StaticTextWidget(boss, _font, xpos, ypos, "Datastream Pointers");
|
||||||
|
|
||||||
myDatastreamPointers = new DataGridWidget(boss, _nfont, DS_X,
|
myDatastreamPointers = new DataGridWidget(boss, _nfont, DS_X,
|
||||||
|
@ -136,7 +137,7 @@ CartridgeCDFWidget::CartridgeCDFWidget(
|
||||||
Common::Base::Fmt::_16_2_2);
|
Common::Base::Fmt::_16_2_2);
|
||||||
myJumpStreamIncrements->setTarget(this);
|
myJumpStreamIncrements->setTarget(this);
|
||||||
myJumpStreamIncrements->setEditable(false);
|
myJumpStreamIncrements->setEditable(false);
|
||||||
xpos = HBORDER; ypos += myLineHeight * 11 + VGAP * 3;
|
xpos = HBORDER; ypos += myLineHeight * 11 + VGAP * 2;
|
||||||
|
|
||||||
lwidth = _font.getStringWidth("Waveform Sizes ");
|
lwidth = _font.getStringWidth("Waveform Sizes ");
|
||||||
|
|
||||||
|
@ -201,32 +202,7 @@ CartridgeCDFWidget::CartridgeCDFWidget(
|
||||||
mySamplePointer->setEditable(false);
|
mySamplePointer->setEditable(false);
|
||||||
|
|
||||||
xpos = HBORDER; ypos += myLineHeight + VGAP * 2;
|
xpos = HBORDER; ypos += myLineHeight + VGAP * 2;
|
||||||
new StaticTextWidget(boss, _font, xpos, ypos + 1, "Last ARM run stats:");
|
addCycleWidgets(xpos, ypos);
|
||||||
xpos = HBORDER + INDENT; ypos += myLineHeight + VGAP;
|
|
||||||
StaticTextWidget* s = new StaticTextWidget(boss, _font, xpos, ypos + 1, "Mem. cycles ");
|
|
||||||
myThumbMemCycles = new EditTextWidget(boss, _font, s->getRight(), ypos - 1,
|
|
||||||
EditTextWidget::calcWidth(_font, 6), myLineHeight, "");
|
|
||||||
myThumbMemCycles->setEditable(false);
|
|
||||||
myThumbMemCycles->setToolTip("Number of memory cycles of last ARM run.");
|
|
||||||
|
|
||||||
s = new StaticTextWidget(boss, _font, myThumbMemCycles->getRight() + _fontWidth * 2, ypos + 1, "Fetches ");
|
|
||||||
myThumbFetches = new EditTextWidget(boss, _font, s->getRight(), ypos - 1,
|
|
||||||
EditTextWidget::calcWidth(_font, 6), myLineHeight, "");
|
|
||||||
myThumbFetches->setEditable(false);
|
|
||||||
myThumbFetches->setToolTip("Number of fetches/instructions of last ARM run.");
|
|
||||||
|
|
||||||
ypos += myLineHeight + VGAP;
|
|
||||||
s = new StaticTextWidget(boss, _font, xpos, ypos + 1, "Reads ");
|
|
||||||
myThumbReads = new EditTextWidget(boss, _font, myThumbMemCycles->getLeft(), ypos - 1,
|
|
||||||
EditTextWidget::calcWidth(_font, 6), myLineHeight, "");
|
|
||||||
myThumbReads->setEditable(false);
|
|
||||||
myThumbReads->setToolTip("Number of reads of last ARM run.");
|
|
||||||
|
|
||||||
s = new StaticTextWidget(boss, _font, myThumbReads->getRight() + _fontWidth * 2, ypos + 1, "Writes ");
|
|
||||||
myThumbWrites = new EditTextWidget(boss, _font, myThumbFetches->getLeft(), ypos - 1,
|
|
||||||
EditTextWidget::calcWidth(_font, 6), myLineHeight, "");
|
|
||||||
myThumbWrites->setEditable(false);
|
|
||||||
myThumbWrites->setToolTip("Number of write of last ARM run.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -274,6 +250,8 @@ void CartridgeCDFWidget::saveOldState()
|
||||||
myOldState.internalram.push_back(myCart.myRAM[i]);
|
myOldState.internalram.push_back(myCart.myRAM[i]);
|
||||||
|
|
||||||
myOldState.samplepointer.push_back(myCart.getSample());
|
myOldState.samplepointer.push_back(myCart.getSample());
|
||||||
|
|
||||||
|
CartridgeARMWidget::saveOldState();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -405,17 +383,8 @@ void CartridgeCDFWidget::loadConfig()
|
||||||
mySamplePointer->setCrossed(true);
|
mySamplePointer->setCrossed(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
myThumbMemCycles->setText(Common::Base::toString(myCart.stats().fetches
|
// ARM cycles
|
||||||
+ myCart.stats().reads + myCart.stats().writes,
|
CartridgeARMWidget::loadConfig();
|
||||||
Common::Base::Fmt::_10_6));
|
|
||||||
myThumbFetches->setText(Common::Base::toString(myCart.stats().fetches,
|
|
||||||
Common::Base::Fmt::_10_6));
|
|
||||||
myThumbReads->setText(Common::Base::toString(myCart.stats().reads,
|
|
||||||
Common::Base::Fmt::_10_6));
|
|
||||||
myThumbWrites->setText(Common::Base::toString(myCart.stats().writes,
|
|
||||||
Common::Base::Fmt::_10_6));
|
|
||||||
|
|
||||||
CartDebugWidget::loadConfig();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -429,6 +398,8 @@ void CartridgeCDFWidget::handleCommand(CommandSender* sender,
|
||||||
myCart.lockBank();
|
myCart.lockBank();
|
||||||
invalidate();
|
invalidate();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
CartridgeARMWidget::handleCommand(sender, cmd, data, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -23,11 +23,12 @@ class CheckboxWidget;
|
||||||
class DataGridWidget;
|
class DataGridWidget;
|
||||||
class StaticTextWidget;
|
class StaticTextWidget;
|
||||||
class EditTextWidget;
|
class EditTextWidget;
|
||||||
|
class SliderWidget;
|
||||||
|
|
||||||
#include "CartCDF.hxx"
|
#include "CartCDF.hxx"
|
||||||
#include "CartDebugWidget.hxx"
|
#include "CartARMWidget.hxx"
|
||||||
|
|
||||||
class CartridgeCDFWidget : public CartDebugWidget
|
class CartridgeCDFWidget : public CartridgeARMWidget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CartridgeCDFWidget(GuiObject* boss, const GUI::Font& lfont,
|
CartridgeCDFWidget(GuiObject* boss, const GUI::Font& lfont,
|
||||||
|
@ -70,10 +71,6 @@ class CartridgeCDFWidget : public CartDebugWidget
|
||||||
|
|
||||||
CheckboxWidget* myFastFetch{nullptr};
|
CheckboxWidget* myFastFetch{nullptr};
|
||||||
CheckboxWidget* myDigitalSample{nullptr};
|
CheckboxWidget* myDigitalSample{nullptr};
|
||||||
EditTextWidget* myThumbMemCycles{nullptr};
|
|
||||||
EditTextWidget* myThumbFetches{nullptr};
|
|
||||||
EditTextWidget* myThumbReads{nullptr};
|
|
||||||
EditTextWidget* myThumbWrites{nullptr};
|
|
||||||
|
|
||||||
CartState myOldState;
|
CartState myOldState;
|
||||||
|
|
||||||
|
@ -86,8 +83,8 @@ class CartridgeCDFWidget : public CartDebugWidget
|
||||||
static string describeCDFVersion(CartridgeCDF::CDFSubtype subtype);
|
static string describeCDFVersion(CartridgeCDF::CDFSubtype subtype);
|
||||||
|
|
||||||
void saveOldState() override;
|
void saveOldState() override;
|
||||||
|
|
||||||
void loadConfig() override;
|
void loadConfig() override;
|
||||||
|
|
||||||
void handleCommand(CommandSender* sender, int cmd, int data, int id) override;
|
void handleCommand(CommandSender* sender, int cmd, int data, int id) override;
|
||||||
|
|
||||||
string bankState() override;
|
string bankState() override;
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
CartridgeDPCPlusWidget::CartridgeDPCPlusWidget(
|
CartridgeDPCPlusWidget::CartridgeDPCPlusWidget(
|
||||||
GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont,
|
GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont,
|
||||||
int x, int y, int w, int h, CartridgeDPCPlus& cart)
|
int x, int y, int w, int h, CartridgeDPCPlus& cart)
|
||||||
: CartDebugWidget(boss, lfont, nfont, x, y, w, h),
|
: CartridgeARMWidget(boss, lfont, nfont, x, y, w, h, cart),
|
||||||
myCart{cart}
|
myCart{cart}
|
||||||
{
|
{
|
||||||
size_t size = cart.mySize;
|
size_t size = cart.mySize;
|
||||||
|
@ -181,33 +181,7 @@ CartridgeDPCPlusWidget::CartridgeDPCPlusWidget(
|
||||||
myIMLDA->setEditable(false);
|
myIMLDA->setEditable(false);
|
||||||
|
|
||||||
xpos = 2; ypos += myLineHeight + 4 * 1;
|
xpos = 2; ypos += myLineHeight + 4 * 1;
|
||||||
new StaticTextWidget(boss, _font, xpos, ypos + 1, "Last ARM run stats:");
|
addCycleWidgets(xpos, ypos);
|
||||||
xpos = 2 + _font.getMaxCharWidth() * 2; ypos += myLineHeight + 4;
|
|
||||||
StaticTextWidget* s = new StaticTextWidget(boss, _font, xpos, ypos + 1, "Mem. cycles ");
|
|
||||||
myThumbMemCycles = new EditTextWidget(boss, _font, s->getRight(), ypos - 1,
|
|
||||||
EditTextWidget::calcWidth(_font, 6), myLineHeight, "");
|
|
||||||
myThumbMemCycles->setEditable(false);
|
|
||||||
myThumbMemCycles->setToolTip("Number of memory cycles of last ARM run.");
|
|
||||||
|
|
||||||
s = new StaticTextWidget(boss, _font, myThumbMemCycles->getRight() + _fontWidth * 2, ypos + 1, "Fetches ");
|
|
||||||
myThumbFetches = new EditTextWidget(boss, _font, s->getRight(), ypos - 1,
|
|
||||||
EditTextWidget::calcWidth(_font, 6), myLineHeight, "");
|
|
||||||
myThumbFetches->setEditable(false);
|
|
||||||
myThumbFetches->setToolTip("Number of fetches/instructions of last ARM run.");
|
|
||||||
|
|
||||||
ypos += myLineHeight + 4;
|
|
||||||
s = new StaticTextWidget(boss, _font, xpos, ypos + 1, "Reads ");
|
|
||||||
myThumbReads = new EditTextWidget(boss, _font, myThumbMemCycles->getLeft(), ypos - 1,
|
|
||||||
EditTextWidget::calcWidth(_font, 6), myLineHeight, "");
|
|
||||||
myThumbReads->setEditable(false);
|
|
||||||
myThumbReads->setToolTip("Number of reads of last ARM run.");
|
|
||||||
|
|
||||||
s = new StaticTextWidget(boss, _font, myThumbReads->getRight() + _fontWidth * 2, ypos + 1, "Writes ");
|
|
||||||
myThumbWrites = new EditTextWidget(boss, _font, myThumbFetches->getLeft(), ypos - 1,
|
|
||||||
EditTextWidget::calcWidth(_font, 6), myLineHeight, "");
|
|
||||||
myThumbWrites->setEditable(false);
|
|
||||||
myThumbWrites->setToolTip("Number of write of last ARM run.");
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -246,6 +220,8 @@ void CartridgeDPCPlusWidget::saveOldState()
|
||||||
myOldState.internalram.push_back(myCart.myDisplayImage[i]);
|
myOldState.internalram.push_back(myCart.myDisplayImage[i]);
|
||||||
|
|
||||||
myOldState.bank = myCart.getBank();
|
myOldState.bank = myCart.getBank();
|
||||||
|
|
||||||
|
CartridgeARMWidget::saveOldState();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -336,17 +312,7 @@ void CartridgeDPCPlusWidget::loadConfig()
|
||||||
myFastFetch->setState(myCart.myFastFetch);
|
myFastFetch->setState(myCart.myFastFetch);
|
||||||
myIMLDA->setState(myCart.myLDAimmediate);
|
myIMLDA->setState(myCart.myLDAimmediate);
|
||||||
|
|
||||||
myThumbMemCycles->setText(Common::Base::toString(myCart.stats().fetches
|
CartridgeARMWidget::loadConfig();
|
||||||
+ myCart.stats().reads + myCart.stats().writes,
|
|
||||||
Common::Base::Fmt::_10_6));
|
|
||||||
myThumbFetches->setText(Common::Base::toString(myCart.stats().fetches,
|
|
||||||
Common::Base::Fmt::_10_6));
|
|
||||||
myThumbReads->setText(Common::Base::toString(myCart.stats().reads,
|
|
||||||
Common::Base::Fmt::_10_6));
|
|
||||||
myThumbWrites->setText(Common::Base::toString(myCart.stats().writes,
|
|
||||||
Common::Base::Fmt::_10_6));
|
|
||||||
|
|
||||||
CartDebugWidget::loadConfig();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -360,6 +326,8 @@ void CartridgeDPCPlusWidget::handleCommand(CommandSender* sender,
|
||||||
myCart.lockBank();
|
myCart.lockBank();
|
||||||
invalidate();
|
invalidate();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
CartridgeARMWidget::handleCommand(sender, cmd, data, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -24,9 +24,9 @@ class CheckboxWidget;
|
||||||
class DataGridWidget;
|
class DataGridWidget;
|
||||||
class EditTextWidget;
|
class EditTextWidget;
|
||||||
|
|
||||||
#include "CartDebugWidget.hxx"
|
#include "CartARMWidget.hxx"
|
||||||
|
|
||||||
class CartridgeDPCPlusWidget : public CartDebugWidget
|
class CartridgeDPCPlusWidget : public CartridgeARMWidget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CartridgeDPCPlusWidget(GuiObject* boss, const GUI::Font& lfont,
|
CartridgeDPCPlusWidget(GuiObject* boss, const GUI::Font& lfont,
|
||||||
|
@ -66,10 +66,6 @@ class CartridgeDPCPlusWidget : public CartDebugWidget
|
||||||
CheckboxWidget* myFastFetch{nullptr};
|
CheckboxWidget* myFastFetch{nullptr};
|
||||||
CheckboxWidget* myIMLDA{nullptr};
|
CheckboxWidget* myIMLDA{nullptr};
|
||||||
DataGridWidget* myRandom{nullptr};
|
DataGridWidget* myRandom{nullptr};
|
||||||
EditTextWidget* myThumbMemCycles{nullptr};
|
|
||||||
EditTextWidget* myThumbFetches{nullptr};
|
|
||||||
EditTextWidget* myThumbReads{nullptr};
|
|
||||||
EditTextWidget* myThumbWrites{nullptr};
|
|
||||||
|
|
||||||
CartState myOldState;
|
CartState myOldState;
|
||||||
|
|
||||||
|
|
|
@ -337,7 +337,7 @@ bool DataGridWidget::handleKeyDown(StellaKey key, StellaMod mod)
|
||||||
{
|
{
|
||||||
// Ignore all mod keys
|
// Ignore all mod keys
|
||||||
if(StellaModTest::isControl(mod) || StellaModTest::isAlt(mod))
|
if(StellaModTest::isControl(mod) || StellaModTest::isAlt(mod))
|
||||||
return true;
|
return false;
|
||||||
|
|
||||||
bool handled = true;
|
bool handled = true;
|
||||||
bool dirty = false;
|
bool dirty = false;
|
||||||
|
@ -737,6 +737,7 @@ void DataGridWidget::startEditMode()
|
||||||
dialog().tooltip().hide();
|
dialog().tooltip().hide();
|
||||||
enableEditMode(true);
|
enableEditMode(true);
|
||||||
setText("", true); // Erase current entry when starting editing
|
setText("", true); // Erase current entry when starting editing
|
||||||
|
backupString() = "@@"; // dummy value to process Escape correctly key when nothing is entered
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -782,6 +783,7 @@ void DataGridWidget::endEditMode()
|
||||||
}
|
}
|
||||||
|
|
||||||
setSelectedValue(value);
|
setSelectedValue(value);
|
||||||
|
commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -789,6 +791,7 @@ void DataGridWidget::abortEditMode()
|
||||||
{
|
{
|
||||||
if(_editMode)
|
if(_editMode)
|
||||||
{
|
{
|
||||||
|
abort();
|
||||||
// Undo any changes made
|
// Undo any changes made
|
||||||
assert(_selectedItem >= 0);
|
assert(_selectedItem >= 0);
|
||||||
enableEditMode(false);
|
enableEditMode(false);
|
||||||
|
|
|
@ -111,6 +111,10 @@ void DebuggerDialog::handleKeyDown(StellaKey key, StellaMod mod, bool repeated)
|
||||||
instance().eventHandler().enableTextEvents(false);
|
instance().eventHandler().enableTextEvents(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Process widget keys first
|
||||||
|
if(_focusedWidget && _focusedWidget->handleKeyDown(key, mod))
|
||||||
|
return;
|
||||||
|
|
||||||
// special debugger keys first (cannot be remapped)
|
// special debugger keys first (cannot be remapped)
|
||||||
if (StellaModTest::isControl(mod))
|
if (StellaModTest::isControl(mod))
|
||||||
{
|
{
|
||||||
|
@ -186,7 +190,7 @@ void DebuggerDialog::handleKeyDown(StellaKey key, StellaMod mod, bool repeated)
|
||||||
// events which need special handling in debugger
|
// events which need special handling in debugger
|
||||||
case Event::TakeSnapshot:
|
case Event::TakeSnapshot:
|
||||||
if(!repeated)
|
if(!repeated)
|
||||||
instance().debugger().parser().run("savesnap");
|
instance().debugger().parser().run("saveSnap");
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case Event::Rewind1Menu:
|
case Event::Rewind1Menu:
|
||||||
|
@ -319,7 +323,7 @@ void DebuggerDialog::doAdvance()
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void DebuggerDialog::doScanlineAdvance()
|
void DebuggerDialog::doScanlineAdvance()
|
||||||
{
|
{
|
||||||
instance().debugger().parser().run("scanline #1");
|
instance().debugger().parser().run("scanLine #1");
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -367,7 +371,7 @@ void DebuggerDialog::doExitDebugger()
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void DebuggerDialog::doExitRom()
|
void DebuggerDialog::doExitRom()
|
||||||
{
|
{
|
||||||
instance().debugger().parser().run("exitrom");
|
instance().debugger().parser().run("exitRom");
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -33,16 +33,16 @@ class KeyboardWidget : public ControllerWidget
|
||||||
const Event::Type* myEvent{nullptr};
|
const Event::Type* myEvent{nullptr};
|
||||||
|
|
||||||
static constexpr std::array<Event::Type, 12> ourLeftEvents = {{
|
static constexpr std::array<Event::Type, 12> ourLeftEvents = {{
|
||||||
Event::KeyboardZero1, Event::KeyboardZero2, Event::KeyboardZero3,
|
Event::LeftKeyboard1, Event::LeftKeyboard2, Event::LeftKeyboard3,
|
||||||
Event::KeyboardZero4, Event::KeyboardZero5, Event::KeyboardZero6,
|
Event::LeftKeyboard4, Event::LeftKeyboard5, Event::LeftKeyboard6,
|
||||||
Event::KeyboardZero7, Event::KeyboardZero8, Event::KeyboardZero9,
|
Event::LeftKeyboard7, Event::LeftKeyboard8, Event::LeftKeyboard9,
|
||||||
Event::KeyboardZeroStar, Event::KeyboardZero0, Event::KeyboardZeroPound
|
Event::LeftKeyboardStar, Event::LeftKeyboard0, Event::LeftKeyboardPound
|
||||||
}};
|
}};
|
||||||
static constexpr std::array<Event::Type, 12> ourRightEvents = {{
|
static constexpr std::array<Event::Type, 12> ourRightEvents = {{
|
||||||
Event::KeyboardOne1, Event::KeyboardOne2, Event::KeyboardOne3,
|
Event::RightKeyboard1, Event::RightKeyboard2, Event::RightKeyboard3,
|
||||||
Event::KeyboardOne4, Event::KeyboardOne5, Event::KeyboardOne6,
|
Event::RightKeyboard4, Event::RightKeyboard5, Event::RightKeyboard6,
|
||||||
Event::KeyboardOne7, Event::KeyboardOne8, Event::KeyboardOne9,
|
Event::RightKeyboard7, Event::RightKeyboard8, Event::RightKeyboard9,
|
||||||
Event::KeyboardOneStar, Event::KeyboardOne0, Event::KeyboardOnePound
|
Event::RightKeyboardStar, Event::RightKeyboard0, Event::RightKeyboardPound
|
||||||
}};
|
}};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -40,13 +40,7 @@
|
||||||
PromptWidget::PromptWidget(GuiObject* boss, const GUI::Font& font,
|
PromptWidget::PromptWidget(GuiObject* boss, const GUI::Font& font,
|
||||||
int x, int y, int w, int h)
|
int x, int y, int w, int h)
|
||||||
: Widget(boss, font, x, y, w - ScrollBarWidget::scrollBarWidth(font), h),
|
: Widget(boss, font, x, y, w - ScrollBarWidget::scrollBarWidth(font), h),
|
||||||
CommandSender(boss),
|
CommandSender(boss)
|
||||||
_historySize{0},
|
|
||||||
_historyIndex{0},
|
|
||||||
_historyLine{0},
|
|
||||||
_makeDirty{false},
|
|
||||||
_firstTime{true},
|
|
||||||
_exitedEarly{false}
|
|
||||||
{
|
{
|
||||||
_flags = Widget::FLAG_ENABLED | Widget::FLAG_CLEARBG | Widget::FLAG_RETAIN_FOCUS |
|
_flags = Widget::FLAG_ENABLED | Widget::FLAG_CLEARBG | Widget::FLAG_RETAIN_FOCUS |
|
||||||
Widget::FLAG_WANTS_TAB | Widget::FLAG_WANTS_RAWDATA;
|
Widget::FLAG_WANTS_TAB | Widget::FLAG_WANTS_RAWDATA;
|
||||||
|
@ -68,9 +62,6 @@ PromptWidget::PromptWidget(GuiObject* boss, const GUI::Font& font,
|
||||||
ScrollBarWidget::scrollBarWidth(_font), _h);
|
ScrollBarWidget::scrollBarWidth(_font), _h);
|
||||||
_scrollBar->setTarget(this);
|
_scrollBar->setTarget(this);
|
||||||
|
|
||||||
// Init colors
|
|
||||||
_inverse = false;
|
|
||||||
|
|
||||||
clearScreen();
|
clearScreen();
|
||||||
|
|
||||||
addFocusWidget(this);
|
addFocusWidget(this);
|
||||||
|
@ -137,6 +128,8 @@ void PromptWidget::printPrompt()
|
||||||
|
|
||||||
print(PROMPT);
|
print(PROMPT);
|
||||||
_promptStartPos = _promptEndPos = _currentPos;
|
_promptStartPos = _promptEndPos = _currentPos;
|
||||||
|
|
||||||
|
resetFunctions();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -150,6 +143,8 @@ bool PromptWidget::handleText(char text)
|
||||||
_promptEndPos++;
|
_promptEndPos++;
|
||||||
putcharIntern(text);
|
putcharIntern(text);
|
||||||
scrollToCurrent();
|
scrollToCurrent();
|
||||||
|
|
||||||
|
resetFunctions();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -157,323 +152,171 @@ bool PromptWidget::handleText(char text)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool PromptWidget::handleKeyDown(StellaKey key, StellaMod mod)
|
bool PromptWidget::handleKeyDown(StellaKey key, StellaMod mod)
|
||||||
{
|
{
|
||||||
bool handled = true;
|
bool handled = true,
|
||||||
bool dirty = false;
|
dirty = true,
|
||||||
|
changeInput = false,
|
||||||
|
resetAutoComplete = true,
|
||||||
|
resetHistoryScroll = true;
|
||||||
|
|
||||||
switch(key)
|
// Uses normal edit events + special prompt events
|
||||||
|
Event::Type event = instance().eventHandler().eventForKey(EventMode::kEditMode, key, mod);
|
||||||
|
if(event == Event::NoType)
|
||||||
|
event = instance().eventHandler().eventForKey(EventMode::kPromptMode, key, mod);
|
||||||
|
|
||||||
|
switch(event)
|
||||||
{
|
{
|
||||||
case KBDK_RETURN:
|
case Event::EndEdit:
|
||||||
case KBDK_KP_ENTER:
|
|
||||||
{
|
{
|
||||||
nextLine();
|
if(execute())
|
||||||
|
return true;
|
||||||
assert(_promptEndPos >= _promptStartPos);
|
|
||||||
int len = _promptEndPos - _promptStartPos;
|
|
||||||
|
|
||||||
if (len > 0)
|
|
||||||
{
|
|
||||||
// Copy the user input to command
|
|
||||||
string command;
|
|
||||||
for (int i = 0; i < len; i++)
|
|
||||||
command += buffer(_promptStartPos + i) & 0x7f;
|
|
||||||
|
|
||||||
// Add the input to the history
|
|
||||||
addToHistory(command.c_str());
|
|
||||||
|
|
||||||
// Pass the command to the debugger, and print the result
|
|
||||||
string result = instance().debugger().run(command);
|
|
||||||
|
|
||||||
// This is a bit of a hack
|
|
||||||
// Certain commands remove the debugger dialog from underneath us,
|
|
||||||
// so we shouldn't print any messages
|
|
||||||
// Those commands will return '_EXIT_DEBUGGER' as their result
|
|
||||||
if(result == "_EXIT_DEBUGGER")
|
|
||||||
{
|
|
||||||
_exitedEarly = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if(result == "_NO_PROMPT")
|
|
||||||
return true;
|
|
||||||
else if(result != "")
|
|
||||||
print(result + "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
printPrompt();
|
printPrompt();
|
||||||
dirty = true;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case KBDK_TAB:
|
// special events (auto complete & history scrolling)
|
||||||
{
|
case Event::UINavNext:
|
||||||
// Tab completion: we complete either commands or labels, but not
|
dirty = changeInput = autoComplete(+1);
|
||||||
// both at once.
|
resetAutoComplete = false;
|
||||||
|
|
||||||
if(_currentPos <= _promptStartPos)
|
|
||||||
break;
|
|
||||||
|
|
||||||
scrollToCurrent();
|
|
||||||
int len = _promptEndPos - _promptStartPos;
|
|
||||||
if(len > 255) len = 255;
|
|
||||||
|
|
||||||
int lastDelimPos = -1;
|
|
||||||
char delimiter = '\0';
|
|
||||||
|
|
||||||
char inputStr[256]; // NOLINT (will be rewritten soon)
|
|
||||||
for (int i = 0; i < len; i++)
|
|
||||||
{
|
|
||||||
inputStr[i] = buffer(_promptStartPos + i) & 0x7f;
|
|
||||||
// whitespace characters
|
|
||||||
if(strchr("{*@<> =[]()+-/&|!^~%", inputStr[i]))
|
|
||||||
{
|
|
||||||
lastDelimPos = i;
|
|
||||||
delimiter = inputStr[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
inputStr[len] = '\0';
|
|
||||||
size_t strLen = len - lastDelimPos - 1;
|
|
||||||
|
|
||||||
StringList list;
|
|
||||||
string completionList;
|
|
||||||
string prefix;
|
|
||||||
|
|
||||||
if(lastDelimPos < 0)
|
|
||||||
{
|
|
||||||
// no delimiters, do only command completion:
|
|
||||||
const DebuggerParser& parser = instance().debugger().parser();
|
|
||||||
parser.getCompletions(inputStr, list);
|
|
||||||
|
|
||||||
if(list.size() < 1)
|
|
||||||
break;
|
|
||||||
|
|
||||||
sort(list.begin(), list.end());
|
|
||||||
completionList = list[0];
|
|
||||||
for(uInt32 i = 1; i < list.size(); ++i)
|
|
||||||
completionList += " " + list[i];
|
|
||||||
prefix = getCompletionPrefix(list);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Special case for 'help' command
|
|
||||||
if(BSPF::startsWithIgnoreCase(inputStr, "help"))
|
|
||||||
{
|
|
||||||
instance().debugger().parser().getCompletions(inputStr + lastDelimPos + 1, list);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// do not show ALL labels without any filter as it makes no sense
|
|
||||||
if(strLen > 0)
|
|
||||||
{
|
|
||||||
// we got a delimiter, so this must be a label or a function
|
|
||||||
const Debugger& dbg = instance().debugger();
|
|
||||||
|
|
||||||
dbg.cartDebug().getCompletions(inputStr + lastDelimPos + 1, list);
|
|
||||||
dbg.getCompletions(inputStr + lastDelimPos + 1, list);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(list.size() < 1)
|
|
||||||
break;
|
|
||||||
|
|
||||||
sort(list.begin(), list.end());
|
|
||||||
completionList = list[0];
|
|
||||||
for(uInt32 i = 1; i < list.size(); ++i)
|
|
||||||
completionList += " " + list[i];
|
|
||||||
prefix = getCompletionPrefix(list);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: tab through list
|
|
||||||
|
|
||||||
if(list.size() == 1)
|
|
||||||
{
|
|
||||||
// add to buffer as though user typed it (plus a space)
|
|
||||||
_currentPos = _promptStartPos + lastDelimPos + 1;
|
|
||||||
const char* clptr = completionList.c_str();
|
|
||||||
while(*clptr != '\0')
|
|
||||||
putcharIntern(*clptr++);
|
|
||||||
|
|
||||||
putcharIntern(' ');
|
|
||||||
_promptEndPos = _currentPos;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
nextLine();
|
|
||||||
// add to buffer as-is, then add PROMPT plus whatever we have so far
|
|
||||||
_currentPos = _promptStartPos + lastDelimPos + 1;
|
|
||||||
|
|
||||||
print("\n");
|
|
||||||
print(completionList);
|
|
||||||
print("\n");
|
|
||||||
print(PROMPT);
|
|
||||||
|
|
||||||
_promptStartPos = _currentPos;
|
|
||||||
|
|
||||||
if(prefix.length() < strLen)
|
|
||||||
{
|
|
||||||
for(int i = 0; i < len; i++)
|
|
||||||
putcharIntern(inputStr[i]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for(int i = 0; i < lastDelimPos; i++)
|
|
||||||
putcharIntern(inputStr[i]);
|
|
||||||
|
|
||||||
if(lastDelimPos > 0)
|
|
||||||
putcharIntern(delimiter);
|
|
||||||
|
|
||||||
print(prefix);
|
|
||||||
}
|
|
||||||
_promptEndPos = _currentPos;
|
|
||||||
}
|
|
||||||
dirty = true;
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
case KBDK_BACKSPACE:
|
case Event::UINavPrev:
|
||||||
if (_currentPos > _promptStartPos)
|
dirty = changeInput = autoComplete(-1);
|
||||||
|
resetAutoComplete = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Event::UILeft: // mapped to KBDK_DOWN by default
|
||||||
|
dirty = changeInput = historyScroll(-1);
|
||||||
|
resetHistoryScroll = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Event::UIRight: // mapped to KBDK_UP by default
|
||||||
|
dirty = changeInput = historyScroll(+1);
|
||||||
|
resetHistoryScroll = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// input modifying events
|
||||||
|
case Event::Backspace:
|
||||||
|
if(_currentPos > _promptStartPos)
|
||||||
|
{
|
||||||
killChar(-1);
|
killChar(-1);
|
||||||
|
changeInput = true;
|
||||||
|
}
|
||||||
scrollToCurrent();
|
scrollToCurrent();
|
||||||
dirty = true;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case KBDK_DELETE:
|
case Event::Delete:
|
||||||
case KBDK_KP_PERIOD: // actually the num delete
|
killChar(+1);
|
||||||
if(StellaModTest::isShift(mod))
|
changeInput = true;
|
||||||
textCut();
|
|
||||||
else
|
|
||||||
killChar(+1);
|
|
||||||
dirty = true;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case KBDK_PAGEUP:
|
case Event::DeleteEnd:
|
||||||
if (StellaModTest::isShift(mod))
|
killLine(+1);
|
||||||
{
|
changeInput = true;
|
||||||
// Don't scroll up when at top of buffer
|
|
||||||
if(_scrollLine < _linesPerPage)
|
|
||||||
break;
|
|
||||||
|
|
||||||
_scrollLine -= _linesPerPage - 1;
|
|
||||||
if (_scrollLine < _firstLineInBuffer + _linesPerPage - 1)
|
|
||||||
_scrollLine = _firstLineInBuffer + _linesPerPage - 1;
|
|
||||||
updateScrollBuffer();
|
|
||||||
|
|
||||||
dirty = true;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case KBDK_PAGEDOWN:
|
case Event::DeleteHome:
|
||||||
if (StellaModTest::isShift(mod))
|
killLine(-1);
|
||||||
{
|
changeInput = true;
|
||||||
// Don't scroll down when at bottom of buffer
|
|
||||||
if(_scrollLine >= _promptEndPos / _lineWidth)
|
|
||||||
break;
|
|
||||||
|
|
||||||
_scrollLine += _linesPerPage - 1;
|
|
||||||
if (_scrollLine > _promptEndPos / _lineWidth)
|
|
||||||
_scrollLine = _promptEndPos / _lineWidth;
|
|
||||||
updateScrollBuffer();
|
|
||||||
|
|
||||||
dirty = true;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case KBDK_HOME:
|
case Event::DeleteLeftWord:
|
||||||
if (StellaModTest::isShift(mod))
|
killWord();
|
||||||
{
|
changeInput = true;
|
||||||
_scrollLine = _firstLineInBuffer + _linesPerPage - 1;
|
|
||||||
updateScrollBuffer();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
_currentPos = _promptStartPos;
|
|
||||||
|
|
||||||
dirty = true;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case KBDK_END:
|
case Event::Cut:
|
||||||
if (StellaModTest::isShift(mod))
|
textCut();
|
||||||
{
|
changeInput = true;
|
||||||
_scrollLine = _promptEndPos / _lineWidth;
|
|
||||||
if (_scrollLine < _linesPerPage - 1)
|
|
||||||
_scrollLine = _linesPerPage - 1;
|
|
||||||
updateScrollBuffer();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
_currentPos = _promptEndPos;
|
|
||||||
|
|
||||||
dirty = true;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case KBDK_UP:
|
case Event::Copy:
|
||||||
if (StellaModTest::isShift(mod))
|
textCopy();
|
||||||
{
|
|
||||||
if(_scrollLine <= _firstLineInBuffer + _linesPerPage - 1)
|
|
||||||
break;
|
|
||||||
|
|
||||||
_scrollLine -= 1;
|
|
||||||
updateScrollBuffer();
|
|
||||||
|
|
||||||
dirty = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
historyScroll(+1);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case KBDK_DOWN:
|
case Event::Paste:
|
||||||
if (StellaModTest::isShift(mod))
|
textPaste();
|
||||||
{
|
changeInput = true;
|
||||||
// Don't scroll down when at bottom of buffer
|
|
||||||
if(_scrollLine >= _promptEndPos / _lineWidth)
|
|
||||||
break;
|
|
||||||
|
|
||||||
_scrollLine += 1;
|
|
||||||
updateScrollBuffer();
|
|
||||||
|
|
||||||
dirty = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
historyScroll(-1);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case KBDK_RIGHT:
|
// cursor events
|
||||||
if (_currentPos < _promptEndPos)
|
case Event::MoveHome:
|
||||||
|
_currentPos = _promptStartPos;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Event::MoveEnd:
|
||||||
|
_currentPos = _promptEndPos;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Event::MoveRightChar:
|
||||||
|
if(_currentPos < _promptEndPos)
|
||||||
_currentPos++;
|
_currentPos++;
|
||||||
|
|
||||||
dirty = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case KBDK_LEFT:
|
|
||||||
if (_currentPos > _promptStartPos)
|
|
||||||
_currentPos--;
|
|
||||||
|
|
||||||
dirty = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case KBDK_INSERT:
|
|
||||||
if(StellaModTest::isShift(mod))
|
|
||||||
{
|
|
||||||
textPaste();
|
|
||||||
dirty = true;
|
|
||||||
}
|
|
||||||
else if(StellaModTest::isControl(mod))
|
|
||||||
{
|
|
||||||
textCopy();
|
|
||||||
dirty = true;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
handled = false;
|
handled = false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case Event::MoveLeftChar:
|
||||||
|
if(_currentPos > _promptStartPos)
|
||||||
|
_currentPos--;
|
||||||
|
else
|
||||||
|
handled = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// scrolling events
|
||||||
|
case Event::UIUp:
|
||||||
|
if(_scrollLine <= _firstLineInBuffer + _linesPerPage - 1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
_scrollLine -= 1;
|
||||||
|
updateScrollBuffer();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Event::UIDown:
|
||||||
|
// Don't scroll down when at bottom of buffer
|
||||||
|
if(_scrollLine >= _promptEndPos / _lineWidth)
|
||||||
|
break;
|
||||||
|
|
||||||
|
_scrollLine += 1;
|
||||||
|
updateScrollBuffer();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Event::UIPgUp:
|
||||||
|
// Don't scroll up when at top of buffer
|
||||||
|
if(_scrollLine < _linesPerPage)
|
||||||
|
break;
|
||||||
|
|
||||||
|
_scrollLine -= _linesPerPage - 1;
|
||||||
|
if(_scrollLine < _firstLineInBuffer + _linesPerPage - 1)
|
||||||
|
_scrollLine = _firstLineInBuffer + _linesPerPage - 1;
|
||||||
|
updateScrollBuffer();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Event::UIPgDown:
|
||||||
|
// Don't scroll down when at bottom of buffer
|
||||||
|
if(_scrollLine >= _promptEndPos / _lineWidth)
|
||||||
|
break;
|
||||||
|
|
||||||
|
_scrollLine += _linesPerPage - 1;
|
||||||
|
if(_scrollLine > _promptEndPos / _lineWidth)
|
||||||
|
_scrollLine = _promptEndPos / _lineWidth;
|
||||||
|
updateScrollBuffer();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Event::UIHome:
|
||||||
|
_scrollLine = _firstLineInBuffer + _linesPerPage - 1;
|
||||||
|
updateScrollBuffer();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Event::UIEnd:
|
||||||
|
_scrollLine = _promptEndPos / _lineWidth;
|
||||||
|
if(_scrollLine < _linesPerPage - 1)
|
||||||
|
_scrollLine = _linesPerPage - 1;
|
||||||
|
updateScrollBuffer();
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (StellaModTest::isControl(mod))
|
handled = false;
|
||||||
{
|
dirty = false;
|
||||||
specialKeys(key);
|
|
||||||
}
|
|
||||||
else if (StellaModTest::isAlt(mod))
|
|
||||||
{
|
|
||||||
// Placeholder only - this will never be reached
|
|
||||||
}
|
|
||||||
else
|
|
||||||
handled = false;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -481,19 +324,12 @@ bool PromptWidget::handleKeyDown(StellaKey key, StellaMod mod)
|
||||||
if(dirty)
|
if(dirty)
|
||||||
setDirty();
|
setDirty();
|
||||||
|
|
||||||
// There are times when we want the prompt and scrollbar to be marked
|
// Reset special event handling if input has changed
|
||||||
// as dirty *after* they've been drawn above. One such occurrence is
|
// We assume that non-handled events will modify the input too
|
||||||
// when we issue a command that indirectly redraws the entire parent
|
if(!handled || (resetAutoComplete && changeInput))
|
||||||
// dialog (such as 'scanline' or 'frame').
|
_tabCount = -1;
|
||||||
// In those cases, the return code of the command must be shown, but the
|
if(!handled || (resetHistoryScroll && changeInput))
|
||||||
// entire dialog contents are redrawn at a later time. So the prompt and
|
_historyLine = 0;
|
||||||
// scrollbar won't be redrawn unless they're dirty again.
|
|
||||||
if(_makeDirty)
|
|
||||||
{
|
|
||||||
setDirty();
|
|
||||||
_scrollBar->setDirty();
|
|
||||||
_makeDirty = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return handled;
|
return handled;
|
||||||
}
|
}
|
||||||
|
@ -532,9 +368,6 @@ void PromptWidget::handleCommand(CommandSender* sender, int cmd,
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void PromptWidget::loadConfig()
|
void PromptWidget::loadConfig()
|
||||||
{
|
{
|
||||||
// See logic at the end of handleKeyDown for an explanation of this
|
|
||||||
_makeDirty = true;
|
|
||||||
|
|
||||||
// Show the prompt the first time we draw this widget
|
// Show the prompt the first time we draw this widget
|
||||||
if(_firstTime)
|
if(_firstTime)
|
||||||
{
|
{
|
||||||
|
@ -557,6 +390,22 @@ void PromptWidget::loadConfig()
|
||||||
print(instance().debugger().cartDebug().loadConfigFile() + "\n");
|
print(instance().debugger().cartDebug().loadConfigFile() + "\n");
|
||||||
print(instance().debugger().cartDebug().loadListFile() + "\n");
|
print(instance().debugger().cartDebug().loadListFile() + "\n");
|
||||||
print(instance().debugger().cartDebug().loadSymbolFile() + "\n");
|
print(instance().debugger().cartDebug().loadSymbolFile() + "\n");
|
||||||
|
|
||||||
|
bool extra = false;
|
||||||
|
if(instance().settings().getBool("dbg.autosave"))
|
||||||
|
{
|
||||||
|
print(DebuggerParser::inverse(" autoSave enabled "));
|
||||||
|
print("\177 "); // must switch inverse here!
|
||||||
|
extra = true;
|
||||||
|
}
|
||||||
|
if(instance().settings().getBool("dbg.logbreaks"))
|
||||||
|
{
|
||||||
|
print(DebuggerParser::inverse(" logBreaks enabled "));
|
||||||
|
extra = true;
|
||||||
|
}
|
||||||
|
if(extra)
|
||||||
|
print("\n");
|
||||||
|
|
||||||
print(PROMPT);
|
print(PROMPT);
|
||||||
|
|
||||||
_promptStartPos = _promptEndPos = _currentPos;
|
_promptStartPos = _promptEndPos = _currentPos;
|
||||||
|
@ -575,46 +424,6 @@ int PromptWidget::getWidth() const
|
||||||
return _w + ScrollBarWidget::scrollBarWidth(_font);
|
return _w + ScrollBarWidget::scrollBarWidth(_font);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void PromptWidget::specialKeys(StellaKey key)
|
|
||||||
{
|
|
||||||
bool handled = true;
|
|
||||||
|
|
||||||
switch(key)
|
|
||||||
{
|
|
||||||
case KBDK_D:
|
|
||||||
killChar(+1);
|
|
||||||
break;
|
|
||||||
case KBDK_K:
|
|
||||||
killLine(+1);
|
|
||||||
break;
|
|
||||||
case KBDK_U:
|
|
||||||
killLine(-1);
|
|
||||||
break;
|
|
||||||
case KBDK_W:
|
|
||||||
killWord();
|
|
||||||
break;
|
|
||||||
case KBDK_A:
|
|
||||||
textSelectAll();
|
|
||||||
break;
|
|
||||||
case KBDK_X:
|
|
||||||
textCut();
|
|
||||||
break;
|
|
||||||
case KBDK_C:
|
|
||||||
textCopy();
|
|
||||||
break;
|
|
||||||
case KBDK_V:
|
|
||||||
textPaste();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
handled = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(handled)
|
|
||||||
setDirty();
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void PromptWidget::killChar(int direction)
|
void PromptWidget::killChar(int direction)
|
||||||
{
|
{
|
||||||
|
@ -692,22 +501,16 @@ void PromptWidget::killWord()
|
||||||
_promptEndPos -= cnt;
|
_promptEndPos -= cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void PromptWidget::textSelectAll()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
string PromptWidget::getLine()
|
string PromptWidget::getLine()
|
||||||
{
|
{
|
||||||
#if defined(PSEUDO_CUT_COPY_PASTE)
|
#if defined(PSEUDO_CUT_COPY_PASTE)
|
||||||
assert(_promptEndPos >= _promptStartPos);
|
assert(_promptEndPos >= _promptStartPos);
|
||||||
int len = _promptEndPos - _promptStartPos;
|
|
||||||
string text;
|
string text;
|
||||||
|
|
||||||
// Copy current line to text
|
// Copy current line to text
|
||||||
for(int i = 0; i < len; i++)
|
for(int i = _promptStartPos; i < _promptEndPos; i++)
|
||||||
text += buffer(_promptStartPos + i) & 0x7f;
|
text += buffer(i) & 0x7f;
|
||||||
|
|
||||||
return text;
|
return text;
|
||||||
#endif
|
#endif
|
||||||
|
@ -717,14 +520,14 @@ string PromptWidget::getLine()
|
||||||
void PromptWidget::textCut()
|
void PromptWidget::textCut()
|
||||||
{
|
{
|
||||||
#if defined(PSEUDO_CUT_COPY_PASTE)
|
#if defined(PSEUDO_CUT_COPY_PASTE)
|
||||||
string text = getLine();
|
textCopy();
|
||||||
|
|
||||||
instance().eventHandler().copyText(text);
|
|
||||||
|
|
||||||
// Remove the current line
|
// Remove the current line
|
||||||
_currentPos = _promptStartPos;
|
_currentPos = _promptStartPos;
|
||||||
killLine(1); // to end of line
|
killLine(1); // to end of line
|
||||||
_promptEndPos = _currentPos;
|
_promptEndPos = _currentPos;
|
||||||
|
|
||||||
|
resetFunctions();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -751,65 +554,95 @@ void PromptWidget::textPaste()
|
||||||
instance().eventHandler().pasteText(text);
|
instance().eventHandler().pasteText(text);
|
||||||
print(text);
|
print(text);
|
||||||
_promptEndPos = _currentPos;
|
_promptEndPos = _currentPos;
|
||||||
|
|
||||||
|
resetFunctions();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
int PromptWidget::historyDir(int& index, int direction)
|
||||||
|
{
|
||||||
|
index += direction;
|
||||||
|
if(index < 0)
|
||||||
|
index += int(_history.size());
|
||||||
|
else
|
||||||
|
index %= int(_history.size());
|
||||||
|
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void PromptWidget::historyAdd(const string& entry)
|
||||||
|
{
|
||||||
|
if(_historyIndex >= int(_history.size()))
|
||||||
|
_history.push_back(entry);
|
||||||
|
else
|
||||||
|
_history[_historyIndex] = entry;
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void PromptWidget::addToHistory(const char* str)
|
void PromptWidget::addToHistory(const char* str)
|
||||||
{
|
{
|
||||||
#if defined(BSPF_WINDOWS)
|
// Do not add duplicates, remove old duplicate
|
||||||
strncpy_s(_history[_historyIndex], kLineBufferSize, str, kLineBufferSize - 1);
|
if(_history.size())
|
||||||
#else
|
|
||||||
strncpy(_history[_historyIndex], str, kLineBufferSize - 1);
|
|
||||||
#endif
|
|
||||||
_historyIndex = (_historyIndex + 1) % kHistorySize;
|
|
||||||
_historyLine = 0;
|
|
||||||
|
|
||||||
if (_historySize < kHistorySize)
|
|
||||||
_historySize++;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0 // FIXME
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
int PromptWidget::compareHistory(const char *histLine)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void PromptWidget::historyScroll(int direction)
|
|
||||||
{
|
|
||||||
if (_historySize == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (_historyLine == 0 && direction > 0)
|
|
||||||
{
|
{
|
||||||
int i;
|
int i = _historyIndex;
|
||||||
for (i = 0; i < _promptEndPos - _promptStartPos; i++)
|
int historyEnd = _historyIndex % _history.size();
|
||||||
_history[_historyIndex][i] = buffer(_promptStartPos + i); //FIXME: int to char??
|
|
||||||
|
|
||||||
_history[_historyIndex][i] = '\0';
|
do
|
||||||
}
|
{
|
||||||
|
historyDir(i, -1);
|
||||||
|
|
||||||
// Advance to the next line in the history
|
if(!BSPF::compareIgnoreCase(_history[i], str))
|
||||||
int line = _historyLine + direction;
|
{
|
||||||
if(line < 0)
|
int j = i, prevJ;
|
||||||
line += _historySize + 1;
|
|
||||||
line %= (_historySize + 1);
|
|
||||||
|
|
||||||
// If they press arrow-up with anything in the buffer, search backwards
|
do
|
||||||
// in the history.
|
{
|
||||||
/*
|
prevJ = j;
|
||||||
if(direction < 0 && _currentPos > _promptStartPos) {
|
historyDir(j, +1);
|
||||||
for(;line > 0; line--) {
|
_history[prevJ] = _history[j];
|
||||||
if(compareHistory(_history[line]) == 0)
|
}
|
||||||
|
while(j != historyEnd);
|
||||||
|
|
||||||
|
historyDir(_historyIndex, -1);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
while(i != historyEnd);
|
||||||
}
|
}
|
||||||
*/
|
historyAdd(str);
|
||||||
|
_historyLine = 0; // reset history scroll
|
||||||
|
_historyIndex = (_historyIndex + 1) % kHistorySize;
|
||||||
|
}
|
||||||
|
|
||||||
_historyLine = line;
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
bool PromptWidget::historyScroll(int direction)
|
||||||
|
{
|
||||||
|
if(_history.size() == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// add current input temporarily to history
|
||||||
|
if(_historyLine == 0)
|
||||||
|
historyAdd(getLine());
|
||||||
|
|
||||||
|
// Advance to the next/prev line in the history
|
||||||
|
historyDir(_historyLine, direction);
|
||||||
|
|
||||||
|
// Search the history using the original input
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int idx = _historyLine
|
||||||
|
? (_historyIndex - _historyLine + _history.size()) % int(_history.size())
|
||||||
|
: _historyIndex;
|
||||||
|
|
||||||
|
if(BSPF::startsWithIgnoreCase(_history[idx], _history[_historyIndex]))
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Advance to the next/prev line in the history
|
||||||
|
historyDir(_historyLine, direction);
|
||||||
|
}
|
||||||
|
while(_historyLine); // If _historyLine == 0, nothing was found
|
||||||
|
|
||||||
// Remove the current user text
|
// Remove the current user text
|
||||||
_currentPos = _promptStartPos;
|
_currentPos = _promptStartPos;
|
||||||
|
@ -819,21 +652,145 @@ void PromptWidget::historyScroll(int direction)
|
||||||
scrollToCurrent();
|
scrollToCurrent();
|
||||||
|
|
||||||
// Print the text from the history
|
// Print the text from the history
|
||||||
int idx;
|
int idx = _historyLine
|
||||||
if (_historyLine > 0)
|
? (_historyIndex - _historyLine + _history.size()) % int(_history.size())
|
||||||
idx = (_historyIndex - _historyLine + _historySize) % _historySize;
|
: _historyIndex;
|
||||||
else
|
|
||||||
idx = _historyIndex;
|
|
||||||
|
|
||||||
for (int i = 0; i < kLineBufferSize && _history[idx][i] != '\0'; i++)
|
for(int i = 0; i < kLineBufferSize && _history[idx][i] != '\0'; i++)
|
||||||
putcharIntern(_history[idx][i]);
|
putcharIntern(_history[idx][i]);
|
||||||
|
|
||||||
_promptEndPos = _currentPos;
|
_promptEndPos = _currentPos;
|
||||||
|
|
||||||
// Ensure once more the caret is visible (in case of very long history entries)
|
// Ensure once more the caret is visible (in case of very long history entries)
|
||||||
scrollToCurrent();
|
scrollToCurrent();
|
||||||
|
|
||||||
setDirty();
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
bool PromptWidget::execute()
|
||||||
|
{
|
||||||
|
nextLine();
|
||||||
|
|
||||||
|
assert(_promptEndPos >= _promptStartPos);
|
||||||
|
int len = _promptEndPos - _promptStartPos;
|
||||||
|
|
||||||
|
if(len > 0)
|
||||||
|
{
|
||||||
|
// Copy the user input to command
|
||||||
|
string command = getLine();
|
||||||
|
|
||||||
|
// Add the input to the history
|
||||||
|
addToHistory(command.c_str());
|
||||||
|
|
||||||
|
// Pass the command to the debugger, and print the result
|
||||||
|
string result = instance().debugger().run(command);
|
||||||
|
|
||||||
|
// This is a bit of a hack
|
||||||
|
// Certain commands remove the debugger dialog from underneath us,
|
||||||
|
// so we shouldn't print any messages
|
||||||
|
// Those commands will return '_EXIT_DEBUGGER' as their result
|
||||||
|
if(result == "_EXIT_DEBUGGER")
|
||||||
|
{
|
||||||
|
_exitedEarly = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if(result == "_NO_PROMPT")
|
||||||
|
return true;
|
||||||
|
else if(result != "")
|
||||||
|
print(result + "\n");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
bool PromptWidget::autoComplete(int direction)
|
||||||
|
{
|
||||||
|
// Tab completion: we complete either commands or labels, but not
|
||||||
|
// both at once.
|
||||||
|
|
||||||
|
if(_currentPos <= _promptStartPos)
|
||||||
|
return false; // no input
|
||||||
|
|
||||||
|
scrollToCurrent();
|
||||||
|
|
||||||
|
int len = _promptEndPos - _promptStartPos;
|
||||||
|
|
||||||
|
if(_tabCount != -1)
|
||||||
|
len = int(strlen(_inputStr));
|
||||||
|
if(len > kLineBufferSize - 1)
|
||||||
|
len = kLineBufferSize - 1;
|
||||||
|
|
||||||
|
int lastDelimPos = -1;
|
||||||
|
char delimiter = '\0';
|
||||||
|
|
||||||
|
for(int i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
// copy the input at first tab press only
|
||||||
|
if(_tabCount == -1)
|
||||||
|
_inputStr[i] = buffer(_promptStartPos + i) & 0x7f;
|
||||||
|
// whitespace characters
|
||||||
|
if(strchr("{*@<> =[]()+-/&|!^~%", _inputStr[i]))
|
||||||
|
{
|
||||||
|
lastDelimPos = i;
|
||||||
|
delimiter = _inputStr[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(_tabCount == -1)
|
||||||
|
_inputStr[len] = '\0';
|
||||||
|
|
||||||
|
StringList list;
|
||||||
|
|
||||||
|
if(lastDelimPos == -1)
|
||||||
|
// no delimiters, do only command completion:
|
||||||
|
instance().debugger().parser().getCompletions(_inputStr, list);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
size_t strLen = len - lastDelimPos - 1;
|
||||||
|
// do not show ALL commands/labels without any filter as it makes no sense
|
||||||
|
if(strLen > 0)
|
||||||
|
{
|
||||||
|
// Special case for 'help' command
|
||||||
|
if(BSPF::startsWithIgnoreCase(_inputStr, "help"))
|
||||||
|
instance().debugger().parser().getCompletions(_inputStr + lastDelimPos + 1, list);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// we got a delimiter, so this must be a label or a function
|
||||||
|
const Debugger& dbg = instance().debugger();
|
||||||
|
|
||||||
|
dbg.cartDebug().getCompletions(_inputStr + lastDelimPos + 1, list);
|
||||||
|
dbg.getCompletions(_inputStr + lastDelimPos + 1, list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if(list.size() < 1)
|
||||||
|
return false;
|
||||||
|
sort(list.begin(), list.end());
|
||||||
|
|
||||||
|
if(direction < 0)
|
||||||
|
{
|
||||||
|
if(--_tabCount < 0)
|
||||||
|
_tabCount = int(list.size()) - 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
_tabCount = (_tabCount + 1) % list.size();
|
||||||
|
|
||||||
|
nextLine();
|
||||||
|
_currentPos = _promptStartPos;
|
||||||
|
killLine(1); // kill whole line
|
||||||
|
|
||||||
|
// start with-autocompleted, fixed string...
|
||||||
|
for(int i = 0; i < lastDelimPos; i++)
|
||||||
|
putcharIntern(_inputStr[i]);
|
||||||
|
if(lastDelimPos > 0)
|
||||||
|
putcharIntern(delimiter);
|
||||||
|
|
||||||
|
// ...and add current autocompletion string
|
||||||
|
print(list[_tabCount]);
|
||||||
|
putcharIntern(' ');
|
||||||
|
_promptEndPos = _currentPos;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -1000,30 +957,6 @@ string PromptWidget::saveBuffer(const FilesystemNode& file)
|
||||||
return "unable to save session";
|
return "unable to save session";
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
string PromptWidget::getCompletionPrefix(const StringList& completions)
|
|
||||||
{
|
|
||||||
// Find the number of characters matching for each of the completions provided
|
|
||||||
for(uInt32 len = 1;; ++len)
|
|
||||||
{
|
|
||||||
for(uInt32 i = 0; i < completions.size(); ++i)
|
|
||||||
{
|
|
||||||
string s1 = completions[i];
|
|
||||||
if(s1.length() < len)
|
|
||||||
{
|
|
||||||
return s1.substr(0, len - 1);
|
|
||||||
}
|
|
||||||
string find = s1.substr(0, len);
|
|
||||||
|
|
||||||
for(uInt32 j = i + 1; j < completions.size(); ++j)
|
|
||||||
{
|
|
||||||
if(!BSPF::startsWithIgnoreCase(completions[j], find))
|
|
||||||
return s1.substr(0, len - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void PromptWidget::clearScreen()
|
void PromptWidget::clearScreen()
|
||||||
{
|
{
|
||||||
|
@ -1036,4 +969,21 @@ void PromptWidget::clearScreen()
|
||||||
|
|
||||||
if(!_firstTime)
|
if(!_firstTime)
|
||||||
updateScrollBuffer();
|
updateScrollBuffer();
|
||||||
|
|
||||||
|
resetFunctions();
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void PromptWidget::clearHistory()
|
||||||
|
{
|
||||||
|
_history.clear();
|
||||||
|
_historyIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void PromptWidget::resetFunctions()
|
||||||
|
{
|
||||||
|
// reset special functions
|
||||||
|
_tabCount = -1;
|
||||||
|
_historyLine = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,18 +42,22 @@ class PromptWidget : public Widget, public CommandSender
|
||||||
~PromptWidget() override = default;
|
~PromptWidget() override = default;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ATTRIBUTE_FMT_PRINTF int printf(const char* format, ...);
|
|
||||||
ATTRIBUTE_FMT_PRINTF int vprintf(const char* format, va_list argptr);
|
|
||||||
void print(const string& str);
|
void print(const string& str);
|
||||||
void printPrompt();
|
void printPrompt();
|
||||||
string saveBuffer(const FilesystemNode& file);
|
string saveBuffer(const FilesystemNode& file);
|
||||||
|
|
||||||
// Clear screen and erase all history
|
// Clear screen
|
||||||
void clearScreen();
|
void clearScreen();
|
||||||
|
// Erase all history
|
||||||
|
void clearHistory();
|
||||||
|
|
||||||
void addToHistory(const char *str);
|
void addToHistory(const char *str);
|
||||||
|
|
||||||
|
bool isLoaded() const { return !_firstTime; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
ATTRIBUTE_FMT_PRINTF int printf(const char* format, ...);
|
||||||
|
ATTRIBUTE_FMT_PRINTF int vprintf(const char* format, va_list argptr);
|
||||||
int& buffer(int idx) { return _buffer[idx % kBufferSize]; }
|
int& buffer(int idx) { return _buffer[idx % kBufferSize]; }
|
||||||
|
|
||||||
void drawWidget(bool hilite) override;
|
void drawWidget(bool hilite) override;
|
||||||
|
@ -64,21 +68,22 @@ class PromptWidget : public Widget, public CommandSender
|
||||||
void scrollToCurrent();
|
void scrollToCurrent();
|
||||||
|
|
||||||
// Line editing
|
// Line editing
|
||||||
void specialKeys(StellaKey key);
|
|
||||||
void nextLine();
|
void nextLine();
|
||||||
void killChar(int direction);
|
void killChar(int direction);
|
||||||
void killLine(int direction);
|
void killLine(int direction);
|
||||||
void killWord();
|
void killWord();
|
||||||
|
|
||||||
// Clipboard
|
// Clipboard
|
||||||
void textSelectAll();
|
|
||||||
string getLine();
|
string getLine();
|
||||||
void textCut();
|
void textCut();
|
||||||
void textCopy();
|
void textCopy();
|
||||||
void textPaste();
|
void textPaste();
|
||||||
|
|
||||||
// History
|
// History
|
||||||
void historyScroll(int direction);
|
bool historyScroll(int direction);
|
||||||
|
|
||||||
|
bool execute();
|
||||||
|
bool autoComplete(int direction);
|
||||||
|
|
||||||
void handleMouseDown(int x, int y, MouseButton b, int clickCount) override;
|
void handleMouseDown(int x, int y, MouseButton b, int clickCount) override;
|
||||||
void handleMouseWheel(int x, int y, int direction) override;
|
void handleMouseWheel(int x, int y, int direction) override;
|
||||||
|
@ -92,15 +97,13 @@ class PromptWidget : public Widget, public CommandSender
|
||||||
bool wantsFocus() const override { return true; }
|
bool wantsFocus() const override { return true; }
|
||||||
void loadConfig() override;
|
void loadConfig() override;
|
||||||
|
|
||||||
private:
|
void resetFunctions();
|
||||||
// Get the longest prefix (initially 's') that is in every string in the list
|
|
||||||
string getCompletionPrefix(const StringList& completions);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum {
|
enum {
|
||||||
kBufferSize = 32768,
|
kBufferSize = 32768,
|
||||||
kLineBufferSize = 256,
|
kLineBufferSize = 256,
|
||||||
kHistorySize = 20
|
kHistorySize = 1000
|
||||||
};
|
};
|
||||||
|
|
||||||
int _buffer[kBufferSize]; // NOLINT (will be rewritten soon)
|
int _buffer[kBufferSize]; // NOLINT (will be rewritten soon)
|
||||||
|
@ -118,19 +121,20 @@ class PromptWidget : public Widget, public CommandSender
|
||||||
|
|
||||||
ScrollBarWidget* _scrollBar;
|
ScrollBarWidget* _scrollBar;
|
||||||
|
|
||||||
char _history[kHistorySize][kLineBufferSize]; // NOLINT (will be rewritten soon)
|
std::vector<string> _history;
|
||||||
int _historySize;
|
int _historyIndex{0};
|
||||||
int _historyIndex;
|
int _historyLine{0};
|
||||||
int _historyLine;
|
int _tabCount{-1};
|
||||||
|
char _inputStr[kLineBufferSize];
|
||||||
|
|
||||||
int _kConsoleCharWidth, _kConsoleCharHeight, _kConsoleLineHeight;
|
int _kConsoleCharWidth, _kConsoleCharHeight, _kConsoleLineHeight;
|
||||||
|
|
||||||
bool _inverse;
|
bool _inverse{false};
|
||||||
bool _makeDirty;
|
bool _firstTime{true};
|
||||||
bool _firstTime;
|
bool _exitedEarly{false};
|
||||||
bool _exitedEarly;
|
|
||||||
|
|
||||||
// int compareHistory(const char *histLine);
|
int historyDir(int& index, int direction);
|
||||||
|
void historyAdd(const string& entry);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Following constructors and assignment operators not supported
|
// Following constructors and assignment operators not supported
|
||||||
|
|
|
@ -90,14 +90,14 @@ RiotWidget::RiotWidget(GuiObject* boss, const GUI::Font& lfont,
|
||||||
// SWCHA bits in 'peek' mode
|
// SWCHA bits in 'peek' mode
|
||||||
xpos = 10; ypos += lineHeight + 5;
|
xpos = 10; ypos += lineHeight + 5;
|
||||||
labels.clear();
|
labels.clear();
|
||||||
labels.push_back("P0 right");
|
labels.push_back("Left right");
|
||||||
labels.push_back("P0 left");
|
labels.push_back("Left left");
|
||||||
labels.push_back("P0 down");
|
labels.push_back("Left down");
|
||||||
labels.push_back("P0 up");
|
labels.push_back("Left up");
|
||||||
labels.push_back("P1 right");
|
labels.push_back("Right right");
|
||||||
labels.push_back("P1 left");
|
labels.push_back("Right left");
|
||||||
labels.push_back("P1 down");
|
labels.push_back("Right down");
|
||||||
labels.push_back("P1 up");
|
labels.push_back("Right up");
|
||||||
CREATE_IO_REGS("SWCHA(R)", mySWCHAReadBits, kSWCHARBitsID, true)
|
CREATE_IO_REGS("SWCHA(R)", mySWCHAReadBits, kSWCHARBitsID, true)
|
||||||
|
|
||||||
// SWCHB bits in 'poke' mode
|
// SWCHB bits in 'poke' mode
|
||||||
|
@ -112,8 +112,8 @@ RiotWidget::RiotWidget(GuiObject* boss, const GUI::Font& lfont,
|
||||||
// SWCHB bits in 'peek' mode
|
// SWCHB bits in 'peek' mode
|
||||||
xpos = 10; ypos += lineHeight + 5;
|
xpos = 10; ypos += lineHeight + 5;
|
||||||
labels.clear();
|
labels.clear();
|
||||||
labels.push_back("P1 difficulty");
|
labels.push_back("Right difficulty");
|
||||||
labels.push_back("P0 difficulty");
|
labels.push_back("Left difficulty");
|
||||||
labels.push_back("");
|
labels.push_back("");
|
||||||
labels.push_back("");
|
labels.push_back("");
|
||||||
labels.push_back("Color/B+W");
|
labels.push_back("Color/B+W");
|
||||||
|
@ -210,19 +210,19 @@ RiotWidget::RiotWidget(GuiObject* boss, const GUI::Font& lfont,
|
||||||
|
|
||||||
// PO & P1 difficulty switches
|
// PO & P1 difficulty switches
|
||||||
int pwidth = lfont.getStringWidth("B/easy");
|
int pwidth = lfont.getStringWidth("B/easy");
|
||||||
lwidth = lfont.getStringWidth("P0 Diff ");
|
lwidth = lfont.getStringWidth("Right Diff ");
|
||||||
xpos = col; ypos += 2 * lineHeight;
|
xpos = col; ypos += 2 * lineHeight;
|
||||||
int col2_ypos = ypos;
|
int col2_ypos = ypos;
|
||||||
items.clear();
|
items.clear();
|
||||||
VarList::push_back(items, "B/easy", "b");
|
VarList::push_back(items, "B/easy", "b");
|
||||||
VarList::push_back(items, "A/hard", "a");
|
VarList::push_back(items, "A/hard", "a");
|
||||||
myP0Diff = new PopUpWidget(boss, lfont, xpos, ypos, pwidth, lineHeight, items,
|
myP0Diff = new PopUpWidget(boss, lfont, xpos, ypos, pwidth, lineHeight, items,
|
||||||
"P0 Diff ", lwidth, kP0DiffChanged);
|
"Left Diff ", lwidth, kP0DiffChanged);
|
||||||
myP0Diff->setTarget(this);
|
myP0Diff->setTarget(this);
|
||||||
addFocusWidget(myP0Diff);
|
addFocusWidget(myP0Diff);
|
||||||
ypos += myP0Diff->getHeight() + 5;
|
ypos += myP0Diff->getHeight() + 5;
|
||||||
myP1Diff = new PopUpWidget(boss, lfont, xpos, ypos, pwidth, lineHeight, items,
|
myP1Diff = new PopUpWidget(boss, lfont, xpos, ypos, pwidth, lineHeight, items,
|
||||||
"P1 Diff ", lwidth, kP1DiffChanged);
|
"Right Diff ", lwidth, kP1DiffChanged);
|
||||||
myP1Diff->setTarget(this);
|
myP1Diff->setTarget(this);
|
||||||
addFocusWidget(myP1Diff);
|
addFocusWidget(myP1Diff);
|
||||||
|
|
||||||
|
|
|
@ -304,7 +304,7 @@ bool RomListWidget::handleKeyDown(StellaKey key, StellaMod mod)
|
||||||
{
|
{
|
||||||
// Ignore all Alt-mod keys
|
// Ignore all Alt-mod keys
|
||||||
if(StellaModTest::isAlt(mod))
|
if(StellaModTest::isAlt(mod))
|
||||||
return true;
|
return false;
|
||||||
|
|
||||||
bool handled = true;
|
bool handled = true;
|
||||||
int oldSelectedItem = _selectedItem;
|
int oldSelectedItem = _selectedItem;
|
||||||
|
|
|
@ -137,7 +137,7 @@ void TiaOutputWidget::handleCommand(CommandSender* sender, int cmd, int data, in
|
||||||
lines += instance().console().tia().scanlinesLastFrame();
|
lines += instance().console().tia().scanlinesLastFrame();
|
||||||
if(lines > 0)
|
if(lines > 0)
|
||||||
{
|
{
|
||||||
command << "scanline #" << lines;
|
command << "scanLine #" << lines;
|
||||||
string message = instance().debugger().parser().run(command.str());
|
string message = instance().debugger().parser().run(command.str());
|
||||||
instance().frameBuffer().showTextMessage(message);
|
instance().frameBuffer().showTextMessage(message);
|
||||||
}
|
}
|
||||||
|
@ -146,7 +146,7 @@ void TiaOutputWidget::handleCommand(CommandSender* sender, int cmd, int data, in
|
||||||
{
|
{
|
||||||
ostringstream command;
|
ostringstream command;
|
||||||
int scanline = myClickY + startLine;
|
int scanline = myClickY + startLine;
|
||||||
command << "breakif _scan==#" << scanline;
|
command << "breakIf _scan==#" << scanline;
|
||||||
string message = instance().debugger().parser().run(command.str());
|
string message = instance().debugger().parser().run(command.str());
|
||||||
instance().frameBuffer().showTextMessage(message);
|
instance().frameBuffer().showTextMessage(message);
|
||||||
}
|
}
|
||||||
|
@ -157,7 +157,7 @@ void TiaOutputWidget::handleCommand(CommandSender* sender, int cmd, int data, in
|
||||||
}
|
}
|
||||||
else if(rmb == "snap")
|
else if(rmb == "snap")
|
||||||
{
|
{
|
||||||
instance().debugger().parser().run("savesnap");
|
instance().debugger().parser().run("saveSnap");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,7 +92,7 @@ bool ToggleWidget::handleKeyDown(StellaKey key, StellaMod mod)
|
||||||
{
|
{
|
||||||
// Ignore all mod keys
|
// Ignore all mod keys
|
||||||
if(StellaModTest::isControl(mod) || StellaModTest::isAlt(mod))
|
if(StellaModTest::isControl(mod) || StellaModTest::isAlt(mod))
|
||||||
return true;
|
return false;
|
||||||
|
|
||||||
bool handled = true;
|
bool handled = true;
|
||||||
bool dirty = false, toggle = false;
|
bool dirty = false, toggle = false;
|
||||||
|
|
|
@ -14,6 +14,7 @@ MODULE_OBJS := \
|
||||||
src/debugger/gui/Cart4A50Widget.o \
|
src/debugger/gui/Cart4A50Widget.o \
|
||||||
src/debugger/gui/Cart4KSCWidget.o \
|
src/debugger/gui/Cart4KSCWidget.o \
|
||||||
src/debugger/gui/Cart4KWidget.o \
|
src/debugger/gui/Cart4KWidget.o \
|
||||||
|
src/debugger/gui/CartARMWidget.o \
|
||||||
src/debugger/gui/CartARWidget.o \
|
src/debugger/gui/CartARWidget.o \
|
||||||
src/debugger/gui/CartBFSCWidget.o \
|
src/debugger/gui/CartBFSCWidget.o \
|
||||||
src/debugger/gui/CartBFWidget.o \
|
src/debugger/gui/CartBFWidget.o \
|
||||||
|
|
|
@ -23,13 +23,13 @@ BoosterGrip::BoosterGrip(Jack jack, const Event& event, const System& system)
|
||||||
{
|
{
|
||||||
if(myJack == Jack::Left)
|
if(myJack == Jack::Left)
|
||||||
{
|
{
|
||||||
myTriggerEvent = Event::JoystickZeroFire5;
|
myTriggerEvent = Event::LeftJoystickFire5;
|
||||||
myBoosterEvent = Event::JoystickZeroFire9;
|
myBoosterEvent = Event::LeftJoystickFire9;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
myTriggerEvent = Event::JoystickOneFire5;
|
myTriggerEvent = Event::RightJoystickFire5;
|
||||||
myBoosterEvent = Event::JoystickOneFire9;
|
myBoosterEvent = Event::RightJoystickFire9;
|
||||||
}
|
}
|
||||||
|
|
||||||
setPin(AnalogPin::Five, AnalogReadout::disconnect());
|
setPin(AnalogPin::Five, AnalogReadout::disconnect());
|
||||||
|
|
|
@ -125,6 +125,12 @@ class Cartridge3EPlus: public Cartridge3E
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/**
|
||||||
|
Checks if startup bank randomization is enabled. For this scheme,
|
||||||
|
randomization is not supported (see above).
|
||||||
|
*/
|
||||||
|
bool randomStartBank() const override { return false; }
|
||||||
|
|
||||||
bool checkSwitchBank(uInt16 address, uInt8 value) override;
|
bool checkSwitchBank(uInt16 address, uInt8 value) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -0,0 +1,127 @@
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// SSSS tt lll lll
|
||||||
|
// SS SS tt ll ll
|
||||||
|
// SS tttttt eeee ll ll aaaa
|
||||||
|
// SSSS tt ee ee ll ll aa
|
||||||
|
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
|
||||||
|
// SS SS tt ee ll ll aa aa
|
||||||
|
// SSSS ttt eeeee llll llll aaaaa
|
||||||
|
//
|
||||||
|
// Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony
|
||||||
|
// and the Stella Team
|
||||||
|
//
|
||||||
|
// See the file "License.txt" for information on usage and redistribution of
|
||||||
|
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
#include "System.hxx"
|
||||||
|
#include "Settings.hxx"
|
||||||
|
#include "CartARM.hxx"
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
CartridgeARM::CartridgeARM(const string& md5, const Settings& settings)
|
||||||
|
: Cartridge(settings, md5)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void CartridgeARM::setInitialState()
|
||||||
|
{
|
||||||
|
bool devSettings = mySettings.getBool("dev.settings");
|
||||||
|
|
||||||
|
if(devSettings)
|
||||||
|
{
|
||||||
|
myIncCycles = mySettings.getBool("dev.thumb.inccycles");
|
||||||
|
myThumbEmulator->setChipType(static_cast<Thumbulator::ChipType>(mySettings.getInt("dev.thumb.chiptype")));
|
||||||
|
myThumbEmulator->setMamMode(static_cast<Thumbulator::MamModeType>(mySettings.getInt("dev.thumb.mammode")));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
myIncCycles = false;
|
||||||
|
}
|
||||||
|
enableCycleCount(devSettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void CartridgeARM::consoleChanged(ConsoleTiming timing)
|
||||||
|
{
|
||||||
|
myThumbEmulator->setConsoleTiming(timing);
|
||||||
|
|
||||||
|
constexpr double NTSC = 1193191.66666667; // NTSC 6507 clock rate
|
||||||
|
constexpr double PAL = 1182298; // PAL 6507 clock rate
|
||||||
|
constexpr double SECAM = 1187500; // SECAM 6507 clock rate
|
||||||
|
|
||||||
|
switch(timing)
|
||||||
|
{
|
||||||
|
case ConsoleTiming::ntsc: myClockRate = NTSC; break;
|
||||||
|
case ConsoleTiming::pal: myClockRate = PAL; break;
|
||||||
|
case ConsoleTiming::secam: myClockRate = SECAM; break;
|
||||||
|
default: break; // satisfy compiler
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void CartridgeARM::updateCycles(int cycles)
|
||||||
|
{
|
||||||
|
if(myIncCycles)
|
||||||
|
mySystem->incrementCycles(cycles);
|
||||||
|
#ifdef DEBUGGER_SUPPORT
|
||||||
|
myPrevStats = myStats;
|
||||||
|
myStats = myThumbEmulator->stats();
|
||||||
|
myPrevCycles = myCycles;
|
||||||
|
myCycles = myThumbEmulator->cycles();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void CartridgeARM::incCycles(bool enable)
|
||||||
|
{
|
||||||
|
myIncCycles = enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void CartridgeARM::cycleFactor(double factor)
|
||||||
|
{
|
||||||
|
myThumbEmulator->cycleFactor(factor);
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
bool CartridgeARM::save(Serializer& out) const
|
||||||
|
{
|
||||||
|
#ifdef DEBUGGER_SUPPORT
|
||||||
|
try
|
||||||
|
{
|
||||||
|
out.putInt(myPrevCycles);
|
||||||
|
out.putInt(myPrevStats.instructions);
|
||||||
|
out.putInt(myCycles);
|
||||||
|
out.putInt(myStats.instructions);
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
cerr << "ERROR: CartridgeARM::save" << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
bool CartridgeARM::load(Serializer& in)
|
||||||
|
{
|
||||||
|
#ifdef DEBUGGER_SUPPORT
|
||||||
|
try
|
||||||
|
{
|
||||||
|
myPrevCycles = in.getInt();
|
||||||
|
myPrevStats.instructions = in.getInt();
|
||||||
|
myCycles = in.getInt();
|
||||||
|
myStats.instructions = in.getInt();
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
cerr << "ERROR: CartridgeARM::load" << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -0,0 +1,113 @@
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// SSSS tt lll lll
|
||||||
|
// SS SS tt ll ll
|
||||||
|
// SS tttttt eeee ll ll aaaa
|
||||||
|
// SSSS tt ee ee ll ll aa
|
||||||
|
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
|
||||||
|
// SS SS tt ee ll ll aa aa
|
||||||
|
// SSSS ttt eeeee llll llll aaaaa
|
||||||
|
//
|
||||||
|
// Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony
|
||||||
|
// and the Stella Team
|
||||||
|
//
|
||||||
|
// See the file "License.txt" for information on usage and redistribution of
|
||||||
|
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
#ifndef CARTRIDGE_ARM_HXX
|
||||||
|
#define CARTRIDGE_ARM_HXX
|
||||||
|
|
||||||
|
#include "Thumbulator.hxx"
|
||||||
|
#include "Cart.hxx"
|
||||||
|
|
||||||
|
/**
|
||||||
|
Abstract base class for ARM carts.
|
||||||
|
|
||||||
|
@author Thomas Jentzsch
|
||||||
|
*/
|
||||||
|
class CartridgeARM : public Cartridge
|
||||||
|
{
|
||||||
|
friend class CartridgeARMWidget;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CartridgeARM(const string& md5, const Settings& settings);
|
||||||
|
~CartridgeARM() override = default;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/**
|
||||||
|
Notification method invoked by the system when the console type
|
||||||
|
has changed. We need this to inform the Thumbulator that the
|
||||||
|
timing has changed.
|
||||||
|
|
||||||
|
@param timing Enum representing the new console type
|
||||||
|
*/
|
||||||
|
void consoleChanged(ConsoleTiming timing) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Save the current state of this cart to the given Serializer.
|
||||||
|
|
||||||
|
@param out The Serializer object to use
|
||||||
|
@return False on any errors, else true
|
||||||
|
*/
|
||||||
|
bool save(Serializer& out) const override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Load the current state of this cart from the given Serializer.
|
||||||
|
|
||||||
|
@param in The Serializer object to use
|
||||||
|
@return False on any errors, else true
|
||||||
|
*/
|
||||||
|
bool load(Serializer& in) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sets the initial state of the MAM mode
|
||||||
|
*/
|
||||||
|
virtual void setInitialState();
|
||||||
|
|
||||||
|
void enableCycleCount(bool enable) const { myThumbEmulator->enableCycleCount(enable); }
|
||||||
|
// Get number of memory accesses of last and last but one ARM runs.
|
||||||
|
void updateCycles(int cycles);
|
||||||
|
#ifdef DEBUGGER_SUPPORT
|
||||||
|
const Thumbulator::Stats& stats() const { return myStats; }
|
||||||
|
const Thumbulator::Stats& prevStats() const { return myPrevStats; }
|
||||||
|
uInt32 cycles() const { return myCycles; }
|
||||||
|
uInt32 prevCycles() const { return myPrevCycles; }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void incCycles(bool enable);
|
||||||
|
void cycleFactor(double factor);
|
||||||
|
double cycleFactor() const { return myThumbEmulator->cycleFactor(); }
|
||||||
|
Thumbulator::ChipPropsType setChipType(Thumbulator::ChipType chipType) {
|
||||||
|
return myThumbEmulator->setChipType(chipType);
|
||||||
|
}
|
||||||
|
void lockMamMode(bool lock) { myThumbEmulator->lockMamMode(lock); }
|
||||||
|
void setMamMode(Thumbulator::MamModeType mamMode) { myThumbEmulator->setMamMode(mamMode); }
|
||||||
|
Thumbulator::MamModeType mamMode() const { return myThumbEmulator->mamMode(); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Pointer to the Thumb ARM emulator object
|
||||||
|
unique_ptr<Thumbulator> myThumbEmulator;
|
||||||
|
|
||||||
|
// ARM code increases 6507 cycles
|
||||||
|
bool myIncCycles{false};
|
||||||
|
|
||||||
|
// Console clock rate
|
||||||
|
double myClockRate{1193191.66666667};
|
||||||
|
#ifdef DEBUGGER_SUPPORT
|
||||||
|
Thumbulator::Stats myStats{0};
|
||||||
|
Thumbulator::Stats myPrevStats{0};
|
||||||
|
uInt32 myCycles{0};
|
||||||
|
uInt32 myPrevCycles{0};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Following constructors and assignment operators not supported
|
||||||
|
CartridgeARM() = delete;
|
||||||
|
CartridgeARM(const CartridgeARM&) = delete;
|
||||||
|
CartridgeARM(CartridgeARM&&) = delete;
|
||||||
|
CartridgeARM& operator=(const CartridgeARM&) = delete;
|
||||||
|
CartridgeARM& operator=(CartridgeARM&&) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -23,7 +23,6 @@
|
||||||
#include "System.hxx"
|
#include "System.hxx"
|
||||||
#include "M6532.hxx"
|
#include "M6532.hxx"
|
||||||
#include "TIA.hxx"
|
#include "TIA.hxx"
|
||||||
#include "Thumbulator.hxx"
|
|
||||||
#include "CartBUS.hxx"
|
#include "CartBUS.hxx"
|
||||||
#include "exception/FatalEmulationError.hxx"
|
#include "exception/FatalEmulationError.hxx"
|
||||||
|
|
||||||
|
@ -43,7 +42,7 @@
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
CartridgeBUS::CartridgeBUS(const ByteBuffer& image, size_t size,
|
CartridgeBUS::CartridgeBUS(const ByteBuffer& image, size_t size,
|
||||||
const string& md5, const Settings& settings)
|
const string& md5, const Settings& settings)
|
||||||
: Cartridge(settings, md5),
|
: CartridgeARM(md5, settings),
|
||||||
myImage{make_unique<uInt8[]>(32_KB)}
|
myImage{make_unique<uInt8[]>(32_KB)}
|
||||||
{
|
{
|
||||||
// Copy the ROM image into my buffer
|
// Copy the ROM image into my buffer
|
||||||
|
@ -72,6 +71,7 @@ CartridgeBUS::CartridgeBUS(const ByteBuffer& image, size_t size,
|
||||||
0x00000808,
|
0x00000808,
|
||||||
0x40001FDC,
|
0x40001FDC,
|
||||||
devSettings ? settings.getBool("dev.thumb.trapfatal") : false,
|
devSettings ? settings.getBool("dev.thumb.trapfatal") : false,
|
||||||
|
devSettings ? settings.getFloat("dev.thumb.cyclefactor") : 1.0,
|
||||||
Thumbulator::ConfigureFor::BUS,
|
Thumbulator::ConfigureFor::BUS,
|
||||||
this);
|
this);
|
||||||
|
|
||||||
|
@ -112,12 +112,8 @@ void CartridgeBUS::setInitialState()
|
||||||
mySTYZeroPageAddress = myJMPoperandAddress = 0;
|
mySTYZeroPageAddress = myJMPoperandAddress = 0;
|
||||||
|
|
||||||
myFastJumpActive = 0;
|
myFastJumpActive = 0;
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
CartridgeARM::setInitialState();
|
||||||
void CartridgeBUS::consoleChanged(ConsoleTiming timing)
|
|
||||||
{
|
|
||||||
myThumbEmulator->setConsoleTiming(timing);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -147,7 +143,7 @@ inline void CartridgeBUS::updateMusicModeDataFetchers()
|
||||||
myAudioCycles = mySystem->cycles();
|
myAudioCycles = mySystem->cycles();
|
||||||
|
|
||||||
// Calculate the number of BUS OSC clocks since the last update
|
// Calculate the number of BUS OSC clocks since the last update
|
||||||
double clocks = ((20000.0 * cycles) / 1193191.66666667) + myFractionalClocks;
|
double clocks = ((20000.0 * cycles) / myClockRate) + myFractionalClocks;
|
||||||
uInt32 wholeClocks = uInt32(clocks);
|
uInt32 wholeClocks = uInt32(clocks);
|
||||||
myFractionalClocks = clocks - double(wholeClocks);
|
myFractionalClocks = clocks - double(wholeClocks);
|
||||||
|
|
||||||
|
@ -167,10 +163,11 @@ inline void CartridgeBUS::callFunction(uInt8 value)
|
||||||
// time for Stella as ARM code "runs in zero 6507 cycles".
|
// time for Stella as ARM code "runs in zero 6507 cycles".
|
||||||
case 255: // call without IRQ driven audio
|
case 255: // call without IRQ driven audio
|
||||||
try {
|
try {
|
||||||
Int32 cycles = Int32(mySystem->cycles() - myARMCycles);
|
uInt32 cycles = uInt32(mySystem->cycles() - myARMCycles);
|
||||||
myARMCycles = mySystem->cycles();
|
|
||||||
|
|
||||||
myThumbEmulator->run(cycles);
|
myARMCycles = mySystem->cycles();
|
||||||
|
myThumbEmulator->run(cycles, value == 254);
|
||||||
|
updateCycles(cycles);
|
||||||
}
|
}
|
||||||
catch(const runtime_error& e) {
|
catch(const runtime_error& e) {
|
||||||
if(!mySystem->autodetectMode())
|
if(!mySystem->autodetectMode())
|
||||||
|
@ -588,6 +585,8 @@ bool CartridgeBUS::save(Serializer& out) const
|
||||||
|
|
||||||
// Indicates if in the middle of a fast jump
|
// Indicates if in the middle of a fast jump
|
||||||
out.putByte(myFastJumpActive);
|
out.putByte(myFastJumpActive);
|
||||||
|
|
||||||
|
CartridgeARM::save(out);
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
|
@ -629,6 +628,8 @@ bool CartridgeBUS::load(Serializer& in)
|
||||||
|
|
||||||
// Indicates if in the middle of a fast jump
|
// Indicates if in the middle of a fast jump
|
||||||
myFastJumpActive = in.getByte();
|
myFastJumpActive = in.getByte();
|
||||||
|
|
||||||
|
CartridgeARM::load(in);
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
|
|
|
@ -19,14 +19,13 @@
|
||||||
#define CARTRIDGE_BUS_HXX
|
#define CARTRIDGE_BUS_HXX
|
||||||
|
|
||||||
class System;
|
class System;
|
||||||
class Thumbulator;
|
|
||||||
#ifdef DEBUGGER_SUPPORT
|
#ifdef DEBUGGER_SUPPORT
|
||||||
#include "CartBUSWidget.hxx"
|
#include "CartBUSWidget.hxx"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "bspf.hxx"
|
#include "bspf.hxx"
|
||||||
#include "Thumbulator.hxx"
|
#include "CartARM.hxx"
|
||||||
#include "Cart.hxx"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Cartridge class used for BUS.
|
Cartridge class used for BUS.
|
||||||
|
@ -41,7 +40,7 @@ class Thumbulator;
|
||||||
@authors: Darrell Spice Jr, Chris Walton, Fred Quimby,
|
@authors: Darrell Spice Jr, Chris Walton, Fred Quimby,
|
||||||
Stephen Anthony, Bradford W. Mott
|
Stephen Anthony, Bradford W. Mott
|
||||||
*/
|
*/
|
||||||
class CartridgeBUS : public Cartridge
|
class CartridgeBUS : public CartridgeARM
|
||||||
{
|
{
|
||||||
friend class CartridgeBUSWidget;
|
friend class CartridgeBUSWidget;
|
||||||
friend class CartridgeRamBUSWidget;
|
friend class CartridgeRamBUSWidget;
|
||||||
|
@ -65,15 +64,6 @@ class CartridgeBUS : public Cartridge
|
||||||
*/
|
*/
|
||||||
void reset() override;
|
void reset() override;
|
||||||
|
|
||||||
/**
|
|
||||||
Notification method invoked by the system when the console type
|
|
||||||
has changed. We need this to inform the Thumbulator that the
|
|
||||||
timing has changed.
|
|
||||||
|
|
||||||
@param timing Enum representing the new console type
|
|
||||||
*/
|
|
||||||
void consoleChanged(ConsoleTiming timing) override;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Install cartridge in the specified system. Invoked by the system
|
Install cartridge in the specified system. Invoked by the system
|
||||||
when the cartridge is attached to it.
|
when the cartridge is attached to it.
|
||||||
|
@ -206,7 +196,7 @@ class CartridgeBUS : public Cartridge
|
||||||
/**
|
/**
|
||||||
Sets the initial state of the DPC pointers and RAM
|
Sets the initial state of the DPC pointers and RAM
|
||||||
*/
|
*/
|
||||||
void setInitialState();
|
void setInitialState() override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Updates any data fetchers in music mode based on the number of
|
Updates any data fetchers in music mode based on the number of
|
||||||
|
@ -233,9 +223,6 @@ class CartridgeBUS : public Cartridge
|
||||||
uInt32 getWaveformSize(uInt8 index) const;
|
uInt32 getWaveformSize(uInt8 index) const;
|
||||||
uInt32 getSample();
|
uInt32 getSample();
|
||||||
|
|
||||||
// Get number of memory accesses of last ARM run.
|
|
||||||
const Thumbulator::Stats& stats() const { return myThumbEmulator->stats(); }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// The 32K ROM image of the cartridge
|
// The 32K ROM image of the cartridge
|
||||||
ByteBuffer myImage;
|
ByteBuffer myImage;
|
||||||
|
@ -255,9 +242,6 @@ class CartridgeBUS : public Cartridge
|
||||||
// $1800 - 2K C Variable & Stack
|
// $1800 - 2K C Variable & Stack
|
||||||
std::array<uInt8, 8_KB> myRAM;
|
std::array<uInt8, 8_KB> myRAM;
|
||||||
|
|
||||||
// Pointer to the Thumb ARM emulator object
|
|
||||||
unique_ptr<Thumbulator> myThumbEmulator;
|
|
||||||
|
|
||||||
// Indicates the offset into the ROM image (aligns to current bank)
|
// Indicates the offset into the ROM image (aligns to current bank)
|
||||||
uInt16 myBankOffset{0};
|
uInt16 myBankOffset{0};
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "System.hxx"
|
#include "System.hxx"
|
||||||
#include "Thumbulator.hxx"
|
|
||||||
#include "CartCDF.hxx"
|
#include "CartCDF.hxx"
|
||||||
#include "TIA.hxx"
|
#include "TIA.hxx"
|
||||||
#include "exception/FatalEmulationError.hxx"
|
#include "exception/FatalEmulationError.hxx"
|
||||||
|
@ -65,7 +64,7 @@ namespace {
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
CartridgeCDF::CartridgeCDF(const ByteBuffer& image, size_t size,
|
CartridgeCDF::CartridgeCDF(const ByteBuffer& image, size_t size,
|
||||||
const string& md5, const Settings& settings)
|
const string& md5, const Settings& settings)
|
||||||
: Cartridge(settings, md5)
|
: CartridgeARM(md5, settings)
|
||||||
{
|
{
|
||||||
// Copy the ROM image into my buffer
|
// Copy the ROM image into my buffer
|
||||||
mySize = std::min(size, 512_KB);
|
mySize = std::min(size, 512_KB);
|
||||||
|
@ -108,6 +107,8 @@ CartridgeCDF::CartridgeCDF(const ByteBuffer& image, size_t size,
|
||||||
static_cast<uInt32>(mySize),
|
static_cast<uInt32>(mySize),
|
||||||
cBase, cStart, cStack,
|
cBase, cStart, cStack,
|
||||||
devSettings ? settings.getBool("dev.thumb.trapfatal") : false,
|
devSettings ? settings.getBool("dev.thumb.trapfatal") : false,
|
||||||
|
devSettings ? static_cast<double>(
|
||||||
|
settings.getFloat("dev.thumb.cyclefactor")) : 1.0,
|
||||||
thumulatorConfiguration(myCDFSubtype),
|
thumulatorConfiguration(myCDFSubtype),
|
||||||
this);
|
this);
|
||||||
|
|
||||||
|
@ -145,12 +146,8 @@ void CartridgeCDF::setInitialState()
|
||||||
|
|
||||||
myBankOffset = myLDAimmediateOperandAddress = myJMPoperandAddress = 0;
|
myBankOffset = myLDAimmediateOperandAddress = myJMPoperandAddress = 0;
|
||||||
myFastJumpActive = myFastJumpStream = 0;
|
myFastJumpActive = myFastJumpStream = 0;
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
CartridgeARM::setInitialState();
|
||||||
void CartridgeCDF::consoleChanged(ConsoleTiming timing)
|
|
||||||
{
|
|
||||||
myThumbEmulator->setConsoleTiming(timing);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -175,7 +172,7 @@ inline void CartridgeCDF::updateMusicModeDataFetchers()
|
||||||
myAudioCycles = mySystem->cycles();
|
myAudioCycles = mySystem->cycles();
|
||||||
|
|
||||||
// Calculate the number of CDF OSC clocks since the last update
|
// Calculate the number of CDF OSC clocks since the last update
|
||||||
double clocks = ((20000.0 * cycles) / 1193191.66666667) + myFractionalClocks;
|
double clocks = ((20000.0 * cycles) / myClockRate) + myFractionalClocks;
|
||||||
uInt32 wholeClocks = uInt32(clocks);
|
uInt32 wholeClocks = uInt32(clocks);
|
||||||
myFractionalClocks = clocks - double(wholeClocks);
|
myFractionalClocks = clocks - double(wholeClocks);
|
||||||
|
|
||||||
|
@ -195,10 +192,11 @@ inline void CartridgeCDF::callFunction(uInt8 value)
|
||||||
// time for Stella as ARM code "runs in zero 6507 cycles".
|
// time for Stella as ARM code "runs in zero 6507 cycles".
|
||||||
case 255: // call without IRQ driven audio
|
case 255: // call without IRQ driven audio
|
||||||
try {
|
try {
|
||||||
Int32 cycles = Int32(mySystem->cycles() - myARMCycles);
|
uInt32 cycles = uInt32(mySystem->cycles() - myARMCycles);
|
||||||
myARMCycles = mySystem->cycles();
|
|
||||||
|
|
||||||
myThumbEmulator->run(cycles);
|
myARMCycles = mySystem->cycles();
|
||||||
|
myThumbEmulator->run(cycles, value == 254);
|
||||||
|
updateCycles(cycles);
|
||||||
}
|
}
|
||||||
catch(const runtime_error& e) {
|
catch(const runtime_error& e) {
|
||||||
if(!mySystem->autodetectMode())
|
if(!mySystem->autodetectMode())
|
||||||
|
@ -560,6 +558,8 @@ bool CartridgeCDF::save(Serializer& out) const
|
||||||
out.putLong(myAudioCycles);
|
out.putLong(myAudioCycles);
|
||||||
out.putDouble(myFractionalClocks);
|
out.putDouble(myFractionalClocks);
|
||||||
out.putLong(myARMCycles);
|
out.putLong(myARMCycles);
|
||||||
|
|
||||||
|
CartridgeARM::save(out);
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
|
@ -600,6 +600,8 @@ bool CartridgeCDF::load(Serializer& in)
|
||||||
myAudioCycles = in.getLong();
|
myAudioCycles = in.getLong();
|
||||||
myFractionalClocks = in.getDouble();
|
myFractionalClocks = in.getDouble();
|
||||||
myARMCycles = in.getLong();
|
myARMCycles = in.getLong();
|
||||||
|
|
||||||
|
CartridgeARM::load(in);
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
|
|
|
@ -21,8 +21,7 @@
|
||||||
class System;
|
class System;
|
||||||
|
|
||||||
#include "bspf.hxx"
|
#include "bspf.hxx"
|
||||||
#include "Thumbulator.hxx"
|
#include "CartARM.hxx"
|
||||||
#include "Cart.hxx"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Cartridge class used for CDF/CDFJ/CDFJ+.
|
Cartridge class used for CDF/CDFJ/CDFJ+.
|
||||||
|
@ -52,7 +51,7 @@ class System;
|
||||||
@authors: Darrell Spice Jr, Chris Walton, Fred Quimby, John Champeau
|
@authors: Darrell Spice Jr, Chris Walton, Fred Quimby, John Champeau
|
||||||
Thomas Jentzsch, Stephen Anthony, Bradford W. Mott
|
Thomas Jentzsch, Stephen Anthony, Bradford W. Mott
|
||||||
*/
|
*/
|
||||||
class CartridgeCDF : public Cartridge
|
class CartridgeCDF : public CartridgeARM
|
||||||
{
|
{
|
||||||
friend class CartridgeCDFWidget;
|
friend class CartridgeCDFWidget;
|
||||||
friend class CartridgeCDFInfoWidget;
|
friend class CartridgeCDFInfoWidget;
|
||||||
|
@ -86,15 +85,6 @@ class CartridgeCDF : public Cartridge
|
||||||
*/
|
*/
|
||||||
void reset() override;
|
void reset() override;
|
||||||
|
|
||||||
/**
|
|
||||||
Notification method invoked by the system when the console type
|
|
||||||
has changed. We need this to inform the Thumbulator that the
|
|
||||||
timing has changed.
|
|
||||||
|
|
||||||
@param timing Enum representing the new console type
|
|
||||||
*/
|
|
||||||
void consoleChanged(ConsoleTiming timing) override;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Install cartridge in the specified system. Invoked by the system
|
Install cartridge in the specified system. Invoked by the system
|
||||||
when the cartridge is attached to it.
|
when the cartridge is attached to it.
|
||||||
|
@ -238,7 +228,7 @@ class CartridgeCDF : public Cartridge
|
||||||
/**
|
/**
|
||||||
Sets the initial state of the DPC pointers and RAM
|
Sets the initial state of the DPC pointers and RAM
|
||||||
*/
|
*/
|
||||||
void setInitialState();
|
void setInitialState() override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Updates any data fetchers in music mode based on the number of
|
Updates any data fetchers in music mode based on the number of
|
||||||
|
@ -263,9 +253,6 @@ class CartridgeCDF : public Cartridge
|
||||||
uInt32 getSample();
|
uInt32 getSample();
|
||||||
void setupVersion();
|
void setupVersion();
|
||||||
|
|
||||||
// Get number of memory accesses of last ARM run.
|
|
||||||
const Thumbulator::Stats& stats() const { return myThumbEmulator->stats(); }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// The ROM image of the cartridge
|
// The ROM image of the cartridge
|
||||||
ByteBuffer myImage{nullptr};
|
ByteBuffer myImage{nullptr};
|
||||||
|
@ -291,9 +278,6 @@ class CartridgeCDF : public Cartridge
|
||||||
// $0800 - Display Data, C Variables & Stack
|
// $0800 - Display Data, C Variables & Stack
|
||||||
std::array<uInt8, 32_KB> myRAM;
|
std::array<uInt8, 32_KB> myRAM;
|
||||||
|
|
||||||
// Pointer to the Thumb ARM emulator object
|
|
||||||
unique_ptr<Thumbulator> myThumbEmulator;
|
|
||||||
|
|
||||||
// Indicates the offset into the ROM image (aligns to current bank)
|
// Indicates the offset into the ROM image (aligns to current bank)
|
||||||
uInt16 myBankOffset{0};
|
uInt16 myBankOffset{0};
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,22 @@ void CartridgeCTY::reset()
|
||||||
bank(startBank());
|
bank(startBank());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void CartridgeCTY::consoleChanged(ConsoleTiming timing)
|
||||||
|
{
|
||||||
|
constexpr double NTSC = 1193191.66666667; // NTSC 6507 clock rate
|
||||||
|
constexpr double PAL = 1182298.0; // PAL 6507 clock rate
|
||||||
|
constexpr double SECAM = 1187500.0; // SECAM 6507 clock rate
|
||||||
|
|
||||||
|
switch(timing)
|
||||||
|
{
|
||||||
|
case ConsoleTiming::ntsc: myClockRate = NTSC; break;
|
||||||
|
case ConsoleTiming::pal: myClockRate = PAL; break;
|
||||||
|
case ConsoleTiming::secam: myClockRate = SECAM; break;
|
||||||
|
default: break; // satisfy compiler
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void CartridgeCTY::install(System& system)
|
void CartridgeCTY::install(System& system)
|
||||||
{
|
{
|
||||||
|
@ -573,7 +589,7 @@ inline void CartridgeCTY::updateMusicModeDataFetchers()
|
||||||
myAudioCycles = mySystem->cycles();
|
myAudioCycles = mySystem->cycles();
|
||||||
|
|
||||||
// Calculate the number of CTY OSC clocks since the last update
|
// Calculate the number of CTY OSC clocks since the last update
|
||||||
double clocks = ((20000.0 * cycles) / 1193191.66666667) + myFractionalClocks;
|
double clocks = ((20000.0 * cycles) / myClockRate) + myFractionalClocks;
|
||||||
uInt32 wholeClocks = uInt32(clocks);
|
uInt32 wholeClocks = uInt32(clocks);
|
||||||
myFractionalClocks = clocks - double(wholeClocks);
|
myFractionalClocks = clocks - double(wholeClocks);
|
||||||
|
|
||||||
|
|
|
@ -128,6 +128,15 @@ class CartridgeCTY : public Cartridge
|
||||||
*/
|
*/
|
||||||
void reset() override;
|
void reset() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Notification method invoked by the system when the console type
|
||||||
|
has changed. We need this to inform the Thumbulator that the
|
||||||
|
timing has changed.
|
||||||
|
|
||||||
|
@param timing Enum representing the new console type
|
||||||
|
*/
|
||||||
|
void consoleChanged(ConsoleTiming timing) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Install cartridge in the specified system. Invoked by the system
|
Install cartridge in the specified system. Invoked by the system
|
||||||
when the cartridge is attached to it.
|
when the cartridge is attached to it.
|
||||||
|
@ -271,6 +280,9 @@ class CartridgeCTY : public Cartridge
|
||||||
// The 64 bytes of RAM accessible at $1000 - $1080
|
// The 64 bytes of RAM accessible at $1000 - $1080
|
||||||
std::array<uInt8, 64> myRAM;
|
std::array<uInt8, 64> myRAM;
|
||||||
|
|
||||||
|
// Console clock rate
|
||||||
|
double myClockRate{1193191.66666667};
|
||||||
|
|
||||||
// Operation type (written to $1000, used by hotspot $1FF4)
|
// Operation type (written to $1000, used by hotspot $1FF4)
|
||||||
uInt8 myOperationType{0};
|
uInt8 myOperationType{0};
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,22 @@ void CartridgeDPC::reset()
|
||||||
myDpcPitch = mySettings.getInt(AudioSettings::SETTING_DPC_PITCH);
|
myDpcPitch = mySettings.getInt(AudioSettings::SETTING_DPC_PITCH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void CartridgeDPC::consoleChanged(ConsoleTiming timing)
|
||||||
|
{
|
||||||
|
constexpr double NTSC = 1193191.66666667; // NTSC 6507 clock rate
|
||||||
|
constexpr double PAL = 1182298.0; // PAL 6507 clock rate
|
||||||
|
constexpr double SECAM = 1187500.0; // SECAM 6507 clock rate
|
||||||
|
|
||||||
|
switch(timing)
|
||||||
|
{
|
||||||
|
case ConsoleTiming::ntsc: myClockRate = NTSC; break;
|
||||||
|
case ConsoleTiming::pal: myClockRate = PAL; break;
|
||||||
|
case ConsoleTiming::secam: myClockRate = SECAM; break;
|
||||||
|
default: break; // satisfy compiler
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void CartridgeDPC::install(System& system)
|
void CartridgeDPC::install(System& system)
|
||||||
{
|
{
|
||||||
|
@ -82,7 +98,7 @@ inline void CartridgeDPC::updateMusicModeDataFetchers()
|
||||||
myAudioCycles = mySystem->cycles();
|
myAudioCycles = mySystem->cycles();
|
||||||
|
|
||||||
// Calculate the number of DPC OSC clocks since the last update
|
// Calculate the number of DPC OSC clocks since the last update
|
||||||
double clocks = ((myDpcPitch * cycles) / 1193191.66666667) + myFractionalClocks;
|
double clocks = ((myDpcPitch * cycles) / myClockRate) + myFractionalClocks;
|
||||||
uInt32 wholeClocks = uInt32(clocks);
|
uInt32 wholeClocks = uInt32(clocks);
|
||||||
myFractionalClocks = clocks - double(wholeClocks);
|
myFractionalClocks = clocks - double(wholeClocks);
|
||||||
|
|
||||||
|
|
|
@ -53,18 +53,28 @@ class CartridgeDPC : public CartridgeF8
|
||||||
~CartridgeDPC() override = default;
|
~CartridgeDPC() override = default;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
Reset device to its power-on state
|
||||||
|
*/
|
||||||
|
void reset() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Notification method invoked by the system when the console type
|
||||||
|
has changed. We need this to inform the Thumbulator that the
|
||||||
|
timing has changed.
|
||||||
|
|
||||||
|
@param timing Enum representing the new console type
|
||||||
|
*/
|
||||||
|
|
||||||
|
void consoleChanged(ConsoleTiming timing) override;
|
||||||
/**
|
/**
|
||||||
Install cartridge in the specified system. Invoked by the system
|
Install cartridge in the specified system. Invoked by the system
|
||||||
when the cartridge is attached to it.
|
when the cartridge is attached to it.
|
||||||
|
|
||||||
@param system The system the device should install itself in
|
@param system The system the device should install itself in
|
||||||
*/
|
*/
|
||||||
void install(System& system) override;
|
|
||||||
|
|
||||||
/**
|
void install(System& system) override;
|
||||||
Reset device to its power-on state
|
|
||||||
*/
|
|
||||||
void reset() override;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Patch the cartridge ROM.
|
Patch the cartridge ROM.
|
||||||
|
@ -147,6 +157,9 @@ class CartridgeDPC : public CartridgeF8
|
||||||
void updateMusicModeDataFetchers();
|
void updateMusicModeDataFetchers();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// Console clock rate
|
||||||
|
double myClockRate{1193191.66666667};
|
||||||
|
|
||||||
// Pointer to the 2K display ROM image of the cartridge
|
// Pointer to the 2K display ROM image of the cartridge
|
||||||
uInt8* myDisplayImage{nullptr};
|
uInt8* myDisplayImage{nullptr};
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
#endif
|
#endif
|
||||||
#include "MD5.hxx"
|
#include "MD5.hxx"
|
||||||
#include "System.hxx"
|
#include "System.hxx"
|
||||||
#include "Thumbulator.hxx"
|
|
||||||
#include "CartDPCPlus.hxx"
|
#include "CartDPCPlus.hxx"
|
||||||
#include "TIA.hxx"
|
#include "TIA.hxx"
|
||||||
#include "exception/FatalEmulationError.hxx"
|
#include "exception/FatalEmulationError.hxx"
|
||||||
|
@ -28,7 +27,7 @@
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
CartridgeDPCPlus::CartridgeDPCPlus(const ByteBuffer& image, size_t size,
|
CartridgeDPCPlus::CartridgeDPCPlus(const ByteBuffer& image, size_t size,
|
||||||
const string& md5, const Settings& settings)
|
const string& md5, const Settings& settings)
|
||||||
: Cartridge(settings, md5),
|
: CartridgeARM(md5, settings),
|
||||||
myImage{make_unique<uInt8[]>(32_KB)},
|
myImage{make_unique<uInt8[]>(32_KB)},
|
||||||
mySize{std::min(size, 32_KB)}
|
mySize{std::min(size, 32_KB)}
|
||||||
{
|
{
|
||||||
|
@ -58,6 +57,8 @@ CartridgeDPCPlus::CartridgeDPCPlus(const ByteBuffer& image, size_t size,
|
||||||
0x00000C08,
|
0x00000C08,
|
||||||
0x40001FDC,
|
0x40001FDC,
|
||||||
devSettings ? settings.getBool("dev.thumb.trapfatal") : false,
|
devSettings ? settings.getBool("dev.thumb.trapfatal") : false,
|
||||||
|
devSettings ? static_cast<double>(
|
||||||
|
settings.getFloat("dev.thumb.cyclefactor")) : 1.0,
|
||||||
Thumbulator::ConfigureFor::DPCplus,
|
Thumbulator::ConfigureFor::DPCplus,
|
||||||
this);
|
this);
|
||||||
|
|
||||||
|
@ -118,12 +119,8 @@ void CartridgeDPCPlus::setInitialState()
|
||||||
myFastFetch = myLDAimmediate = false;
|
myFastFetch = myLDAimmediate = false;
|
||||||
myAudioCycles = myARMCycles = 0;
|
myAudioCycles = myARMCycles = 0;
|
||||||
myFractionalClocks = 0.0;
|
myFractionalClocks = 0.0;
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
CartridgeARM::setInitialState();
|
||||||
void CartridgeDPCPlus::consoleChanged(ConsoleTiming timing)
|
|
||||||
{
|
|
||||||
myThumbEmulator->setConsoleTiming(timing);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -165,7 +162,7 @@ inline void CartridgeDPCPlus::updateMusicModeDataFetchers()
|
||||||
myAudioCycles = mySystem->cycles();
|
myAudioCycles = mySystem->cycles();
|
||||||
|
|
||||||
// Calculate the number of DPC+ OSC clocks since the last update
|
// Calculate the number of DPC+ OSC clocks since the last update
|
||||||
double clocks = ((20000.0 * cycles) / 1193191.66666667) + myFractionalClocks;
|
double clocks = ((20000.0 * cycles) / myClockRate) + myFractionalClocks;
|
||||||
uInt32 wholeClocks = uInt32(clocks);
|
uInt32 wholeClocks = uInt32(clocks);
|
||||||
myFractionalClocks = clocks - double(wholeClocks);
|
myFractionalClocks = clocks - double(wholeClocks);
|
||||||
|
|
||||||
|
@ -200,10 +197,11 @@ inline void CartridgeDPCPlus::callFunction(uInt8 value)
|
||||||
// time for Stella as ARM code "runs in zero 6507 cycles".
|
// time for Stella as ARM code "runs in zero 6507 cycles".
|
||||||
case 255: // call without IRQ driven audio
|
case 255: // call without IRQ driven audio
|
||||||
try {
|
try {
|
||||||
Int32 cycles = Int32(mySystem->cycles() - myARMCycles);
|
uInt32 cycles = uInt32(mySystem->cycles() - myARMCycles);
|
||||||
myARMCycles = mySystem->cycles();
|
|
||||||
|
|
||||||
myThumbEmulator->run(cycles);
|
myARMCycles = mySystem->cycles();
|
||||||
|
myThumbEmulator->run(cycles, value == 254);
|
||||||
|
updateCycles(cycles);
|
||||||
}
|
}
|
||||||
catch(const runtime_error& e) {
|
catch(const runtime_error& e) {
|
||||||
if(!mySystem->autodetectMode())
|
if(!mySystem->autodetectMode())
|
||||||
|
@ -710,6 +708,8 @@ bool CartridgeDPCPlus::save(Serializer& out) const
|
||||||
|
|
||||||
// Clock info for Thumbulator
|
// Clock info for Thumbulator
|
||||||
out.putLong(myARMCycles);
|
out.putLong(myARMCycles);
|
||||||
|
|
||||||
|
CartridgeARM::save(out);
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
|
@ -771,6 +771,8 @@ bool CartridgeDPCPlus::load(Serializer& in)
|
||||||
|
|
||||||
// Clock info for Thumbulator
|
// Clock info for Thumbulator
|
||||||
myARMCycles = in.getLong();
|
myARMCycles = in.getLong();
|
||||||
|
|
||||||
|
CartridgeARM::load(in);
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
|
|
|
@ -20,13 +20,12 @@
|
||||||
|
|
||||||
class System;
|
class System;
|
||||||
|
|
||||||
#include "Thumbulator.hxx"
|
|
||||||
#ifdef DEBUGGER_SUPPORT
|
#ifdef DEBUGGER_SUPPORT
|
||||||
#include "CartDPCPlusWidget.hxx"
|
#include "CartDPCPlusWidget.hxx"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "bspf.hxx"
|
#include "bspf.hxx"
|
||||||
#include "Cart.hxx"
|
#include "CartARM.hxx"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Cartridge class used for DPC+, derived from Pitfall II. There are six 4K
|
Cartridge class used for DPC+, derived from Pitfall II. There are six 4K
|
||||||
|
@ -42,7 +41,7 @@ class System;
|
||||||
|
|
||||||
@authors Darrell Spice Jr, Fred Quimby, Stephen Anthony, Bradford W. Mott
|
@authors Darrell Spice Jr, Fred Quimby, Stephen Anthony, Bradford W. Mott
|
||||||
*/
|
*/
|
||||||
class CartridgeDPCPlus : public Cartridge
|
class CartridgeDPCPlus : public CartridgeARM
|
||||||
{
|
{
|
||||||
friend class CartridgeDPCPlusWidget;
|
friend class CartridgeDPCPlusWidget;
|
||||||
friend class CartridgeRamDPCPlusWidget;
|
friend class CartridgeRamDPCPlusWidget;
|
||||||
|
@ -66,15 +65,6 @@ class CartridgeDPCPlus : public Cartridge
|
||||||
*/
|
*/
|
||||||
void reset() override;
|
void reset() override;
|
||||||
|
|
||||||
/**
|
|
||||||
Notification method invoked by the system when the console type
|
|
||||||
has changed. We need this to inform the Thumbulator that the
|
|
||||||
timing has changed.
|
|
||||||
|
|
||||||
@param timing Enum representing the new console type
|
|
||||||
*/
|
|
||||||
void consoleChanged(ConsoleTiming timing) override;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Install cartridge in the specified system. Invoked by the system
|
Install cartridge in the specified system. Invoked by the system
|
||||||
when the cartridge is attached to it.
|
when the cartridge is attached to it.
|
||||||
|
@ -200,7 +190,7 @@ class CartridgeDPCPlus : public Cartridge
|
||||||
/**
|
/**
|
||||||
Sets the initial state of the DPC pointers and RAM
|
Sets the initial state of the DPC pointers and RAM
|
||||||
*/
|
*/
|
||||||
void setInitialState();
|
void setInitialState() override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Clocks the random number generator to move it to its next state
|
Clocks the random number generator to move it to its next state
|
||||||
|
@ -223,9 +213,6 @@ class CartridgeDPCPlus : public Cartridge
|
||||||
*/
|
*/
|
||||||
void callFunction(uInt8 value);
|
void callFunction(uInt8 value);
|
||||||
|
|
||||||
// Get number of memory accesses of last ARM run.
|
|
||||||
const Thumbulator::Stats& stats() const { return myThumbEmulator->stats(); }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// The ROM image and size
|
// The ROM image and size
|
||||||
ByteBuffer myImage;
|
ByteBuffer myImage;
|
||||||
|
@ -243,9 +230,6 @@ class CartridgeDPCPlus : public Cartridge
|
||||||
// 1K Frequency Data
|
// 1K Frequency Data
|
||||||
std::array<uInt8, 8_KB> myDPCRAM;
|
std::array<uInt8, 8_KB> myDPCRAM;
|
||||||
|
|
||||||
// Pointer to the Thumb ARM emulator object
|
|
||||||
unique_ptr<Thumbulator> myThumbEmulator;
|
|
||||||
|
|
||||||
// Pointer to the 1K frequency table
|
// Pointer to the 1K frequency table
|
||||||
uInt8* myFrequencyImage{nullptr};
|
uInt8* myFrequencyImage{nullptr};
|
||||||
|
|
||||||
|
|
|
@ -134,6 +134,10 @@ Bankswitch::Type CartDetector::autodetectType(const ByteBuffer& image, size_t si
|
||||||
{
|
{
|
||||||
if (isProbablyCTY(image, size))
|
if (isProbablyCTY(image, size))
|
||||||
type = Bankswitch::Type::_CTY;
|
type = Bankswitch::Type::_CTY;
|
||||||
|
else if(isProbablyCDF(image, size))
|
||||||
|
type = Bankswitch::Type::_CDF;
|
||||||
|
else if(isProbablyDPCplus(image, size))
|
||||||
|
type = Bankswitch::Type::_DPCP;
|
||||||
else if(isProbablySC(image, size))
|
else if(isProbablySC(image, size))
|
||||||
type = Bankswitch::Type::_F4SC;
|
type = Bankswitch::Type::_F4SC;
|
||||||
else if(isProbably3EX(image, size))
|
else if(isProbably3EX(image, size))
|
||||||
|
@ -144,10 +148,6 @@ Bankswitch::Type CartDetector::autodetectType(const ByteBuffer& image, size_t si
|
||||||
type = Bankswitch::Type::_3F;
|
type = Bankswitch::Type::_3F;
|
||||||
else if (isProbablyBUS(image, size))
|
else if (isProbablyBUS(image, size))
|
||||||
type = Bankswitch::Type::_BUS;
|
type = Bankswitch::Type::_BUS;
|
||||||
else if (isProbablyCDF(image, size))
|
|
||||||
type = Bankswitch::Type::_CDF;
|
|
||||||
else if(isProbablyDPCplus(image, size))
|
|
||||||
type = Bankswitch::Type::_DPCP;
|
|
||||||
else if(isProbablyFA2(image, size))
|
else if(isProbablyFA2(image, size))
|
||||||
type = Bankswitch::Type::_FA2;
|
type = Bankswitch::Type::_FA2;
|
||||||
else if (isProbablyFC(image, size))
|
else if (isProbablyFC(image, size))
|
||||||
|
@ -166,12 +166,12 @@ Bankswitch::Type CartDetector::autodetectType(const ByteBuffer& image, size_t si
|
||||||
{
|
{
|
||||||
if(isProbably3EX(image, size))
|
if(isProbably3EX(image, size))
|
||||||
type = Bankswitch::Type::_3EX;
|
type = Bankswitch::Type::_3EX;
|
||||||
|
else if (isProbablyCDF(image, size))
|
||||||
|
type = Bankswitch::Type::_CDF;
|
||||||
else if(isProbably3E(image, size))
|
else if(isProbably3E(image, size))
|
||||||
type = Bankswitch::Type::_3E;
|
type = Bankswitch::Type::_3E;
|
||||||
else if(isProbably3F(image, size))
|
else if(isProbably3F(image, size))
|
||||||
type = Bankswitch::Type::_3F;
|
type = Bankswitch::Type::_3F;
|
||||||
else if (isProbablyCDF(image, size))
|
|
||||||
type = Bankswitch::Type::_CDF;
|
|
||||||
else if(isProbably4A50(image, size))
|
else if(isProbably4A50(image, size))
|
||||||
type = Bankswitch::Type::_4A50;
|
type = Bankswitch::Type::_4A50;
|
||||||
else if(isProbablyEF(image, size, type))
|
else if(isProbablyEF(image, size, type))
|
||||||
|
@ -195,6 +195,8 @@ Bankswitch::Type CartDetector::autodetectType(const ByteBuffer& image, size_t si
|
||||||
type = Bankswitch::Type::_CDF;
|
type = Bankswitch::Type::_CDF;
|
||||||
else if(isProbably4A50(image, size))
|
else if(isProbably4A50(image, size))
|
||||||
type = Bankswitch::Type::_4A50;
|
type = Bankswitch::Type::_4A50;
|
||||||
|
else if(isProbablyCDF(image, size))
|
||||||
|
type = Bankswitch::Type::_CDF;
|
||||||
else /*if(isProbablySB(image, size))*/
|
else /*if(isProbablySB(image, size))*/
|
||||||
type = Bankswitch::Type::_SB;
|
type = Bankswitch::Type::_SB;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,15 +25,15 @@ Driving::Driving(Jack jack, const Event& event, const System& system, bool altma
|
||||||
{
|
{
|
||||||
if(!altmap)
|
if(!altmap)
|
||||||
{
|
{
|
||||||
myCCWEvent = Event::JoystickZeroLeft;
|
myCCWEvent = Event::LeftJoystickLeft;
|
||||||
myCWEvent = Event::JoystickZeroRight;
|
myCWEvent = Event::LeftJoystickRight;
|
||||||
myFireEvent = Event::JoystickZeroFire;
|
myFireEvent = Event::LeftJoystickFire;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
myCCWEvent = Event::JoystickTwoLeft;
|
myCCWEvent = Event::QTJoystickThreeLeft;
|
||||||
myCWEvent = Event::JoystickTwoRight;
|
myCWEvent = Event::QTJoystickThreeRight;
|
||||||
myFireEvent = Event::JoystickTwoFire;
|
myFireEvent = Event::QTJoystickThreeFire;
|
||||||
}
|
}
|
||||||
myXAxisValue = Event::SALeftAxis0Value; // joystick input
|
myXAxisValue = Event::SALeftAxis0Value; // joystick input
|
||||||
myYAxisValue = Event::SALeftAxis1Value; // driving controller input
|
myYAxisValue = Event::SALeftAxis1Value; // driving controller input
|
||||||
|
@ -42,15 +42,15 @@ Driving::Driving(Jack jack, const Event& event, const System& system, bool altma
|
||||||
{
|
{
|
||||||
if(!altmap)
|
if(!altmap)
|
||||||
{
|
{
|
||||||
myCCWEvent = Event::JoystickOneLeft;
|
myCCWEvent = Event::RightJoystickLeft;
|
||||||
myCWEvent = Event::JoystickOneRight;
|
myCWEvent = Event::RightJoystickRight;
|
||||||
myFireEvent = Event::JoystickOneFire;
|
myFireEvent = Event::RightJoystickFire;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
myCCWEvent = Event::JoystickThreeLeft;
|
myCCWEvent = Event::QTJoystickFourLeft;
|
||||||
myCWEvent = Event::JoystickThreeRight;
|
myCWEvent = Event::QTJoystickFourRight;
|
||||||
myFireEvent = Event::JoystickThreeFire;
|
myFireEvent = Event::QTJoystickFourFire;
|
||||||
}
|
}
|
||||||
myXAxisValue = Event::SARightAxis0Value; // joystick input
|
myXAxisValue = Event::SARightAxis0Value; // joystick input
|
||||||
myYAxisValue = Event::SARightAxis1Value; // driving controller input
|
myYAxisValue = Event::SARightAxis1Value; // driving controller input
|
||||||
|
|
|
@ -42,25 +42,25 @@ class Event
|
||||||
ConsoleRightDiffA, ConsoleRightDiffB, ConsoleRightDiffToggle,
|
ConsoleRightDiffA, ConsoleRightDiffB, ConsoleRightDiffToggle,
|
||||||
ConsoleSelect, ConsoleReset,
|
ConsoleSelect, ConsoleReset,
|
||||||
|
|
||||||
JoystickZeroUp, JoystickZeroDown, JoystickZeroLeft, JoystickZeroRight,
|
LeftJoystickUp, LeftJoystickDown, LeftJoystickLeft, LeftJoystickRight,
|
||||||
JoystickZeroFire, JoystickZeroFire5, JoystickZeroFire9,
|
LeftJoystickFire, LeftJoystickFire5, LeftJoystickFire9,
|
||||||
JoystickOneUp, JoystickOneDown, JoystickOneLeft, JoystickOneRight,
|
RightJoystickUp, RightJoystickDown, RightJoystickLeft, RightJoystickRight,
|
||||||
JoystickOneFire, JoystickOneFire5, JoystickOneFire9,
|
RightJoystickFire, RightJoystickFire5, RightJoystickFire9,
|
||||||
|
|
||||||
PaddleZeroDecrease, PaddleZeroIncrease, PaddleZeroAnalog, PaddleZeroFire,
|
LeftPaddleADecrease, LeftPaddleAIncrease, LeftPaddleAAnalog, LeftPaddleAFire,
|
||||||
PaddleOneDecrease, PaddleOneIncrease, PaddleOneAnalog, PaddleOneFire,
|
LeftPaddleBDecrease, LeftPaddleBIncrease, LeftPaddleBAnalog, LeftPaddleBFire,
|
||||||
PaddleTwoDecrease, PaddleTwoIncrease, PaddleTwoAnalog, PaddleTwoFire,
|
RightPaddleADecrease, RightPaddleAIncrease, RightPaddleAAnalog, RightPaddleAFire,
|
||||||
PaddleThreeDecrease, PaddleThreeIncrease, PaddleThreeAnalog, PaddleThreeFire,
|
RightPaddleBDecrease, RightPaddleBIncrease, RightPaddleBAnalog, RightPaddleBFire,
|
||||||
|
|
||||||
KeyboardZero1, KeyboardZero2, KeyboardZero3,
|
LeftKeyboard1, LeftKeyboard2, LeftKeyboard3,
|
||||||
KeyboardZero4, KeyboardZero5, KeyboardZero6,
|
LeftKeyboard4, LeftKeyboard5, LeftKeyboard6,
|
||||||
KeyboardZero7, KeyboardZero8, KeyboardZero9,
|
LeftKeyboard7, LeftKeyboard8, LeftKeyboard9,
|
||||||
KeyboardZeroStar, KeyboardZero0, KeyboardZeroPound,
|
LeftKeyboardStar, LeftKeyboard0, LeftKeyboardPound,
|
||||||
|
|
||||||
KeyboardOne1, KeyboardOne2, KeyboardOne3,
|
RightKeyboard1, RightKeyboard2, RightKeyboard3,
|
||||||
KeyboardOne4, KeyboardOne5, KeyboardOne6,
|
RightKeyboard4, RightKeyboard5, RightKeyboard6,
|
||||||
KeyboardOne7, KeyboardOne8, KeyboardOne9,
|
RightKeyboard7, RightKeyboard8, RightKeyboard9,
|
||||||
KeyboardOneStar, KeyboardOne0, KeyboardOnePound,
|
RightKeyboardStar, RightKeyboard0, RightKeyboardPound,
|
||||||
|
|
||||||
CompuMateFunc, CompuMateShift,
|
CompuMateFunc, CompuMateShift,
|
||||||
CompuMate0, CompuMate1, CompuMate2, CompuMate3, CompuMate4,
|
CompuMate0, CompuMate1, CompuMate2, CompuMate3, CompuMate4,
|
||||||
|
@ -129,10 +129,10 @@ class Event
|
||||||
DecreaseAutoFire, IncreaseAutoFire,
|
DecreaseAutoFire, IncreaseAutoFire,
|
||||||
DecreaseSpeed, IncreaseSpeed,
|
DecreaseSpeed, IncreaseSpeed,
|
||||||
|
|
||||||
JoystickTwoUp, JoystickTwoDown, JoystickTwoLeft, JoystickTwoRight,
|
QTJoystickThreeUp, QTJoystickThreeDown, QTJoystickThreeLeft, QTJoystickThreeRight,
|
||||||
JoystickTwoFire,
|
QTJoystickThreeFire,
|
||||||
JoystickThreeUp, JoystickThreeDown, JoystickThreeLeft, JoystickThreeRight,
|
QTJoystickFourUp, QTJoystickFourDown, QTJoystickFourLeft, QTJoystickFourRight,
|
||||||
JoystickThreeFire,
|
QTJoystickFourFire,
|
||||||
|
|
||||||
ToggleCorrectAspectRatio,
|
ToggleCorrectAspectRatio,
|
||||||
|
|
||||||
|
@ -167,7 +167,7 @@ class Event
|
||||||
DecreaseMouseAxesRange, IncreaseMouseAxesRange,
|
DecreaseMouseAxesRange, IncreaseMouseAxesRange,
|
||||||
|
|
||||||
SALeftAxis0Value, SALeftAxis1Value, SARightAxis0Value, SARightAxis1Value,
|
SALeftAxis0Value, SALeftAxis1Value, SARightAxis0Value, SARightAxis1Value,
|
||||||
PaddleFourFire, PaddleFiveFire, PaddleSixFire, PaddleSevenFire,
|
QTPaddle3AFire, QTPaddle3BFire, QTPaddle4AFire, QTPaddle4BFire,
|
||||||
UIHelp,
|
UIHelp,
|
||||||
LastType
|
LastType
|
||||||
};
|
};
|
||||||
|
@ -229,10 +229,10 @@ class Event
|
||||||
{
|
{
|
||||||
switch(type)
|
switch(type)
|
||||||
{
|
{
|
||||||
case Event::PaddleZeroAnalog:
|
case Event::LeftPaddleAAnalog:
|
||||||
case Event::PaddleOneAnalog:
|
case Event::LeftPaddleBAnalog:
|
||||||
case Event::PaddleTwoAnalog:
|
case Event::RightPaddleAAnalog:
|
||||||
case Event::PaddleThreeAnalog:
|
case Event::RightPaddleBAnalog:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
@ -256,62 +256,62 @@ class Event
|
||||||
// Hold controller related events
|
// Hold controller related events
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
static const Event::EventSet LeftJoystickEvents = {
|
static const Event::EventSet LeftJoystickEvents = {
|
||||||
Event::JoystickZeroUp, Event::JoystickZeroDown, Event::JoystickZeroLeft, Event::JoystickZeroRight,
|
Event::LeftJoystickUp, Event::LeftJoystickDown, Event::LeftJoystickLeft, Event::LeftJoystickRight,
|
||||||
Event::JoystickZeroFire, Event::JoystickZeroFire5, Event::JoystickZeroFire9,
|
Event::LeftJoystickFire, Event::LeftJoystickFire5, Event::LeftJoystickFire9,
|
||||||
};
|
};
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
static const Event::EventSet Left2JoystickEvents = {
|
static const Event::EventSet QTJoystick3Events = {
|
||||||
Event::JoystickTwoUp, Event::JoystickTwoDown, Event::JoystickTwoLeft, Event::JoystickTwoRight,
|
Event::QTJoystickThreeUp, Event::QTJoystickThreeDown, Event::QTJoystickThreeLeft, Event::QTJoystickThreeRight,
|
||||||
Event::JoystickTwoFire
|
Event::QTJoystickThreeFire
|
||||||
};
|
};
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
static const Event::EventSet RightJoystickEvents = {
|
static const Event::EventSet RightJoystickEvents = {
|
||||||
Event::JoystickOneUp, Event::JoystickOneDown, Event::JoystickOneLeft, Event::JoystickOneRight,
|
Event::RightJoystickUp, Event::RightJoystickDown, Event::RightJoystickLeft, Event::RightJoystickRight,
|
||||||
Event::JoystickOneFire, Event::JoystickOneFire5, Event::JoystickOneFire9,
|
Event::RightJoystickFire, Event::RightJoystickFire5, Event::RightJoystickFire9,
|
||||||
};
|
};
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
static const Event::EventSet Right2JoystickEvents = {
|
static const Event::EventSet QTJoystick4Events = {
|
||||||
Event::JoystickThreeUp, Event::JoystickThreeDown, Event::JoystickThreeLeft, Event::JoystickThreeRight,
|
Event::QTJoystickFourUp, Event::QTJoystickFourDown, Event::QTJoystickFourLeft, Event::QTJoystickFourRight,
|
||||||
Event::JoystickThreeFire
|
Event::QTJoystickFourFire
|
||||||
};
|
};
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
static const Event::EventSet LeftPaddlesEvents = {
|
static const Event::EventSet LeftPaddlesEvents = {
|
||||||
Event::PaddleZeroDecrease, Event::PaddleZeroIncrease, Event::PaddleZeroAnalog, Event::PaddleZeroFire,
|
Event::LeftPaddleADecrease, Event::LeftPaddleAIncrease, Event::LeftPaddleAAnalog, Event::LeftPaddleAFire,
|
||||||
Event::PaddleOneDecrease, Event::PaddleOneIncrease, Event::PaddleOneAnalog, Event::PaddleOneFire,
|
Event::LeftPaddleBDecrease, Event::LeftPaddleBIncrease, Event::LeftPaddleBAnalog, Event::LeftPaddleBFire,
|
||||||
};
|
};
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
static const Event::EventSet Left2PaddlesEvents = {
|
static const Event::EventSet QTPaddles3Events = {
|
||||||
// Only fire buttons supported by QuadTari
|
// Only fire buttons supported by QuadTari
|
||||||
Event::PaddleFourFire, Event::PaddleFiveFire
|
Event::QTPaddle3AFire, Event::QTPaddle3BFire
|
||||||
};
|
};
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
static const Event::EventSet RightPaddlesEvents = {
|
static const Event::EventSet RightPaddlesEvents = {
|
||||||
Event::PaddleTwoDecrease, Event::PaddleTwoIncrease, Event::PaddleTwoAnalog, Event::PaddleTwoFire,
|
Event::RightPaddleADecrease, Event::RightPaddleAIncrease, Event::RightPaddleAAnalog, Event::RightPaddleAFire,
|
||||||
Event::PaddleThreeDecrease, Event::PaddleThreeIncrease, Event::PaddleThreeAnalog, Event::PaddleThreeFire,
|
Event::RightPaddleBDecrease, Event::RightPaddleBIncrease, Event::RightPaddleBAnalog, Event::RightPaddleBFire,
|
||||||
};
|
};
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
static const Event::EventSet Right2PaddlesEvents = {
|
static const Event::EventSet QTPaddles4Events = {
|
||||||
// Only fire buttons supported by QuadTari
|
// Only fire buttons supported by QuadTari
|
||||||
Event::PaddleSixFire, Event::PaddleSevenFire
|
Event::QTPaddle4AFire, Event::QTPaddle4BFire
|
||||||
};
|
};
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
static const Event::EventSet LeftKeypadEvents = {
|
static const Event::EventSet LeftKeyboardEvents = {
|
||||||
Event::KeyboardZero1, Event::KeyboardZero2, Event::KeyboardZero3,
|
Event::LeftKeyboard1, Event::LeftKeyboard2, Event::LeftKeyboard3,
|
||||||
Event::KeyboardZero4, Event::KeyboardZero5, Event::KeyboardZero6,
|
Event::LeftKeyboard4, Event::LeftKeyboard5, Event::LeftKeyboard6,
|
||||||
Event::KeyboardZero7, Event::KeyboardZero8, Event::KeyboardZero9,
|
Event::LeftKeyboard7, Event::LeftKeyboard8, Event::LeftKeyboard9,
|
||||||
Event::KeyboardZeroStar, Event::KeyboardZero0, Event::KeyboardZeroPound,
|
Event::LeftKeyboardStar, Event::LeftKeyboard0, Event::LeftKeyboardPound,
|
||||||
};
|
};
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
static const Event::EventSet RightKeypadEvents = {
|
static const Event::EventSet RightKeyboardEvents = {
|
||||||
Event::KeyboardOne1, Event::KeyboardOne2, Event::KeyboardOne3,
|
Event::RightKeyboard1, Event::RightKeyboard2, Event::RightKeyboard3,
|
||||||
Event::KeyboardOne4, Event::KeyboardOne5, Event::KeyboardOne6,
|
Event::RightKeyboard4, Event::RightKeyboard5, Event::RightKeyboard6,
|
||||||
Event::KeyboardOne7, Event::KeyboardOne8, Event::KeyboardOne9,
|
Event::RightKeyboard7, Event::RightKeyboard8, Event::RightKeyboard9,
|
||||||
Event::KeyboardOneStar, Event::KeyboardOne0, Event::KeyboardOnePound,
|
Event::RightKeyboardStar, Event::RightKeyboard0, Event::RightKeyboardPound,
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -54,6 +54,7 @@
|
||||||
#endif
|
#endif
|
||||||
#ifdef DEBUGGER_SUPPORT
|
#ifdef DEBUGGER_SUPPORT
|
||||||
#include "Debugger.hxx"
|
#include "Debugger.hxx"
|
||||||
|
#include "DebuggerParser.hxx"
|
||||||
#endif
|
#endif
|
||||||
#ifdef GUI_SUPPORT
|
#ifdef GUI_SUPPORT
|
||||||
#include "Menu.hxx"
|
#include "Menu.hxx"
|
||||||
|
@ -68,6 +69,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
using namespace std::placeholders;
|
using namespace std::placeholders;
|
||||||
|
using json = nlohmann::json;
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
EventHandler::EventHandler(OSystem& osystem)
|
EventHandler::EventHandler(OSystem& osystem)
|
||||||
|
@ -89,11 +91,6 @@ void EventHandler::initialize()
|
||||||
// Create joystick handler (to handle all physical joystick functionality)
|
// Create joystick handler (to handle all physical joystick functionality)
|
||||||
myPJoyHandler = make_unique<PhysicalJoystickHandler>(myOSystem, *this, myEvent);
|
myPJoyHandler = make_unique<PhysicalJoystickHandler>(myOSystem, *this, myEvent);
|
||||||
|
|
||||||
// Erase the 'combo' array
|
|
||||||
for(int i = 0; i < COMBO_SIZE; ++i)
|
|
||||||
for(int j = 0; j < EVENTS_PER_COMBO; ++j)
|
|
||||||
myComboTable[i][j] = Event::NoType;
|
|
||||||
|
|
||||||
// Make sure the event/action mappings are correctly set,
|
// Make sure the event/action mappings are correctly set,
|
||||||
// and fill the ActionList structure with valid values
|
// and fill the ActionList structure with valid values
|
||||||
setComboMap();
|
setComboMap();
|
||||||
|
@ -163,11 +160,6 @@ void EventHandler::addPhysicalJoystick(const PhysicalJoystickPtr& joy)
|
||||||
|
|
||||||
setActionMappings(EventMode::kEmulationMode);
|
setActionMappings(EventMode::kEmulationMode);
|
||||||
setActionMappings(EventMode::kMenuMode);
|
setActionMappings(EventMode::kMenuMode);
|
||||||
|
|
||||||
ostringstream buf;
|
|
||||||
buf << "Added joystick " << ID << ":" << endl
|
|
||||||
<< " " << joy->about() << endl;
|
|
||||||
Logger::info(buf.str());
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -758,84 +750,84 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated)
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
// If enabled, make sure 'impossible' joystick directions aren't allowed
|
// If enabled, make sure 'impossible' joystick directions aren't allowed
|
||||||
case Event::JoystickZeroUp:
|
case Event::LeftJoystickUp:
|
||||||
if(!myAllowAllDirectionsFlag && pressed)
|
if(!myAllowAllDirectionsFlag && pressed)
|
||||||
myEvent.set(Event::JoystickZeroDown, 0);
|
myEvent.set(Event::LeftJoystickDown, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Event::JoystickZeroDown:
|
case Event::LeftJoystickDown:
|
||||||
if(!myAllowAllDirectionsFlag && pressed)
|
if(!myAllowAllDirectionsFlag && pressed)
|
||||||
myEvent.set(Event::JoystickZeroUp, 0);
|
myEvent.set(Event::LeftJoystickUp, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Event::JoystickZeroLeft:
|
case Event::LeftJoystickLeft:
|
||||||
if(!myAllowAllDirectionsFlag && pressed)
|
if(!myAllowAllDirectionsFlag && pressed)
|
||||||
myEvent.set(Event::JoystickZeroRight, 0);
|
myEvent.set(Event::LeftJoystickRight, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Event::JoystickZeroRight:
|
case Event::LeftJoystickRight:
|
||||||
if(!myAllowAllDirectionsFlag && pressed)
|
if(!myAllowAllDirectionsFlag && pressed)
|
||||||
myEvent.set(Event::JoystickZeroLeft, 0);
|
myEvent.set(Event::LeftJoystickLeft, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Event::JoystickOneUp:
|
case Event::RightJoystickUp:
|
||||||
if(!myAllowAllDirectionsFlag && pressed)
|
if(!myAllowAllDirectionsFlag && pressed)
|
||||||
myEvent.set(Event::JoystickOneDown, 0);
|
myEvent.set(Event::RightJoystickDown, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Event::JoystickOneDown:
|
case Event::RightJoystickDown:
|
||||||
if(!myAllowAllDirectionsFlag && pressed)
|
if(!myAllowAllDirectionsFlag && pressed)
|
||||||
myEvent.set(Event::JoystickOneUp, 0);
|
myEvent.set(Event::RightJoystickUp, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Event::JoystickOneLeft:
|
case Event::RightJoystickLeft:
|
||||||
if(!myAllowAllDirectionsFlag && pressed)
|
if(!myAllowAllDirectionsFlag && pressed)
|
||||||
myEvent.set(Event::JoystickOneRight, 0);
|
myEvent.set(Event::RightJoystickRight, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Event::JoystickOneRight:
|
case Event::RightJoystickRight:
|
||||||
if(!myAllowAllDirectionsFlag && pressed)
|
if(!myAllowAllDirectionsFlag && pressed)
|
||||||
myEvent.set(Event::JoystickOneLeft, 0);
|
myEvent.set(Event::RightJoystickLeft, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Event::JoystickTwoUp:
|
case Event::QTJoystickThreeUp:
|
||||||
if(!myAllowAllDirectionsFlag && pressed)
|
if(!myAllowAllDirectionsFlag && pressed)
|
||||||
myEvent.set(Event::JoystickTwoDown, 0);
|
myEvent.set(Event::QTJoystickThreeDown, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Event::JoystickTwoDown:
|
case Event::QTJoystickThreeDown:
|
||||||
if(!myAllowAllDirectionsFlag && pressed)
|
if(!myAllowAllDirectionsFlag && pressed)
|
||||||
myEvent.set(Event::JoystickTwoUp, 0);
|
myEvent.set(Event::QTJoystickThreeUp, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Event::JoystickTwoLeft:
|
case Event::QTJoystickThreeLeft:
|
||||||
if(!myAllowAllDirectionsFlag && pressed)
|
if(!myAllowAllDirectionsFlag && pressed)
|
||||||
myEvent.set(Event::JoystickTwoRight, 0);
|
myEvent.set(Event::QTJoystickThreeRight, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Event::JoystickTwoRight:
|
case Event::QTJoystickThreeRight:
|
||||||
if(!myAllowAllDirectionsFlag && pressed)
|
if(!myAllowAllDirectionsFlag && pressed)
|
||||||
myEvent.set(Event::JoystickTwoLeft, 0);
|
myEvent.set(Event::QTJoystickThreeLeft, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Event::JoystickThreeUp:
|
case Event::QTJoystickFourUp:
|
||||||
if(!myAllowAllDirectionsFlag && pressed)
|
if(!myAllowAllDirectionsFlag && pressed)
|
||||||
myEvent.set(Event::JoystickThreeDown, 0);
|
myEvent.set(Event::QTJoystickFourDown, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Event::JoystickThreeDown:
|
case Event::QTJoystickFourDown:
|
||||||
if(!myAllowAllDirectionsFlag && pressed)
|
if(!myAllowAllDirectionsFlag && pressed)
|
||||||
myEvent.set(Event::JoystickThreeUp, 0);
|
myEvent.set(Event::QTJoystickFourUp, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Event::JoystickThreeLeft:
|
case Event::QTJoystickFourLeft:
|
||||||
if(!myAllowAllDirectionsFlag && pressed)
|
if(!myAllowAllDirectionsFlag && pressed)
|
||||||
myEvent.set(Event::JoystickThreeRight, 0);
|
myEvent.set(Event::QTJoystickFourRight, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Event::JoystickThreeRight:
|
case Event::QTJoystickFourRight:
|
||||||
if(!myAllowAllDirectionsFlag && pressed)
|
if(!myAllowAllDirectionsFlag && pressed)
|
||||||
myEvent.set(Event::JoystickThreeLeft, 0);
|
myEvent.set(Event::QTJoystickFourLeft, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -2087,27 +2079,27 @@ void EventHandler::handleConsoleStartupEvents()
|
||||||
const string& holdjoy0 = myOSystem.settings().getString("holdjoy0");
|
const string& holdjoy0 = myOSystem.settings().getString("holdjoy0");
|
||||||
|
|
||||||
if(BSPF::containsIgnoreCase(holdjoy0, "U"))
|
if(BSPF::containsIgnoreCase(holdjoy0, "U"))
|
||||||
handleEvent(Event::JoystickZeroUp);
|
handleEvent(Event::LeftJoystickUp);
|
||||||
if(BSPF::containsIgnoreCase(holdjoy0, "D"))
|
if(BSPF::containsIgnoreCase(holdjoy0, "D"))
|
||||||
handleEvent(Event::JoystickZeroDown);
|
handleEvent(Event::LeftJoystickDown);
|
||||||
if(BSPF::containsIgnoreCase(holdjoy0, "L"))
|
if(BSPF::containsIgnoreCase(holdjoy0, "L"))
|
||||||
handleEvent(Event::JoystickZeroLeft);
|
handleEvent(Event::LeftJoystickLeft);
|
||||||
if(BSPF::containsIgnoreCase(holdjoy0, "R"))
|
if(BSPF::containsIgnoreCase(holdjoy0, "R"))
|
||||||
handleEvent(Event::JoystickZeroRight);
|
handleEvent(Event::LeftJoystickRight);
|
||||||
if(BSPF::containsIgnoreCase(holdjoy0, "F"))
|
if(BSPF::containsIgnoreCase(holdjoy0, "F"))
|
||||||
handleEvent(Event::JoystickZeroFire);
|
handleEvent(Event::LeftJoystickFire);
|
||||||
|
|
||||||
const string& holdjoy1 = myOSystem.settings().getString("holdjoy1");
|
const string& holdjoy1 = myOSystem.settings().getString("holdjoy1");
|
||||||
if(BSPF::containsIgnoreCase(holdjoy1, "U"))
|
if(BSPF::containsIgnoreCase(holdjoy1, "U"))
|
||||||
handleEvent(Event::JoystickOneUp);
|
handleEvent(Event::RightJoystickUp);
|
||||||
if(BSPF::containsIgnoreCase(holdjoy1, "D"))
|
if(BSPF::containsIgnoreCase(holdjoy1, "D"))
|
||||||
handleEvent(Event::JoystickOneDown);
|
handleEvent(Event::RightJoystickDown);
|
||||||
if(BSPF::containsIgnoreCase(holdjoy1, "L"))
|
if(BSPF::containsIgnoreCase(holdjoy1, "L"))
|
||||||
handleEvent(Event::JoystickOneLeft);
|
handleEvent(Event::RightJoystickLeft);
|
||||||
if(BSPF::containsIgnoreCase(holdjoy1, "R"))
|
if(BSPF::containsIgnoreCase(holdjoy1, "R"))
|
||||||
handleEvent(Event::JoystickOneRight);
|
handleEvent(Event::RightJoystickRight);
|
||||||
if(BSPF::containsIgnoreCase(holdjoy1, "F"))
|
if(BSPF::containsIgnoreCase(holdjoy1, "F"))
|
||||||
handleEvent(Event::JoystickOneFire);
|
handleEvent(Event::RightJoystickFire);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -2263,12 +2255,19 @@ void EventHandler::setActionMappings(EventMode mode)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void EventHandler::setComboMap()
|
void EventHandler::setComboMap()
|
||||||
{
|
{
|
||||||
// Since istringstream swallows whitespace, we have to make the
|
|
||||||
// delimiters be spaces
|
|
||||||
string list = myOSystem.settings().getString("combomap");
|
|
||||||
replace(list.begin(), list.end(), ':', ' ');
|
|
||||||
istringstream buf(list);
|
|
||||||
const Int32 version = myOSystem.settings().getInt("event_ver");
|
const Int32 version = myOSystem.settings().getInt("event_ver");
|
||||||
|
const string serializedMapping = myOSystem.settings().getString("combomap");
|
||||||
|
json mapping;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
mapping = json::parse(serializedMapping);
|
||||||
|
}
|
||||||
|
catch(const json::exception&)
|
||||||
|
{
|
||||||
|
Logger::info("converting legacy combo mapping");
|
||||||
|
mapping = convertLegacyComboMapping(serializedMapping);
|
||||||
|
}
|
||||||
|
|
||||||
// Erase the 'combo' array
|
// Erase the 'combo' array
|
||||||
auto ERASE_ALL = [&]() {
|
auto ERASE_ALL = [&]() {
|
||||||
|
@ -2277,48 +2276,84 @@ void EventHandler::setComboMap()
|
||||||
myComboTable[i][j] = Event::NoType;
|
myComboTable[i][j] = Event::NoType;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ERASE_ALL();
|
||||||
|
|
||||||
// Compare if event list version has changed so that combo maps became invalid
|
// Compare if event list version has changed so that combo maps became invalid
|
||||||
if(version != Event::VERSION || !buf.good())
|
if(version == Event::VERSION)
|
||||||
ERASE_ALL();
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
// Get combo count, which should be the first int in the list
|
|
||||||
// If it isn't, then we treat the entire list as invalid
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string key;
|
for(const json& combo : mapping)
|
||||||
buf >> key;
|
|
||||||
if(BSPF::stringToInt(key) == COMBO_SIZE)
|
|
||||||
{
|
{
|
||||||
// Fill the combomap table with events for as long as they exist
|
int i = combo.at("combo").get<Event::Type>() - Event::Combo1,
|
||||||
int combocount = 0;
|
j = 0;
|
||||||
while(buf >> key && combocount < COMBO_SIZE)
|
json events = combo.at("events");
|
||||||
{
|
|
||||||
// Each event in a comboevent is separated by a comma
|
|
||||||
replace(key.begin(), key.end(), ',', ' ');
|
|
||||||
istringstream buf2(key);
|
|
||||||
|
|
||||||
int eventcount = 0;
|
for(const json& event : events)
|
||||||
while(buf2 >> key && eventcount < EVENTS_PER_COMBO)
|
myComboTable[i][j++] = event;
|
||||||
{
|
|
||||||
myComboTable[combocount][eventcount] = Event::Type(BSPF::stringToInt(key));
|
|
||||||
++eventcount;
|
|
||||||
}
|
|
||||||
++combocount;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
ERASE_ALL();
|
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(const json::exception&)
|
||||||
{
|
{
|
||||||
|
Logger::error("ignoring bad combo mapping");
|
||||||
ERASE_ALL();
|
ERASE_ALL();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
saveComboMapping();
|
saveComboMapping();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
json EventHandler::convertLegacyComboMapping(string list)
|
||||||
|
{
|
||||||
|
json convertedMapping = json::array();
|
||||||
|
|
||||||
|
// Since istringstream swallows whitespace, we have to make the
|
||||||
|
// delimiters be spaces
|
||||||
|
std::replace(list.begin(), list.end(), ':', ' ');
|
||||||
|
std::replace(list.begin(), list.end(), ',', ' ');
|
||||||
|
istringstream buf(list);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
int numCombos;
|
||||||
|
// Get combo count, which should be the first int in the list
|
||||||
|
// If it isn't, then we treat the entire list as invalid
|
||||||
|
buf >> numCombos;
|
||||||
|
|
||||||
|
if(numCombos == COMBO_SIZE)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < COMBO_SIZE; ++i)
|
||||||
|
{
|
||||||
|
json events = json::array();
|
||||||
|
|
||||||
|
for(int j = 0; j < EVENTS_PER_COMBO; ++j)
|
||||||
|
{
|
||||||
|
int event;
|
||||||
|
|
||||||
|
buf >> event;
|
||||||
|
// skip all NoType events
|
||||||
|
if(event != Event::NoType)
|
||||||
|
events.push_back(Event::Type(event));
|
||||||
|
}
|
||||||
|
// only store if there are any NoType events
|
||||||
|
if(events.size())
|
||||||
|
{
|
||||||
|
json combo;
|
||||||
|
|
||||||
|
combo["combo"] = Event::Type(Event::Combo1 + i);
|
||||||
|
combo["events"] = events;
|
||||||
|
convertedMapping.push_back(combo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
Logger::error("Legacy combo map conversion failed!");
|
||||||
|
}
|
||||||
|
return convertedMapping;
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void EventHandler::removePhysicalJoystickFromDatabase(const string& name)
|
void EventHandler::removePhysicalJoystickFromDatabase(const string& name)
|
||||||
{
|
{
|
||||||
|
@ -2423,18 +2458,32 @@ void EventHandler::saveJoyMapping()
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void EventHandler::saveComboMapping()
|
void EventHandler::saveComboMapping()
|
||||||
{
|
{
|
||||||
// Iterate through the combomap table and create a colon-separated list
|
json mapping = json::array();
|
||||||
// For each combo event, create a comma-separated list of its events
|
|
||||||
// Prepend the event count, so we can check it on next load
|
// Iterate through the combomap table and convert into json format
|
||||||
ostringstream buf;
|
|
||||||
buf << COMBO_SIZE;
|
|
||||||
for(int i = 0; i < COMBO_SIZE; ++i)
|
for(int i = 0; i < COMBO_SIZE; ++i)
|
||||||
{
|
{
|
||||||
buf << ":" << myComboTable[i][0];
|
json events = json::array();
|
||||||
for(int j = 1; j < EVENTS_PER_COMBO; ++j)
|
|
||||||
buf << "," << myComboTable[i][j];
|
for(int j = 0; j < EVENTS_PER_COMBO; ++j)
|
||||||
|
{
|
||||||
|
int event = myComboTable[i][j];
|
||||||
|
|
||||||
|
// skip all NoType events
|
||||||
|
if(event != Event::NoType)
|
||||||
|
events.push_back(Event::Type(event));
|
||||||
|
}
|
||||||
|
// only store if there are any NoType events
|
||||||
|
if(events.size())
|
||||||
|
{
|
||||||
|
json combo;
|
||||||
|
|
||||||
|
combo["combo"] = Event::Type(Event::Combo1 + i);
|
||||||
|
combo["events"] = events;
|
||||||
|
mapping.push_back(combo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
myOSystem.settings().setValue("combomap", buf.str());
|
myOSystem.settings().setValue("combomap", mapping.dump(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -2535,7 +2584,7 @@ StringList EventHandler::getActionList(const Event::EventSet& events, EventMode
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
VariantList EventHandler::getComboList(EventMode /**/) const
|
VariantList EventHandler::getComboList() const
|
||||||
{
|
{
|
||||||
// For now, this only works in emulation mode
|
// For now, this only works in emulation mode
|
||||||
VariantList l;
|
VariantList l;
|
||||||
|
@ -2589,9 +2638,9 @@ void EventHandler::setComboListForEvent(Event::Type event, const StringList& eve
|
||||||
{
|
{
|
||||||
if(event >= Event::Combo1 && event <= Event::Combo16)
|
if(event >= Event::Combo1 && event <= Event::Combo16)
|
||||||
{
|
{
|
||||||
assert(events.size() == 8);
|
assert(events.size() == EVENTS_PER_COMBO);
|
||||||
const int combo = event - Event::Combo1;
|
const int combo = event - Event::Combo1;
|
||||||
for(uInt32 i = 0; i < 8; ++i)
|
for(uInt32 i = 0; i < EVENTS_PER_COMBO; ++i)
|
||||||
{
|
{
|
||||||
uInt32 idx = BSPF::stringToInt(events[i]);
|
uInt32 idx = BSPF::stringToInt(events[i]);
|
||||||
if(idx < ourEmulActionList.size())
|
if(idx < ourEmulActionList.size())
|
||||||
|
@ -2996,12 +3045,15 @@ void EventHandler::exitEmulation(bool checkLauncher)
|
||||||
const bool activeTM = myOSystem.settings().getBool(
|
const bool activeTM = myOSystem.settings().getBool(
|
||||||
myOSystem.settings().getBool("dev.settings") ? "dev.timemachine" : "plr.timemachine");
|
myOSystem.settings().getBool("dev.settings") ? "dev.timemachine" : "plr.timemachine");
|
||||||
|
|
||||||
|
|
||||||
if (saveOnExit == "all" && activeTM)
|
if (saveOnExit == "all" && activeTM)
|
||||||
handleEvent(Event::SaveAllStates);
|
handleEvent(Event::SaveAllStates);
|
||||||
else if (saveOnExit == "current")
|
else if (saveOnExit == "current")
|
||||||
handleEvent(Event::SaveState);
|
handleEvent(Event::SaveState);
|
||||||
|
|
||||||
|
#if DEBUGGER_SUPPORT
|
||||||
|
myOSystem.debugger().quit();
|
||||||
|
#endif
|
||||||
|
|
||||||
if (checkLauncher)
|
if (checkLauncher)
|
||||||
{
|
{
|
||||||
// Go back to the launcher, or immediately quit
|
// Go back to the launcher, or immediately quit
|
||||||
|
@ -3036,12 +3088,12 @@ EventHandler::EmulActionList EventHandler::ourEmulActionList = { {
|
||||||
{ Event::ConsoleBlackWhite, "Black & White TV", "" },
|
{ Event::ConsoleBlackWhite, "Black & White TV", "" },
|
||||||
{ Event::ConsoleColorToggle, "Toggle Color / B&W TV", "" },
|
{ Event::ConsoleColorToggle, "Toggle Color / B&W TV", "" },
|
||||||
{ Event::Console7800Pause, "7800 Pause Key", "" },
|
{ Event::Console7800Pause, "7800 Pause Key", "" },
|
||||||
{ Event::ConsoleLeftDiffA, "P0 Difficulty A", "" },
|
{ Event::ConsoleLeftDiffA, "Left Difficulty A", "" },
|
||||||
{ Event::ConsoleLeftDiffB, "P0 Difficulty B", "" },
|
{ Event::ConsoleLeftDiffB, "Left Difficulty B", "" },
|
||||||
{ Event::ConsoleLeftDiffToggle, "P0 Toggle Difficulty", "" },
|
{ Event::ConsoleLeftDiffToggle, "Toggle Left Difficulty", "" },
|
||||||
{ Event::ConsoleRightDiffA, "P1 Difficulty A", "" },
|
{ Event::ConsoleRightDiffA, "Right Difficulty A", "" },
|
||||||
{ Event::ConsoleRightDiffB, "P1 Difficulty B", "" },
|
{ Event::ConsoleRightDiffB, "Right Difficulty B", "" },
|
||||||
{ Event::ConsoleRightDiffToggle, "P1 Toggle Difficulty", "" },
|
{ Event::ConsoleRightDiffToggle, "Toggle Right Difficulty", "" },
|
||||||
{ Event::SaveState, "Save state", "" },
|
{ Event::SaveState, "Save state", "" },
|
||||||
{ Event::SaveAllStates, "Save all TM states of current game", "" },
|
{ Event::SaveAllStates, "Save all TM states of current game", "" },
|
||||||
{ Event::PreviousState, "Change to previous state slot", "" },
|
{ Event::PreviousState, "Change to previous state slot", "" },
|
||||||
|
@ -3056,84 +3108,84 @@ EventHandler::EmulActionList EventHandler::ourEmulActionList = { {
|
||||||
{ Event::ToggleContSnapshotsFrame,"Save continuous snapsh. (every frame)", "" },
|
{ Event::ToggleContSnapshotsFrame,"Save continuous snapsh. (every frame)", "" },
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
{ Event::JoystickZeroUp, "P0 Joystick Up", "" },
|
{ Event::LeftJoystickUp, "Left Joystick Up", "" },
|
||||||
{ Event::JoystickZeroDown, "P0 Joystick Down", "" },
|
{ Event::LeftJoystickDown, "Left Joystick Down", "" },
|
||||||
{ Event::JoystickZeroLeft, "P0 Joystick Left", "" },
|
{ Event::LeftJoystickLeft, "Left Joystick Left", "" },
|
||||||
{ Event::JoystickZeroRight, "P0 Joystick Right", "" },
|
{ Event::LeftJoystickRight, "Left Joystick Right", "" },
|
||||||
{ Event::JoystickZeroFire, "P0 Joystick Fire", "" },
|
{ Event::LeftJoystickFire, "Left Joystick Fire", "" },
|
||||||
{ Event::JoystickZeroFire5, "P0 Booster Top Booster Button", "" },
|
{ Event::LeftJoystickFire5, "Left Booster Top Booster Button", "" },
|
||||||
{ Event::JoystickZeroFire9, "P0 Booster Handle Grip Trigger", "" },
|
{ Event::LeftJoystickFire9, "Left Booster Handle Grip Trigger", "" },
|
||||||
|
|
||||||
{ Event::JoystickOneUp, "P1 Joystick Up", "" },
|
{ Event::RightJoystickUp, "Right Joystick Up", "" },
|
||||||
{ Event::JoystickOneDown, "P1 Joystick Down", "" },
|
{ Event::RightJoystickDown, "Right Joystick Down", "" },
|
||||||
{ Event::JoystickOneLeft, "P1 Joystick Left", "" },
|
{ Event::RightJoystickLeft, "Right Joystick Left", "" },
|
||||||
{ Event::JoystickOneRight, "P1 Joystick Right", "" },
|
{ Event::RightJoystickRight, "Right Joystick Right", "" },
|
||||||
{ Event::JoystickOneFire, "P1 Joystick Fire", "" },
|
{ Event::RightJoystickFire, "Right Joystick Fire", "" },
|
||||||
{ Event::JoystickOneFire5, "P1 Booster Top Booster Button", "" },
|
{ Event::RightJoystickFire5, "Right Booster Top Booster Button", "" },
|
||||||
{ Event::JoystickOneFire9, "P1 Booster Handle Grip Trigger", "" },
|
{ Event::RightJoystickFire9, "Right Booster Handle Grip Trigger", "" },
|
||||||
|
|
||||||
{ Event::JoystickTwoUp, "P2 Joystick Up", "" },
|
{ Event::QTJoystickThreeUp, "QuadTari Joystick 3 Up", "" },
|
||||||
{ Event::JoystickTwoDown, "P2 Joystick Down", "" },
|
{ Event::QTJoystickThreeDown, "QuadTari Joystick 3 Down", "" },
|
||||||
{ Event::JoystickTwoLeft, "P2 Joystick Left", "" },
|
{ Event::QTJoystickThreeLeft, "QuadTari Joystick 3 Left", "" },
|
||||||
{ Event::JoystickTwoRight, "P2 Joystick Right", "" },
|
{ Event::QTJoystickThreeRight, "QuadTari Joystick 3 Right", "" },
|
||||||
{ Event::JoystickTwoFire, "P2 Joystick Fire", "" },
|
{ Event::QTJoystickThreeFire, "QuadTari Joystick 3 Fire", "" },
|
||||||
|
|
||||||
{ Event::JoystickThreeUp, "P3 Joystick Up", "" },
|
{ Event::QTJoystickFourUp, "QuadTari Joystick 4 Up", "" },
|
||||||
{ Event::JoystickThreeDown, "P3 Joystick Down", "" },
|
{ Event::QTJoystickFourDown, "QuadTari Joystick 4 Down", "" },
|
||||||
{ Event::JoystickThreeLeft, "P3 Joystick Left", "" },
|
{ Event::QTJoystickFourLeft, "QuadTari Joystick 4 Left", "" },
|
||||||
{ Event::JoystickThreeRight, "P3 Joystick Right", "" },
|
{ Event::QTJoystickFourRight, "QuadTari Joystick 4 Right", "" },
|
||||||
{ Event::JoystickThreeFire, "P3 Joystick Fire", "" },
|
{ Event::QTJoystickFourFire, "QuadTari Joystick 4 Fire", "" },
|
||||||
|
|
||||||
{ Event::PaddleZeroAnalog, "Paddle 0 Analog", "" },
|
{ Event::LeftPaddleAAnalog, "Left Paddle A Analog", "" },
|
||||||
{ Event::PaddleZeroIncrease, "Paddle 0 Turn Left", "" },
|
{ Event::LeftPaddleAIncrease, "Left Paddle A Turn Left", "" },
|
||||||
{ Event::PaddleZeroDecrease, "Paddle 0 Turn Right", "" },
|
{ Event::LeftPaddleADecrease, "Left Paddle A Turn Right", "" },
|
||||||
{ Event::PaddleZeroFire, "Paddle 0 Fire", "" },
|
{ Event::LeftPaddleAFire, "Left Paddle A Fire", "" },
|
||||||
|
|
||||||
{ Event::PaddleOneAnalog, "Paddle 1 Analog", "" },
|
{ Event::LeftPaddleBAnalog, "Left Paddle B Analog", "" },
|
||||||
{ Event::PaddleOneIncrease, "Paddle 1 Turn Left", "" },
|
{ Event::LeftPaddleBIncrease, "Left Paddle B Turn Left", "" },
|
||||||
{ Event::PaddleOneDecrease, "Paddle 1 Turn Right", "" },
|
{ Event::LeftPaddleBDecrease, "Left Paddle B Turn Right", "" },
|
||||||
{ Event::PaddleOneFire, "Paddle 1 Fire", "" },
|
{ Event::LeftPaddleBFire, "Left Paddle B Fire", "" },
|
||||||
|
|
||||||
{ Event::PaddleTwoAnalog, "Paddle 2 Analog", "" },
|
{ Event::RightPaddleAAnalog, "Right Paddle A Analog", "" },
|
||||||
{ Event::PaddleTwoIncrease, "Paddle 2 Turn Left", "" },
|
{ Event::RightPaddleAIncrease, "Right Paddle A Turn Left", "" },
|
||||||
{ Event::PaddleTwoDecrease, "Paddle 2 Turn Right", "" },
|
{ Event::RightPaddleADecrease, "Right Paddle A Turn Right", "" },
|
||||||
{ Event::PaddleTwoFire, "Paddle 2 Fire", "" },
|
{ Event::RightPaddleAFire, "Right Paddle A Fire", "" },
|
||||||
|
|
||||||
{ Event::PaddleThreeAnalog, "Paddle 3 Analog", "" },
|
{ Event::RightPaddleBAnalog, "Right Paddle B Analog", "" },
|
||||||
{ Event::PaddleThreeIncrease, "Paddle 3 Turn Left", "" },
|
{ Event::RightPaddleBIncrease, "Right Paddle B Turn Left", "" },
|
||||||
{ Event::PaddleThreeDecrease, "Paddle 3 Turn Right", "" },
|
{ Event::RightPaddleBDecrease, "Right Paddle B Turn Right", "" },
|
||||||
{ Event::PaddleThreeFire, "Paddle 3 Fire", "" },
|
{ Event::RightPaddleBFire, "Right Paddle B Fire", "" },
|
||||||
|
|
||||||
{ Event::PaddleFourFire, "Paddle 4 Fire", "" },
|
{ Event::QTPaddle3AFire, "QuadTari Paddle 3A Fire", "" },
|
||||||
{ Event::PaddleFiveFire, "Paddle 5 Fire", "" },
|
{ Event::QTPaddle3BFire, "QuadTari Paddle 3B Fire", "" },
|
||||||
{ Event::PaddleSixFire, "Paddle 6 Fire", "" },
|
{ Event::QTPaddle4AFire, "QuadTari Paddle 4A Fire", "" },
|
||||||
{ Event::PaddleSevenFire, "Paddle 7 Fire", "" },
|
{ Event::QTPaddle4BFire, "QuadTari Paddle 4B Fire", "" },
|
||||||
|
|
||||||
{ Event::KeyboardZero1, "P0 Keyboard 1", "" },
|
{ Event::LeftKeyboard1, "Left Keyboard 1", "" },
|
||||||
{ Event::KeyboardZero2, "P0 Keyboard 2", "" },
|
{ Event::LeftKeyboard2, "Left Keyboard 2", "" },
|
||||||
{ Event::KeyboardZero3, "P0 Keyboard 3", "" },
|
{ Event::LeftKeyboard3, "Left Keyboard 3", "" },
|
||||||
{ Event::KeyboardZero4, "P0 Keyboard 4", "" },
|
{ Event::LeftKeyboard4, "Left Keyboard 4", "" },
|
||||||
{ Event::KeyboardZero5, "P0 Keyboard 5", "" },
|
{ Event::LeftKeyboard5, "Left Keyboard 5", "" },
|
||||||
{ Event::KeyboardZero6, "P0 Keyboard 6", "" },
|
{ Event::LeftKeyboard6, "Left Keyboard 6", "" },
|
||||||
{ Event::KeyboardZero7, "P0 Keyboard 7", "" },
|
{ Event::LeftKeyboard7, "Left Keyboard 7", "" },
|
||||||
{ Event::KeyboardZero8, "P0 Keyboard 8", "" },
|
{ Event::LeftKeyboard8, "Left Keyboard 8", "" },
|
||||||
{ Event::KeyboardZero9, "P0 Keyboard 9", "" },
|
{ Event::LeftKeyboard9, "Left Keyboard 9", "" },
|
||||||
{ Event::KeyboardZeroStar, "P0 Keyboard *", "" },
|
{ Event::LeftKeyboardStar, "Left Keyboard *", "" },
|
||||||
{ Event::KeyboardZero0, "P0 Keyboard 0", "" },
|
{ Event::LeftKeyboard0, "Left Keyboard 0", "" },
|
||||||
{ Event::KeyboardZeroPound, "P0 Keyboard #", "" },
|
{ Event::LeftKeyboardPound, "Left Keyboard #", "" },
|
||||||
|
|
||||||
{ Event::KeyboardOne1, "P1 Keyboard 1", "" },
|
{ Event::RightKeyboard1, "Right Keyboard 1", "" },
|
||||||
{ Event::KeyboardOne2, "P1 Keyboard 2", "" },
|
{ Event::RightKeyboard2, "Right Keyboard 2", "" },
|
||||||
{ Event::KeyboardOne3, "P1 Keyboard 3", "" },
|
{ Event::RightKeyboard3, "Right Keyboard 3", "" },
|
||||||
{ Event::KeyboardOne4, "P1 Keyboard 4", "" },
|
{ Event::RightKeyboard4, "Right Keyboard 4", "" },
|
||||||
{ Event::KeyboardOne5, "P1 Keyboard 5", "" },
|
{ Event::RightKeyboard5, "Right Keyboard 5", "" },
|
||||||
{ Event::KeyboardOne6, "P1 Keyboard 6", "" },
|
{ Event::RightKeyboard6, "Right Keyboard 6", "" },
|
||||||
{ Event::KeyboardOne7, "P1 Keyboard 7", "" },
|
{ Event::RightKeyboard7, "Right Keyboard 7", "" },
|
||||||
{ Event::KeyboardOne8, "P1 Keyboard 8", "" },
|
{ Event::RightKeyboard8, "Right Keyboard 8", "" },
|
||||||
{ Event::KeyboardOne9, "P1 Keyboard 9", "" },
|
{ Event::RightKeyboard9, "Right Keyboard 9", "" },
|
||||||
{ Event::KeyboardOneStar, "P1 Keyboard *", "" },
|
{ Event::RightKeyboardStar, "Right Keyboard *", "" },
|
||||||
{ Event::KeyboardOne0, "P1 Keyboard 0", "" },
|
{ Event::RightKeyboard0, "Right Keyboard 0", "" },
|
||||||
{ Event::KeyboardOnePound, "P1 Keyboard #", "" },
|
{ Event::RightKeyboardPound, "Right Keyboard #", "" },
|
||||||
// Video
|
// Video
|
||||||
{ Event::ToggleFullScreen, "Toggle fullscreen", "" },
|
{ Event::ToggleFullScreen, "Toggle fullscreen", "" },
|
||||||
#ifdef ADAPTABLE_REFRESH_SUPPORT
|
#ifdef ADAPTABLE_REFRESH_SUPPORT
|
||||||
|
@ -3234,7 +3286,7 @@ EventHandler::EmulActionList EventHandler::ourEmulActionList = { {
|
||||||
{ Event::DecreaseDrivingSense, "Decrease driving sensitivity", "" },
|
{ Event::DecreaseDrivingSense, "Decrease driving sensitivity", "" },
|
||||||
{ Event::IncreaseDrivingSense, "Increase driving sensitivity", "" },
|
{ Event::IncreaseDrivingSense, "Increase driving sensitivity", "" },
|
||||||
{ Event::PreviousCursorVisbility, "Select prev. cursor visibility mode", "" },
|
{ Event::PreviousCursorVisbility, "Select prev. cursor visibility mode", "" },
|
||||||
{ Event::NextCursorVisbility, "Select next cursor visibility mode" ,"" },
|
{ Event::NextCursorVisbility, "Select next cursor visibility mode", "" },
|
||||||
{ Event::ToggleGrabMouse, "Toggle grab mouse", "" },
|
{ Event::ToggleGrabMouse, "Toggle grab mouse", "" },
|
||||||
{ Event::PreviousLeftPort, "Select previous left controller", "" },
|
{ Event::PreviousLeftPort, "Select previous left controller", "" },
|
||||||
{ Event::NextLeftPort, "Select next left controller", "" },
|
{ Event::NextLeftPort, "Select next left controller", "" },
|
||||||
|
@ -3363,35 +3415,35 @@ const Event::EventSet EventHandler::ConsoleEvents = {
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
const Event::EventSet EventHandler::JoystickEvents = {
|
const Event::EventSet EventHandler::JoystickEvents = {
|
||||||
Event::JoystickZeroUp, Event::JoystickZeroDown, Event::JoystickZeroLeft, Event::JoystickZeroRight,
|
Event::LeftJoystickUp, Event::LeftJoystickDown, Event::LeftJoystickLeft, Event::LeftJoystickRight,
|
||||||
Event::JoystickZeroFire, Event::JoystickZeroFire5, Event::JoystickZeroFire9,
|
Event::LeftJoystickFire, Event::LeftJoystickFire5, Event::LeftJoystickFire9,
|
||||||
Event::JoystickOneUp, Event::JoystickOneDown, Event::JoystickOneLeft, Event::JoystickOneRight,
|
Event::RightJoystickUp, Event::RightJoystickDown, Event::RightJoystickLeft, Event::RightJoystickRight,
|
||||||
Event::JoystickOneFire, Event::JoystickOneFire5, Event::JoystickOneFire9,
|
Event::RightJoystickFire, Event::RightJoystickFire5, Event::RightJoystickFire9,
|
||||||
Event::JoystickTwoUp, Event::JoystickTwoDown, Event::JoystickTwoLeft, Event::JoystickTwoRight,
|
Event::QTJoystickThreeUp, Event::QTJoystickThreeDown, Event::QTJoystickThreeLeft, Event::QTJoystickThreeRight,
|
||||||
Event::JoystickTwoFire,
|
Event::QTJoystickThreeFire,
|
||||||
Event::JoystickThreeUp, Event::JoystickThreeDown, Event::JoystickThreeLeft, Event::JoystickThreeRight,
|
Event::QTJoystickFourUp, Event::QTJoystickFourDown, Event::QTJoystickFourLeft, Event::QTJoystickFourRight,
|
||||||
Event::JoystickThreeFire,
|
Event::QTJoystickFourFire,
|
||||||
};
|
};
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
const Event::EventSet EventHandler::PaddlesEvents = {
|
const Event::EventSet EventHandler::PaddlesEvents = {
|
||||||
Event::PaddleZeroDecrease, Event::PaddleZeroIncrease, Event::PaddleZeroAnalog, Event::PaddleZeroFire,
|
Event::LeftPaddleADecrease, Event::LeftPaddleAIncrease, Event::LeftPaddleAAnalog, Event::LeftPaddleAFire,
|
||||||
Event::PaddleOneDecrease, Event::PaddleOneIncrease, Event::PaddleOneAnalog, Event::PaddleOneFire,
|
Event::LeftPaddleBDecrease, Event::LeftPaddleBIncrease, Event::LeftPaddleBAnalog, Event::LeftPaddleBFire,
|
||||||
Event::PaddleTwoDecrease, Event::PaddleTwoIncrease, Event::PaddleTwoAnalog, Event::PaddleTwoFire,
|
Event::RightPaddleADecrease, Event::RightPaddleAIncrease, Event::RightPaddleAAnalog, Event::RightPaddleAFire,
|
||||||
Event::PaddleThreeDecrease, Event::PaddleThreeIncrease, Event::PaddleThreeAnalog, Event::PaddleThreeFire,
|
Event::RightPaddleBDecrease, Event::RightPaddleBIncrease, Event::RightPaddleBAnalog, Event::RightPaddleBFire,
|
||||||
Event::PaddleFourFire, Event::PaddleFiveFire,Event::PaddleSixFire,Event::PaddleSevenFire,
|
Event::QTPaddle3AFire, Event::QTPaddle3BFire,Event::QTPaddle4AFire,Event::QTPaddle4BFire,
|
||||||
};
|
};
|
||||||
|
|
||||||
const Event::EventSet EventHandler::KeyboardEvents = {
|
const Event::EventSet EventHandler::KeyboardEvents = {
|
||||||
Event::KeyboardZero1, Event::KeyboardZero2, Event::KeyboardZero3,
|
Event::LeftKeyboard1, Event::LeftKeyboard2, Event::LeftKeyboard3,
|
||||||
Event::KeyboardZero4, Event::KeyboardZero5, Event::KeyboardZero6,
|
Event::LeftKeyboard4, Event::LeftKeyboard5, Event::LeftKeyboard6,
|
||||||
Event::KeyboardZero7, Event::KeyboardZero8, Event::KeyboardZero9,
|
Event::LeftKeyboard7, Event::LeftKeyboard8, Event::LeftKeyboard9,
|
||||||
Event::KeyboardZeroStar, Event::KeyboardZero0, Event::KeyboardZeroPound,
|
Event::LeftKeyboardStar, Event::LeftKeyboard0, Event::LeftKeyboardPound,
|
||||||
|
|
||||||
Event::KeyboardOne1, Event::KeyboardOne2, Event::KeyboardOne3,
|
Event::RightKeyboard1, Event::RightKeyboard2, Event::RightKeyboard3,
|
||||||
Event::KeyboardOne4, Event::KeyboardOne5, Event::KeyboardOne6,
|
Event::RightKeyboard4, Event::RightKeyboard5, Event::RightKeyboard6,
|
||||||
Event::KeyboardOne7, Event::KeyboardOne8, Event::KeyboardOne9,
|
Event::RightKeyboard7, Event::RightKeyboard8, Event::RightKeyboard9,
|
||||||
Event::KeyboardOneStar, Event::KeyboardOne0, Event::KeyboardOnePound,
|
Event::RightKeyboardStar, Event::RightKeyboard0, Event::RightKeyboardPound,
|
||||||
};
|
};
|
||||||
|
|
||||||
const Event::EventSet EventHandler::DevicesEvents = {
|
const Event::EventSet EventHandler::DevicesEvents = {
|
||||||
|
@ -3436,8 +3488,3 @@ const Event::EventSet EventHandler::DebugEvents = {
|
||||||
Event::ToggleColorLoss,
|
Event::ToggleColorLoss,
|
||||||
Event::ToggleJitter,
|
Event::ToggleJitter,
|
||||||
};
|
};
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
const Event::EventSet EventHandler::EditEvents = {
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
|
@ -175,7 +175,7 @@ class EventHandler
|
||||||
bool frying() const { return myFryingFlag; }
|
bool frying() const { return myFryingFlag; }
|
||||||
|
|
||||||
StringList getActionList(Event::Group group) const;
|
StringList getActionList(Event::Group group) const;
|
||||||
VariantList getComboList(EventMode mode) const;
|
VariantList getComboList() const;
|
||||||
|
|
||||||
/** Used to access the list of events assigned to a specific combo event. */
|
/** Used to access the list of events assigned to a specific combo event. */
|
||||||
StringList getComboListForEvent(Event::Type event) const;
|
StringList getComboListForEvent(Event::Type event) const;
|
||||||
|
@ -296,11 +296,6 @@ class EventHandler
|
||||||
*/
|
*/
|
||||||
void setDefaultMapping(Event::Type event, EventMode mode);
|
void setDefaultMapping(Event::Type event, EventMode mode);
|
||||||
|
|
||||||
/**
|
|
||||||
Sets the combo event mappings to those in the 'combomap' setting
|
|
||||||
*/
|
|
||||||
void setComboMap();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Joystick emulates 'impossible' directions (ie, left & right
|
Joystick emulates 'impossible' directions (ie, left & right
|
||||||
at the same time).
|
at the same time).
|
||||||
|
@ -378,6 +373,11 @@ class EventHandler
|
||||||
bool myQwertz{false};
|
bool myQwertz{false};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sets the combo event mappings to those in the 'combomap' setting
|
||||||
|
*/
|
||||||
|
void setComboMap();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Methods which are called by derived classes to handle specific types
|
Methods which are called by derived classes to handle specific types
|
||||||
of input.
|
of input.
|
||||||
|
@ -548,7 +548,6 @@ class EventHandler
|
||||||
static const Event::EventSet DevicesEvents;
|
static const Event::EventSet DevicesEvents;
|
||||||
static const Event::EventSet ComboEvents;
|
static const Event::EventSet ComboEvents;
|
||||||
static const Event::EventSet DebugEvents;
|
static const Event::EventSet DebugEvents;
|
||||||
static const Event::EventSet EditEvents;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
The following methods take care of assigning action mappings.
|
The following methods take care of assigning action mappings.
|
||||||
|
@ -556,6 +555,7 @@ class EventHandler
|
||||||
void setActionMappings(EventMode mode);
|
void setActionMappings(EventMode mode);
|
||||||
void setDefaultKeymap(Event::Type, EventMode mode);
|
void setDefaultKeymap(Event::Type, EventMode mode);
|
||||||
void setDefaultJoymap(Event::Type, EventMode mode);
|
void setDefaultJoymap(Event::Type, EventMode mode);
|
||||||
|
static nlohmann::json convertLegacyComboMapping(string list);
|
||||||
void saveComboMapping();
|
void saveComboMapping();
|
||||||
|
|
||||||
StringList getActionList(EventMode mode) const;
|
StringList getActionList(EventMode mode) const;
|
||||||
|
|
|
@ -80,10 +80,11 @@ enum class EventMode {
|
||||||
kMenuMode, // mapping used for dialogs
|
kMenuMode, // mapping used for dialogs
|
||||||
kJoystickMode, // 4 extra modes for mapping controller keys separately for emulation mode
|
kJoystickMode, // 4 extra modes for mapping controller keys separately for emulation mode
|
||||||
kPaddlesMode,
|
kPaddlesMode,
|
||||||
kKeypadMode,
|
kKeyboardMode,
|
||||||
kCompuMateMode, // cannot be remapped
|
kCompuMateMode, // cannot be remapped
|
||||||
kCommonMode, // mapping common between controllers
|
kCommonMode, // mapping common between controllers
|
||||||
kEditMode, // mapping used in editable widgets
|
kEditMode, // mapping used in editable widgets
|
||||||
|
kPromptMode, // extra mappings used in debugger's prompt widget
|
||||||
kNumModes
|
kNumModes
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -347,9 +347,10 @@ bool FBSurface::isWhiteSpace(const char s) const
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
int FBSurface::drawString(const GUI::Font& font, const string& s,
|
int FBSurface::drawString(const GUI::Font& font, const string& s,
|
||||||
int x, int y, int w, int h,
|
int x, int y, int w, int h,
|
||||||
ColorId color, TextAlign align,
|
ColorId color, TextAlign align,
|
||||||
int deltax, bool useEllipsis, ColorId shadowColor)
|
int deltax, bool useEllipsis, ColorId shadowColor,
|
||||||
|
size_t linkStart, size_t linkLen, bool underline)
|
||||||
{
|
{
|
||||||
int lines = 0;
|
int lines = 0;
|
||||||
|
|
||||||
|
@ -357,14 +358,17 @@ int FBSurface::drawString(const GUI::Font& font, const string& s,
|
||||||
string inStr = s;
|
string inStr = s;
|
||||||
|
|
||||||
// draw multiline string
|
// draw multiline string
|
||||||
//while (font.getStringWidth(inStr) > w && h >= font.getFontHeight() * 2)
|
|
||||||
while(inStr.length() && h >= font.getFontHeight() * 2)
|
while(inStr.length() && h >= font.getFontHeight() * 2)
|
||||||
{
|
{
|
||||||
// String is too wide.
|
// String is too wide.
|
||||||
string leftStr, rightStr;
|
string leftStr, rightStr;
|
||||||
|
|
||||||
splitString(font, inStr, w, leftStr, rightStr);
|
splitString(font, inStr, w, leftStr, rightStr);
|
||||||
drawString(font, leftStr, x, y, w, color, align, deltax, false, shadowColor);
|
drawString(font, leftStr, x, y, w, color, align, deltax, false, shadowColor,
|
||||||
|
linkStart, linkLen, underline);
|
||||||
|
if(linkStart != string::npos)
|
||||||
|
linkStart = std::max(0, int(linkStart - leftStr.length()));
|
||||||
|
|
||||||
h -= font.getFontHeight();
|
h -= font.getFontHeight();
|
||||||
y += font.getFontHeight();
|
y += font.getFontHeight();
|
||||||
inStr = rightStr;
|
inStr = rightStr;
|
||||||
|
@ -372,7 +376,8 @@ int FBSurface::drawString(const GUI::Font& font, const string& s,
|
||||||
}
|
}
|
||||||
if(inStr.length())
|
if(inStr.length())
|
||||||
{
|
{
|
||||||
drawString(font, inStr, x, y, w, color, align, deltax, useEllipsis, shadowColor);
|
drawString(font, inStr, x, y, w, color, align, deltax, useEllipsis, shadowColor,
|
||||||
|
linkStart, linkLen, underline);
|
||||||
lines++;
|
lines++;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -383,7 +388,8 @@ int FBSurface::drawString(const GUI::Font& font, const string& s,
|
||||||
void FBSurface::drawString(const GUI::Font& font, const string& s,
|
void FBSurface::drawString(const GUI::Font& font, const string& s,
|
||||||
int x, int y, int w,
|
int x, int y, int w,
|
||||||
ColorId color, TextAlign align,
|
ColorId color, TextAlign align,
|
||||||
int deltax, bool useEllipsis, ColorId shadowColor)
|
int deltax, bool useEllipsis, ColorId shadowColor,
|
||||||
|
size_t linkStart, size_t linkLen, bool underline)
|
||||||
{
|
{
|
||||||
#ifdef GUI_SUPPORT
|
#ifdef GUI_SUPPORT
|
||||||
const string ELLIPSIS = "\x1d"; // "..."
|
const string ELLIPSIS = "\x1d"; // "..."
|
||||||
|
@ -424,16 +430,30 @@ void FBSurface::drawString(const GUI::Font& font, const string& s,
|
||||||
x = x + w - width;
|
x = x + w - width;
|
||||||
|
|
||||||
x += deltax;
|
x += deltax;
|
||||||
|
|
||||||
|
int x0 = x, x1 = 0;
|
||||||
|
|
||||||
for(i = 0; i < str.size(); ++i)
|
for(i = 0; i < str.size(); ++i)
|
||||||
{
|
{
|
||||||
w = font.getCharWidth(str[i]);
|
w = font.getCharWidth(str[i]);
|
||||||
if(x+w > rightX)
|
if(x + w > rightX)
|
||||||
break;
|
break;
|
||||||
if(x >= leftX)
|
if(x >= leftX)
|
||||||
drawChar(font, str[i], x, y, color, shadowColor);
|
{
|
||||||
|
if(i == linkStart)
|
||||||
|
x0 = x;
|
||||||
|
else if(i < linkStart + linkLen)
|
||||||
|
x1 = x + w;
|
||||||
|
|
||||||
|
drawChar(font, str[i], x, y,
|
||||||
|
(i >= linkStart && i < linkStart + linkLen) ? kTextColorLink : color,
|
||||||
|
shadowColor);
|
||||||
|
}
|
||||||
x += w;
|
x += w;
|
||||||
}
|
}
|
||||||
|
if(underline && x1 > 0)
|
||||||
|
hLine(x0, y + font.getFontHeight() - 1, x1, kTextColorLink);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -211,41 +211,52 @@ class FBSurface
|
||||||
/**
|
/**
|
||||||
This method should be called to draw the specified string.
|
This method should be called to draw the specified string.
|
||||||
|
|
||||||
@param font The font to draw the string with
|
@param font The font to draw the string with
|
||||||
@param s The string to draw
|
@param s The string to draw
|
||||||
@param x The x coordinate
|
@param x The x coordinate
|
||||||
@param y The y coordinate
|
@param y The y coordinate
|
||||||
@param w The width of the string area
|
@param w The width of the string area
|
||||||
@param h The height of the string area (for multi line strings)
|
@param h The height of the string area (for multi line strings)
|
||||||
@param color The color of the text
|
@param color The color of the text
|
||||||
@param align The alignment of the text in the string width area
|
@param align The alignment of the text in the string width area
|
||||||
@param deltax FIXME
|
@param deltax The horizontal scroll offset
|
||||||
@param useEllipsis Whether to use '...' when the string is too long
|
@param useEllipsis Whether to use '...' when the string is too long
|
||||||
|
@param shadowColor The shadow color of the text
|
||||||
|
@param linkStart The start position of a link in drawn string
|
||||||
|
@param linkLen The length of a link in drawn string
|
||||||
|
@param underline Whether to underline the link
|
||||||
@return Number of lines drawn
|
@return Number of lines drawn
|
||||||
*/
|
*/
|
||||||
|
|
||||||
virtual int drawString(
|
virtual int drawString(const GUI::Font& font, const string& s, int x, int y, int w, int h,
|
||||||
const GUI::Font& font, const string& s, int x, int y, int w, int h,
|
ColorId color, TextAlign align = TextAlign::Left,
|
||||||
ColorId color, TextAlign align = TextAlign::Left,
|
int deltax = 0, bool useEllipsis = true, ColorId shadowColor = kNone,
|
||||||
int deltax = 0, bool useEllipsis = true, ColorId shadowColor = kNone);
|
size_t linkStart = string::npos, size_t linkLen = string::npos,
|
||||||
|
bool underline = false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This method should be called to draw the specified string.
|
This method should be called to draw the specified string.
|
||||||
|
|
||||||
@param font The font to draw the string with
|
@param font The font to draw the string with
|
||||||
@param s The string to draw
|
@param s The string to draw
|
||||||
@param x The x coordinate
|
@param x The x coordinate
|
||||||
@param y The y coordinate
|
@param y The y coordinate
|
||||||
@param w The width of the string area
|
@param w The width of the string area
|
||||||
@param color The color of the text
|
@param color The color of the text
|
||||||
@param align The alignment of the text in the string width area
|
@param align The alignment of the text in the string width area
|
||||||
@param deltax FIXME
|
@param deltax The horizontal scroll offset
|
||||||
@param useEllipsis Whether to use '...' when the string is too long
|
@param useEllipsis Whether to use '...' when the string is too long
|
||||||
|
@param shadowColor The shadow color of the text
|
||||||
|
@param linkStart The start position of a link in drawn string
|
||||||
|
@param linkLen The length of a link in drawn string
|
||||||
|
@param underline Whether to underline the link
|
||||||
|
|
||||||
*/
|
*/
|
||||||
virtual void drawString(
|
virtual void drawString(const GUI::Font& font, const string& s, int x, int y, int w,
|
||||||
const GUI::Font& font, const string& s, int x, int y, int w,
|
ColorId color, TextAlign align = TextAlign::Left,
|
||||||
ColorId color, TextAlign align = TextAlign::Left,
|
int deltax = 0, bool useEllipsis = true, ColorId shadowColor = kNone,
|
||||||
int deltax = 0, bool useEllipsis = true, ColorId shadowColor = kNone);
|
size_t linkStart = string::npos, size_t linkLen = string::npos,
|
||||||
|
bool underline = false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Splits a given string to a given width considering whitespaces.
|
Splits a given string to a given width considering whitespaces.
|
||||||
|
|
|
@ -67,6 +67,7 @@ FrameBuffer::FrameBuffer(OSystem& osystem)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
FrameBuffer::~FrameBuffer()
|
FrameBuffer::~FrameBuffer()
|
||||||
{
|
{
|
||||||
|
cerr << "~FrameBuffer()\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -885,63 +886,28 @@ void FrameBuffer::setPauseDelay()
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
unique_ptr<FBSurface> FrameBuffer::allocateSurface(
|
shared_ptr<FBSurface> FrameBuffer::allocateSurface(
|
||||||
int w, int h, ScalingInterpolation inter, const uInt32* data)
|
int w, int h, ScalingInterpolation inter, const uInt32* data)
|
||||||
{
|
{
|
||||||
return myBackend->createSurface(w, h, inter, data);
|
mySurfaceList.push_back(myBackend->createSurface(w, h, inter, data));
|
||||||
|
return mySurfaceList.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void FrameBuffer::deallocateSurface(shared_ptr<FBSurface> surface)
|
||||||
|
{
|
||||||
|
if(surface)
|
||||||
|
{
|
||||||
|
cerr << "deallocateSurface: " << surface << endl;
|
||||||
|
mySurfaceList.remove(surface);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FrameBuffer::resetSurfaces()
|
void FrameBuffer::resetSurfaces()
|
||||||
{
|
{
|
||||||
switch(myOSystem.eventHandler().state())
|
for(auto& surface: mySurfaceList)
|
||||||
{
|
surface->reload();
|
||||||
case EventHandlerState::NONE:
|
|
||||||
case EventHandlerState::EMULATION:
|
|
||||||
case EventHandlerState::PAUSE:
|
|
||||||
case EventHandlerState::PLAYBACK:
|
|
||||||
#ifdef GUI_SUPPORT
|
|
||||||
myMsg.surface->reload();
|
|
||||||
myStatsMsg.surface->reload();
|
|
||||||
#endif
|
|
||||||
myTIASurface->resetSurfaces();
|
|
||||||
break;
|
|
||||||
|
|
||||||
#ifdef GUI_SUPPORT
|
|
||||||
case EventHandlerState::OPTIONSMENU:
|
|
||||||
myOSystem.menu().resetSurfaces();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EventHandlerState::CMDMENU:
|
|
||||||
myOSystem.commandMenu().resetSurfaces();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EventHandlerState::HIGHSCORESMENU:
|
|
||||||
myOSystem.highscoresMenu().resetSurfaces();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EventHandlerState::MESSAGEMENU:
|
|
||||||
myOSystem.messageMenu().resetSurfaces();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EventHandlerState::TIMEMACHINE:
|
|
||||||
myOSystem.timeMachine().resetSurfaces();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EventHandlerState::LAUNCHER:
|
|
||||||
myOSystem.launcher().resetSurfaces();
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef DEBUGGER_SUPPORT
|
|
||||||
case EventHandlerState::DEBUGGER:
|
|
||||||
myOSystem.debugger().resetSurfaces();
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
update(UpdateMode::REDRAW); // force full update
|
update(UpdateMode::REDRAW); // force full update
|
||||||
}
|
}
|
||||||
|
@ -1419,6 +1385,7 @@ void FrameBuffer::toggleGrabMouse(bool toggle)
|
||||||
kTextColorHi Highlighted text color
|
kTextColorHi Highlighted text color
|
||||||
kTextColorEm Emphasized text color
|
kTextColorEm Emphasized text color
|
||||||
kTextColorInv Color for selected text
|
kTextColorInv Color for selected text
|
||||||
|
kTextColorLink Color for links
|
||||||
*** UI elements (dialog and widgets) ***
|
*** UI elements (dialog and widgets) ***
|
||||||
kDlgColor Dialog background
|
kDlgColor Dialog background
|
||||||
kWidColor Widget background
|
kWidColor Widget background
|
||||||
|
@ -1454,7 +1421,7 @@ void FrameBuffer::toggleGrabMouse(bool toggle)
|
||||||
*/
|
*/
|
||||||
UIPaletteArray FrameBuffer::ourStandardUIPalette = {
|
UIPaletteArray FrameBuffer::ourStandardUIPalette = {
|
||||||
{ 0x686868, 0x000000, 0xa38c61, 0xdccfa5, 0x404040, // base
|
{ 0x686868, 0x000000, 0xa38c61, 0xdccfa5, 0x404040, // base
|
||||||
0x000000, 0xac3410, 0x9f0000, 0xf0f0cf, // text
|
0x000000, 0xac3410, 0x9f0000, 0xf0f0cf, 0xac3410, // text
|
||||||
0xc9af7c, 0xf0f0cf, 0xd55941, 0xc80000, // UI elements
|
0xc9af7c, 0xf0f0cf, 0xd55941, 0xc80000, // UI elements
|
||||||
0xac3410, 0xd55941, 0x686868, 0xdccfa5, 0xf0f0cf, 0xf0f0cf, // buttons
|
0xac3410, 0xd55941, 0x686868, 0xdccfa5, 0xf0f0cf, 0xf0f0cf, // buttons
|
||||||
0xac3410, // checkbox
|
0xac3410, // checkbox
|
||||||
|
@ -1467,7 +1434,7 @@ UIPaletteArray FrameBuffer::ourStandardUIPalette = {
|
||||||
|
|
||||||
UIPaletteArray FrameBuffer::ourClassicUIPalette = {
|
UIPaletteArray FrameBuffer::ourClassicUIPalette = {
|
||||||
{ 0x686868, 0x000000, 0x404040, 0x404040, 0x404040, // base
|
{ 0x686868, 0x000000, 0x404040, 0x404040, 0x404040, // base
|
||||||
0x20a020, 0x00ff00, 0xc80000, 0x000000, // text
|
0x20a020, 0x00ff00, 0xc80000, 0x000000, 0x00ff00, // text
|
||||||
0x000000, 0x000000, 0x00ff00, 0xc80000, // UI elements
|
0x000000, 0x000000, 0x00ff00, 0xc80000, // UI elements
|
||||||
0x000000, 0x000000, 0x686868, 0x00ff00, 0x20a020, 0x00ff00, // buttons
|
0x000000, 0x000000, 0x686868, 0x00ff00, 0x20a020, 0x00ff00, // buttons
|
||||||
0x20a020, // checkbox
|
0x20a020, // checkbox
|
||||||
|
@ -1480,7 +1447,7 @@ UIPaletteArray FrameBuffer::ourClassicUIPalette = {
|
||||||
|
|
||||||
UIPaletteArray FrameBuffer::ourLightUIPalette = {
|
UIPaletteArray FrameBuffer::ourLightUIPalette = {
|
||||||
{ 0x808080, 0x000000, 0xc0c0c0, 0xe1e1e1, 0x333333, // base
|
{ 0x808080, 0x000000, 0xc0c0c0, 0xe1e1e1, 0x333333, // base
|
||||||
0x000000, 0xBDDEF9, 0x0078d7, 0x000000, // text
|
0x000000, 0xBDDEF9, 0x0078d7, 0x000000, 0x005aa1, // text
|
||||||
0xf0f0f0, 0xffffff, 0x0078d7, 0x0f0f0f, // UI elements
|
0xf0f0f0, 0xffffff, 0x0078d7, 0x0f0f0f, // UI elements
|
||||||
0xe1e1e1, 0xe5f1fb, 0x808080, 0x0078d7, 0x000000, 0x000000, // buttons
|
0xe1e1e1, 0xe5f1fb, 0x808080, 0x0078d7, 0x000000, 0x000000, // buttons
|
||||||
0x333333, // checkbox
|
0x333333, // checkbox
|
||||||
|
@ -1493,7 +1460,7 @@ UIPaletteArray FrameBuffer::ourLightUIPalette = {
|
||||||
|
|
||||||
UIPaletteArray FrameBuffer::ourDarkUIPalette = {
|
UIPaletteArray FrameBuffer::ourDarkUIPalette = {
|
||||||
{ 0x646464, 0xc0c0c0, 0x3c3c3c, 0x282828, 0x989898, // base
|
{ 0x646464, 0xc0c0c0, 0x3c3c3c, 0x282828, 0x989898, // base
|
||||||
0xc0c0c0, 0x1567a5, 0x0059a3, 0xc0c0c0, // text
|
0xc0c0c0, 0x1567a5, 0x0064b7, 0xc0c0c0, 0x1d92e0, // text
|
||||||
0x202020, 0x000000, 0x0059a3, 0xb0b0b0, // UI elements
|
0x202020, 0x000000, 0x0059a3, 0xb0b0b0, // UI elements
|
||||||
0x282828, 0x00467f, 0x646464, 0x0059a3, 0xc0c0c0, 0xc0c0c0, // buttons
|
0x282828, 0x00467f, 0x646464, 0x0059a3, 0xc0c0c0, 0xc0c0c0, // buttons
|
||||||
0x989898, // checkbox
|
0x989898, // checkbox
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
#ifndef FRAMEBUFFER_HXX
|
#ifndef FRAMEBUFFER_HXX
|
||||||
#define FRAMEBUFFER_HXX
|
#define FRAMEBUFFER_HXX
|
||||||
|
|
||||||
#include <map>
|
#include <list>
|
||||||
|
|
||||||
class OSystem;
|
class OSystem;
|
||||||
class Console;
|
class Console;
|
||||||
|
@ -158,13 +158,21 @@ class FrameBuffer
|
||||||
|
|
||||||
@return A pointer to a valid surface object, or nullptr
|
@return A pointer to a valid surface object, or nullptr
|
||||||
*/
|
*/
|
||||||
unique_ptr<FBSurface> allocateSurface(
|
shared_ptr<FBSurface> allocateSurface(
|
||||||
int w,
|
int w,
|
||||||
int h,
|
int h,
|
||||||
ScalingInterpolation inter = ScalingInterpolation::none,
|
ScalingInterpolation inter = ScalingInterpolation::none,
|
||||||
const uInt32* data = nullptr
|
const uInt32* data = nullptr
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Deallocate a previously allocated surface. If no such surface exists,
|
||||||
|
this method does nothing.
|
||||||
|
|
||||||
|
@param surface The surface to remove/deallocate
|
||||||
|
*/
|
||||||
|
void deallocateSurface(shared_ptr<FBSurface> surface);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Set up the TIA/emulation palette. Due to the way the palette is stored,
|
Set up the TIA/emulation palette. Due to the way the palette is stored,
|
||||||
a call to this method implicitly calls setUIPalette() too.
|
a call to this method implicitly calls setUIPalette() too.
|
||||||
|
@ -521,7 +529,7 @@ class FrameBuffer
|
||||||
int x{0}, y{0}, w{0}, h{0};
|
int x{0}, y{0}, w{0}, h{0};
|
||||||
MessagePosition position{MessagePosition::BottomCenter};
|
MessagePosition position{MessagePosition::BottomCenter};
|
||||||
ColorId color{kNone};
|
ColorId color{kNone};
|
||||||
unique_ptr<FBSurface> surface;
|
shared_ptr<FBSurface> surface;
|
||||||
bool enabled{false};
|
bool enabled{false};
|
||||||
bool dirty{false};
|
bool dirty{false};
|
||||||
bool showGauge{false};
|
bool showGauge{false};
|
||||||
|
@ -540,6 +548,9 @@ class FrameBuffer
|
||||||
// Minimum TIA zoom level that can be used for this framebuffer
|
// Minimum TIA zoom level that can be used for this framebuffer
|
||||||
float myTIAMinZoom{2.F};
|
float myTIAMinZoom{2.F};
|
||||||
|
|
||||||
|
// Holds a reference to all the surfaces that have been created
|
||||||
|
std::list<shared_ptr<FBSurface>> mySurfaceList;
|
||||||
|
|
||||||
// Maximum message width [chars]
|
// Maximum message width [chars]
|
||||||
static constexpr int MESSAGE_WIDTH = 56;
|
static constexpr int MESSAGE_WIDTH = 56;
|
||||||
// Maximum gauge bar width [chars]
|
// Maximum gauge bar width [chars]
|
||||||
|
|
|
@ -77,39 +77,40 @@ static constexpr ColorId
|
||||||
kTextColorHi = 262,
|
kTextColorHi = 262,
|
||||||
kTextColorEm = 263,
|
kTextColorEm = 263,
|
||||||
kTextColorInv = 264,
|
kTextColorInv = 264,
|
||||||
|
kTextColorLink = 265,
|
||||||
// *** UI elements(dialog and widgets) ***
|
// *** UI elements(dialog and widgets) ***
|
||||||
kDlgColor = 265,
|
kDlgColor = 266,
|
||||||
kWidColor = 266,
|
kWidColor = 267,
|
||||||
kWidColorHi = 267,
|
kWidColorHi = 268,
|
||||||
kWidFrameColor = 268,
|
kWidFrameColor = 269,
|
||||||
// *** Button colors ***
|
// *** Button colors ***
|
||||||
kBtnColor = 269,
|
kBtnColor = 270,
|
||||||
kBtnColorHi = 270,
|
kBtnColorHi = 271,
|
||||||
kBtnBorderColor = 271,
|
kBtnBorderColor = 272,
|
||||||
kBtnBorderColorHi = 272,
|
kBtnBorderColorHi = 273,
|
||||||
kBtnTextColor = 273,
|
kBtnTextColor = 274,
|
||||||
kBtnTextColorHi = 274,
|
kBtnTextColorHi = 275,
|
||||||
// *** Checkbox colors ***
|
// *** Checkbox colors ***
|
||||||
kCheckColor = 275,
|
kCheckColor = 276,
|
||||||
// *** Scrollbar colors ***
|
// *** Scrollbar colors ***
|
||||||
kScrollColor = 276,
|
kScrollColor = 277,
|
||||||
kScrollColorHi = 277,
|
kScrollColorHi = 278,
|
||||||
// *** Debugger colors ***
|
// *** Debugger colors ***
|
||||||
kDbgChangedColor = 278,
|
kDbgChangedColor = 279,
|
||||||
kDbgChangedTextColor = 279,
|
kDbgChangedTextColor = 280,
|
||||||
kDbgColorHi = 280,
|
kDbgColorHi = 281,
|
||||||
kDbgColorRed = 281, // Note: this must be < 0x11e (286)! (see PromptWidget::putcharIntern)
|
kDbgColorRed = 282, // Note: this must be < 0x11e (286)! (see PromptWidget::putcharIntern)
|
||||||
// *** Slider colors ***
|
// *** Slider colors ***
|
||||||
kSliderColor = 282,
|
kSliderColor = 283,
|
||||||
kSliderColorHi = 283,
|
kSliderColorHi = 284,
|
||||||
kSliderBGColor = 284,
|
kSliderBGColor = 285,
|
||||||
kSliderBGColorHi = 285,
|
kSliderBGColorHi = 286,
|
||||||
kSliderBGColorLo = 286,
|
kSliderBGColorLo = 287,
|
||||||
// *** Other colors ***
|
// *** Other colors ***
|
||||||
kColorInfo = 287,
|
kColorInfo = 288,
|
||||||
kColorTitleBar = 288,
|
kColorTitleBar = 289,
|
||||||
kColorTitleText = 289,
|
kColorTitleText = 290,
|
||||||
kNumColors = 290,
|
kNumColors = 291,
|
||||||
kNone = 0 // placeholder to represent default/no color
|
kNone = 0 // placeholder to represent default/no color
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
|
@ -22,11 +22,12 @@ Genesis::Genesis(Jack jack, const Event& event, const System& system)
|
||||||
: Joystick(jack, event, system, Controller::Type::Genesis)
|
: Joystick(jack, event, system, Controller::Type::Genesis)
|
||||||
{
|
{
|
||||||
if(myJack == Jack::Left)
|
if(myJack == Jack::Left)
|
||||||
myButtonCEvent = Event::JoystickZeroFire5;
|
myButtonCEvent = Event::LeftJoystickFire5;
|
||||||
else
|
else
|
||||||
myButtonCEvent = Event::JoystickOneFire5;
|
myButtonCEvent = Event::RightJoystickFire5;
|
||||||
|
|
||||||
setPin(AnalogPin::Five, AnalogReadout::connectToVcc());
|
setPin(AnalogPin::Five, AnalogReadout::connectToVcc());
|
||||||
|
setPin(AnalogPin::Nine, AnalogReadout::connectToVcc());
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -32,38 +32,38 @@ Joystick::Joystick(Jack jack, const Event& event, const System& system,
|
||||||
{
|
{
|
||||||
if(!altmap)
|
if(!altmap)
|
||||||
{
|
{
|
||||||
myUpEvent = Event::JoystickZeroUp;
|
myUpEvent = Event::LeftJoystickUp;
|
||||||
myDownEvent = Event::JoystickZeroDown;
|
myDownEvent = Event::LeftJoystickDown;
|
||||||
myLeftEvent = Event::JoystickZeroLeft;
|
myLeftEvent = Event::LeftJoystickLeft;
|
||||||
myRightEvent = Event::JoystickZeroRight;
|
myRightEvent = Event::LeftJoystickRight;
|
||||||
myFireEvent = Event::JoystickZeroFire;
|
myFireEvent = Event::LeftJoystickFire;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
myUpEvent = Event::JoystickTwoUp;
|
myUpEvent = Event::QTJoystickThreeUp;
|
||||||
myDownEvent = Event::JoystickTwoDown;
|
myDownEvent = Event::QTJoystickThreeDown;
|
||||||
myLeftEvent = Event::JoystickTwoLeft;
|
myLeftEvent = Event::QTJoystickThreeLeft;
|
||||||
myRightEvent = Event::JoystickTwoRight;
|
myRightEvent = Event::QTJoystickThreeRight;
|
||||||
myFireEvent = Event::JoystickTwoFire;
|
myFireEvent = Event::QTJoystickThreeFire;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(!altmap)
|
if(!altmap)
|
||||||
{
|
{
|
||||||
myUpEvent = Event::JoystickOneUp;
|
myUpEvent = Event::RightJoystickUp;
|
||||||
myDownEvent = Event::JoystickOneDown;
|
myDownEvent = Event::RightJoystickDown;
|
||||||
myLeftEvent = Event::JoystickOneLeft;
|
myLeftEvent = Event::RightJoystickLeft;
|
||||||
myRightEvent = Event::JoystickOneRight;
|
myRightEvent = Event::RightJoystickRight;
|
||||||
myFireEvent = Event::JoystickOneFire;
|
myFireEvent = Event::RightJoystickFire;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
myUpEvent = Event::JoystickThreeUp;
|
myUpEvent = Event::QTJoystickFourUp;
|
||||||
myDownEvent = Event::JoystickThreeDown;
|
myDownEvent = Event::QTJoystickFourDown;
|
||||||
myLeftEvent = Event::JoystickThreeLeft;
|
myLeftEvent = Event::QTJoystickFourLeft;
|
||||||
myRightEvent = Event::JoystickThreeRight;
|
myRightEvent = Event::QTJoystickFourRight;
|
||||||
myFireEvent = Event::JoystickThreeFire;
|
myFireEvent = Event::QTJoystickFourFire;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,33 +24,33 @@ Keyboard::Keyboard(Jack jack, const Event& event, const System& system)
|
||||||
{
|
{
|
||||||
if(myJack == Jack::Left)
|
if(myJack == Jack::Left)
|
||||||
{
|
{
|
||||||
myOneEvent = Event::KeyboardZero1;
|
myOneEvent = Event::LeftKeyboard1;
|
||||||
myTwoEvent = Event::KeyboardZero2;
|
myTwoEvent = Event::LeftKeyboard2;
|
||||||
myThreeEvent = Event::KeyboardZero3;
|
myThreeEvent = Event::LeftKeyboard3;
|
||||||
myFourEvent = Event::KeyboardZero4;
|
myFourEvent = Event::LeftKeyboard4;
|
||||||
myFiveEvent = Event::KeyboardZero5;
|
myFiveEvent = Event::LeftKeyboard5;
|
||||||
mySixEvent = Event::KeyboardZero6;
|
mySixEvent = Event::LeftKeyboard6;
|
||||||
mySevenEvent = Event::KeyboardZero7;
|
mySevenEvent = Event::LeftKeyboard7;
|
||||||
myEightEvent = Event::KeyboardZero8;
|
myEightEvent = Event::LeftKeyboard8;
|
||||||
myNineEvent = Event::KeyboardZero9;
|
myNineEvent = Event::LeftKeyboard9;
|
||||||
myStarEvent = Event::KeyboardZeroStar;
|
myStarEvent = Event::LeftKeyboardStar;
|
||||||
myZeroEvent = Event::KeyboardZero0;
|
myZeroEvent = Event::LeftKeyboard0;
|
||||||
myPoundEvent = Event::KeyboardZeroPound;
|
myPoundEvent = Event::LeftKeyboardPound;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
myOneEvent = Event::KeyboardOne1;
|
myOneEvent = Event::RightKeyboard1;
|
||||||
myTwoEvent = Event::KeyboardOne2;
|
myTwoEvent = Event::RightKeyboard2;
|
||||||
myThreeEvent = Event::KeyboardOne3;
|
myThreeEvent = Event::RightKeyboard3;
|
||||||
myFourEvent = Event::KeyboardOne4;
|
myFourEvent = Event::RightKeyboard4;
|
||||||
myFiveEvent = Event::KeyboardOne5;
|
myFiveEvent = Event::RightKeyboard5;
|
||||||
mySixEvent = Event::KeyboardOne6;
|
mySixEvent = Event::RightKeyboard6;
|
||||||
mySevenEvent = Event::KeyboardOne7;
|
mySevenEvent = Event::RightKeyboard7;
|
||||||
myEightEvent = Event::KeyboardOne8;
|
myEightEvent = Event::RightKeyboard8;
|
||||||
myNineEvent = Event::KeyboardOne9;
|
myNineEvent = Event::RightKeyboard9;
|
||||||
myStarEvent = Event::KeyboardOneStar;
|
myStarEvent = Event::RightKeyboardStar;
|
||||||
myZeroEvent = Event::KeyboardOne0;
|
myZeroEvent = Event::RightKeyboard0;
|
||||||
myPoundEvent = Event::KeyboardOnePound;
|
myPoundEvent = Event::RightKeyboardPound;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ void KidVid::update()
|
||||||
myTape = 0; // rewind Kid Vid tape
|
myTape = 0; // rewind Kid Vid tape
|
||||||
closeSampleFile();
|
closeSampleFile();
|
||||||
}
|
}
|
||||||
if(myEvent.get(Event::KeyboardOne1))
|
if(myEvent.get(Event::RightKeyboard1))
|
||||||
{
|
{
|
||||||
myTape = 2;
|
myTape = 2;
|
||||||
myIdx = myGame == KVBBEARS ? KVBLOCKBITS : 0;
|
myIdx = myGame == KVBBEARS ? KVBLOCKBITS : 0;
|
||||||
|
@ -61,7 +61,7 @@ void KidVid::update()
|
||||||
openSampleFile();
|
openSampleFile();
|
||||||
//cerr << "myTape = " << myTape << endl;
|
//cerr << "myTape = " << myTape << endl;
|
||||||
}
|
}
|
||||||
else if(myEvent.get(Event::KeyboardOne2))
|
else if(myEvent.get(Event::RightKeyboard2))
|
||||||
{
|
{
|
||||||
myTape = 3;
|
myTape = 3;
|
||||||
myIdx = myGame == KVBBEARS ? KVBLOCKBITS : 0;
|
myIdx = myGame == KVBBEARS ? KVBLOCKBITS : 0;
|
||||||
|
@ -70,7 +70,7 @@ void KidVid::update()
|
||||||
openSampleFile();
|
openSampleFile();
|
||||||
//cerr << "myTape = " << myTape << endl;
|
//cerr << "myTape = " << myTape << endl;
|
||||||
}
|
}
|
||||||
else if(myEvent.get(Event::KeyboardOne3))
|
else if(myEvent.get(Event::RightKeyboard3))
|
||||||
{
|
{
|
||||||
if(myGame == KVBBEARS) /* Berenstain Bears ? */
|
if(myGame == KVBBEARS) /* Berenstain Bears ? */
|
||||||
{
|
{
|
||||||
|
|
|
@ -116,7 +116,7 @@ bool Lightgun::read(DigitalPin pin)
|
||||||
void Lightgun::update()
|
void Lightgun::update()
|
||||||
{
|
{
|
||||||
// Digital events (from keyboard or joystick hats & buttons)
|
// Digital events (from keyboard or joystick hats & buttons)
|
||||||
bool firePressed = myEvent.get(Event::JoystickZeroFire) != 0;
|
bool firePressed = myEvent.get(Event::LeftJoystickFire) != 0;
|
||||||
|
|
||||||
// We allow left and right mouse buttons for fire button
|
// We allow left and right mouse buttons for fire button
|
||||||
firePressed = firePressed
|
firePressed = firePressed
|
||||||
|
|
|
@ -93,6 +93,7 @@ void M6502::reset()
|
||||||
myGhostReadsTrap = mySettings.getBool("dbg.ghostreadstrap");
|
myGhostReadsTrap = mySettings.getBool("dbg.ghostreadstrap");
|
||||||
myReadFromWritePortBreak = devSettings ? mySettings.getBool("dev.rwportbreak") : false;
|
myReadFromWritePortBreak = devSettings ? mySettings.getBool("dev.rwportbreak") : false;
|
||||||
myWriteToReadPortBreak = devSettings ? mySettings.getBool("dev.wrportbreak") : false;
|
myWriteToReadPortBreak = devSettings ? mySettings.getBool("dev.wrportbreak") : false;
|
||||||
|
myLogBreaks = mySettings.getBool("dbg.logbreaks");
|
||||||
|
|
||||||
myLastBreakCycle = ULLONG_MAX;
|
myLastBreakCycle = ULLONG_MAX;
|
||||||
}
|
}
|
||||||
|
@ -162,7 +163,7 @@ inline void M6502::poke(uInt16 address, uInt8 value, Device::AccessFlags flags)
|
||||||
{
|
{
|
||||||
myJustHitWriteTrapFlag = true;
|
myJustHitWriteTrapFlag = true;
|
||||||
stringstream msg;
|
stringstream msg;
|
||||||
msg << "WTrap[" << Common::Base::HEX2 << cond << "]" << (myTrapCondNames[cond].empty() ? ": " : "If: {" + myTrapCondNames[cond] + "} ");
|
msg << "WTrap[" << Common::Base::HEX2 << cond << "]" << (myTrapCondNames[cond].empty() ? ":" : "If: {" + myTrapCondNames[cond] + "}");
|
||||||
myHitTrapInfo.message = msg.str();
|
myHitTrapInfo.message = msg.str();
|
||||||
myHitTrapInfo.address = address;
|
myHitTrapInfo.address = address;
|
||||||
}
|
}
|
||||||
|
@ -243,10 +244,16 @@ inline void M6502::_execute(uInt64 cycles, DispatchResult& result)
|
||||||
myJustHitReadTrapFlag = myJustHitWriteTrapFlag = false;
|
myJustHitReadTrapFlag = myJustHitWriteTrapFlag = false;
|
||||||
|
|
||||||
myLastBreakCycle = mySystem->cycles();
|
myLastBreakCycle = mySystem->cycles();
|
||||||
result.setDebugger(currentCycles, myHitTrapInfo.message,
|
|
||||||
read ? "Read trap" : "Write trap",
|
if(myLogBreaks)
|
||||||
myHitTrapInfo.address, read);
|
myDebugger->log(myHitTrapInfo.message);
|
||||||
return;
|
else
|
||||||
|
{
|
||||||
|
result.setDebugger(currentCycles, myHitTrapInfo.message + " ",
|
||||||
|
read ? "Read trap" : "Write trap",
|
||||||
|
myHitTrapInfo.address, read);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(myBreakPoints.isInitialized())
|
if(myBreakPoints.isInitialized())
|
||||||
|
@ -260,15 +267,21 @@ inline void M6502::_execute(uInt64 cycles, DispatchResult& result)
|
||||||
if(myBreakPoints.get(PC, bank) & BreakpointMap::ONE_SHOT)
|
if(myBreakPoints.get(PC, bank) & BreakpointMap::ONE_SHOT)
|
||||||
{
|
{
|
||||||
myBreakPoints.erase(PC, bank);
|
myBreakPoints.erase(PC, bank);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ostringstream msg;
|
if(myLogBreaks)
|
||||||
|
myDebugger->log("BP:");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ostringstream msg;
|
||||||
|
|
||||||
msg << "BP: $" << Common::Base::HEX4 << PC << ", bank #" << std::dec << int(bank);
|
msg << "BP: $" << Common::Base::HEX4 << PC << ", bank #" << std::dec << int(bank);
|
||||||
result.setDebugger(currentCycles, msg.str(), "Breakpoint");
|
result.setDebugger(currentCycles, msg.str(), "Breakpoint");
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,11 +290,19 @@ inline void M6502::_execute(uInt64 cycles, DispatchResult& result)
|
||||||
{
|
{
|
||||||
ostringstream msg;
|
ostringstream msg;
|
||||||
|
|
||||||
msg << "CBP[" << Common::Base::HEX2 << cond << "]: " << myCondBreakNames[cond];
|
|
||||||
|
|
||||||
myLastBreakCycle = mySystem->cycles();
|
myLastBreakCycle = mySystem->cycles();
|
||||||
result.setDebugger(currentCycles, msg.str(), "Conditional breakpoint");
|
|
||||||
return;
|
if(myLogBreaks)
|
||||||
|
{
|
||||||
|
msg << "CBP[" << Common::Base::HEX2 << cond << "]:";
|
||||||
|
myDebugger->log(msg.str());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
msg << "CBP[" << Common::Base::HEX2 << cond << "]: " << myCondBreakNames[cond];
|
||||||
|
result.setDebugger(currentCycles, msg.str(), "Conditional breakpoint");
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -255,6 +255,8 @@ class M6502 : public Serializable
|
||||||
void setGhostReadsTrap(bool enable) { myGhostReadsTrap = enable; }
|
void setGhostReadsTrap(bool enable) { myGhostReadsTrap = enable; }
|
||||||
void setReadFromWritePortBreak(bool enable) { myReadFromWritePortBreak = enable; }
|
void setReadFromWritePortBreak(bool enable) { myReadFromWritePortBreak = enable; }
|
||||||
void setWriteToReadPortBreak(bool enable) { myWriteToReadPortBreak = enable; }
|
void setWriteToReadPortBreak(bool enable) { myWriteToReadPortBreak = enable; }
|
||||||
|
void setLogBreaks(bool enable) { myLogBreaks = enable; }
|
||||||
|
bool getLogBreaks() { return myLogBreaks; }
|
||||||
#endif // DEBUGGER_SUPPORT
|
#endif // DEBUGGER_SUPPORT
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -469,6 +471,7 @@ class M6502 : public Serializable
|
||||||
bool myReadFromWritePortBreak{false}; // trap on reads from write ports
|
bool myReadFromWritePortBreak{false}; // trap on reads from write ports
|
||||||
bool myWriteToReadPortBreak{false}; // trap on writes to read ports
|
bool myWriteToReadPortBreak{false}; // trap on writes to read ports
|
||||||
bool myStepStateByInstruction{false};
|
bool myStepStateByInstruction{false};
|
||||||
|
bool myLogBreaks{false}; // log breaks/taps and continue emulation
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Following constructors and assignment operators not supported
|
// Following constructors and assignment operators not supported
|
||||||
|
|
|
@ -111,6 +111,7 @@ OSystem::OSystem()
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
OSystem::~OSystem()
|
OSystem::~OSystem()
|
||||||
{
|
{
|
||||||
|
cerr << "~OSystem()\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -103,6 +103,7 @@ class OSystem
|
||||||
@return The frame buffer
|
@return The frame buffer
|
||||||
*/
|
*/
|
||||||
FrameBuffer& frameBuffer() const { return *myFrameBuffer; }
|
FrameBuffer& frameBuffer() const { return *myFrameBuffer; }
|
||||||
|
bool hasFrameBuffer() const { return myFrameBuffer.get() != nullptr; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Get the sound object of the system.
|
Get the sound object of the system.
|
||||||
|
|
|
@ -49,65 +49,65 @@ Paddles::Paddles(Jack jack, const Event& event, const System& system,
|
||||||
{
|
{
|
||||||
if(!altmap)
|
if(!altmap)
|
||||||
{
|
{
|
||||||
// First paddle is 0, second is 1
|
// First paddle is left A, second is left B
|
||||||
myP0AxisValue = Event::PaddleZeroAnalog;
|
myAAxisValue = Event::LeftPaddleAAnalog;
|
||||||
myP1AxisValue = Event::PaddleOneAnalog;
|
myBAxisValue = Event::LeftPaddleBAnalog;
|
||||||
myP0FireEvent = Event::PaddleZeroFire;
|
myLeftAFireEvent = Event::LeftPaddleAFire;
|
||||||
myP1FireEvent = Event::PaddleOneFire;
|
myLeftBFireEvent = Event::LeftPaddleBFire;
|
||||||
|
|
||||||
// These can be affected by changes in axis orientation
|
// These can be affected by changes in axis orientation
|
||||||
myP0DecEvent = Event::PaddleZeroDecrease;
|
myLeftADecEvent = Event::LeftPaddleADecrease;
|
||||||
myP0IncEvent = Event::PaddleZeroIncrease;
|
myLeftAIncEvent = Event::LeftPaddleAIncrease;
|
||||||
myP1DecEvent = Event::PaddleOneDecrease;
|
myLeftBDecEvent = Event::LeftPaddleBDecrease;
|
||||||
myP1IncEvent = Event::PaddleOneIncrease;
|
myLeftBIncEvent = Event::LeftPaddleBIncrease;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// First paddle is 4, second is 5 (fire buttons only)
|
// First paddle is QT 3A, second is QT 3B (fire buttons only)
|
||||||
myP0FireEvent = Event::PaddleFourFire;
|
myLeftAFireEvent = Event::QTPaddle3AFire;
|
||||||
myP1FireEvent = Event::PaddleFiveFire;
|
myLeftBFireEvent = Event::QTPaddle3BFire;
|
||||||
|
|
||||||
myP0AxisValue = myP1AxisValue =
|
myAAxisValue = myBAxisValue =
|
||||||
myP0DecEvent = myP0IncEvent =
|
myLeftADecEvent = myLeftAIncEvent =
|
||||||
myP1DecEvent = myP1IncEvent = Event::NoType;
|
myLeftBDecEvent = myLeftBIncEvent = Event::NoType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else // Jack is right port
|
else // Jack is right port
|
||||||
{
|
{
|
||||||
if(!altmap)
|
if(!altmap)
|
||||||
{
|
{
|
||||||
// First paddle is 2, second is 3
|
// First paddle is right A, second is right B
|
||||||
myP0AxisValue = Event::PaddleTwoAnalog;
|
myAAxisValue = Event::RightPaddleAAnalog;
|
||||||
myP1AxisValue = Event::PaddleThreeAnalog;
|
myBAxisValue = Event::RightPaddleBAnalog;
|
||||||
myP0FireEvent = Event::PaddleTwoFire;
|
myLeftAFireEvent = Event::RightPaddleAFire;
|
||||||
myP1FireEvent = Event::PaddleThreeFire;
|
myLeftBFireEvent = Event::RightPaddleBFire;
|
||||||
|
|
||||||
// These can be affected by changes in axis orientation
|
// These can be affected by changes in axis orientation
|
||||||
myP0DecEvent = Event::PaddleTwoDecrease;
|
myLeftADecEvent = Event::RightPaddleADecrease;
|
||||||
myP0IncEvent = Event::PaddleTwoIncrease;
|
myLeftAIncEvent = Event::RightPaddleAIncrease;
|
||||||
myP1DecEvent = Event::PaddleThreeDecrease;
|
myLeftBDecEvent = Event::RightPaddleBDecrease;
|
||||||
myP1IncEvent = Event::PaddleThreeIncrease;
|
myLeftBIncEvent = Event::RightPaddleBIncrease;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// First paddle is 6, second is 7 (fire buttons only)
|
// First paddle is QT 4A, second is QT 4B (fire buttons only)
|
||||||
myP0FireEvent = Event::PaddleSixFire;
|
myLeftAFireEvent = Event::QTPaddle4AFire;
|
||||||
myP1FireEvent = Event::PaddleSevenFire;
|
myLeftBFireEvent = Event::QTPaddle4BFire;
|
||||||
|
|
||||||
myP0AxisValue = myP1AxisValue =
|
myAAxisValue = myBAxisValue =
|
||||||
myP0DecEvent = myP0IncEvent =
|
myLeftADecEvent = myLeftAIncEvent =
|
||||||
myP1DecEvent = myP1IncEvent = Event::NoType;
|
myLeftBDecEvent = myLeftBIncEvent = Event::NoType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Some games swap the paddles
|
// Some games swap the paddles
|
||||||
if(swappaddle)
|
if(swappaddle)
|
||||||
{
|
{
|
||||||
// First paddle is 1|3, second is 0|2
|
// First paddle is right A|B, second is left A|B
|
||||||
swapEvents(myP0AxisValue, myP1AxisValue);
|
swapEvents(myAAxisValue, myBAxisValue);
|
||||||
swapEvents(myP0FireEvent, myP1FireEvent);
|
swapEvents(myLeftAFireEvent, myLeftBFireEvent);
|
||||||
swapEvents(myP0DecEvent, myP1DecEvent);
|
swapEvents(myLeftADecEvent, myLeftBDecEvent);
|
||||||
swapEvents(myP0IncEvent, myP1IncEvent);
|
swapEvents(myLeftAIncEvent, myLeftBIncEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Direction of movement can be swapped
|
// Direction of movement can be swapped
|
||||||
|
@ -115,8 +115,8 @@ Paddles::Paddles(Jack jack, const Event& event, const System& system,
|
||||||
// result in either increasing or decreasing paddle movement
|
// result in either increasing or decreasing paddle movement
|
||||||
if(swapdir)
|
if(swapdir)
|
||||||
{
|
{
|
||||||
swapEvents(myP0DecEvent, myP0IncEvent);
|
swapEvents(myLeftADecEvent, myLeftAIncEvent);
|
||||||
swapEvents(myP1DecEvent, myP1IncEvent);
|
swapEvents(myLeftBDecEvent, myLeftBIncEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The following are independent of whether or not the port
|
// The following are independent of whether or not the port
|
||||||
|
@ -159,8 +159,8 @@ void Paddles::update()
|
||||||
setPin(DigitalPin::Four, true);
|
setPin(DigitalPin::Four, true);
|
||||||
|
|
||||||
// Digital events (from keyboard or joystick hats & buttons)
|
// Digital events (from keyboard or joystick hats & buttons)
|
||||||
bool firePressedP0 = myEvent.get(myP0FireEvent) != 0;
|
bool firePressedA = myEvent.get(myLeftAFireEvent) != 0;
|
||||||
bool firePressedP1 = myEvent.get(myP1FireEvent) != 0;
|
bool firePressedB = myEvent.get(myLeftBFireEvent) != 0;
|
||||||
|
|
||||||
// Paddle movement is a very difficult thing to accurately emulate,
|
// Paddle movement is a very difficult thing to accurately emulate,
|
||||||
// since it originally came from an analog device that had very
|
// since it originally came from an analog device that had very
|
||||||
|
@ -175,7 +175,7 @@ void Paddles::update()
|
||||||
|
|
||||||
if(!updateAnalogAxes())
|
if(!updateAnalogAxes())
|
||||||
{
|
{
|
||||||
updateMouse(firePressedP0, firePressedP1);
|
updateMouse(firePressedA, firePressedB);
|
||||||
updateDigitalAxes();
|
updateDigitalAxes();
|
||||||
|
|
||||||
// Only change state if the charge has actually changed
|
// Only change state if the charge has actually changed
|
||||||
|
@ -191,8 +191,8 @@ void Paddles::update()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setPin(DigitalPin::Four, !getAutoFireState(firePressedP0));
|
setPin(DigitalPin::Four, !getAutoFireState(firePressedA));
|
||||||
setPin(DigitalPin::Three, !getAutoFireStateP1(firePressedP1));
|
setPin(DigitalPin::Three, !getAutoFireStateP1(firePressedB));
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -221,8 +221,8 @@ bool Paddles::updateAnalogAxes()
|
||||||
const double baseFactor = bFac[DEJITTER_BASE];
|
const double baseFactor = bFac[DEJITTER_BASE];
|
||||||
const double diffFactor = dFac[DEJITTER_DIFF];
|
const double diffFactor = dFac[DEJITTER_DIFF];
|
||||||
|
|
||||||
int sa_xaxis = myEvent.get(myP0AxisValue);
|
int sa_xaxis = myEvent.get(myAAxisValue);
|
||||||
int sa_yaxis = myEvent.get(myP1AxisValue);
|
int sa_yaxis = myEvent.get(myBAxisValue);
|
||||||
bool sa_changed = false;
|
bool sa_changed = false;
|
||||||
|
|
||||||
if(abs(myLastAxisX - sa_xaxis) > 10)
|
if(abs(myLastAxisX - sa_xaxis) > 10)
|
||||||
|
@ -261,7 +261,7 @@ bool Paddles::updateAnalogAxes()
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Paddles::updateMouse(bool& firePressedP0, bool& firePressedP1)
|
void Paddles::updateMouse(bool& firePressedA, bool& firePressedB)
|
||||||
{
|
{
|
||||||
// Mouse motion events give relative movement
|
// Mouse motion events give relative movement
|
||||||
// That is, they're only relevant if they're non-zero
|
// That is, they're only relevant if they're non-zero
|
||||||
|
@ -272,11 +272,11 @@ void Paddles::updateMouse(bool& firePressedP0, bool& firePressedP1)
|
||||||
(myEvent.get(myAxisMouseMotion) * MOUSE_SENSITIVITY),
|
(myEvent.get(myAxisMouseMotion) * MOUSE_SENSITIVITY),
|
||||||
TRIGMIN, TRIGRANGE);
|
TRIGMIN, TRIGRANGE);
|
||||||
if(myMPaddleID == 0)
|
if(myMPaddleID == 0)
|
||||||
firePressedP0 = firePressedP0
|
firePressedA = firePressedA
|
||||||
|| myEvent.get(Event::MouseButtonLeftValue)
|
|| myEvent.get(Event::MouseButtonLeftValue)
|
||||||
|| myEvent.get(Event::MouseButtonRightValue);
|
|| myEvent.get(Event::MouseButtonRightValue);
|
||||||
else
|
else
|
||||||
firePressedP1 = firePressedP1
|
firePressedB = firePressedB
|
||||||
|| myEvent.get(Event::MouseButtonLeftValue)
|
|| myEvent.get(Event::MouseButtonLeftValue)
|
||||||
|| myEvent.get(Event::MouseButtonRightValue);
|
|| myEvent.get(Event::MouseButtonRightValue);
|
||||||
}
|
}
|
||||||
|
@ -290,10 +290,10 @@ void Paddles::updateMouse(bool& firePressedP0, bool& firePressedP1)
|
||||||
(myEvent.get(Event::MouseAxisXMove) * MOUSE_SENSITIVITY),
|
(myEvent.get(Event::MouseAxisXMove) * MOUSE_SENSITIVITY),
|
||||||
TRIGMIN, TRIGRANGE);
|
TRIGMIN, TRIGRANGE);
|
||||||
if(myMPaddleIDX == 0)
|
if(myMPaddleIDX == 0)
|
||||||
firePressedP0 = firePressedP0
|
firePressedA = firePressedA
|
||||||
|| myEvent.get(Event::MouseButtonLeftValue);
|
|| myEvent.get(Event::MouseButtonLeftValue);
|
||||||
else
|
else
|
||||||
firePressedP1 = firePressedP1
|
firePressedB = firePressedB
|
||||||
|| myEvent.get(Event::MouseButtonLeftValue);
|
|| myEvent.get(Event::MouseButtonLeftValue);
|
||||||
}
|
}
|
||||||
if(myMPaddleIDY > -1)
|
if(myMPaddleIDY > -1)
|
||||||
|
@ -302,10 +302,10 @@ void Paddles::updateMouse(bool& firePressedP0, bool& firePressedP1)
|
||||||
(myEvent.get(Event::MouseAxisYMove) * MOUSE_SENSITIVITY),
|
(myEvent.get(Event::MouseAxisYMove) * MOUSE_SENSITIVITY),
|
||||||
TRIGMIN, TRIGRANGE);
|
TRIGMIN, TRIGRANGE);
|
||||||
if(myMPaddleIDY == 0)
|
if(myMPaddleIDY == 0)
|
||||||
firePressedP0 = firePressedP0
|
firePressedA = firePressedA
|
||||||
|| myEvent.get(Event::MouseButtonRightValue);
|
|| myEvent.get(Event::MouseButtonRightValue);
|
||||||
else
|
else
|
||||||
firePressedP1 = firePressedP1
|
firePressedB = firePressedB
|
||||||
|| myEvent.get(Event::MouseButtonRightValue);
|
|| myEvent.get(Event::MouseButtonRightValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -316,45 +316,45 @@ void Paddles::updateDigitalAxes()
|
||||||
{
|
{
|
||||||
// Finally, consider digital input, where movement happens
|
// Finally, consider digital input, where movement happens
|
||||||
// until a digital event is released
|
// until a digital event is released
|
||||||
if(myKeyRepeat0)
|
if(myKeyRepeatA)
|
||||||
{
|
{
|
||||||
myPaddleRepeat0++;
|
myPaddleRepeatA++;
|
||||||
if(myPaddleRepeat0 > DIGITAL_SENSITIVITY)
|
if(myPaddleRepeatA > DIGITAL_SENSITIVITY)
|
||||||
myPaddleRepeat0 = DIGITAL_DISTANCE;
|
myPaddleRepeatA = DIGITAL_DISTANCE;
|
||||||
}
|
}
|
||||||
if(myKeyRepeat1)
|
if(myKeyRepeatB)
|
||||||
{
|
{
|
||||||
myPaddleRepeat1++;
|
myPaddleRepeatB++;
|
||||||
if(myPaddleRepeat1 > DIGITAL_SENSITIVITY)
|
if(myPaddleRepeatB > DIGITAL_SENSITIVITY)
|
||||||
myPaddleRepeat1 = DIGITAL_DISTANCE;
|
myPaddleRepeatB = DIGITAL_DISTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
myKeyRepeat0 = false;
|
myKeyRepeatA = false;
|
||||||
myKeyRepeat1 = false;
|
myKeyRepeatB = false;
|
||||||
|
|
||||||
if(myEvent.get(myP0DecEvent))
|
if(myEvent.get(myLeftADecEvent))
|
||||||
{
|
{
|
||||||
myKeyRepeat0 = true;
|
myKeyRepeatA = true;
|
||||||
if(myCharge[myAxisDigitalZero] > myPaddleRepeat0)
|
if(myCharge[myAxisDigitalZero] > myPaddleRepeatA)
|
||||||
myCharge[myAxisDigitalZero] -= myPaddleRepeat0;
|
myCharge[myAxisDigitalZero] -= myPaddleRepeatA;
|
||||||
}
|
}
|
||||||
if(myEvent.get(myP0IncEvent))
|
if(myEvent.get(myLeftAIncEvent))
|
||||||
{
|
{
|
||||||
myKeyRepeat0 = true;
|
myKeyRepeatA = true;
|
||||||
if((myCharge[myAxisDigitalZero] + myPaddleRepeat0) < TRIGRANGE)
|
if((myCharge[myAxisDigitalZero] + myPaddleRepeatA) < TRIGRANGE)
|
||||||
myCharge[myAxisDigitalZero] += myPaddleRepeat0;
|
myCharge[myAxisDigitalZero] += myPaddleRepeatA;
|
||||||
}
|
}
|
||||||
if(myEvent.get(myP1DecEvent))
|
if(myEvent.get(myLeftBDecEvent))
|
||||||
{
|
{
|
||||||
myKeyRepeat1 = true;
|
myKeyRepeatB = true;
|
||||||
if(myCharge[myAxisDigitalOne] > myPaddleRepeat1)
|
if(myCharge[myAxisDigitalOne] > myPaddleRepeatB)
|
||||||
myCharge[myAxisDigitalOne] -= myPaddleRepeat1;
|
myCharge[myAxisDigitalOne] -= myPaddleRepeatB;
|
||||||
}
|
}
|
||||||
if(myEvent.get(myP1IncEvent))
|
if(myEvent.get(myLeftBIncEvent))
|
||||||
{
|
{
|
||||||
myKeyRepeat1 = true;
|
myKeyRepeatB = true;
|
||||||
if((myCharge[myAxisDigitalOne] + myPaddleRepeat1) < TRIGRANGE)
|
if((myCharge[myAxisDigitalOne] + myPaddleRepeatB) < TRIGRANGE)
|
||||||
myCharge[myAxisDigitalOne] += myPaddleRepeat1;
|
myCharge[myAxisDigitalOne] += myPaddleRepeatB;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -174,18 +174,18 @@ class Paddles : public Controller
|
||||||
|
|
||||||
// Pre-compute the events we care about based on given port
|
// Pre-compute the events we care about based on given port
|
||||||
// This will eliminate test for left or right port in update()
|
// This will eliminate test for left or right port in update()
|
||||||
Event::Type myP0AxisValue, myP1AxisValue,
|
Event::Type myAAxisValue, myBAxisValue,
|
||||||
myP0DecEvent, myP0IncEvent,
|
myLeftADecEvent, myLeftAIncEvent,
|
||||||
myP1DecEvent, myP1IncEvent,
|
myLeftBDecEvent, myLeftBIncEvent,
|
||||||
myP0FireEvent, myP1FireEvent,
|
myLeftAFireEvent, myLeftBFireEvent,
|
||||||
myAxisMouseMotion;
|
myAxisMouseMotion;
|
||||||
|
|
||||||
// The following are used for the various mouse-axis modes
|
// The following are used for the various mouse-axis modes
|
||||||
int myMPaddleID{-1}; // paddle to emulate in 'automatic' mode
|
int myMPaddleID{-1}; // paddle to emulate in 'automatic' mode
|
||||||
int myMPaddleIDX{-1}, myMPaddleIDY{-1}; // paddles to emulate in 'specific axis' mode
|
int myMPaddleIDX{-1}, myMPaddleIDY{-1}; // paddles to emulate in 'specific axis' mode
|
||||||
|
|
||||||
bool myKeyRepeat0{false}, myKeyRepeat1{false};
|
bool myKeyRepeatA{false}, myKeyRepeatB{false};
|
||||||
int myPaddleRepeat0{0}, myPaddleRepeat1{0};
|
int myPaddleRepeatA{0}, myPaddleRepeatB{0};
|
||||||
std::array<int, 2> myCharge{TRIGRANGE/2, TRIGRANGE/2}, myLastCharge{0};
|
std::array<int, 2> myCharge{TRIGRANGE/2, TRIGRANGE/2}, myLastCharge{0};
|
||||||
int myLastAxisX{0}, myLastAxisY{0};
|
int myLastAxisX{0}, myLastAxisY{0};
|
||||||
int myAxisDigitalZero{0}, myAxisDigitalOne{0};
|
int myAxisDigitalZero{0}, myAxisDigitalOne{0};
|
||||||
|
@ -211,7 +211,7 @@ class Paddles : public Controller
|
||||||
/**
|
/**
|
||||||
Update the entire state according to mouse events currently set.
|
Update the entire state according to mouse events currently set.
|
||||||
*/
|
*/
|
||||||
void updateMouse(bool& firePressedP0, bool& firePressedP1);
|
void updateMouse(bool& firePressedA, bool& firePressedB);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Update the axes pin state according to the keyboard events currently set.
|
Update the axes pin state according to the keyboard events currently set.
|
||||||
|
|
|
@ -90,7 +90,7 @@ void PointingDevice::update()
|
||||||
myTrackBallDown, myTrackBallLinesV, myScanCountV, myFirstScanOffsetV);
|
myTrackBallDown, myTrackBallLinesV, myScanCountV, myFirstScanOffsetV);
|
||||||
|
|
||||||
// We allow left and right mouse buttons for fire button
|
// We allow left and right mouse buttons for fire button
|
||||||
setPin(DigitalPin::Six, !getAutoFireState(myEvent.get(Event::JoystickZeroFire) ||
|
setPin(DigitalPin::Six, !getAutoFireState(myEvent.get(Event::LeftJoystickFire) ||
|
||||||
myEvent.get(Event::MouseButtonLeftValue) || myEvent.get(Event::MouseButtonRightValue)));
|
myEvent.get(Event::MouseButtonLeftValue) || myEvent.get(Event::MouseButtonRightValue)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -188,6 +188,8 @@ Settings::Settings()
|
||||||
setPermanent("dbg.fontstyle", "0");
|
setPermanent("dbg.fontstyle", "0");
|
||||||
setPermanent("dbg.uhex", "false");
|
setPermanent("dbg.uhex", "false");
|
||||||
setPermanent("dbg.ghostreadstrap", "true");
|
setPermanent("dbg.ghostreadstrap", "true");
|
||||||
|
setPermanent("dbg.logbreaks", "false");
|
||||||
|
setPermanent("dbg.autosave", "false");
|
||||||
setPermanent("dis.resolve", "true");
|
setPermanent("dis.resolve", "true");
|
||||||
setPermanent("dis.gfxformat", "2");
|
setPermanent("dis.gfxformat", "2");
|
||||||
setPermanent("dis.showaddr", "true");
|
setPermanent("dis.showaddr", "true");
|
||||||
|
@ -240,10 +242,16 @@ Settings::Settings()
|
||||||
setPermanent("dev.tm.uncompressed", 600);
|
setPermanent("dev.tm.uncompressed", 600);
|
||||||
setPermanent("dev.tm.interval", "1f"); // = 1 frame
|
setPermanent("dev.tm.interval", "1f"); // = 1 frame
|
||||||
setPermanent("dev.tm.horizon", "30s"); // = ~30 seconds
|
setPermanent("dev.tm.horizon", "30s"); // = ~30 seconds
|
||||||
// Thumb ARM emulation options
|
|
||||||
setPermanent("dev.thumb.trapfatal", "true");
|
|
||||||
setPermanent("dev.detectedinfo", "true");
|
setPermanent("dev.detectedinfo", "true");
|
||||||
setPermanent("dev.eepromaccess", "true");
|
setPermanent("dev.eepromaccess", "true");
|
||||||
|
// Thumb ARM emulation options
|
||||||
|
setPermanent("dev.thumb.trapfatal", "true");
|
||||||
|
#ifdef DEBUGGER_SUPPORT
|
||||||
|
setPermanent("dev.thumb.inccycles", "true");
|
||||||
|
setPermanent("dev.thumb.cyclefactor", "1.05");
|
||||||
|
setPermanent("dev.thumb.chiptype", "0"); // = LPC2103
|
||||||
|
setPermanent("dev.thumb.mammode", "2");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -613,7 +621,9 @@ void Settings::usage() const
|
||||||
<< " -dbg.fontstyle <0-3> Font style to use in debugger window (bold vs.\n"
|
<< " -dbg.fontstyle <0-3> Font style to use in debugger window (bold vs.\n"
|
||||||
<< " normal)\n"
|
<< " normal)\n"
|
||||||
<< " -dbg.ghostreadstrap <1|0> Debugger traps on 'ghost' reads\n"
|
<< " -dbg.ghostreadstrap <1|0> Debugger traps on 'ghost' reads\n"
|
||||||
<< " -dbg.uhex <0|1> lower-/uppercase HEX display\n"
|
<< " -dbg.uhex <0|1> Lower-/uppercase HEX display\n"
|
||||||
|
<< " -dbg.logbreaks <0|1> Log breaks and traps and continue emulation\n"
|
||||||
|
<< " -dbg.autosave <0|1> Automatically save breaks, traps etc.\n"
|
||||||
<< " -break <address> Set a breakpoint at 'address'\n"
|
<< " -break <address> Set a breakpoint at 'address'\n"
|
||||||
<< " -debug Start in debugger mode\n"
|
<< " -debug Start in debugger mode\n"
|
||||||
<< endl
|
<< endl
|
||||||
|
@ -674,12 +684,19 @@ void Settings::usage() const
|
||||||
<< " -dev.tiadriven <1|0> Drive unused TIA pins randomly on a\n"
|
<< " -dev.tiadriven <1|0> Drive unused TIA pins randomly on a\n"
|
||||||
<< " read/peek\n"
|
<< " read/peek\n"
|
||||||
#ifdef DEBUGGER_SUPPORT
|
#ifdef DEBUGGER_SUPPORT
|
||||||
<< " -dev.rwportbreak <1|0> Debugger breaks on reads from write ports\n"
|
<< " -dev.rwportbreak <1|0> Debugger breaks on reads from write ports\n"
|
||||||
<< " -dev.wrportbreak <1|0> Debugger breaks on writes to read ports\n"
|
<< " -dev.wrportbreak <1|0> Debugger breaks on writes to read ports\n"
|
||||||
#endif
|
#endif
|
||||||
<< " -dev.thumb.trapfatal <1|0> Determines whether errors in ARM emulation\n"
|
<< " -dev.thumb.trapfatal <1|0> Determines whether errors in ARM emulation\n"
|
||||||
<< " throw an exception\n"
|
<< " throw an exception\n"
|
||||||
<< " -dev.eepromaccess <1|0> Enable messages for AtariVox/SaveKey access\n"
|
#ifdef DEBUGGER_SUPPORT
|
||||||
|
<< " -dev.thumb.inccycles <1|0> Determines whether ARM emulation cycles\n"
|
||||||
|
<< " increase system cycles\n"
|
||||||
|
<< " -dev.thumb.cyclefactor <float> Sets the ARM cycles correction multiplier\n"
|
||||||
|
<< " -dev.thumb.chiptype <0|1> Selects the ARM chip type\n"
|
||||||
|
<< " -dev.thumb.mammode <0-3> Selects the LPC's MAM mode\n"
|
||||||
|
#endif
|
||||||
|
<< " -dev.eepromaccess <1|0> Enable messages for AtariVox/SaveKey access\n"
|
||||||
<< " messages\n"
|
<< " messages\n"
|
||||||
<< " -dev.tia.type <standard|custom| Selects a TIA type\n"
|
<< " -dev.tia.type <standard|custom| Selects a TIA type\n"
|
||||||
<< " koolaidman|\n"
|
<< " koolaidman|\n"
|
||||||
|
|
|
@ -541,12 +541,3 @@ bool TIASurface::correctAspect() const
|
||||||
{
|
{
|
||||||
return myOSystem.settings().getBool("tia.correct_aspect");
|
return myOSystem.settings().getBool("tia.correct_aspect");
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void TIASurface::resetSurfaces()
|
|
||||||
{
|
|
||||||
myTiaSurface->reload();
|
|
||||||
mySLineSurface->reload();
|
|
||||||
myBaseTiaSurface->reload();
|
|
||||||
myShadeSurface->reload();
|
|
||||||
}
|
|
||||||
|
|
|
@ -49,7 +49,7 @@ class TIASurface
|
||||||
Creates a new TIASurface object
|
Creates a new TIASurface object
|
||||||
*/
|
*/
|
||||||
explicit TIASurface(OSystem& system);
|
explicit TIASurface(OSystem& system);
|
||||||
virtual ~TIASurface();
|
~TIASurface();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Set the TIA object, which is needed for actually rendering the TIA image.
|
Set the TIA object, which is needed for actually rendering the TIA image.
|
||||||
|
@ -183,11 +183,6 @@ class TIASurface
|
||||||
*/
|
*/
|
||||||
void updateSurfaceSettings();
|
void updateSurfaceSettings();
|
||||||
|
|
||||||
/**
|
|
||||||
Issue a 'reload' to each surface.
|
|
||||||
*/
|
|
||||||
void resetSurfaces();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
Average current calculated buffer's pixel with previous calculated buffer's pixel (50:50).
|
Average current calculated buffer's pixel with previous calculated buffer's pixel (50:50).
|
||||||
|
@ -213,7 +208,8 @@ class TIASurface
|
||||||
FrameBuffer& myFB;
|
FrameBuffer& myFB;
|
||||||
TIA* myTIA{nullptr};
|
TIA* myTIA{nullptr};
|
||||||
|
|
||||||
unique_ptr<FBSurface> myTiaSurface, mySLineSurface, myBaseTiaSurface, myShadeSurface;
|
shared_ptr<FBSurface> myTiaSurface, mySLineSurface,
|
||||||
|
myBaseTiaSurface, myShadeSurface;
|
||||||
|
|
||||||
// NTSC object to use in TIA rendering mode
|
// NTSC object to use in TIA rendering mode
|
||||||
NTSCFilter myNTSCFilter;
|
NTSCFilter myNTSCFilter;
|
||||||
|
|
|
@ -32,7 +32,6 @@ class Cartridge;
|
||||||
|
|
||||||
#ifdef RETRON77
|
#ifdef RETRON77
|
||||||
#define UNSAFE_OPTIMIZATIONS
|
#define UNSAFE_OPTIMIZATIONS
|
||||||
#define NO_THUMB_STATS
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define ROMADDMASK 0x7FFFF
|
#define ROMADDMASK 0x7FFFF
|
||||||
|
@ -46,6 +45,17 @@ class Cartridge;
|
||||||
#define CPSR_C (1u<<29)
|
#define CPSR_C (1u<<29)
|
||||||
#define CPSR_V (1u<<28)
|
#define CPSR_V (1u<<28)
|
||||||
|
|
||||||
|
#ifdef DEBUGGER_SUPPORT
|
||||||
|
#define THUMB_CYCLE_COUNT
|
||||||
|
//#define COUNT_OPS
|
||||||
|
#define THUMB_STATS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef THUMB_CYCLE_COUNT
|
||||||
|
//#define EMULATE_PIPELINE // enable coarse ARM pipeline emulation (TODO)
|
||||||
|
#define TIMER_0 // enable timer 0 support (e.g. for measuring cycle count)
|
||||||
|
#endif
|
||||||
|
|
||||||
class Thumbulator
|
class Thumbulator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -59,16 +69,37 @@ class Thumbulator
|
||||||
CDFJplus, // cartridges of type CDFJ+
|
CDFJplus, // cartridges of type CDFJ+
|
||||||
DPCplus // cartridges of type DPC+
|
DPCplus // cartridges of type DPC+
|
||||||
};
|
};
|
||||||
|
enum class ChipType {
|
||||||
|
LPC2101, // Harmony (includes LPC2103)
|
||||||
|
LPC2104_OC, // Dev cart overclocked (includes LPC2105)
|
||||||
|
LPC2104, // Dev cart (includes LPC2105)
|
||||||
|
LPC213x, // future use (includes LPC2132)
|
||||||
|
numTypes
|
||||||
|
};
|
||||||
|
enum class MamModeType {
|
||||||
|
mode0, mode1, mode2, modeX
|
||||||
|
};
|
||||||
|
struct ChipPropsType {
|
||||||
|
double MHz;
|
||||||
|
uInt32 flashCycles;
|
||||||
|
uInt32 flashBanks;
|
||||||
|
};
|
||||||
struct Stats {
|
struct Stats {
|
||||||
#ifndef NO_THUMB_STATS
|
uInt32 instructions{0};
|
||||||
uInt32 fetches{0}, reads{0}, writes{0};
|
#ifdef THUMB_STATS
|
||||||
|
uInt32 reads{0}, writes{0};
|
||||||
|
uInt32 nCylces{0}, sCylces{0}, iCylces{0};
|
||||||
|
uInt32 branches{0}, taken{0};
|
||||||
|
uInt32 mamPrefetchHits{0}, mamPrefetchMisses{0};
|
||||||
|
uInt32 mamBranchHits{0}, mamBranchMisses{0};
|
||||||
|
uInt32 mamDataHits{0}, mamDataMisses{0};
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
Thumbulator(const uInt16* rom_ptr, uInt16* ram_ptr, uInt32 rom_size,
|
Thumbulator(const uInt16* rom_ptr, uInt16* ram_ptr, uInt32 rom_size,
|
||||||
const uInt32 c_base, const uInt32 c_start, const uInt32 c_stack,
|
const uInt32 c_base, const uInt32 c_start, const uInt32 c_stack,
|
||||||
bool traponfatal, Thumbulator::ConfigureFor configurefor,
|
bool traponfatal, double cyclefactor,
|
||||||
|
Thumbulator::ConfigureFor configurefor,
|
||||||
Cartridge* cartridge);
|
Cartridge* cartridge);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -79,11 +110,24 @@ class Thumbulator
|
||||||
@return The results of any debugging output (if enabled),
|
@return The results of any debugging output (if enabled),
|
||||||
otherwise an empty string
|
otherwise an empty string
|
||||||
*/
|
*/
|
||||||
string run();
|
string run(uInt32& cycles, bool irqDrivenAudio);
|
||||||
string run(uInt32 cycles);
|
void enableCycleCount(bool enable) { _countCycles = enable; }
|
||||||
const Stats& stats() const { return _stats; }
|
const Stats& stats() const { return _stats; }
|
||||||
|
uInt32 cycles() const { return _totalCycles; }
|
||||||
|
ChipPropsType setChipType(ChipType type);
|
||||||
|
void setMamMode(MamModeType mode) { mamcr = mode; }
|
||||||
|
void lockMamMode(bool lock) { _lockMamcr = lock; }
|
||||||
|
MamModeType mamMode() const { return static_cast<MamModeType>(mamcr); }
|
||||||
|
|
||||||
#ifndef UNSAFE_OPTIMIZATIONS
|
#ifdef THUMB_CYCLE_COUNT
|
||||||
|
void cycleFactor(double factor) { _armCyclesFactor = factor; }
|
||||||
|
double cycleFactor() const { return _armCyclesFactor; }
|
||||||
|
#else
|
||||||
|
void cycleFactor(double) { }
|
||||||
|
double cycleFactor() const { return 1.0; }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef UNSAFE_OPTIMIZATIONS
|
||||||
/**
|
/**
|
||||||
Normally when a fatal error is encountered, the ARM emulation
|
Normally when a fatal error is encountered, the ARM emulation
|
||||||
immediately throws an exception and exits. This method allows execution
|
immediately throws an exception and exits. This method allows execution
|
||||||
|
@ -96,8 +140,8 @@ class Thumbulator
|
||||||
|
|
||||||
@param enable Enable (the default) or disable exceptions on fatal errors
|
@param enable Enable (the default) or disable exceptions on fatal errors
|
||||||
*/
|
*/
|
||||||
static void trapFatalErrors(bool enable) { trapOnFatal = enable; }
|
void trapFatalErrors(bool enable) { trapOnFatal = enable; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Inform the Thumbulator class about the console currently in use,
|
Inform the Thumbulator class about the console currently in use,
|
||||||
|
@ -155,18 +199,35 @@ class Thumbulator
|
||||||
sxth,
|
sxth,
|
||||||
tst,
|
tst,
|
||||||
uxtb,
|
uxtb,
|
||||||
uxth
|
uxth,
|
||||||
|
numOps
|
||||||
};
|
};
|
||||||
|
#ifdef THUMB_CYCLE_COUNT
|
||||||
|
enum class CycleType {
|
||||||
|
S, N, I // Sequential, Non-sequential, Internal
|
||||||
|
};
|
||||||
|
enum class AccessType {
|
||||||
|
prefetch, branch, data
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
const std::array<ChipPropsType, uInt32(ChipType::numTypes)> ChipProps =
|
||||||
|
{{
|
||||||
|
{ 70.0, 4, 1 }, // LPC2101_02_03
|
||||||
|
{ 70.0, 4, 2 }, // LPC2104_05_06 Overclocked
|
||||||
|
{ 60.0, 3, 2 }, // LPC2104_05_06
|
||||||
|
{ 60.0, 3, 1 }, // LPC2132..
|
||||||
|
}};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
string doRun(uInt32& cycles, bool irqDrivenAudio);
|
||||||
uInt32 read_register(uInt32 reg);
|
uInt32 read_register(uInt32 reg);
|
||||||
void write_register(uInt32 reg, uInt32 data);
|
void write_register(uInt32 reg, uInt32 data, bool isFlowBreak = true);
|
||||||
uInt32 fetch16(uInt32 addr);
|
uInt32 fetch16(uInt32 addr);
|
||||||
uInt32 read16(uInt32 addr);
|
uInt32 read16(uInt32 addr);
|
||||||
uInt32 read32(uInt32 addr);
|
uInt32 read32(uInt32 addr);
|
||||||
#ifndef UNSAFE_OPTIMIZATIONS
|
#ifndef UNSAFE_OPTIMIZATIONS
|
||||||
bool isProtected(uInt32 addr);
|
bool isProtected(uInt32 addr);
|
||||||
#endif
|
#endif
|
||||||
void write16(uInt32 addr, uInt32 data);
|
void write16(uInt32 addr, uInt32 data);
|
||||||
void write32(uInt32 addr, uInt32 data);
|
void write32(uInt32 addr, uInt32 data);
|
||||||
void updateTimer(uInt32 cycles);
|
void updateTimer(uInt32 cycles);
|
||||||
|
@ -180,7 +241,7 @@ class Thumbulator
|
||||||
void do_cflag_bit(uInt32 x);
|
void do_cflag_bit(uInt32 x);
|
||||||
void do_vflag_bit(uInt32 x);
|
void do_vflag_bit(uInt32 x);
|
||||||
|
|
||||||
#ifndef UNSAFE_OPTIMIZATIONS
|
#ifndef UNSAFE_OPTIMIZATIONS
|
||||||
// Throw a runtime_error exception containing an error referencing the
|
// Throw a runtime_error exception containing an error referencing the
|
||||||
// given message and variables
|
// given message and variables
|
||||||
// Note that the return value is never used in these methods
|
// Note that the return value is never used in these methods
|
||||||
|
@ -189,10 +250,18 @@ class Thumbulator
|
||||||
|
|
||||||
void dump_counters();
|
void dump_counters();
|
||||||
void dump_regs();
|
void dump_regs();
|
||||||
#endif
|
#endif
|
||||||
int execute();
|
int execute();
|
||||||
int reset();
|
int reset();
|
||||||
|
|
||||||
|
#ifdef THUMB_CYCLE_COUNT
|
||||||
|
bool isMamBuffered(uInt32 addr, AccessType = AccessType::data);
|
||||||
|
void incCycles(AccessType accessType, uInt32 cycles);
|
||||||
|
void incSCycles(uInt32 addr, AccessType = AccessType::data);
|
||||||
|
void incNCycles(uInt32 addr, AccessType = AccessType::data);
|
||||||
|
void incICycles(uInt32 m = 1);
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const uInt16* rom{nullptr};
|
const uInt16* rom{nullptr};
|
||||||
uInt32 romSize{0};
|
uInt32 romSize{0};
|
||||||
|
@ -202,26 +271,58 @@ class Thumbulator
|
||||||
const unique_ptr<Op[]> decodedRom; // NOLINT
|
const unique_ptr<Op[]> decodedRom; // NOLINT
|
||||||
uInt16* ram{nullptr};
|
uInt16* ram{nullptr};
|
||||||
std::array<uInt32, 16> reg_norm; // normal execution mode, do not have a thread mode
|
std::array<uInt32, 16> reg_norm; // normal execution mode, do not have a thread mode
|
||||||
uInt32 cpsr{0}, mamcr{0};
|
uInt32 cpsr{0};
|
||||||
|
MamModeType mamcr{MamModeType::mode0};
|
||||||
bool handler_mode{false};
|
bool handler_mode{false};
|
||||||
uInt32 systick_ctrl{0}, systick_reload{0}, systick_count{0}, systick_calibrate{0};
|
uInt32 systick_ctrl{0}, systick_reload{0}, systick_count{0}, systick_calibrate{0};
|
||||||
#ifndef UNSAFE_OPTIMIZATIONS
|
ChipType _chipType{ChipType::LPC2101};
|
||||||
uInt32 instructions{0};
|
ConsoleTiming _consoleTiming{ConsoleTiming::ntsc};
|
||||||
#endif
|
double _MHz{70.0};
|
||||||
Stats _stats;
|
uInt32 _flashCycles{4};
|
||||||
|
uInt32 _flashBanks{1};
|
||||||
|
Stats _stats{0};
|
||||||
|
bool _irqDrivenAudio{false};
|
||||||
|
uInt32 _totalCycles{0};
|
||||||
|
|
||||||
// For emulation of LPC2103's timer 1, used for NTSC/PAL/SECAM detection.
|
// For emulation of LPC2103's timer 1, used for NTSC/PAL/SECAM detection.
|
||||||
// Register names from documentation:
|
// Register names from documentation:
|
||||||
// http://www.nxp.com/documents/user_manual/UM10161.pdf
|
// http://www.nxp.com/documents/user_manual/UM10161.pdf
|
||||||
uInt32 T1TCR{0}; // Timer 1 Timer Control Register
|
#ifdef TIMER_0
|
||||||
uInt32 T1TC{0}; // Timer 1 Timer Counter
|
uInt32 T0TCR{0}; // Timer 0 Timer Control Register
|
||||||
|
uInt32 T0TC{0}; // Timer 0 Timer Counter
|
||||||
|
uInt32 tim0Start{0}; // _totalCycles when Timer 0 got started last time
|
||||||
|
uInt32 tim0Total{0}; // total cycles of Timer 0
|
||||||
|
#endif
|
||||||
|
uInt32 T1TCR{0}; // Timer 1 Timer Control Register
|
||||||
|
uInt32 T1TC{0}; // Timer 1 Timer Counter
|
||||||
|
uInt32 tim1Start{0}; // _totalCycles when Timer 1 got started last time
|
||||||
|
uInt32 tim1Total{0}; // total cycles of Timer 1
|
||||||
double timing_factor{0.0};
|
double timing_factor{0.0};
|
||||||
|
|
||||||
#ifndef UNSAFE_OPTIMIZATIONS
|
#ifndef UNSAFE_OPTIMIZATIONS
|
||||||
ostringstream statusMsg;
|
ostringstream statusMsg;
|
||||||
|
bool trapOnFatal{true};
|
||||||
|
#endif
|
||||||
|
bool _countCycles{false};
|
||||||
|
bool _lockMamcr{false};
|
||||||
|
|
||||||
static bool trapOnFatal;
|
#ifdef THUMB_CYCLE_COUNT
|
||||||
#endif
|
double _armCyclesFactor{1.05};
|
||||||
|
uInt32 _pipeIdx{0};
|
||||||
|
CycleType _prefetchCycleType[3]{CycleType::S};
|
||||||
|
CycleType _lastCycleType[3]{CycleType::S};
|
||||||
|
AccessType _prefetchAccessType[3]{AccessType::data};
|
||||||
|
#ifdef EMULATE_PIPELINE
|
||||||
|
uInt32 _fetchPipeline{0}; // reserve fetch cycles resulting from pipelining (execution stage)
|
||||||
|
uInt32 _memory0Pipeline{0}, _memory1Pipeline{0};
|
||||||
|
#endif
|
||||||
|
uInt32 _prefetchBufferAddr[2]{0};
|
||||||
|
uInt32 _branchBufferAddr[2]{0};
|
||||||
|
uInt32 _dataBufferAddr{0};
|
||||||
|
#endif
|
||||||
|
#ifdef COUNT_OPS
|
||||||
|
uInt32 opCount[size_t(Op::numOps)]{0};
|
||||||
|
#endif
|
||||||
|
|
||||||
ConfigureFor configuration;
|
ConfigureFor configuration;
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ MODULE_OBJS := \
|
||||||
src/emucore/Bankswitch.o \
|
src/emucore/Bankswitch.o \
|
||||||
src/emucore/Booster.o \
|
src/emucore/Booster.o \
|
||||||
src/emucore/Cart.o \
|
src/emucore/Cart.o \
|
||||||
|
src/emucore/CartARM.o \
|
||||||
src/emucore/CartCreator.o \
|
src/emucore/CartCreator.o \
|
||||||
src/emucore/CartDetector.o \
|
src/emucore/CartDetector.o \
|
||||||
src/emucore/CartEnhanced.o \
|
src/emucore/CartEnhanced.o \
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "Widget.hxx"
|
#include "Widget.hxx"
|
||||||
#include "Font.hxx"
|
#include "Font.hxx"
|
||||||
#include "WhatsNewDialog.hxx"
|
#include "WhatsNewDialog.hxx"
|
||||||
|
#include "MediaFactory.hxx"
|
||||||
|
|
||||||
#include "AboutDialog.hxx"
|
#include "AboutDialog.hxx"
|
||||||
|
|
||||||
|
@ -80,8 +81,10 @@ AboutDialog::AboutDialog(OSystem& osystem, DialogContainer& parent,
|
||||||
xpos = HBORDER * 2; ypos += lineHeight + VGAP * 2;
|
xpos = HBORDER * 2; ypos += lineHeight + VGAP * 2;
|
||||||
for(int i = 0; i < myLinesPerPage; i++)
|
for(int i = 0; i < myLinesPerPage; i++)
|
||||||
{
|
{
|
||||||
myDesc.push_back(new StaticTextWidget(this, font, xpos, ypos, _w - xpos * 2,
|
StaticTextWidget* s = new StaticTextWidget(this, font, xpos, ypos, _w - xpos * 2,
|
||||||
fontHeight, "", TextAlign::Left));
|
fontHeight, "", TextAlign::Left, kNone);
|
||||||
|
s->setID(i);
|
||||||
|
myDesc.push_back(s);
|
||||||
myDescStr.emplace_back("");
|
myDescStr.emplace_back("");
|
||||||
ypos += fontHeight;
|
ypos += fontHeight;
|
||||||
}
|
}
|
||||||
|
@ -160,9 +163,8 @@ void AboutDialog::updateStrings(int page, int lines, string& title)
|
||||||
|
|
||||||
case 4:
|
case 4:
|
||||||
title = "Cast of thousands";
|
title = "Cast of thousands";
|
||||||
ADD_ATEXT("\\L\\c0""Special thanks to AtariAge for introducing the");
|
ADD_ATEXT("\\L\\c0""Special thanks to <AtariAge> for introducing the");
|
||||||
ADD_ATEXT("\\L\\c0""Atari 2600 to a whole new generation.");
|
ADD_ATEXT("\\L\\c0""Atari 2600 to a whole new generation.");
|
||||||
ADD_ATEXT("\\L\\c2"" http://www.atariage.com");
|
|
||||||
ADD_ALINE();
|
ADD_ALINE();
|
||||||
ADD_ATEXT("\\L\\c0""Finally, a huge thanks to the original Atari 2600");
|
ADD_ATEXT("\\L\\c0""Finally, a huge thanks to the original Atari 2600");
|
||||||
ADD_ATEXT("\\L\\c0""VCS team for giving us the magic, and to the");
|
ADD_ATEXT("\\L\\c0""VCS team for giving us the magic, and to the");
|
||||||
|
@ -242,6 +244,24 @@ void AboutDialog::displayInfo()
|
||||||
myDesc[i]->setAlign(align);
|
myDesc[i]->setAlign(align);
|
||||||
myDesc[i]->setTextColor(color);
|
myDesc[i]->setTextColor(color);
|
||||||
myDesc[i]->setLabel(str);
|
myDesc[i]->setLabel(str);
|
||||||
|
// add some labeled links
|
||||||
|
if(BSPF::containsIgnoreCase(str, "see manual"))
|
||||||
|
myDesc[i]->setUrl("https://stella-emu.github.io/docs/index.html#License", "manual");
|
||||||
|
else if(BSPF::containsIgnoreCase(str, "Stephen Anthony"))
|
||||||
|
myDesc[i]->setUrl("http://minbar.org", "Stephen Anthony");
|
||||||
|
else if(BSPF::containsIgnoreCase(str, "Bradford W. Mott"))
|
||||||
|
myDesc[i]->setUrl("www.intellimedia.ncsu.edu/people/bwmott", "Bradford W. Mott");
|
||||||
|
else if(BSPF::containsIgnoreCase(str, "ScummVM project"))
|
||||||
|
myDesc[i]->setUrl("www.scummvm.org", "ScummVM");
|
||||||
|
else if(BSPF::containsIgnoreCase(str, "Ian Bogost"))
|
||||||
|
myDesc[i]->setUrl("http://bogost.com", "Ian Bogost");
|
||||||
|
else if(BSPF::containsIgnoreCase(str, "CRT Simulation"))
|
||||||
|
myDesc[i]->setUrl("http://blargg.8bitalley.com/libs/ntsc.html", "CRT Simulation effects");
|
||||||
|
else if(BSPF::containsIgnoreCase(str, "<AtariAge>"))
|
||||||
|
myDesc[i]->setUrl("www.atariage.com", "AtariAge", "<AtariAge>");
|
||||||
|
else
|
||||||
|
// extract URL from label
|
||||||
|
myDesc[i]->setUrl();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Redraw entire dialog
|
// Redraw entire dialog
|
||||||
|
@ -280,7 +300,52 @@ void AboutDialog::handleCommand(CommandSender* sender, int cmd, int data, int id
|
||||||
myWhatsNewDialog->open();
|
myWhatsNewDialog->open();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case StaticTextWidget::kOpenUrlCmd:
|
||||||
|
{
|
||||||
|
const string url = myDesc[id]->getUrl();
|
||||||
|
|
||||||
|
if(url != EmptyString)
|
||||||
|
MediaFactory::openURL(url);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Dialog::handleCommand(sender, cmd, data, 0);
|
Dialog::handleCommand(sender, cmd, data, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
const string AboutDialog::getUrl(const string& str) const
|
||||||
|
{
|
||||||
|
bool isUrl = false;
|
||||||
|
size_t start = 0, len = 0;
|
||||||
|
|
||||||
|
for(size_t i = 0; i < str.size(); ++i)
|
||||||
|
{
|
||||||
|
string remainder = str.substr(i);
|
||||||
|
char ch = str[i];
|
||||||
|
|
||||||
|
if(!isUrl
|
||||||
|
&& (BSPF::startsWithIgnoreCase(remainder, "http://")
|
||||||
|
|| BSPF::startsWithIgnoreCase(remainder, "https://")
|
||||||
|
|| BSPF::startsWithIgnoreCase(remainder, "www.")))
|
||||||
|
{
|
||||||
|
isUrl = true;
|
||||||
|
start = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// hack, change mode without changing string length
|
||||||
|
if(isUrl)
|
||||||
|
{
|
||||||
|
if((ch == ' ' || ch == ')' || ch == '>'))
|
||||||
|
isUrl = false;
|
||||||
|
else
|
||||||
|
len++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(len)
|
||||||
|
return str.substr(start, len);
|
||||||
|
else
|
||||||
|
return EmptyString;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,7 @@ class AboutDialog : public Dialog
|
||||||
void handleCommand(CommandSender* sender, int cmd, int data, int id) override;
|
void handleCommand(CommandSender* sender, int cmd, int data, int id) override;
|
||||||
void updateStrings(int page, int lines, string& title);
|
void updateStrings(int page, int lines, string& title);
|
||||||
void displayInfo();
|
void displayInfo();
|
||||||
|
const string getUrl(const string& text) const;
|
||||||
|
|
||||||
void loadConfig() override { displayInfo(); }
|
void loadConfig() override { displayInfo(); }
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ ColorWidget::ColorWidget(GuiObject* boss, const GUI::Font& font,
|
||||||
_framed{framed},
|
_framed{framed},
|
||||||
_cmd{cmd}
|
_cmd{cmd}
|
||||||
{
|
{
|
||||||
_flags = Widget::FLAG_ENABLED | Widget::FLAG_CLEARBG | Widget::FLAG_RETAIN_FOCUS;
|
_flags = Widget::FLAG_ENABLED | Widget::FLAG_CLEARBG;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -45,6 +45,8 @@ class ColorWidget : public Widget, public CommandSender
|
||||||
void setCrossed(bool enable);
|
void setCrossed(bool enable);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
void handleMouseEntered() override { }
|
||||||
|
void handleMouseLeft() override { }
|
||||||
void drawWidget(bool hilite) override;
|
void drawWidget(bool hilite) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -168,6 +168,13 @@ const string& ContextMenu::getSelectedName() const
|
||||||
return (_selectedItem >= 0) ? _entries[_selectedItem].first : EmptyString;
|
return (_selectedItem >= 0) ? _entries[_selectedItem].first : EmptyString;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void ContextMenu::setSelectedName(const string& name)
|
||||||
|
{
|
||||||
|
if(_selectedItem >= 0)
|
||||||
|
_entries[_selectedItem].first = name;
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
const Variant& ContextMenu::getSelectedTag() const
|
const Variant& ContextMenu::getSelectedTag() const
|
||||||
{
|
{
|
||||||
|
|