mirror of https://github.com/stella-emu/stella.git
Merge branch 'master' of https://github.com/stella-emu/stella
This commit is contained in:
commit
c06658a275
|
@ -31,3 +31,5 @@ src/**/*.psess
|
|||
src/**/*.vspx
|
||||
src/**/**.pdb
|
||||
Stella.xcscheme
|
||||
src/tools/fonts/*
|
||||
|
||||
|
|
49
Changes.txt
49
Changes.txt
|
@ -12,7 +12,43 @@
|
|||
Release History
|
||||
===========================================================================
|
||||
|
||||
6.0.2 to 6.1: (MM dd, 2020)
|
||||
6.1 to 6.2: (??? ??, 2020)
|
||||
|
||||
* Added that paddle centering and sensitivity can be adjusted (TODO: Doc)
|
||||
|
||||
* Added that Driving controller sensitivity can be adjusted (TODO: Doc)
|
||||
|
||||
* Added high scores: Score addresses, game variation etc. can be defined for
|
||||
a game. This allows the user to save high scores for these games. For each
|
||||
game and variation, the top 10 scores can be saved. (TODO: Doc)
|
||||
|
||||
* Add option which lets default ROM path follow launcher navigation (TODO: Doc)
|
||||
|
||||
* Added displaying last write address in the debugger.
|
||||
|
||||
* Added detection of color and audio data in DiStella.
|
||||
|
||||
* Restored 'cfg' directory for Distella config files.
|
||||
|
||||
-Have fun!
|
||||
|
||||
|
||||
6.1 to 6.1.1: (April 4, 2020)
|
||||
|
||||
* Fixed crash in 3E bankswitching scheme when writing to ROM addresses.
|
||||
|
||||
* Fix snapshots on Retina HiDPI displays capturing only the top-left
|
||||
corner.
|
||||
|
||||
* Fixed wrong color for BK (background) swatch in the debugger.
|
||||
|
||||
* Fixed 'Right Diff' button in Command menu changing left difficulty
|
||||
instead.
|
||||
|
||||
* Fixed compilation of libretro port on Debian Buster.
|
||||
|
||||
|
||||
6.0.2 to 6.1: (March 22, 2020)
|
||||
|
||||
* IMPORTANT NOTES:
|
||||
- Because of major event remapping changes, all remappings will be reset
|
||||
|
@ -119,7 +155,9 @@
|
|||
|
||||
* Added option to change pitch of Pitfall II music.
|
||||
|
||||
* ROM Info Launcher can now display multiple lines per property and
|
||||
* ROM Info Viewer size is not limited to fixed zoom steps anymore.
|
||||
|
||||
* ROM Info Viewer can now display multiple lines per property and the
|
||||
bank switching type.
|
||||
|
||||
* In file listings, you can now select directories by holding 'Shift' on
|
||||
|
@ -179,6 +217,10 @@
|
|||
* Fixed bug in DPC+ scheme; 'fast fetch mode' was enabled at startup,
|
||||
when it should be disabled by default.
|
||||
|
||||
* Some more work on DPC+ playfield 'jitter' effect for certain older DPC+
|
||||
driver versions; more ROMs are now detected properly. Special thanks
|
||||
to SpiceWare for his research in this area.
|
||||
|
||||
* Added proper Retron77 port.
|
||||
|
||||
* Added proper libretro port, and fixed display for OpenGLES renderers.
|
||||
|
@ -192,7 +234,8 @@
|
|||
|
||||
* Updated included PNG library to latest stable version.
|
||||
|
||||
-Have fun!
|
||||
* Updated UNIX configure script to work with the gcc version 10 and
|
||||
above.
|
||||
|
||||
|
||||
6.0.1 to 6.0.2: (October 11, 2019)
|
||||
|
|
|
@ -458,11 +458,17 @@ elif test "$have_gcc" = yes; then
|
|||
fi
|
||||
|
||||
case $cxx_version in
|
||||
4.[7-9]|4.[7-9].[0-9]|4.[7-9].[0-9][-.]*|[5-9]|[5-9].[0-9]|[5-9].[0-9].[0-9]|[5-9].[0-9].[0-9][-.]*)
|
||||
[1-9]*)
|
||||
_cxx_major=`echo $cxx_version | cut -d '.' -f 1`
|
||||
_cxx_minor=`echo $cxx_version | cut -d '.' -f 2`
|
||||
cxx_version="$cxx_version, ok"
|
||||
cxx_verc_fail=no
|
||||
# Need at least version 4.7
|
||||
if [ $_cxx_major -ge 5 ] || [ $_cxx_major -eq 4 -a $_cxx_minor -ge 7 ]; then
|
||||
cxx_version="$cxx_version, ok"
|
||||
cxx_verc_fail=no
|
||||
else
|
||||
cxx_version="$cxx_version, bad"
|
||||
cxx_verc_fail=yes
|
||||
fi
|
||||
;;
|
||||
'not found')
|
||||
cxx_verc_fail=yes
|
||||
|
|
|
@ -1,3 +1,17 @@
|
|||
stella (6.1.1-1) stable; urgency=high
|
||||
|
||||
* Version 6.1.1 release
|
||||
|
||||
-- Stephen Anthony <sa666666@gmail.com> Sat, 04 Apr 2020 17:09:59 -0230
|
||||
|
||||
|
||||
stella (6.1-1) stable; urgency=high
|
||||
|
||||
* Version 6.1 release
|
||||
|
||||
-- Stephen Anthony <sa666666@gmail.com> Sun, 22 Mar 2020 17:09:59 -0230
|
||||
|
||||
|
||||
stella (6.0.2-1) stable; urgency=high
|
||||
|
||||
* Version 6.0.2 release
|
||||
|
|
|
@ -121,13 +121,14 @@ feature that no other 2600 debugger has; it's <b>completely</b> cross-platform.<
|
|||
|
||||
<li>Supports Distella 'configuration directives', which may be used to
|
||||
override automatic code/data determination in the disassembly. For now,
|
||||
the following directives are supported: CODE, GFX, PGFX, DATA, ROW.
|
||||
These directives can be entered at the debugger prompt, or (automatically)
|
||||
the following directives are supported: CODE, GFX, PGFX, COL, PCOL, BCOL, AUD, DATA, ROW.
|
||||
These directives can be entered at the debugger prompt, or be (automatically)
|
||||
loaded and saved in configuration files.</li>
|
||||
|
||||
<li>Extensive disassembly support, both from the emulation core and with help
|
||||
from Distella. Where possible, the disassembly differentiates between code,
|
||||
player graphics and playfield graphics (ie, addresses stored in GRPx and PFx)
|
||||
player and playfield graphics, colors and audio (ie, addresses stored in
|
||||
GRPx, PFx, COLUxx, AUDxx)
|
||||
and data (addresses used as an operand of a command). Code sections are also
|
||||
differentiated between actual code, and 'tentative' code (ie, areas that may
|
||||
represent code sections, but haven't actually been executed yet). Such
|
||||
|
@ -906,7 +907,9 @@ Type "help 'cmd'" to see extended information about the given command.</p>
|
|||
|
||||
<pre>
|
||||
a - Set Accumulator to <value>
|
||||
aud - Mark 'AUD' range in disassembly
|
||||
base - Set default number base to <base> (bin, dec, hex)
|
||||
bcol - Mark 'BCOL' range in disassembly
|
||||
break - Set/clear breakpoint at <address> and <bank>
|
||||
breakif - Set/clear breakpoint on <condition>
|
||||
breaklabel - Set/clear breakpoint on <address> (no mirrors, all banks)
|
||||
|
@ -919,6 +922,7 @@ clearsavestateifs - Clear all savestate points
|
|||
clearwatches - Clear all watches
|
||||
cls - Clear prompt area of text
|
||||
code - Mark 'CODE' range in disassembly
|
||||
col - Mark 'COL' range in disassembly
|
||||
colortest - Show value xx as TIA color
|
||||
d - Decimal Mode Flag: set (0 or 1), or toggle (no arg)
|
||||
data - Mark 'DATA' range in disassembly
|
||||
|
@ -959,6 +963,7 @@ clearsavestateifs - Clear all savestate points
|
|||
n - Negative Flag: set (0 or 1), or toggle (no arg)
|
||||
palette - Show current TIA palette
|
||||
pc - Set Program Counter to address xx
|
||||
pcol - Mark 'PCOL' range in disassembly
|
||||
pgfx - Mark 'PGFX' range in disassembly
|
||||
print - Evaluate/print expression xx in hex/dec/binary
|
||||
ram - Show ZP RAM, or set address xx to yy1 [yy2 ...]
|
||||
|
@ -1193,6 +1198,8 @@ the reason will be shown as follows:
|
|||
<li>"WTrap:" for write traps</li>
|
||||
<li>"RTrapIf:" for conditional read traps</li>
|
||||
<li>"WTrapIf:" for conditional write traps</li>
|
||||
<li>"RWP:" for reads from write ports</li>
|
||||
<li>"WRP:" for writes to read ports</li>
|
||||
</ul>
|
||||
</p>
|
||||
See the <a href="#BreakpointsEtc"><b>Breakpoints, watches and traps...</b></a>
|
||||
|
@ -1215,6 +1222,8 @@ registers. For example, consider the command 'LDA ($80),Y'. The operand of
|
|||
the command resolves to some address, which isn't always easy to determine at
|
||||
first glance. The 'Src Addr' area shows the actual resulting operand/address
|
||||
being used with the given opcode.</p>
|
||||
<p>The destination address of the last write is shown besides 'Dest'.</p>
|
||||
|
||||
<p>There's not much else to say about the CPU Registers widget: if you know 6502
|
||||
assembly, it's pretty self-explanatory. If you don't, well, you should
|
||||
learn :)</p>
|
||||
|
@ -1369,21 +1378,78 @@ can use. These are known as 'directives', and partly correspond to configuration
|
|||
options from the standalone Distella program. They are listed in order of
|
||||
decreasing hierarchy:</p>
|
||||
<table border="1" cellpadding=4>
|
||||
<tr><td><b>CODE</b></td><td>Addresses which have appeared in the program counter, or
|
||||
which tentatively can appear in the program counter. These can be edited in hex.</td></tr>
|
||||
<tr><td><b>GFX</b></td><td>Addresses which contain data stored in the player graphics registers
|
||||
(GRP0/GRP1). These addresses are shown with a bitmap of the graphics, which
|
||||
can be edited in either hex or binary. The bitmap is shown as large blocks.</td></tr>
|
||||
<tr><td><b>PGFX</b></td><td>Addresses which contain data stored in the playfield graphics registers
|
||||
(PF0/PF1/PF2). These addresses are shown with a bitmap of the graphics, which
|
||||
can be edited in either hex or binary. The bitmap is shown as small dashes.</td></tr>
|
||||
<tr><td><b>DATA</b></td><td>Addresses used as an operand for some opcode. These can be edited
|
||||
in hex.</td></tr>
|
||||
<tr><td><b>ROW</b></td><td>Addresses not used as any of the above. These are shown up
|
||||
to 8 per line, and cannot be edited.</td></tr>
|
||||
<tr>
|
||||
<td>
|
||||
<b>CODE</b>
|
||||
</td><td>
|
||||
Addresses which have appeared in the program counter, or
|
||||
which tentatively can appear in the program counter. These can be edited in hex.
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td>
|
||||
<b>GFX</b>
|
||||
</td><td>
|
||||
Addresses which contain data stored in the player graphics registers
|
||||
(GRP0/GRP1). These addresses are shown with a bitmap of the graphics, which
|
||||
can be edited in either hex or binary. The bitmap is shown as large blocks.
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td>
|
||||
<b>PGFX</b>
|
||||
</td><td>
|
||||
Addresses which contain data stored in the playfield graphics registers
|
||||
(PF0/PF1/PF2). These addresses are shown with a bitmap of the graphics, which
|
||||
can be edited in either hex or binary. The bitmap is shown as small dashes.
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td>
|
||||
<b>COL</b>
|
||||
</td><td>
|
||||
Addresses which contain data stored in the player color registers
|
||||
(COLUP0/COLUP1). These addresses are shown as color constants, which
|
||||
can be edited in hex. The color constant names are depending on the ROM's TV type.
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td>
|
||||
<b>PCOL</b>
|
||||
</td><td>
|
||||
Addresses which contain data stored in the playfield color register
|
||||
(COLUPF). These addresses are shown as color constants, which
|
||||
can be edited in hex. The color constant names are depending on the ROM's TV type.
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td>
|
||||
<b>BCOL</b>
|
||||
</td><td>
|
||||
Addresses which contain data stored in the background color register
|
||||
(COLUBK). These addresses are shown as color constants, which
|
||||
can be edited in hex. The color constant names are depending on the ROM's TV type.
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td>
|
||||
<b>AUD</b>
|
||||
</td><td>
|
||||
Addresses which contain data stored in the audio registers
|
||||
(AUDC0/AUDC1/AUDF0/AUDF1/AUDV0/AUDV1). These can be edited
|
||||
in hex.
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td>
|
||||
<b>DATA</b>
|
||||
</td><td>
|
||||
Addresses used as an operand for some opcode. These can be edited
|
||||
in hex.
|
||||
</td>
|
||||
</tr><tr>
|
||||
<td>
|
||||
<b>ROW</b>
|
||||
</td><td>
|
||||
Addresses not used as any of the above. These are shown up
|
||||
to 8 per line and cannot be edited.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
<p>For code sections, the 6502 mnemonic will be UPPERCASE for all standard instructions,
|
||||
or lowercase for "illegal" 6502 instructions (like "dcp"). If automatic resolving
|
||||
of code sections has been disabled for any reason, you'll likely see a lot
|
||||
|
@ -1445,7 +1511,8 @@ isn't already a defined label).</li>
|
|||
in either binary or hexidecimal.</li>
|
||||
|
||||
<li><b>Use address relocation</b>: Corresponds to the Distella '-r' option
|
||||
(Relocate calls out of address range).</li>
|
||||
(Relocate calls out of address range).</br>
|
||||
Note: The code will continue to run fine, but the ROM image will be altered.</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
@ -1520,12 +1587,12 @@ the RAM in the DPC scheme is not viewable by the 6507, so its addresses start fr
|
|||
<br>
|
||||
<h1><a name="DistellaConfiguration">Distella Configuration Files</a></h1>
|
||||
<p>As mentioned in <a href="#Disassembly"><b>ROM Disassembly</b></a>, Stella supports the following directives:
|
||||
CODE/GFX/PGFX/DATA/ROW. While the debugger will try to automatically mark address
|
||||
CODE, GFX, PGFX, COL, PCOL, BCOL, AUD, DATA, ROW. While the debugger will try to automatically mark address
|
||||
space with the appropriate directive, there are times when it will fail. There are
|
||||
several options in this case:</p>
|
||||
<ol>
|
||||
<li><b>Manually set the directives</b>: Directives can be set in the debugger
|
||||
prompt with the code/gfx/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
|
||||
will remove that directive from the range.</li>
|
||||
<li><b>Use configuration files</b>: Configuration files can be used to automatically
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 1.8 KiB |
Binary file not shown.
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 62 KiB |
Binary file not shown.
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 3.3 KiB |
Binary file not shown.
|
@ -70,7 +70,7 @@
|
|||
|
||||
<br><br><br>
|
||||
|
||||
<center><b>February 1999 - January 2020</b></center>
|
||||
<center><b>February 1999 - March 2020</b></center>
|
||||
<center><b>The Stella Team</b></center>
|
||||
<center><b><a href="https://stella-emu.github.io">Stella Homepage</a></b></center>
|
||||
|
||||
|
@ -2371,7 +2371,7 @@
|
|||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><pre>-launcherfont <small|medium|large></pre></td>
|
||||
<td><pre>-launcherfont <small|low_medium|medium|large|large12|large14|large16></pre></td>
|
||||
<td>Set the size of the font in the ROM launcher.</td>
|
||||
</tr>
|
||||
|
||||
|
@ -2382,9 +2382,10 @@
|
|||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><pre>-romviewer <0|1|2></pre></td>
|
||||
<td>Hide ROM Info Viewer in ROM launcher mode (0), or use the
|
||||
given zoom level (1 or 2).</td>
|
||||
<td><pre>-romviewer <float></pre></td>
|
||||
<td>Hide ROM Info Viewer in ROM launcher mode (0) or use the
|
||||
given zoom level.</br>
|
||||
Note: The zoom level is converted into a percentage in the UI.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
|
@ -3079,8 +3080,8 @@
|
|||
launcher and fonts, as well as the 'ROM Info Viewer' can be changed in
|
||||
<b>UI Settings - Launcher</b> dialog, as shown below:</p>
|
||||
<img src="graphics/options_ui.png">
|
||||
<p>Most of the options are self-explanatory, except for the 'ROM Info
|
||||
viewer', which is described below.</p>
|
||||
<p>Most of the options are self-explanatory, except for the 'ROM info
|
||||
width', which is described below.</p>
|
||||
|
||||
<h3><b><a name="ROMInfoViewer">ROM Info Viewer</a></b></h3>
|
||||
|
||||
|
@ -3092,27 +3093,21 @@
|
|||
for each new release of Stella. Note that the snapshots can be any size
|
||||
generated by Stella; they will be resized accordingly.</p>
|
||||
|
||||
<p>Currently, there are several restrictions for this feature:</p>
|
||||
<ol>
|
||||
<li>The ROM Info Viewer can be shown in 1x or 2x mode only.</li>
|
||||
<li>To view snapshots in 1x mode, the ROM launcher window must be sized at
|
||||
least 640x480. If the launcher isn't large enough, the functionality
|
||||
will be disabled.</li>
|
||||
<li>To view snapshots in 2x mode, the ROM launcher window must be sized at
|
||||
least 1000x720. If the launcher isn't large enough, an attempt will
|
||||
be made to use 1x mode.</li>
|
||||
</ol>
|
||||
The ROM Info Viewer's width can be defined between 0% (off) and 100%. The
|
||||
value is relative to the launcher width. For too small or too large values,
|
||||
Stella will automatically correct the width at runtime so that the ROM names
|
||||
and the current ROM's information always have enough space.
|
||||
|
||||
<p>The following snapshots illustrate the various font sizes and rom info
|
||||
zoom levels:</p>
|
||||
widths:</p>
|
||||
|
||||
<p>ROM Info Viewer in 1x mode, UI sized 800x480, small launcher font:</p>
|
||||
<p>ROM Info Viewer width at 40%, UI sized 800x480, small launcher font:</p>
|
||||
<img src="graphics/rominfo_1x_small.png">
|
||||
|
||||
<p>ROM Info Viewer in 1x mode, UI sized 1000x720, medium launcher font:</p>
|
||||
<p>ROM Info Viewer width at 32%, UI sized 1000x720, medium launcher font:</p>
|
||||
<img src="graphics/rominfo_1x_large.png">
|
||||
|
||||
<p>ROM Info Viewer in 2x mode, UI sized 1280x900, large launcher font:</p>
|
||||
<p>ROM Info Viewer width at 50% , UI sized 1280x900, large launcher font:</p>
|
||||
<img src="graphics/rominfo_2x_small.png">
|
||||
|
||||
<p>The text box in the upper right corner can be used to narrow down the
|
||||
|
|
|
@ -58,7 +58,7 @@
|
|||
|
||||
<center><h1>Stella for RetroN 77</h1></center>
|
||||
<center><h2>Atari 2600 VCS emulator</h2></center>
|
||||
<center>Release 6.1 Beta 1</center>
|
||||
<center>Release 6.1</center>
|
||||
<center><h2>Quick Navigation Guide</h2></center>
|
||||
<br/>
|
||||
|
||||
|
|
|
@ -137,12 +137,12 @@ class FrameBufferSDL2 : public FrameBuffer
|
|||
/**
|
||||
Transform from window to renderer coordinates, x direction
|
||||
*/
|
||||
int scaleX(int x) const { return (x * myRenderW) / myWindowW; }
|
||||
int scaleX(int x) const override { return (x * myRenderW) / myWindowW; }
|
||||
|
||||
/**
|
||||
Transform from window to renderer coordinates, y direction
|
||||
*/
|
||||
int scaleY(int y) const { return (y * myRenderH) / myWindowH; }
|
||||
int scaleY(int y) const override { return (y * myRenderH) / myWindowH; }
|
||||
|
||||
protected:
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
*/
|
||||
namespace Common {
|
||||
|
||||
template <class T, uInt32 CAPACITY = 100>
|
||||
template <typename T, uInt32 CAPACITY = 100>
|
||||
class LinkedObjectPool
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -124,7 +124,7 @@ MouseControl::MouseControl(Console& console, const string& mode)
|
|||
int m_range = 100;
|
||||
if(!(m_axis >> m_range))
|
||||
m_range = 100;
|
||||
Paddles::setPaddleRange(m_range);
|
||||
Paddles::setDigitalPaddleRange(m_range);
|
||||
|
||||
// If the mouse isn't used at all, we still need one item in the list
|
||||
if(myModeList.size() == 0)
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "TIASurface.hxx"
|
||||
#include "Version.hxx"
|
||||
#include "PNGLibrary.hxx"
|
||||
#include "Rect.hxx"
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
PNGLibrary::PNGLibrary(OSystem& osystem)
|
||||
|
@ -129,7 +130,13 @@ void PNGLibrary::saveImage(const string& filename, const VariantList& comments)
|
|||
throw runtime_error("ERROR: Couldn't create snapshot file");
|
||||
|
||||
const FrameBuffer& fb = myOSystem.frameBuffer();
|
||||
const Common::Rect& rect = fb.imageRect();
|
||||
|
||||
const Common::Rect& rectUnscaled = fb.imageRect();
|
||||
const Common::Rect rect(
|
||||
Common::Point(fb.scaleX(rectUnscaled.x()), fb.scaleY(rectUnscaled.y())),
|
||||
fb.scaleX(rectUnscaled.w()), fb.scaleY(rectUnscaled.h())
|
||||
);
|
||||
|
||||
png_uint_32 width = rect.w(), height = rect.h();
|
||||
|
||||
// Get framebuffer pixel data (we get ABGR format)
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
*/
|
||||
namespace Common {
|
||||
|
||||
template <class T, uInt32 CAPACITY = 50>
|
||||
template <typename T, uInt32 CAPACITY = 50>
|
||||
class FixedStack
|
||||
{
|
||||
private:
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#ifndef STATE_MANAGER_HXX
|
||||
#define STATE_MANAGER_HXX
|
||||
|
||||
#define STATE_HEADER "06000008state"
|
||||
#define STATE_HEADER "06010000state"
|
||||
|
||||
class OSystem;
|
||||
class RewindManager;
|
||||
|
|
|
@ -22,19 +22,19 @@
|
|||
|
||||
namespace Vec {
|
||||
|
||||
template<class T>
|
||||
template<typename T>
|
||||
void append(vector<T>& dst, const vector<T>& src)
|
||||
{
|
||||
dst.insert(dst.cend(), src.cbegin(), src.cend());
|
||||
}
|
||||
|
||||
template<class T>
|
||||
template<typename T>
|
||||
void insertAt(vector<T>& dst, uInt32 idx, const T& element)
|
||||
{
|
||||
dst.insert(dst.cbegin()+idx, element);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
template<typename T>
|
||||
void removeAt(vector<T>& dst, uInt32 idx)
|
||||
{
|
||||
dst.erase(dst.cbegin()+idx);
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#ifndef VERSION_HXX
|
||||
#define VERSION_HXX
|
||||
|
||||
#define STELLA_VERSION "6.1_rc1"
|
||||
#define STELLA_BUILD "5657"
|
||||
#define STELLA_VERSION "6.2_pre"
|
||||
#define STELLA_BUILD "5741"
|
||||
|
||||
#endif
|
||||
|
|
|
@ -119,16 +119,16 @@ namespace BSPF
|
|||
#endif
|
||||
|
||||
// Make 2D-arrays using std::array less verbose
|
||||
template<class T, size_t ROW, size_t COL>
|
||||
template<typename T, size_t ROW, size_t COL>
|
||||
using array2D = std::array<std::array<T, COL>, ROW>;
|
||||
|
||||
// Combines 'max' and 'min', and clamps value to the upper/lower value
|
||||
// if it is outside the specified range
|
||||
template<class T> inline T clamp(T val, T lower, T upper)
|
||||
template<typename T> inline T clamp(T val, T lower, T upper)
|
||||
{
|
||||
return (val < lower) ? lower : (val > upper) ? upper : val;
|
||||
}
|
||||
template<class T> inline void clamp(T& val, T lower, T upper, T setVal)
|
||||
template<typename T> inline void clamp(T& val, T lower, T upper, T setVal)
|
||||
{
|
||||
if(val < lower || val > upper) val = setVal;
|
||||
}
|
||||
|
|
|
@ -32,7 +32,10 @@
|
|||
#include "CartRamWidget.hxx"
|
||||
#include "RomWidget.hxx"
|
||||
#include "Base.hxx"
|
||||
#include "Device.hxx"
|
||||
#include "exception/EmulationWarning.hxx"
|
||||
#include "TIA.hxx"
|
||||
#include "M6532.hxx"
|
||||
|
||||
using Common::Base;
|
||||
using std::hex;
|
||||
|
@ -68,16 +71,12 @@ CartDebug::CartDebug(Debugger& dbg, Console& console, const OSystem& osystem)
|
|||
}
|
||||
|
||||
// Create bank information for each potential bank, and an extra one for ZP RAM
|
||||
// Banksizes greater than 4096 indicate multi-bank ROMs, but we handle only
|
||||
// 4K pieces at a time
|
||||
// Banksizes less than 4K use the actual value
|
||||
size_t banksize = 0;
|
||||
myConsole.cartridge().getImage(banksize);
|
||||
|
||||
BankInfo info;
|
||||
info.size = std::min<size_t>(banksize, 4_KB);
|
||||
for(uInt32 i = 0; i < myConsole.cartridge().bankCount(); ++i)
|
||||
{
|
||||
info.size = myConsole.cartridge().bankSize(i);
|
||||
myBankInfo.push_back(info);
|
||||
}
|
||||
|
||||
info.size = 128; // ZP RAM
|
||||
myBankInfo.push_back(info);
|
||||
|
@ -85,7 +84,7 @@ CartDebug::CartDebug(Debugger& dbg, Console& console, const OSystem& osystem)
|
|||
// We know the address for the startup bank right now
|
||||
myBankInfo[myConsole.cartridge().startBank()].addressList.push_front(
|
||||
myDebugger.dpeek(0xfffc));
|
||||
addLabel("Start", myDebugger.dpeek(0xfffc, DATA));
|
||||
addLabel("Start", myDebugger.dpeek(0xfffc, Device::DATA)); // TOOD: ::CODE???
|
||||
|
||||
// Add system equates
|
||||
for(uInt16 addr = 0x00; addr <= 0x0F; ++addr)
|
||||
|
@ -156,6 +155,18 @@ void CartDebug::saveOldState()
|
|||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
int CartDebug::lastReadAddress()
|
||||
{
|
||||
return mySystem.m6502().lastReadAddress();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
int CartDebug::lastWriteAddress()
|
||||
{
|
||||
return mySystem.m6502().lastWriteAddress();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
int CartDebug::lastReadBaseAddress()
|
||||
{
|
||||
|
@ -225,11 +236,29 @@ string CartDebug::toString()
|
|||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartDebug::disassemble(bool force)
|
||||
{
|
||||
uInt16 PC = myDebugger.cpuDebug().pc();
|
||||
int bank = (PC & 0x1000) ? getBank(PC) : int(myBankInfo.size()) - 1;
|
||||
|
||||
return disassemble(bank, PC, force);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartDebug::disassembleBank(int bank)
|
||||
{
|
||||
BankInfo& info = myBankInfo[bank];
|
||||
|
||||
info.offset = myConsole.cartridge().bankOrigin(bank);
|
||||
|
||||
return disassemble(bank, info.offset, true);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartDebug::disassemble(int bank, uInt16 PC, bool force)
|
||||
{
|
||||
// Test current disassembly; don't re-disassemble if it hasn't changed
|
||||
// Also check if the current PC is in the current list
|
||||
bool bankChanged = myConsole.cartridge().bankChanged();
|
||||
uInt16 PC = myDebugger.cpuDebug().pc();
|
||||
int pcline = addressToLine(PC);
|
||||
bool pcfound = (pcline != -1) && (uInt32(pcline) < myDisassembly.list.size()) &&
|
||||
(myDisassembly.list[pcline].disasm[0] != '.');
|
||||
|
@ -241,8 +270,9 @@ bool CartDebug::disassemble(bool force)
|
|||
if(changed)
|
||||
{
|
||||
// Are we disassembling from ROM or ZP RAM?
|
||||
BankInfo& info = (PC & 0x1000) ? myBankInfo[getBank(PC)] :
|
||||
myBankInfo[myBankInfo.size()-1];
|
||||
BankInfo& info = myBankInfo[bank];
|
||||
//(PC & 0x1000) ? myBankInfo[getBank(PC)] :
|
||||
//myBankInfo[myBankInfo.size()-1];
|
||||
|
||||
// If the offset has changed, all old addresses must be 'converted'
|
||||
// For example, if the list contains any $fxxx and the address space is now
|
||||
|
@ -304,8 +334,8 @@ bool CartDebug::fillDisassemblyList(BankInfo& info, uInt16 search)
|
|||
const DisassemblyTag& tag = myDisassembly.list[i];
|
||||
const uInt16 address = tag.address & 0xFFF;
|
||||
|
||||
// Exclude 'ROW'; they don't have a valid address
|
||||
if(tag.type != CartDebug::ROW)
|
||||
// Exclude 'Device::ROW'; they don't have a valid address
|
||||
if(tag.type != Device::ROW)
|
||||
{
|
||||
// Create a mapping from addresses to line numbers
|
||||
myAddrToLineList.emplace(address, i);
|
||||
|
@ -331,7 +361,7 @@ int CartDebug::addressToLine(uInt16 address) const
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
string CartDebug::disassemble(uInt16 start, uInt16 lines) const
|
||||
string CartDebug::disassembleLines(uInt16 start, uInt16 lines) const
|
||||
{
|
||||
// Fill the string with disassembled data
|
||||
start &= 0xFFF;
|
||||
|
@ -346,7 +376,7 @@ string CartDebug::disassemble(uInt16 start, uInt16 lines) const
|
|||
if((tag.address & 0xfff) >= start)
|
||||
{
|
||||
if(begin == list_size) begin = end;
|
||||
if(tag.type != CartDebug::ROW)
|
||||
if(tag.type != Device::ROW)
|
||||
length = std::max(length, uInt32(tag.disasm.length()));
|
||||
|
||||
--lines;
|
||||
|
@ -357,7 +387,7 @@ string CartDebug::disassemble(uInt16 start, uInt16 lines) const
|
|||
for(uInt32 i = begin; i < end; ++i)
|
||||
{
|
||||
const CartDebug::DisassemblyTag& tag = myDisassembly.list[i];
|
||||
if(tag.type == CartDebug::NONE)
|
||||
if(tag.type == Device::NONE)
|
||||
continue;
|
||||
else if(tag.address)
|
||||
buffer << std::uppercase << std::hex << std::setw(4)
|
||||
|
@ -374,7 +404,7 @@ string CartDebug::disassemble(uInt16 start, uInt16 lines) const
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartDebug::addDirective(CartDebug::DisasmType type,
|
||||
bool CartDebug::addDirective(Device::AccessType type,
|
||||
uInt16 start, uInt16 end, int bank)
|
||||
{
|
||||
if(end < start || start == 0 || end == 0)
|
||||
|
@ -813,12 +843,13 @@ string CartDebug::loadSymbolFile()
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
string CartDebug::loadConfigFile()
|
||||
{
|
||||
// The default naming/location for config files is the ROM dir based on the
|
||||
// actual ROM filename
|
||||
// The default naming/location for config files is the CFG dir and based
|
||||
// on the actual ROM filename
|
||||
|
||||
if(myCfgFile == "")
|
||||
{
|
||||
FilesystemNode cfg(myOSystem.romFile().getPathWithExt("") + ".cfg");
|
||||
FilesystemNode romNode(myOSystem.romFile().getPathWithExt("") + ".cfg");
|
||||
FilesystemNode cfg(myOSystem.cfgDir() + romNode.getName());
|
||||
if(cfg.isFile() && cfg.isReadable())
|
||||
myCfgFile = cfg.getPath();
|
||||
else
|
||||
|
@ -876,28 +907,48 @@ string CartDebug::loadConfigFile()
|
|||
else if(BSPF::startsWithIgnoreCase(directive, "CODE"))
|
||||
{
|
||||
buf >> hex >> start >> hex >> end;
|
||||
addDirective(CartDebug::CODE, start, end, currentbank);
|
||||
addDirective(Device::CODE, start, end, currentbank);
|
||||
}
|
||||
else if(BSPF::startsWithIgnoreCase(directive, "GFX"))
|
||||
{
|
||||
buf >> hex >> start >> hex >> end;
|
||||
addDirective(CartDebug::GFX, start, end, currentbank);
|
||||
addDirective(Device::GFX, start, end, currentbank);
|
||||
}
|
||||
else if(BSPF::startsWithIgnoreCase(directive, "PGFX"))
|
||||
{
|
||||
buf >> hex >> start >> hex >> end;
|
||||
addDirective(CartDebug::PGFX, start, end, currentbank);
|
||||
addDirective(Device::PGFX, start, end, currentbank);
|
||||
}
|
||||
else if(BSPF::startsWithIgnoreCase(directive, "COL"))
|
||||
{
|
||||
buf >> hex >> start >> hex >> end;
|
||||
addDirective(Device::COL, start, end, currentbank);
|
||||
}
|
||||
else if(BSPF::startsWithIgnoreCase(directive, "PCOL"))
|
||||
{
|
||||
buf >> hex >> start >> hex >> end;
|
||||
addDirective(Device::PCOL, start, end, currentbank);
|
||||
}
|
||||
else if(BSPF::startsWithIgnoreCase(directive, "BCOL"))
|
||||
{
|
||||
buf >> hex >> start >> hex >> end;
|
||||
addDirective(Device::BCOL, start, end, currentbank);
|
||||
}
|
||||
else if(BSPF::startsWithIgnoreCase(directive, "AUD"))
|
||||
{
|
||||
buf >> hex >> start >> hex >> end;
|
||||
addDirective(Device::AUD, start, end, currentbank);
|
||||
}
|
||||
else if(BSPF::startsWithIgnoreCase(directive, "DATA"))
|
||||
{
|
||||
buf >> hex >> start >> hex >> end;
|
||||
addDirective(CartDebug::DATA, start, end, currentbank);
|
||||
addDirective(Device::DATA, start, end, currentbank);
|
||||
}
|
||||
else if(BSPF::startsWithIgnoreCase(directive, "ROW"))
|
||||
{
|
||||
buf >> hex >> start;
|
||||
buf >> hex >> end;
|
||||
addDirective(CartDebug::ROW, start, end, currentbank);
|
||||
addDirective(Device::ROW, start, end, currentbank);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -914,14 +965,14 @@ string CartDebug::loadConfigFile()
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
string CartDebug::saveConfigFile()
|
||||
{
|
||||
// The default naming/location for config files is the ROM dir based on the
|
||||
// actual ROM filename
|
||||
// The default naming/location for config files is the CFG dir and based
|
||||
// on the actual ROM filename
|
||||
|
||||
FilesystemNode cfg;
|
||||
if(myCfgFile == "")
|
||||
{
|
||||
cfg = FilesystemNode(myOSystem.romFile().getPathWithExt("") + ".cfg");
|
||||
if(cfg.isFile() && cfg.isWritable())
|
||||
FilesystemNode romNode(myOSystem.romFile().getPathWithExt("") + ".cfg");
|
||||
FilesystemNode cfg(myOSystem.cfgDir() + romNode.getName());
|
||||
if(cfg.getParent().isWritable())
|
||||
myCfgFile = cfg.getPath();
|
||||
else
|
||||
return DebuggerParser::red("config file \'" + cfg.getShortPath() + "\' not writable");
|
||||
|
@ -930,13 +981,14 @@ string CartDebug::saveConfigFile()
|
|||
const string& name = myConsole.properties().get(PropType::Cart_Name);
|
||||
const string& md5 = myConsole.properties().get(PropType::Cart_MD5);
|
||||
|
||||
FilesystemNode cfg(myCfgFile);
|
||||
ofstream out(cfg.getPath());
|
||||
if(!out.is_open())
|
||||
return "Unable to save directives to " + cfg.getShortPath();
|
||||
|
||||
// Store all bank information
|
||||
out << "//Stella.pro: \"" << name << "\"" << endl
|
||||
<< "//MD5: " << md5 << endl
|
||||
out << "// Stella.pro: \"" << name << "\"" << endl
|
||||
<< "// MD5: " << md5 << endl
|
||||
<< endl;
|
||||
for(uInt32 b = 0; b < myConsole.cartridge().bankCount(); ++b)
|
||||
{
|
||||
|
@ -954,6 +1006,25 @@ string CartDebug::saveConfigFile()
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
string CartDebug::saveDisassembly()
|
||||
{
|
||||
string NTSC_COLOR[16] = {
|
||||
"BLACK", "YELLOW", "BROWN", "ORANGE",
|
||||
"RED", "MAUVE", "VIOLET", "PURPLE",
|
||||
"BLUE", "BLUE_CYAN", "CYAN", "CYAN_GREEN",
|
||||
"GREEN", "GREEN_YELLOW", "GREEN_BEIGE", "BEIGE"
|
||||
};
|
||||
string PAL_COLOR[16] = {
|
||||
"BLACK0", "BLACK1", "YELLOW", "GREEN_YELLOW",
|
||||
"ORANGE", "GREEN", "RED", "CYAN_GREEN",
|
||||
"MAUVE", "CYAN", "VIOLET", "BLUE_CYAN",
|
||||
"PURPLE", "BLUE", "BLACKE", "BLACKF"
|
||||
};
|
||||
string SECAM_COLOR[8] = {
|
||||
"BLACK", "BLUE", "RED", "PURPLE",
|
||||
"GREEN", "CYAN", "YELLOW", "WHITE"
|
||||
};
|
||||
bool isNTSC = myConsole.timing() == ConsoleTiming::ntsc;
|
||||
bool isPAL = myConsole.timing() == ConsoleTiming::pal;
|
||||
|
||||
if(myDisasmFile == "")
|
||||
{
|
||||
const string& propsname =
|
||||
|
@ -972,11 +1043,6 @@ string CartDebug::saveDisassembly()
|
|||
// We can't print the header to the disassembly until it's actually
|
||||
// been processed; therefore buffer output to a string first
|
||||
ostringstream buf;
|
||||
buf << "\n\n;***********************************************************\n"
|
||||
<< "; Bank " << myConsole.cartridge().getBank();
|
||||
if (myConsole.cartridge().bankCount() > 1)
|
||||
buf << " / 0.." << myConsole.cartridge().bankCount() - 1;
|
||||
buf << "\n;***********************************************************\n\n";
|
||||
|
||||
// Use specific settings for disassembly output
|
||||
// This will most likely differ from what you see in the debugger
|
||||
|
@ -992,13 +1058,35 @@ string CartDebug::saveDisassembly()
|
|||
|
||||
Disassembly disasm;
|
||||
disasm.list.reserve(2048);
|
||||
for(int bank = 0; bank < myConsole.cartridge().bankCount(); ++bank)
|
||||
uInt16 bankCount = myConsole.cartridge().bankCount();
|
||||
uInt16 oldBank = myConsole.cartridge().getBank();
|
||||
|
||||
// prepare for switching banks
|
||||
myConsole.cartridge().unlockBank();
|
||||
uInt32 origin = 0;
|
||||
|
||||
for(int bank = 0; bank < bankCount; ++bank)
|
||||
{
|
||||
// TODO: not every CartDebugWidget does it like that, we need a method
|
||||
myConsole.cartridge().unlockBank();
|
||||
myConsole.cartridge().bank(bank);
|
||||
myConsole.cartridge().lockBank();
|
||||
|
||||
BankInfo& info = myBankInfo[bank];
|
||||
|
||||
disassembleBank(bank);
|
||||
|
||||
// An empty address list means that DiStella can't do a disassembly
|
||||
if(info.addressList.size() == 0)
|
||||
continue;
|
||||
|
||||
buf << "\n\n;***********************************************************\n"
|
||||
<< "; Bank " << bank;
|
||||
if (bankCount > 1)
|
||||
buf << " / 0.." << bankCount - 1;
|
||||
buf << "\n;***********************************************************\n\n";
|
||||
|
||||
|
||||
// Disassemble bank
|
||||
disasm.list.clear();
|
||||
DiStella distella(*this, disasm.list, info, settings,
|
||||
|
@ -1007,8 +1095,14 @@ string CartDebug::saveDisassembly()
|
|||
if (myReserved.breakFound)
|
||||
addLabel("Break", myDebugger.dpeek(0xfffe));
|
||||
|
||||
buf << " SEG CODE\n"
|
||||
<< " ORG $" << Base::HEX4 << info.offset << "\n\n";
|
||||
buf << " SEG CODE\n";
|
||||
|
||||
if(bankCount == 1)
|
||||
buf << " ORG $" << Base::HEX4 << info.offset << "\n\n";
|
||||
else
|
||||
buf << " ORG $" << Base::HEX4 << origin << "\n"
|
||||
<< " RORG $" << Base::HEX4 << info.offset << "\n\n";
|
||||
origin += uInt32(info.size);
|
||||
|
||||
// Format in 'distella' style
|
||||
for(uInt32 i = 0; i < disasm.list.size(); ++i)
|
||||
|
@ -1022,50 +1116,62 @@ string CartDebug::saveDisassembly()
|
|||
|
||||
switch(tag.type)
|
||||
{
|
||||
case CartDebug::CODE:
|
||||
{
|
||||
case Device::CODE:
|
||||
buf << ALIGN(32) << tag.disasm << tag.ccount.substr(0, 5) << tag.ctotal << tag.ccount.substr(5, 2);
|
||||
if (tag.disasm.find("WSYNC") != std::string::npos)
|
||||
buf << "\n;---------------------------------------";
|
||||
break;
|
||||
}
|
||||
case CartDebug::ROW:
|
||||
{
|
||||
|
||||
case Device::ROW:
|
||||
buf << ".byte " << ALIGN(32) << tag.disasm.substr(6, 8*4-1) << "; $" << Base::HEX4 << tag.address << " (*)";
|
||||
break;
|
||||
}
|
||||
case CartDebug::GFX:
|
||||
{
|
||||
|
||||
case Device::GFX:
|
||||
buf << ".byte " << (settings.gfxFormat == Base::Fmt::_2 ? "%" : "$")
|
||||
<< tag.bytes << " ; |";
|
||||
for(int c = 12; c < 20; ++c)
|
||||
buf << ((tag.disasm[c] == '\x1e') ? "#" : " ");
|
||||
buf << ALIGN(13) << "|" << "$" << Base::HEX4 << tag.address << " (G)";
|
||||
break;
|
||||
}
|
||||
case CartDebug::PGFX:
|
||||
{
|
||||
|
||||
case Device::PGFX:
|
||||
buf << ".byte " << (settings.gfxFormat == Base::Fmt::_2 ? "%" : "$")
|
||||
<< tag.bytes << " ; |";
|
||||
for(int c = 12; c < 20; ++c)
|
||||
buf << ((tag.disasm[c] == '\x1f') ? "*" : " ");
|
||||
buf << ALIGN(13) << "|" << "$" << Base::HEX4 << tag.address << " (P)";
|
||||
break;
|
||||
}
|
||||
case CartDebug::DATA:
|
||||
{
|
||||
|
||||
case Device::COL:
|
||||
buf << ".byte " << ALIGN(32) << tag.disasm.substr(6, 15) << "; $" << Base::HEX4 << tag.address << " (C)";
|
||||
break;
|
||||
|
||||
case Device::PCOL:
|
||||
buf << ".byte " << ALIGN(32) << tag.disasm.substr(6, 15) << "; $" << Base::HEX4 << tag.address << " (CP)";
|
||||
break;
|
||||
|
||||
case Device::BCOL:
|
||||
buf << ".byte " << ALIGN(32) << tag.disasm.substr(6, 15) << "; $" << Base::HEX4 << tag.address << " (CB)";
|
||||
break;
|
||||
|
||||
case Device::AUD:
|
||||
buf << ".byte " << ALIGN(32) << tag.disasm.substr(6, 8 * 4 - 1) << "; $" << Base::HEX4 << tag.address << " (A)";
|
||||
break;
|
||||
|
||||
case Device::DATA:
|
||||
buf << ".byte " << ALIGN(32) << tag.disasm.substr(6, 8 * 4 - 1) << "; $" << Base::HEX4 << tag.address << " (D)";
|
||||
break;
|
||||
}
|
||||
case CartDebug::NONE:
|
||||
|
||||
case Device::NONE:
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
} // switch
|
||||
buf << "\n";
|
||||
}
|
||||
}
|
||||
myConsole.cartridge().unlockBank();
|
||||
myConsole.cartridge().bank(oldBank);
|
||||
myConsole.cartridge().lockBank();
|
||||
|
||||
// Some boilerplate, similar to what DiStella adds
|
||||
auto timeinfo = BSPF::localTime();
|
||||
|
@ -1075,23 +1181,49 @@ string CartDebug::saveDisassembly()
|
|||
<< "; ROM properties name : " << myConsole.properties().get(PropType::Cart_Name) << "\n"
|
||||
<< "; ROM properties MD5 : " << myConsole.properties().get(PropType::Cart_MD5) << "\n"
|
||||
<< "; Bankswitch type : " << myConsole.cartridge().about() << "\n;\n"
|
||||
<< "; Legend: * = CODE not yet run (tentative code)\n"
|
||||
<< "; D = DATA directive (referenced in some way)\n"
|
||||
<< "; G = GFX directive, shown as '#' (stored in player, missile, ball)\n"
|
||||
<< "; P = PGFX directive, shown as '*' (stored in playfield)\n"
|
||||
<< "; i = indexed accessed only\n"
|
||||
<< "; c = used by code executed in RAM\n"
|
||||
<< "; s = used by stack\n"
|
||||
<< "; ! = page crossed, 1 cycle penalty\n"
|
||||
<< "; Legend: * = CODE not yet run (tentative code)\n"
|
||||
<< "; D = DATA directive (referenced in some way)\n"
|
||||
<< "; G = GFX directive, shown as '#' (stored in player, missile, ball)\n"
|
||||
<< "; P = PGFX directive, shown as '*' (stored in playfield)\n"
|
||||
<< "; C = COL directive, shown as color constants (stored in player color)\n"
|
||||
<< "; CP = PCOL directive, shown as color constants (stored in playfield color)\n"
|
||||
<< "; CB = BCOL directive, shown as color constants (stored in background color)\n"
|
||||
<< "; A = AUD directive (stored in audio registers)\n"
|
||||
<< "; i = indexed accessed only\n"
|
||||
<< "; c = used by code executed in RAM\n"
|
||||
<< "; s = used by stack\n"
|
||||
<< "; ! = page crossed, 1 cycle penalty\n"
|
||||
<< "\n processor 6502\n\n";
|
||||
|
||||
out << "\n;-----------------------------------------------------------\n"
|
||||
<< "; Color constants\n"
|
||||
<< ";-----------------------------------------------------------\n\n";
|
||||
|
||||
if(isNTSC)
|
||||
{
|
||||
for(int i = 0; i < 16; ++i)
|
||||
out << ALIGN(16) << NTSC_COLOR[i] << " = $" << Base::HEX2 << (i << 4) << "\n";
|
||||
}
|
||||
else if(isPAL)
|
||||
{
|
||||
for(int i = 0; i < 16; ++i)
|
||||
out << ALIGN(16) << PAL_COLOR[i] << " = $" << Base::HEX2 << (i << 4) << "\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int i = 0; i < 8; ++i)
|
||||
out << ALIGN(16) << SECAM_COLOR[i] << " = $" << Base::HEX1 << (i << 1) << "\n";
|
||||
}
|
||||
out << "\n";
|
||||
|
||||
bool addrUsed = false;
|
||||
for(uInt16 addr = 0x00; addr <= 0x0F; ++addr)
|
||||
addrUsed = addrUsed || myReserved.TIARead[addr] || (mySystem.getAccessFlags(addr) & WRITE);
|
||||
addrUsed = addrUsed || myReserved.TIARead[addr] || (mySystem.getAccessFlags(addr) & Device::WRITE);
|
||||
for(uInt16 addr = 0x00; addr <= 0x3F; ++addr)
|
||||
addrUsed = addrUsed || myReserved.TIAWrite[addr] || (mySystem.getAccessFlags(addr) & DATA);
|
||||
addrUsed = addrUsed || myReserved.TIAWrite[addr] || (mySystem.getAccessFlags(addr) & Device::DATA);
|
||||
for(uInt16 addr = 0x00; addr <= 0x17; ++addr)
|
||||
addrUsed = addrUsed || myReserved.IOReadWrite[addr];
|
||||
|
||||
if(addrUsed)
|
||||
{
|
||||
out << "\n;-----------------------------------------------------------\n"
|
||||
|
@ -1103,7 +1235,7 @@ string CartDebug::saveDisassembly()
|
|||
if(myReserved.TIARead[addr] && ourTIAMnemonicR[addr])
|
||||
out << ALIGN(16) << ourTIAMnemonicR[addr] << "= $"
|
||||
<< Base::HEX2 << right << addr << " ; (R)\n";
|
||||
else if (mySystem.getAccessFlags(addr) & DATA)
|
||||
else if (mySystem.getAccessFlags(addr) & Device::DATA)
|
||||
out << ";" << ALIGN(16-1) << ourTIAMnemonicR[addr] << "= $"
|
||||
<< Base::HEX2 << right << addr << " ; (Ri)\n";
|
||||
out << "\n";
|
||||
|
@ -1113,7 +1245,7 @@ string CartDebug::saveDisassembly()
|
|||
if(myReserved.TIAWrite[addr] && ourTIAMnemonicW[addr])
|
||||
out << ALIGN(16) << ourTIAMnemonicW[addr] << "= $"
|
||||
<< Base::HEX2 << right << addr << " ; (W)\n";
|
||||
else if (mySystem.getAccessFlags(addr) & WRITE)
|
||||
else if (mySystem.getAccessFlags(addr) & Device::WRITE)
|
||||
out << ";" << ALIGN(16-1) << ourTIAMnemonicW[addr] << "= $"
|
||||
<< Base::HEX2 << right << addr << " ; (Wi)\n";
|
||||
out << "\n";
|
||||
|
@ -1128,8 +1260,8 @@ string CartDebug::saveDisassembly()
|
|||
addrUsed = false;
|
||||
for(uInt16 addr = 0x80; addr <= 0xFF; ++addr)
|
||||
addrUsed = addrUsed || myReserved.ZPRAM[addr-0x80]
|
||||
|| (mySystem.getAccessFlags(addr) & (DATA | WRITE))
|
||||
|| (mySystem.getAccessFlags(addr|0x100) & (DATA | WRITE));
|
||||
|| (mySystem.getAccessFlags(addr) & (Device::DATA | Device::WRITE))
|
||||
|| (mySystem.getAccessFlags(addr|0x100) & (Device::DATA | Device::WRITE));
|
||||
if(addrUsed)
|
||||
{
|
||||
bool addLine = false;
|
||||
|
@ -1138,9 +1270,9 @@ string CartDebug::saveDisassembly()
|
|||
<< ";-----------------------------------------------------------\n\n";
|
||||
|
||||
for (uInt16 addr = 0x80; addr <= 0xFF; ++addr) {
|
||||
bool ramUsed = (mySystem.getAccessFlags(addr) & (DATA | WRITE));
|
||||
bool codeUsed = (mySystem.getAccessFlags(addr) & CODE);
|
||||
bool stackUsed = (mySystem.getAccessFlags(addr|0x100) & (DATA | WRITE));
|
||||
bool ramUsed = (mySystem.getAccessFlags(addr) & (Device::DATA | Device::WRITE));
|
||||
bool codeUsed = (mySystem.getAccessFlags(addr) & Device::CODE);
|
||||
bool stackUsed = (mySystem.getAccessFlags(addr|0x100) & (Device::DATA | Device::WRITE));
|
||||
|
||||
if (myReserved.ZPRAM[addr - 0x80] &&
|
||||
myUserLabels.find(addr) == myUserLabels.end()) {
|
||||
|
@ -1196,7 +1328,7 @@ string CartDebug::saveDisassembly()
|
|||
|
||||
stringstream retVal;
|
||||
if(myConsole.cartridge().bankCount() > 1)
|
||||
retVal << DebuggerParser::red("disassembly for multi-bank ROM not fully supported, only currently enabled banks disassembled\n");
|
||||
retVal << DebuggerParser::red("disassembly for multi-bank ROM not fully supported\n");
|
||||
retVal << "saved " << node.getShortPath() << " OK";
|
||||
return retVal.str();
|
||||
}
|
||||
|
@ -1214,12 +1346,27 @@ string CartDebug::saveRom()
|
|||
return DebuggerParser::red("failed to save ROM");
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
string CartDebug::saveAccessFile()
|
||||
{
|
||||
const string& rom = myConsole.properties().get(PropType::Cart_Name) + ".csv";
|
||||
FilesystemNode node(myOSystem.defaultSaveDir() + rom);
|
||||
ofstream out(node.getPath());
|
||||
|
||||
if(out)
|
||||
{
|
||||
out << myConsole.tia().getAccessCounters();
|
||||
out << myConsole.riot().getAccessCounters();
|
||||
out << myConsole.cartridge().getAccessCounters();
|
||||
return "saved access counters as " + node.getShortPath();
|
||||
}
|
||||
else
|
||||
return DebuggerParser::red("failed to save access counters file");
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
string CartDebug::listConfig(int bank)
|
||||
{
|
||||
if(myConsole.cartridge().bankCount() > 1)
|
||||
return DebuggerParser::red("config file for multi-bank ROM not yet supported");
|
||||
|
||||
uInt32 startbank = 0, endbank = bankCount();
|
||||
if(bank >= 0 && bank < bankCount())
|
||||
{
|
||||
|
@ -1232,19 +1379,22 @@ string CartDebug::listConfig(int bank)
|
|||
for(uInt32 b = startbank; b < endbank; ++b)
|
||||
{
|
||||
BankInfo& info = myBankInfo[b];
|
||||
buf << "[" << b << "]" << endl;
|
||||
buf << "Bank [" << b << "]" << endl;
|
||||
for(const auto& i: info.directiveList)
|
||||
{
|
||||
if(i.type != CartDebug::NONE)
|
||||
if(i.type != Device::NONE)
|
||||
{
|
||||
buf << "(*) ";
|
||||
disasmTypeAsString(buf, i.type);
|
||||
AccessTypeAsString(buf, i.type);
|
||||
buf << " " << Base::HEX4 << i.start << " " << Base::HEX4 << i.end << endl;
|
||||
}
|
||||
}
|
||||
getBankDirectives(buf, info);
|
||||
}
|
||||
|
||||
if(myConsole.cartridge().bankCount() > 1)
|
||||
buf << DebuggerParser::red("config file for multi-bank ROM not fully supported") << endl;
|
||||
|
||||
return buf.str();
|
||||
}
|
||||
|
||||
|
@ -1334,15 +1484,15 @@ void CartDebug::getBankDirectives(ostream& buf, BankInfo& info) const
|
|||
|
||||
// Now consider each byte
|
||||
uInt32 prev = info.offset, addr = prev + 1;
|
||||
DisasmType prevType = disasmTypeAbsolute(mySystem.getAccessFlags(prev));
|
||||
Device::AccessType prevType = accessTypeAbsolute(mySystem.getAccessFlags(prev));
|
||||
for( ; addr < info.offset + info.size; ++addr)
|
||||
{
|
||||
DisasmType currType = disasmTypeAbsolute(mySystem.getAccessFlags(addr));
|
||||
Device::AccessType currType = accessTypeAbsolute(mySystem.getAccessFlags(addr));
|
||||
|
||||
// Have we changed to a new type?
|
||||
if(currType != prevType)
|
||||
{
|
||||
disasmTypeAsString(buf, prevType);
|
||||
AccessTypeAsString(buf, prevType);
|
||||
buf << " " << Base::HEX4 << prev << " " << Base::HEX4 << (addr-1) << endl;
|
||||
|
||||
prev = addr;
|
||||
|
@ -1353,13 +1503,13 @@ void CartDebug::getBankDirectives(ostream& buf, BankInfo& info) const
|
|||
// Grab the last directive, making sure it accounts for all remaining space
|
||||
if(prev != addr)
|
||||
{
|
||||
disasmTypeAsString(buf, prevType);
|
||||
AccessTypeAsString(buf, prevType);
|
||||
buf << " " << Base::HEX4 << prev << " " << Base::HEX4 << (addr-1) << endl;
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartDebug::addressTypeAsString(ostream& buf, uInt16 addr) const
|
||||
void CartDebug::accessTypeAsString(ostream& buf, uInt16 addr) const
|
||||
{
|
||||
if(!(addr & 0x1000))
|
||||
{
|
||||
|
@ -1372,70 +1522,88 @@ void CartDebug::addressTypeAsString(ostream& buf, uInt16 addr) const
|
|||
label = myDisLabels[addr & 0xFFF];
|
||||
|
||||
buf << endl << "directive: " << Base::toString(directive, Base::Fmt::_2_8) << " ";
|
||||
disasmTypeAsString(buf, directive);
|
||||
AccessTypeAsString(buf, directive);
|
||||
buf << endl << "emulation: " << Base::toString(debugger, Base::Fmt::_2_8) << " ";
|
||||
disasmTypeAsString(buf, debugger);
|
||||
AccessTypeAsString(buf, debugger);
|
||||
buf << endl << "tentative: " << Base::toString(label, Base::Fmt::_2_8) << " ";
|
||||
disasmTypeAsString(buf, label);
|
||||
AccessTypeAsString(buf, label);
|
||||
buf << endl;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
CartDebug::DisasmType CartDebug::disasmTypeAbsolute(uInt8 flags) const
|
||||
Device::AccessType CartDebug::accessTypeAbsolute(Device::AccessFlags flags) const
|
||||
{
|
||||
if(flags & CartDebug::CODE)
|
||||
return CartDebug::CODE;
|
||||
else if(flags & CartDebug::TCODE)
|
||||
return CartDebug::CODE; // TODO - should this be separate??
|
||||
else if(flags & CartDebug::GFX)
|
||||
return CartDebug::GFX;
|
||||
else if(flags & CartDebug::PGFX)
|
||||
return CartDebug::PGFX;
|
||||
else if(flags & CartDebug::DATA)
|
||||
return CartDebug::DATA;
|
||||
else if(flags & CartDebug::ROW)
|
||||
return CartDebug::ROW;
|
||||
if(flags & Device::CODE)
|
||||
return Device::CODE;
|
||||
else if(flags & Device::TCODE)
|
||||
return Device::CODE; // TODO - should this be separate??
|
||||
else if(flags & Device::GFX)
|
||||
return Device::GFX;
|
||||
else if(flags & Device::PGFX)
|
||||
return Device::PGFX;
|
||||
else if(flags & Device::COL)
|
||||
return Device::COL;
|
||||
else if(flags & Device::PCOL)
|
||||
return Device::PCOL;
|
||||
else if(flags & Device::BCOL)
|
||||
return Device::BCOL;
|
||||
else if(flags & Device::AUD)
|
||||
return Device::AUD;
|
||||
else if(flags & Device::DATA)
|
||||
return Device::DATA;
|
||||
else if(flags & Device::ROW)
|
||||
return Device::ROW;
|
||||
else
|
||||
return CartDebug::NONE;
|
||||
return Device::NONE;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartDebug::disasmTypeAsString(ostream& buf, DisasmType type) const
|
||||
void CartDebug::AccessTypeAsString(ostream& buf, Device::AccessType type) const
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case CartDebug::CODE: buf << "CODE"; break;
|
||||
case CartDebug::TCODE: buf << "TCODE"; break;
|
||||
case CartDebug::GFX: buf << "GFX"; break;
|
||||
case CartDebug::PGFX: buf << "PGFX"; break;
|
||||
case CartDebug::DATA: buf << "DATA"; break;
|
||||
case CartDebug::ROW: buf << "ROW"; break;
|
||||
case CartDebug::REFERENCED:
|
||||
case CartDebug::VALID_ENTRY:
|
||||
case CartDebug::NONE: break;
|
||||
case Device::CODE: buf << "CODE"; break;
|
||||
case Device::TCODE: buf << "TCODE"; break;
|
||||
case Device::GFX: buf << "GFX"; break;
|
||||
case Device::PGFX: buf << "PGFX"; break;
|
||||
case Device::COL: buf << "COL"; break;
|
||||
case Device::PCOL: buf << "PCOL"; break;
|
||||
case Device::BCOL: buf << "BCOL"; break;
|
||||
case Device::AUD: buf << "AUD"; break;
|
||||
case Device::DATA: buf << "DATA"; break;
|
||||
case Device::ROW: buf << "ROW"; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartDebug::disasmTypeAsString(ostream& buf, uInt8 flags) const
|
||||
void CartDebug::AccessTypeAsString(ostream& buf, Device::AccessFlags flags) const
|
||||
{
|
||||
if(flags)
|
||||
{
|
||||
if(flags & CartDebug::CODE)
|
||||
if(flags & Device::CODE)
|
||||
buf << "CODE ";
|
||||
if(flags & CartDebug::TCODE)
|
||||
if(flags & Device::TCODE)
|
||||
buf << "TCODE ";
|
||||
if(flags & CartDebug::GFX)
|
||||
if(flags & Device::GFX)
|
||||
buf << "GFX ";
|
||||
if(flags & CartDebug::PGFX)
|
||||
if(flags & Device::PGFX)
|
||||
buf << "PGFX ";
|
||||
if(flags & CartDebug::DATA)
|
||||
if(flags & Device::COL)
|
||||
buf << "COL ";
|
||||
if(flags & Device::PCOL)
|
||||
buf << "PCOL ";
|
||||
if(flags & Device::BCOL)
|
||||
buf << "BCOL ";
|
||||
if(flags & Device::AUD)
|
||||
buf << "AUD ";
|
||||
if(flags & Device::DATA)
|
||||
buf << "DATA ";
|
||||
if(flags & CartDebug::ROW)
|
||||
if(flags & Device::ROW)
|
||||
buf << "ROW ";
|
||||
if(flags & CartDebug::REFERENCED)
|
||||
if(flags & Device::REFERENCED)
|
||||
buf << "*REFERENCED ";
|
||||
if(flags & CartDebug::VALID_ENTRY)
|
||||
if(flags & Device::VALID_ENTRY)
|
||||
buf << "*VALID_ENTRY ";
|
||||
}
|
||||
else
|
||||
|
|
|
@ -31,6 +31,7 @@ using CartMethod = int (CartDebug::*)();
|
|||
|
||||
#include "bspf.hxx"
|
||||
#include "DebuggerSystem.hxx"
|
||||
#include "Device.hxx"
|
||||
|
||||
class CartState : public DebuggerState
|
||||
{
|
||||
|
@ -47,30 +48,8 @@ class CartDebug : public DebuggerSystem
|
|||
friend class DiStella;
|
||||
|
||||
public:
|
||||
enum DisasmType {
|
||||
NONE = 0,
|
||||
REFERENCED = 1 << 0, /* 0x01, code somewhere in the program references it,
|
||||
i.e. LDA $F372 referenced $F372 */
|
||||
VALID_ENTRY = 1 << 1, /* 0x02, addresses that can have a label placed in front of it.
|
||||
A good counterexample would be "FF00: LDA $FE00"; $FF01
|
||||
would be in the middle of a multi-byte instruction, and
|
||||
therefore cannot be labelled. */
|
||||
|
||||
// The following correspond to specific types that can be set within the
|
||||
// debugger, or specified in a Distella cfg file, and are listed in order
|
||||
// of decreasing hierarchy
|
||||
//
|
||||
CODE = 1 << 7, // 0x80, disassemble-able code segments
|
||||
TCODE = 1 << 6, // 0x40, (tentative) disassemble-able code segments
|
||||
GFX = 1 << 5, // 0x20, addresses loaded into GRPx registers
|
||||
PGFX = 1 << 4, // 0x10, addresses loaded into PFx registers
|
||||
DATA = 1 << 3, // 0x08, addresses loaded into registers other than GRPx / PFx
|
||||
ROW = 1 << 2, // 0x04, all other addresses
|
||||
// special type for poke()
|
||||
WRITE = TCODE // 0x40, address written to
|
||||
};
|
||||
struct DisassemblyTag {
|
||||
DisasmType type{NONE};
|
||||
Device::AccessType type{Device::NONE};
|
||||
uInt16 address{0};
|
||||
string label;
|
||||
string disasm;
|
||||
|
@ -104,28 +83,27 @@ class CartDebug : public DebuggerSystem
|
|||
CartDebugWidget* getDebugWidget() const { return myDebugWidget; }
|
||||
void setDebugWidget(CartDebugWidget* w) { myDebugWidget = w; }
|
||||
|
||||
|
||||
// Return the address of the last CPU read
|
||||
int lastReadAddress();
|
||||
// Return the address of the last CPU write
|
||||
int lastWriteAddress();
|
||||
|
||||
// Return the base (= non-mirrored) address of the last CPU read
|
||||
int lastReadBaseAddress();
|
||||
// Return the base (= non-mirrored) address of the last CPU write
|
||||
int lastWriteBaseAddress();
|
||||
|
||||
// The following two methods are meant to be used together
|
||||
// First, a call is made to disassemble(), which updates the disassembly
|
||||
// list; it will figure out when an actual complete disassembly is
|
||||
// required, and when the previous results can be used
|
||||
//
|
||||
// Later, successive calls to disassemblyList() simply return the
|
||||
// previous results; no disassembly is done in this case
|
||||
/**
|
||||
Disassemble from the given address using the Distella disassembler
|
||||
Address-to-label mappings (and vice-versa) are also determined here
|
||||
|
||||
@param force Force a re-disassembly, even if the state hasn't changed
|
||||
|
||||
@return True if disassembly changed from previous call, else false
|
||||
*/
|
||||
// TODO
|
||||
bool disassemble(bool force = false);
|
||||
bool disassembleBank(int bank);
|
||||
|
||||
// First, a call is made to disassemble(), which updates the disassembly
|
||||
// list, is required; it will figure out when an actual complete
|
||||
// disassembly is required, and when the previous results can be used
|
||||
//
|
||||
// Later, successive calls to disassembly() simply return the
|
||||
// previous results; no disassembly is done in this case
|
||||
/**
|
||||
Get the results from the most recent call to disassemble()
|
||||
*/
|
||||
|
@ -149,7 +127,7 @@ class CartDebug : public DebuggerSystem
|
|||
|
||||
@return The disassembly represented as a string
|
||||
*/
|
||||
string disassemble(uInt16 start, uInt16 lines) const;
|
||||
string disassembleLines(uInt16 start, uInt16 lines) const;
|
||||
|
||||
/**
|
||||
Add a directive to the disassembler. Directives are basically overrides
|
||||
|
@ -157,14 +135,14 @@ class CartDebug : public DebuggerSystem
|
|||
things can't be automatically determined. For now, these directives
|
||||
have exactly the same syntax as in a distella configuration file.
|
||||
|
||||
@param type Currently, CODE/DATA/GFX are supported
|
||||
@param type Currently, CODE/DATA/GFX/PGFX/COL/PCOL/BCOL/AUD/ROW are supported
|
||||
@param start The start address (inclusive) to mark with the given type
|
||||
@param end The end address (inclusive) to mark with the given type
|
||||
@param bank Bank to which these directive apply (0 indicated current bank)
|
||||
|
||||
@return True if directive was added, else false if it was removed
|
||||
*/
|
||||
bool addDirective(CartDebug::DisasmType type, uInt16 start, uInt16 end,
|
||||
bool addDirective(Device::AccessType type, uInt16 start, uInt16 end,
|
||||
int bank = -1);
|
||||
|
||||
// The following are convenience methods that query the cartridge object
|
||||
|
@ -231,6 +209,11 @@ class CartDebug : public DebuggerSystem
|
|||
string saveDisassembly();
|
||||
string saveRom();
|
||||
|
||||
/**
|
||||
Save access counters file
|
||||
*/
|
||||
string saveAccessFile();
|
||||
|
||||
/**
|
||||
Show Distella directives (both set by the user and determined by Distella)
|
||||
for the given bank (or all banks, if no bank is specified).
|
||||
|
@ -249,18 +232,21 @@ class CartDebug : public DebuggerSystem
|
|||
*/
|
||||
void getCompletions(const char* in, StringList& list) const;
|
||||
|
||||
// Convert given address to corresponding disassembly type and append to buf
|
||||
void addressTypeAsString(ostream& buf, uInt16 addr) const;
|
||||
// Convert given address to corresponding access type and append to buf
|
||||
void accessTypeAsString(ostream& buf, uInt16 addr) const;
|
||||
|
||||
// Convert access enum type to corresponding string and append to buf
|
||||
void AccessTypeAsString(ostream& buf, Device::AccessType type) const;
|
||||
|
||||
private:
|
||||
using AddrToLabel = std::map<uInt16, string>;
|
||||
using LabelToAddr = std::map<string, uInt16,
|
||||
std::function<bool(const string&, const string&)>>;
|
||||
|
||||
using AddrTypeArray = std::array<uInt8, 0x1000>;
|
||||
using AddrTypeArray = std::array<uInt16, 0x1000>;
|
||||
|
||||
struct DirectiveTag {
|
||||
DisasmType type{NONE};
|
||||
Device::AccessType type{Device::NONE};
|
||||
uInt16 start{0};
|
||||
uInt16 end{0};
|
||||
};
|
||||
|
@ -290,6 +276,19 @@ class CartDebug : public DebuggerSystem
|
|||
};
|
||||
ReservedEquates myReserved;
|
||||
|
||||
/**
|
||||
Disassemble from the given address using the Distella disassembler
|
||||
Address-to-label mappings (and vice-versa) are also determined here
|
||||
|
||||
@param bank The current bank to disassemble
|
||||
@param PC A program counter to start with
|
||||
@param force Force a re-disassembly, even if the state hasn't changed
|
||||
|
||||
@return True if disassembly changed from previous call, else false
|
||||
*/
|
||||
bool disassemble(int bank, uInt16 PC, bool force = false);
|
||||
|
||||
|
||||
// Actually call DiStella to fill the DisassemblyList structure
|
||||
// Return whether the search address was actually in the list
|
||||
bool fillDisassemblyList(BankInfo& bankinfo, uInt16 search);
|
||||
|
@ -298,15 +297,12 @@ class CartDebug : public DebuggerSystem
|
|||
// based on its disassembly
|
||||
void getBankDirectives(ostream& buf, BankInfo& info) const;
|
||||
|
||||
// Get disassembly enum type from 'flags', taking precendence into account
|
||||
DisasmType disasmTypeAbsolute(uInt8 flags) const;
|
||||
// Get access enum type from 'flags', taking precendence into account
|
||||
Device::AccessType accessTypeAbsolute(Device::AccessFlags flags) const;
|
||||
|
||||
// Convert disassembly enum type to corresponding string and append to buf
|
||||
void disasmTypeAsString(ostream& buf, DisasmType type) const;
|
||||
|
||||
// Convert all disassembly types in 'flags' to corresponding string and
|
||||
// Convert all access types in 'flags' to corresponding string and
|
||||
// append to buf
|
||||
void disasmTypeAsString(ostream& buf, uInt8 flags) const;
|
||||
void AccessTypeAsString(ostream& buf, Device::AccessFlags flags) const;
|
||||
|
||||
private:
|
||||
const OSystem& myOSystem;
|
||||
|
@ -347,7 +343,7 @@ class CartDebug : public DebuggerSystem
|
|||
uInt16 myLabelLength{8}; // longest pre-defined label
|
||||
|
||||
// Filenames to use for various I/O (currently these are hardcoded)
|
||||
string myListFile, mySymbolFile, myCfgFile, myDisasmFile, myRomFile;
|
||||
string myListFile, mySymbolFile, myCfgFile, myDisasmFile;
|
||||
|
||||
/// Table of instruction mnemonics
|
||||
static std::array<const char*, 16> ourTIAMnemonicR; // read mode
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#include "M6502.hxx"
|
||||
#include "System.hxx"
|
||||
#include "Debugger.hxx"
|
||||
#include "CartDebug.hxx"
|
||||
#include "TIADebug.hxx"
|
||||
|
||||
#include "CpuDebug.hxx"
|
||||
|
@ -46,6 +45,7 @@ const DebuggerState& CpuDebug::getState()
|
|||
myState.srcA = my6502.lastSrcAddressA();
|
||||
myState.srcX = my6502.lastSrcAddressX();
|
||||
myState.srcY = my6502.lastSrcAddressY();
|
||||
myState.dest = my6502.lastWriteAddress();
|
||||
|
||||
Debugger::set_bits(myState.PS, myState.PSbits);
|
||||
|
||||
|
@ -66,6 +66,7 @@ void CpuDebug::saveOldState()
|
|||
myOldState.srcA = my6502.lastSrcAddressA();
|
||||
myOldState.srcX = my6502.lastSrcAddressX();
|
||||
myOldState.srcY = my6502.lastSrcAddressY();
|
||||
myOldState.dest = my6502.lastWriteAddress();
|
||||
|
||||
Debugger::set_bits(myOldState.PS, myOldState.PSbits);
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ class CpuState : public DebuggerState
|
|||
{
|
||||
public:
|
||||
int PC{0}, SP{0}, PS{0}, A{0}, X{0}, Y{0};
|
||||
int srcS{0}, srcA{0}, srcX{0}, srcY{0};
|
||||
int srcS{0}, srcA{0}, srcX{0}, srcY{0}, dest{0};
|
||||
BoolArray PSbits;
|
||||
};
|
||||
|
||||
|
|
|
@ -440,19 +440,19 @@ bool Debugger::writeTrap(uInt16 t)
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt8 Debugger::peek(uInt16 addr, uInt8 flags)
|
||||
uInt8 Debugger::peek(uInt16 addr, Device::AccessFlags flags)
|
||||
{
|
||||
return mySystem.peek(addr, flags);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt16 Debugger::dpeek(uInt16 addr, uInt8 flags)
|
||||
uInt16 Debugger::dpeek(uInt16 addr, Device::AccessFlags flags)
|
||||
{
|
||||
return uInt16(mySystem.peek(addr, flags) | (mySystem.peek(addr+1, flags) << 8));
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void Debugger::poke(uInt16 addr, uInt8 value, uInt8 flags)
|
||||
void Debugger::poke(uInt16 addr, uInt8 value, Device::AccessFlags flags)
|
||||
{
|
||||
mySystem.poke(addr, value, flags);
|
||||
}
|
||||
|
@ -464,26 +464,26 @@ M6502& Debugger::m6502() const
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
int Debugger::peekAsInt(int addr, uInt8 flags)
|
||||
int Debugger::peekAsInt(int addr, Device::AccessFlags flags)
|
||||
{
|
||||
return mySystem.peek(uInt16(addr), flags);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
int Debugger::dpeekAsInt(int addr, uInt8 flags)
|
||||
int Debugger::dpeekAsInt(int addr, Device::AccessFlags flags)
|
||||
{
|
||||
return mySystem.peek(uInt16(addr), flags) |
|
||||
(mySystem.peek(uInt16(addr+1), flags) << 8);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
int Debugger::getAccessFlags(uInt16 addr) const
|
||||
Device::AccessFlags Debugger::getAccessFlags(uInt16 addr) const
|
||||
{
|
||||
return mySystem.getAccessFlags(addr);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void Debugger::setAccessFlags(uInt16 addr, uInt8 flags)
|
||||
void Debugger::setAccessFlags(uInt16 addr, Device::AccessFlags flags)
|
||||
{
|
||||
mySystem.setAccessFlags(addr, flags);
|
||||
}
|
||||
|
@ -887,6 +887,8 @@ std::array<Debugger::PseudoRegister, 11> Debugger::ourPseudoRegisters = { {
|
|||
{ "_vblank", "Whether vertical blank is enabled (1 or 0)" },
|
||||
{ "_vsync", "Whether vertical sync is enabled (1 or 0)" }
|
||||
// CPU address access functions:
|
||||
/*{ "__lastread", "last CPU read address" },
|
||||
{ "__lastwrite", "last CPU write address" },*/
|
||||
/*{ "_lastread", "last CPU read address" },
|
||||
{ "_lastwrite", "last CPU write address" },
|
||||
{ "__lastbaseread", "last CPU read base address" },
|
||||
{ "__lastbasewrite", "last CPU write base address" }*/
|
||||
} };
|
||||
|
|
|
@ -47,6 +47,7 @@ class RewindManager;
|
|||
#include "DialogContainer.hxx"
|
||||
#include "DebuggerDialog.hxx"
|
||||
#include "FrameBufferConstants.hxx"
|
||||
#include "Cart.hxx"
|
||||
#include "bspf.hxx"
|
||||
|
||||
/**
|
||||
|
@ -243,18 +244,18 @@ class Debugger : public DialogContainer
|
|||
static Debugger& debugger() { return *myStaticDebugger; }
|
||||
|
||||
/** Convenience methods to access peek/poke from System */
|
||||
uInt8 peek(uInt16 addr, uInt8 flags = 0);
|
||||
uInt16 dpeek(uInt16 addr, uInt8 flags = 0);
|
||||
void poke(uInt16 addr, uInt8 value, uInt8 flags = 0);
|
||||
uInt8 peek(uInt16 addr, Device::AccessFlags flags = Device::NONE);
|
||||
uInt16 dpeek(uInt16 addr, Device::AccessFlags flags = Device::NONE);
|
||||
void poke(uInt16 addr, uInt8 value, Device::AccessFlags flags = Device::NONE);
|
||||
|
||||
/** Convenience method to access the 6502 from System */
|
||||
M6502& m6502() const;
|
||||
|
||||
/** These are now exposed so Expressions can use them. */
|
||||
int peekAsInt(int addr, uInt8 flags = 0);
|
||||
int dpeekAsInt(int addr, uInt8 flags = 0);
|
||||
int getAccessFlags(uInt16 addr) const;
|
||||
void setAccessFlags(uInt16 addr, uInt8 flags);
|
||||
int peekAsInt(int addr, Device::AccessFlags flags = Device::NONE);
|
||||
int dpeekAsInt(int addr, Device::AccessFlags flags = Device::NONE);
|
||||
Device::AccessFlags getAccessFlags(uInt16 addr) const;
|
||||
void setAccessFlags(uInt16 addr, Device::AccessFlags flags);
|
||||
|
||||
uInt32 getBaseAddress(uInt32 addr, bool read);
|
||||
|
||||
|
|
|
@ -678,6 +678,29 @@ string DebuggerParser::saveScriptFile(string file)
|
|||
return "saved " + node.getShortPath() + " OK";
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void DebuggerParser::executeDirective(Device::AccessType type)
|
||||
{
|
||||
if(argCount != 2)
|
||||
{
|
||||
outputCommandError("specify start and end of range only", myCommand);
|
||||
return;
|
||||
}
|
||||
else if(args[1] < args[0])
|
||||
{
|
||||
commandResult << red("start address must be <= end address");
|
||||
return;
|
||||
}
|
||||
|
||||
bool result = debugger.cartDebug().addDirective(type, args[0], args[1]);
|
||||
|
||||
commandResult << (result ? "added " : "removed ");
|
||||
debugger.cartDebug().AccessTypeAsString(commandResult, type);
|
||||
commandResult << " directive on range $"
|
||||
<< hex << args[0] << " $" << hex << args[1];
|
||||
debugger.rom().invalidate();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// executor methods for commands[] array. All are void, no args.
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -689,6 +712,13 @@ void DebuggerParser::executeA()
|
|||
debugger.cpuDebug().setA(uInt8(args[0]));
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// "aud"
|
||||
void DebuggerParser::executeAud()
|
||||
{
|
||||
executeDirective(Device::AUD);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// "base"
|
||||
void DebuggerParser::executeBase()
|
||||
|
@ -720,6 +750,13 @@ void DebuggerParser::executeBase()
|
|||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// "bcol"
|
||||
void DebuggerParser::executeBCol()
|
||||
{
|
||||
executeDirective(Device::BCOL);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// "break"
|
||||
void DebuggerParser::executeBreak()
|
||||
|
@ -912,22 +949,14 @@ void DebuggerParser::executeCls()
|
|||
// "code"
|
||||
void DebuggerParser::executeCode()
|
||||
{
|
||||
if(argCount != 2)
|
||||
{
|
||||
outputCommandError("specify start and end of range only", myCommand);
|
||||
return;
|
||||
}
|
||||
else if(args[1] < args[0])
|
||||
{
|
||||
commandResult << red("start address must be <= end address");
|
||||
return;
|
||||
}
|
||||
executeDirective(Device::CODE);
|
||||
}
|
||||
|
||||
bool result = debugger.cartDebug().addDirective(
|
||||
CartDebug::CODE, args[0], args[1]);
|
||||
commandResult << (result ? "added" : "removed") << " CODE directive on range $"
|
||||
<< hex << args[0] << " $" << hex << args[1];
|
||||
debugger.rom().invalidate();
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// "col"
|
||||
void DebuggerParser::executeCol()
|
||||
{
|
||||
executeDirective(Device::COL);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -953,22 +982,7 @@ void DebuggerParser::executeD()
|
|||
// "data"
|
||||
void DebuggerParser::executeData()
|
||||
{
|
||||
if(argCount != 2)
|
||||
{
|
||||
outputCommandError("specify start and end of range only", myCommand);
|
||||
return;
|
||||
}
|
||||
else if(args[1] < args[0])
|
||||
{
|
||||
commandResult << red("start address must be <= end address");
|
||||
return;
|
||||
}
|
||||
|
||||
bool result = debugger.cartDebug().addDirective(
|
||||
CartDebug::DATA, args[0], args[1]);
|
||||
commandResult << (result ? "added" : "removed") << " DATA directive on range $"
|
||||
<< hex << args[0] << " $" << hex << args[1];
|
||||
debugger.rom().invalidate();
|
||||
executeDirective(Device::DATA);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -1067,7 +1081,7 @@ void DebuggerParser::executeDisasm()
|
|||
return;
|
||||
}
|
||||
|
||||
commandResult << debugger.cartDebug().disassemble(start, lines);
|
||||
commandResult << debugger.cartDebug().disassembleLines(start, lines);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -1270,22 +1284,7 @@ void DebuggerParser::executeFunction()
|
|||
// "gfx"
|
||||
void DebuggerParser::executeGfx()
|
||||
{
|
||||
if(argCount != 2)
|
||||
{
|
||||
outputCommandError("specify start and end of range only", myCommand);
|
||||
return;
|
||||
}
|
||||
else if(args[1] < args[0])
|
||||
{
|
||||
commandResult << red("start address must be <= end address");
|
||||
return;
|
||||
}
|
||||
|
||||
bool result = debugger.cartDebug().addDirective(
|
||||
CartDebug::GFX, args[0], args[1]);
|
||||
commandResult << (result ? "added" : "removed") << " GFX directive on range $"
|
||||
<< hex << args[0] << " $" << hex << args[1];
|
||||
debugger.rom().invalidate();
|
||||
executeDirective(Device::GFX);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -1626,26 +1625,18 @@ void DebuggerParser::executePc()
|
|||
debugger.cpuDebug().setPC(args[0]);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// "pcol"
|
||||
void DebuggerParser::executePCol()
|
||||
{
|
||||
executeDirective(Device::PCOL);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// "pgfx"
|
||||
void DebuggerParser::executePGfx()
|
||||
{
|
||||
if(argCount != 2)
|
||||
{
|
||||
outputCommandError("specify start and end of range only", myCommand);
|
||||
return;
|
||||
}
|
||||
else if(args[1] < args[0])
|
||||
{
|
||||
commandResult << red("start address must be <= end address");
|
||||
return;
|
||||
}
|
||||
|
||||
bool result = debugger.cartDebug().addDirective(
|
||||
CartDebug::PGFX, args[0], args[1]);
|
||||
commandResult << (result ? "added" : "removed") << " PGFX directive on range $"
|
||||
<< hex << args[0] << " $" << hex << args[1];
|
||||
debugger.rom().invalidate();
|
||||
executeDirective(Device::PGFX);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -1722,22 +1713,7 @@ void DebuggerParser::executeRom()
|
|||
// "row"
|
||||
void DebuggerParser::executeRow()
|
||||
{
|
||||
if(argCount != 2)
|
||||
{
|
||||
outputCommandError("specify start and end of range only", myCommand);
|
||||
return;
|
||||
}
|
||||
else if(args[1] < args[0])
|
||||
{
|
||||
commandResult << red("start address must be <= end address");
|
||||
return;
|
||||
}
|
||||
|
||||
bool result = debugger.cartDebug().addDirective(
|
||||
CartDebug::ROW, args[0], args[1]);
|
||||
commandResult << (result ? "added" : "removed") << " ROW directive on range $"
|
||||
<< hex << args[0] << " $" << hex << args[1];
|
||||
debugger.rom().invalidate();
|
||||
executeDirective(Device::ROW);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -1833,6 +1809,13 @@ void DebuggerParser::executeSave()
|
|||
commandResult << saveScriptFile(argStrings[0]);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// "saveaccess"
|
||||
void DebuggerParser::executeSaveAccess()
|
||||
{
|
||||
commandResult << debugger.cartDebug().saveAccessFile();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// "saveconfig"
|
||||
void DebuggerParser::executeSaveconfig()
|
||||
|
@ -2054,18 +2037,18 @@ void DebuggerParser::executeTraps(bool read, bool write, const string& command,
|
|||
if(read)
|
||||
{
|
||||
if(beginRead != endRead)
|
||||
conditionBuf << "__lastread>=" << Base::toString(beginRead) << "&&__lastread<=" << Base::toString(endRead);
|
||||
conditionBuf << "__lastbaseread>=" << Base::toString(beginRead) << "&&__lastbaseread<=" << Base::toString(endRead);
|
||||
else
|
||||
conditionBuf << "__lastread==" << Base::toString(beginRead);
|
||||
conditionBuf << "__lastbaseread==" << Base::toString(beginRead);
|
||||
}
|
||||
if(read && write)
|
||||
conditionBuf << "||";
|
||||
if(write)
|
||||
{
|
||||
if(beginWrite != endWrite)
|
||||
conditionBuf << "__lastwrite>=" << Base::toString(beginWrite) << "&&__lastwrite<=" << Base::toString(endWrite);
|
||||
conditionBuf << "__lastbasewrite>=" << Base::toString(beginWrite) << "&&__lastbasewrite<=" << Base::toString(endWrite);
|
||||
else
|
||||
conditionBuf << "__lastwrite==" << Base::toString(beginWrite);
|
||||
conditionBuf << "__lastbasewrite==" << Base::toString(beginWrite);
|
||||
}
|
||||
// parenthesize provided condition (end)
|
||||
if(hasCond)
|
||||
|
@ -2194,7 +2177,7 @@ void DebuggerParser::executeType()
|
|||
for(uInt32 i = beg; i <= end; ++i)
|
||||
{
|
||||
commandResult << Base::HEX4 << i << ": ";
|
||||
debugger.cartDebug().addressTypeAsString(commandResult, i);
|
||||
debugger.cartDebug().accessTypeAsString(commandResult, i);
|
||||
commandResult << endl;
|
||||
}
|
||||
}
|
||||
|
@ -2300,7 +2283,7 @@ void DebuggerParser::executeZ()
|
|||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// List of all commands available to the parser
|
||||
std::array<DebuggerParser::Command, 95> DebuggerParser::commands = { {
|
||||
std::array<DebuggerParser::Command, 100> DebuggerParser::commands = { {
|
||||
{
|
||||
"a",
|
||||
"Set Accumulator to <value>",
|
||||
|
@ -2311,6 +2294,16 @@ std::array<DebuggerParser::Command, 95> DebuggerParser::commands = { {
|
|||
std::mem_fn(&DebuggerParser::executeA)
|
||||
},
|
||||
|
||||
{
|
||||
"aud",
|
||||
"Mark 'AUD' range in disassembly",
|
||||
"Start and end of range required\nExample: aud f000 f010",
|
||||
true,
|
||||
false,
|
||||
{ Parameters::ARG_WORD, Parameters::ARG_MULTI_BYTE },
|
||||
std::mem_fn(&DebuggerParser::executeAud)
|
||||
},
|
||||
|
||||
{
|
||||
"base",
|
||||
"Set default number base to <base>",
|
||||
|
@ -2321,6 +2314,17 @@ std::array<DebuggerParser::Command, 95> DebuggerParser::commands = { {
|
|||
std::mem_fn(&DebuggerParser::executeBase)
|
||||
},
|
||||
|
||||
{
|
||||
"bcol",
|
||||
"Mark 'BCOL' range in disassembly",
|
||||
"Start and end of range required\nExample: bcol f000 f010",
|
||||
true,
|
||||
false,
|
||||
{ Parameters::ARG_WORD, Parameters::ARG_MULTI_BYTE },
|
||||
std::mem_fn(&DebuggerParser::executeBCol)
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
"break",
|
||||
"Break at <address> and <bank>",
|
||||
|
@ -2442,6 +2446,16 @@ std::array<DebuggerParser::Command, 95> DebuggerParser::commands = { {
|
|||
std::mem_fn(&DebuggerParser::executeCode)
|
||||
},
|
||||
|
||||
{
|
||||
"col",
|
||||
"Mark 'COL' range in disassembly",
|
||||
"Start and end of range required\nExample: col f000 f010",
|
||||
true,
|
||||
false,
|
||||
{ Parameters::ARG_WORD, Parameters::ARG_MULTI_BYTE },
|
||||
std::mem_fn(&DebuggerParser::executeCol)
|
||||
},
|
||||
|
||||
{
|
||||
"colortest",
|
||||
"Show value xx as TIA color",
|
||||
|
@ -2847,6 +2861,16 @@ std::array<DebuggerParser::Command, 95> DebuggerParser::commands = { {
|
|||
std::mem_fn(&DebuggerParser::executePc)
|
||||
},
|
||||
|
||||
{
|
||||
"pcol",
|
||||
"Mark 'PCOL' range in disassembly",
|
||||
"Start and end of range required\nExample: col f000 f010",
|
||||
true,
|
||||
false,
|
||||
{ Parameters::ARG_WORD, Parameters::ARG_MULTI_BYTE },
|
||||
std::mem_fn(&DebuggerParser::executePCol)
|
||||
},
|
||||
|
||||
{
|
||||
"pgfx",
|
||||
"Mark 'PGFX' range in disassembly",
|
||||
|
@ -2980,6 +3004,16 @@ std::array<DebuggerParser::Command, 95> DebuggerParser::commands = { {
|
|||
std::mem_fn(&DebuggerParser::executeSave)
|
||||
},
|
||||
|
||||
{
|
||||
"saveaccess",
|
||||
"Save the access counters to CSV file",
|
||||
"Example: saveaccess (no parameters)",
|
||||
false,
|
||||
false,
|
||||
{ Parameters::ARG_END_ARGS },
|
||||
std::mem_fn(&DebuggerParser::executeSaveAccess)
|
||||
},
|
||||
|
||||
{
|
||||
"saveconfig",
|
||||
"Save Distella config file (with default name)",
|
||||
|
@ -3182,7 +3216,7 @@ std::array<DebuggerParser::Command, 95> DebuggerParser::commands = { {
|
|||
|
||||
{
|
||||
"type",
|
||||
"Show disassembly type for address xx [yy]",
|
||||
"Show access type for address xx [yy]",
|
||||
"Example: type f000, type f000 f010",
|
||||
true,
|
||||
false,
|
||||
|
|
|
@ -27,6 +27,7 @@ class FilesystemNode;
|
|||
struct Command;
|
||||
|
||||
#include "bspf.hxx"
|
||||
#include "Device.hxx"
|
||||
|
||||
class DebuggerParser
|
||||
{
|
||||
|
@ -97,7 +98,7 @@ class DebuggerParser
|
|||
std::array<Parameters, 10> parms;
|
||||
std::function<void (DebuggerParser*)> executor;
|
||||
};
|
||||
static std::array<Command, 95> commands;
|
||||
static std::array<Command, 100> commands;
|
||||
|
||||
struct Trap
|
||||
{
|
||||
|
@ -140,9 +141,13 @@ class DebuggerParser
|
|||
// output the error with the example provided for the command
|
||||
void outputCommandError(const string& errorMsg, int command);
|
||||
|
||||
void executeDirective(Device::AccessType type);
|
||||
|
||||
// List of available command methods
|
||||
void executeA();
|
||||
void executeAud();
|
||||
void executeBase();
|
||||
void executeBCol();
|
||||
void executeBreak();
|
||||
void executeBreakif();
|
||||
void executeBreaklabel();
|
||||
|
@ -155,6 +160,7 @@ class DebuggerParser
|
|||
void executeClearwatches();
|
||||
void executeCls();
|
||||
void executeCode();
|
||||
void executeCol();
|
||||
void executeColortest();
|
||||
void executeD();
|
||||
void executeData();
|
||||
|
@ -195,6 +201,7 @@ class DebuggerParser
|
|||
void executeN();
|
||||
void executePalette();
|
||||
void executePc();
|
||||
void executePCol();
|
||||
void executePGfx();
|
||||
void executePrint();
|
||||
void executeRam();
|
||||
|
@ -208,6 +215,7 @@ class DebuggerParser
|
|||
void executeRunToPc();
|
||||
void executeS();
|
||||
void executeSave();
|
||||
void executeSaveAccess();
|
||||
void executeSaveallstates();
|
||||
void executeSaveconfig();
|
||||
void executeSavedisassembly();
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -22,6 +22,7 @@
|
|||
|
||||
#include "Base.hxx"
|
||||
#include "CartDebug.hxx"
|
||||
#include "Device.hxx"
|
||||
#include "bspf.hxx"
|
||||
|
||||
/**
|
||||
|
@ -71,11 +72,26 @@ class DiStella
|
|||
CartDebug::AddrTypeArray& directives,
|
||||
CartDebug::ReservedEquates& reserved);
|
||||
|
||||
private:
|
||||
/**
|
||||
Enumeration of the addressing type (RAM, ROM, RIOT, TIA...)
|
||||
*/
|
||||
enum class AddressType : int
|
||||
{
|
||||
INVALID,
|
||||
ROM,
|
||||
TIA,
|
||||
RIOT,
|
||||
ROM_MIRROR,
|
||||
ZP_RAM
|
||||
};
|
||||
|
||||
|
||||
private:
|
||||
// Indicate that a new line of disassembly has been completed
|
||||
// In the original Distella code, this indicated a new line to be printed
|
||||
// Here, we add a new entry to the DisassemblyList
|
||||
void addEntry(CartDebug::DisasmType type);
|
||||
void addEntry(Device::AccessType type);
|
||||
|
||||
// Process directives given in the list
|
||||
// Directives are basically the contents of a distella configuration file
|
||||
|
@ -87,32 +103,32 @@ class DiStella
|
|||
void disasmFromAddress(uInt32 distart);
|
||||
|
||||
bool check_range(uInt16 start, uInt16 end) const;
|
||||
int mark(uInt32 address, uInt8 mask, bool directive = false);
|
||||
bool checkBit(uInt16 address, uInt8 mask, bool useDebugger = true) const;
|
||||
|
||||
bool checkBits(uInt16 address, uInt8 mask, uInt8 notMask, bool useDebugger = true) const;
|
||||
AddressType mark(uInt32 address, uInt16 mask, bool directive = false);
|
||||
bool checkBit(uInt16 address, uInt16 mask, bool useDebugger = true) const;
|
||||
bool checkBits(uInt16 address, uInt16 mask, uInt16 notMask, bool useDebugger = true) const;
|
||||
void outputGraphics();
|
||||
void outputBytes(CartDebug::DisasmType type);
|
||||
void outputColors();
|
||||
void outputBytes(Device::AccessType type);
|
||||
|
||||
// Convenience methods to generate appropriate labels
|
||||
inline void labelA12High(stringstream& buf, uInt8 op, uInt16 addr, int labfound)
|
||||
inline void labelA12High(stringstream& buf, uInt8 op, uInt16 addr, AddressType labfound)
|
||||
{
|
||||
if(!myDbg.getLabel(buf, addr, true))
|
||||
buf << "L" << Common::Base::HEX4 << addr;
|
||||
}
|
||||
inline void labelA12Low(stringstream& buf, uInt8 op, uInt16 addr, int labfound)
|
||||
inline void labelA12Low(stringstream& buf, uInt8 op, uInt16 addr, AddressType labfound)
|
||||
{
|
||||
myDbg.getLabel(buf, addr, ourLookup[op].rw_mode == RWMode::READ, 2);
|
||||
if (labfound == 2)
|
||||
if (labfound == AddressType::TIA)
|
||||
{
|
||||
if(ourLookup[op].rw_mode == RWMode::READ)
|
||||
myReserved.TIARead[addr & 0x0F] = true;
|
||||
else
|
||||
myReserved.TIAWrite[addr & 0x3F] = true;
|
||||
}
|
||||
else if (labfound == 3)
|
||||
else if (labfound == AddressType::RIOT)
|
||||
myReserved.IOReadWrite[(addr & 0xFF) - 0x80] = true;
|
||||
else if (labfound == 5)
|
||||
else if (labfound == AddressType::ZP_RAM)
|
||||
myReserved.ZPRAM[(addr & 0xFF) - 0x80] = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,8 @@ CartridgeDPCPlusWidget::CartridgeDPCPlusWidget(
|
|||
<< "DPC registers accessible @ $F000 - $F07F\n"
|
||||
<< " $F000 - $F03F (R), $F040 - $F07F (W)\n"
|
||||
<< "Banks accessible at hotspots $FFF6 to $FFFB\n"
|
||||
<< "Startup bank = " << cart.startBank() << "\n";
|
||||
<< "Startup bank = " << cart.startBank() << "\n"
|
||||
<< "Ver = " << cart.myDriverMD5;
|
||||
|
||||
#if 0
|
||||
// Eventually, we should query this from the debugger/disassembler
|
||||
|
|
|
@ -93,10 +93,11 @@ CpuWidget::CpuWidget(GuiObject* boss, const GUI::Font& lfont, const GUI::Font& n
|
|||
myCpuDataSrc[i]->setEditable(false, true);
|
||||
src_y += fontHeight+2;
|
||||
}
|
||||
int swidth = lfont.getStringWidth("Source Address");
|
||||
new StaticTextWidget(boss, lfont, xpos, src_y + 4, src_w,
|
||||
fontHeight, swidth <= src_w ? "Source Address" : "Source Addr",
|
||||
TextAlign::Center);
|
||||
|
||||
// Last write destination address
|
||||
new StaticTextWidget(boss, lfont, xpos - fontWidth * 4.5, src_y + 4, "Dest");
|
||||
myCpuDataDest = new EditTextWidget(boss, nfont, xpos, src_y + 2, src_w, fontHeight+1);
|
||||
myCpuDataDest->setEditable(false, true);
|
||||
|
||||
// Add labels for other CPU registers
|
||||
xpos = x;
|
||||
|
@ -325,6 +326,10 @@ void CpuWidget::loadConfig()
|
|||
myCpuDataSrc[3]->setText((srcY != EmptyString ? srcY : Common::Base::toString(state.srcY)),
|
||||
state.srcY != oldstate.srcY);
|
||||
|
||||
const string& dest = state.dest < 0 ? "" : cart.getLabel(state.dest, false);
|
||||
myCpuDataDest->setText((dest != EmptyString ? dest : Common::Base::toString(state.dest)),
|
||||
state.dest != oldstate.dest);
|
||||
|
||||
// Update the PS register booleans
|
||||
changed.clear();
|
||||
for(uInt32 i = 0; i < state.PSbits.size(); ++i)
|
||||
|
|
|
@ -76,6 +76,7 @@ class CpuWidget : public Widget, public CommandSender
|
|||
ToggleBitWidget* myPSRegister{nullptr};
|
||||
EditTextWidget* myPCLabel{nullptr};
|
||||
std::array<EditTextWidget*, 4> myCpuDataSrc{nullptr};
|
||||
EditTextWidget* myCpuDataDest{nullptr};
|
||||
|
||||
private:
|
||||
// Following constructors and assignment operators not supported
|
||||
|
|
|
@ -511,9 +511,10 @@ void RomListWidget::drawWidget(bool hilite)
|
|||
|
||||
// Bytes are only editable if they represent code, graphics, or accessible data
|
||||
// Otherwise, the disassembly should get all remaining space
|
||||
if(dlist[pos].type & (CartDebug::CODE|CartDebug::GFX|CartDebug::PGFX|CartDebug::DATA))
|
||||
if(dlist[pos].type & (Device::CODE|Device::GFX|Device::PGFX|
|
||||
Device::COL|Device::PCOL|Device::BCOL|Device::DATA))
|
||||
{
|
||||
if(dlist[pos].type == CartDebug::CODE)
|
||||
if(dlist[pos].type == Device::CODE)
|
||||
{
|
||||
// Draw mnemonic
|
||||
s.drawString(_font, dlist[pos].disasm.substr(0, 7), xpos + _labelWidth, ypos,
|
||||
|
@ -592,8 +593,8 @@ void RomListWidget::startEditMode()
|
|||
_editMode = true;
|
||||
switch(myDisasm->list[_selectedItem].type)
|
||||
{
|
||||
case CartDebug::GFX:
|
||||
case CartDebug::PGFX:
|
||||
case Device::GFX:
|
||||
case Device::PGFX:
|
||||
_base = DiStella::settings.gfxFormat;
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -143,10 +143,10 @@ void TiaInfoWidget::loadConfig()
|
|||
|
||||
uInt64 total = tia.cyclesLo() + (uInt64(tia.cyclesHi()) << 32);
|
||||
uInt64 totalOld = oldTia.info[2] + (uInt64(oldTia.info[3]) << 32);
|
||||
myTotalCycles->setText(Common::Base::toString(total / 1000000, Common::Base::Fmt::_10_6) + "e6",
|
||||
myTotalCycles->setText(Common::Base::toString(uInt32(total) / 1000000, Common::Base::Fmt::_10_6) + "e6",
|
||||
total != totalOld);
|
||||
uInt32 delta = total - totalOld;
|
||||
myDeltaCycles->setText(Common::Base::toString(delta, Common::Base::Fmt::_10_8)); // no coloring
|
||||
uInt64 delta = total - totalOld;
|
||||
myDeltaCycles->setText(Common::Base::toString(uInt32(delta), Common::Base::Fmt::_10_8)); // no coloring
|
||||
|
||||
int clk = tia.clocksThisLine();
|
||||
myScanlineCount->setText(Common::Base::toString(tia.scanlines(), Common::Base::Fmt::_10_3),
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include "MD5.hxx"
|
||||
#ifdef DEBUGGER_SUPPORT
|
||||
#include "Debugger.hxx"
|
||||
#include "CartDebug.hxx"
|
||||
#include "Base.hxx"
|
||||
#endif
|
||||
|
||||
#include "Cart.hxx"
|
||||
|
@ -39,7 +39,7 @@ Cartridge::Cartridge(const Settings& settings, const string& md5)
|
|||
for(uInt32 i = 0; i < 256; ++i)
|
||||
myRWPRandomValues[i] = rand.next();
|
||||
|
||||
myRAMAccesses.reserve(5);
|
||||
myRamReadAccesses.reserve(5);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -76,6 +76,16 @@ bool Cartridge::bankChanged()
|
|||
return changed;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt16 Cartridge::bankSize(uInt16 bank) const
|
||||
{
|
||||
size_t size;
|
||||
|
||||
getImage(size);
|
||||
|
||||
return std::min(uInt32(size) / bankCount(), 4_KB); // assuming that each bank has the same size
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt8 Cartridge::peekRAM(uInt8& dest, uInt16 address)
|
||||
{
|
||||
|
@ -87,7 +97,7 @@ uInt8 Cartridge::peekRAM(uInt8& dest, uInt16 address)
|
|||
if(!bankLocked() && !mySystem->autodetectMode())
|
||||
{
|
||||
// Record access here; final determination will happen in ::pokeRAM()
|
||||
myRAMAccesses.push_back(address);
|
||||
myRamReadAccesses.push_back(address);
|
||||
dest = value;
|
||||
}
|
||||
#else
|
||||
|
@ -101,11 +111,11 @@ uInt8 Cartridge::peekRAM(uInt8& dest, uInt16 address)
|
|||
void Cartridge::pokeRAM(uInt8& dest, uInt16 address, uInt8 value)
|
||||
{
|
||||
#ifdef DEBUGGER_SUPPORT
|
||||
for(auto i = myRAMAccesses.begin(); i != myRAMAccesses.end(); ++i)
|
||||
for(auto i = myRamReadAccesses.begin(); i != myRamReadAccesses.end(); ++i)
|
||||
{
|
||||
if(*i == address)
|
||||
{
|
||||
myRAMAccesses.erase(i);
|
||||
myRamReadAccesses.erase(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -114,16 +124,96 @@ void Cartridge::pokeRAM(uInt8& dest, uInt16 address, uInt8 value)
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void Cartridge::createCodeAccessBase(size_t size)
|
||||
void Cartridge::createRomAccessArrays(size_t size)
|
||||
{
|
||||
myAccessSize = uInt32(size);
|
||||
#ifdef DEBUGGER_SUPPORT
|
||||
myCodeAccessBase = make_unique<uInt8[]>(size);
|
||||
std::fill_n(myCodeAccessBase.get(), size, CartDebug::ROW);
|
||||
myRomAccessBase = make_unique<Device::AccessFlags[]>(size);
|
||||
std::fill_n(myRomAccessBase.get(), size, Device::ROW);
|
||||
myRomAccessCounter = make_unique<Device::AccessCounter[]>(size * 2);
|
||||
std::fill_n(myRomAccessCounter.get(), size * 2, 0);
|
||||
#else
|
||||
myCodeAccessBase = nullptr;
|
||||
myRomAccessBase = nullptr;
|
||||
myRomAccessCounter = nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef DEBUGGER_SUPPORT
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
string Cartridge::getAccessCounters() const
|
||||
{
|
||||
ostringstream out;
|
||||
uInt32 offset = 0;
|
||||
|
||||
for(uInt16 bank = 0; bank < bankCount(); ++bank)
|
||||
{
|
||||
uInt16 origin = bankOrigin(bank);
|
||||
uInt16 bankSize = this->bankSize(bank);
|
||||
|
||||
out << "Bank " << Common::Base::toString(bank, Common::Base::Fmt::_10_8) << " / 0.."
|
||||
<< Common::Base::toString(bankCount() - 1, Common::Base::Fmt::_10_8) << " reads:\n";
|
||||
for(uInt16 addr = 0; addr < bankSize; ++addr)
|
||||
{
|
||||
out << Common::Base::HEX4 << (addr | origin) << ","
|
||||
<< Common::Base::toString(myRomAccessCounter[offset + addr], Common::Base::Fmt::_10_8) << ", ";
|
||||
}
|
||||
out << "\n";
|
||||
out << "Bank " << Common::Base::toString(bank, Common::Base::Fmt::_10_8) << " / 0.."
|
||||
<< Common::Base::toString(bankCount() - 1, Common::Base::Fmt::_10_8) << " writes:\n";
|
||||
for(uInt16 addr = 0; addr < bankSize; ++addr)
|
||||
{
|
||||
out << Common::Base::HEX4 << (addr | origin) << ","
|
||||
<< Common::Base::toString(myRomAccessCounter[offset + addr + myAccessSize], Common::Base::Fmt::_10_8) << ", ";
|
||||
}
|
||||
out << "\n";
|
||||
|
||||
offset += bankSize;
|
||||
}
|
||||
|
||||
return out.str();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt16 Cartridge::bankOrigin(uInt16 bank) const
|
||||
{
|
||||
// isolate the high 3 address bits, count them and
|
||||
// select the most frequent to define the bank origin
|
||||
// TODO: origin for banks smaller than 4K
|
||||
const int intervals = 0x8000 / 0x100;
|
||||
uInt32 offset = bank * bankSize();
|
||||
//uInt16 addrMask = (4_KB - 1) & ~(bankSize(bank) - 1);
|
||||
//int addrShift = 0;
|
||||
std::array<uInt16, intervals> count; // up to 128 256 byte interval origins
|
||||
|
||||
|
||||
//if(addrMask)
|
||||
// addrShift = log(addrMask) / log(2);
|
||||
//addrMask;
|
||||
|
||||
count.fill(0);
|
||||
for(uInt16 addr = 0x0000; addr < bankSize(bank); ++addr)
|
||||
{
|
||||
Device::AccessFlags flags = myRomAccessBase[offset + addr];
|
||||
// only count really accessed addresses
|
||||
if(flags & ~Device::ROW)
|
||||
{
|
||||
//uInt16 addrBit = addr >> addrShift;
|
||||
count[(flags & Device::HADDR) >> 13]++;
|
||||
}
|
||||
}
|
||||
uInt16 max = 0, maxIdx = 0;
|
||||
for(int idx = 0; idx < intervals; ++idx)
|
||||
{
|
||||
if(count[idx] > max)
|
||||
{
|
||||
max = count[idx];
|
||||
maxIdx = idx;
|
||||
}
|
||||
}
|
||||
return maxIdx << 13 | 0x1000; //| (offset & 0xfff);
|
||||
}
|
||||
#endif
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void Cartridge::initializeRAM(uInt8* arr, size_t size, uInt8 val) const
|
||||
{
|
||||
|
|
|
@ -31,6 +31,7 @@ class GuiObject;
|
|||
#include "Font.hxx"
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
A cartridge is a device which contains the machine code for a
|
||||
game and handles any bankswitching performed by the cartridge.
|
||||
|
@ -112,7 +113,7 @@ class Cartridge : public Device
|
|||
Clears information about all accesses to cart RAM.
|
||||
*/
|
||||
void clearAllRAMAccesses() {
|
||||
myRAMAccesses.clear();
|
||||
myRamReadAccesses.clear();
|
||||
myRamWriteAccess = 0;
|
||||
}
|
||||
|
||||
|
@ -124,7 +125,7 @@ class Cartridge : public Device
|
|||
@return Address of illegal access if one occurred, else 0
|
||||
*/
|
||||
uInt16 getIllegalRAMReadAccess() const {
|
||||
return myRAMAccesses.size() > 0 ? myRAMAccesses[0] : 0;
|
||||
return myRamReadAccesses.size() > 0 ? myRamReadAccesses[0] : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -135,6 +136,22 @@ class Cartridge : public Device
|
|||
@return Address of illegal access if one occurred, else 0
|
||||
*/
|
||||
uInt16 getIllegalRAMWriteAccess() const { return myRamWriteAccess; }
|
||||
|
||||
|
||||
/**
|
||||
Query the access counters
|
||||
|
||||
@return The access counters as comma separated string
|
||||
*/
|
||||
string getAccessCounters() const override;
|
||||
|
||||
/**
|
||||
Determine the bank's origin
|
||||
|
||||
@param bank The bank to query
|
||||
@return The origin of the bank
|
||||
*/
|
||||
uInt16 bankOrigin(uInt16 bank) const;
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
@ -177,6 +194,14 @@ class Cartridge : public Device
|
|||
*/
|
||||
virtual uInt16 bankCount() const { return 1; }
|
||||
|
||||
/**
|
||||
Get the size of a bank.
|
||||
|
||||
@param bank The bank to get the size for
|
||||
@return The bank's size
|
||||
*/
|
||||
virtual uInt16 bankSize(uInt16 bank = 0) const;
|
||||
|
||||
/**
|
||||
Patch the cartridge ROM.
|
||||
|
||||
|
@ -273,7 +298,7 @@ class Cartridge : public Device
|
|||
|
||||
@param size The size of the code-access array to create
|
||||
*/
|
||||
void createCodeAccessBase(size_t size);
|
||||
void createRomAccessArrays(size_t size);
|
||||
|
||||
/**
|
||||
Fill the given RAM array with (possibly random) data.
|
||||
|
@ -321,12 +346,20 @@ class Cartridge : public Device
|
|||
bool myBankChanged{true};
|
||||
|
||||
// The array containing information about every byte of ROM indicating
|
||||
// whether it is used as code.
|
||||
ByteBuffer myCodeAccessBase;
|
||||
// whether it is used as code, data, graphics etc.
|
||||
std::unique_ptr<Device::AccessFlags[]> myRomAccessBase;
|
||||
|
||||
// The array containing information about every byte of ROM indicating
|
||||
// how often it is accessed.
|
||||
std::unique_ptr<Device::AccessCounter[]> myRomAccessCounter;
|
||||
|
||||
|
||||
// Contains address of illegal RAM write access or 0
|
||||
uInt16 myRamWriteAccess{0};
|
||||
|
||||
// Total size of ROM access area (might include RAM too)
|
||||
uInt32 myAccessSize;
|
||||
|
||||
private:
|
||||
// The startup bank to use (where to look for the reset vector address)
|
||||
uInt16 myStartBank{0};
|
||||
|
@ -347,8 +380,10 @@ class Cartridge : public Device
|
|||
// Used when we want the 'Cartridge.StartBank' ROM property
|
||||
StartBankFromPropsFunc myStartBankFromPropsFunc;
|
||||
|
||||
// Contains
|
||||
ShortArray myRAMAccesses;
|
||||
// Used to answer whether an access in the last instruction cycle
|
||||
// generated an illegal read RAM access. Contains address of illegal
|
||||
// access.
|
||||
ShortArray myRamReadAccesses;
|
||||
|
||||
// Following constructors and assignment operators not supported
|
||||
Cartridge() = delete;
|
||||
|
|
|
@ -25,7 +25,7 @@ Cartridge0840::Cartridge0840(const ByteBuffer& image, size_t size,
|
|||
{
|
||||
// Copy the ROM image into my buffer
|
||||
std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin());
|
||||
createCodeAccessBase(myImage.size());
|
||||
createRomAccessArrays(myImage.size());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -137,7 +137,7 @@ bool Cartridge0840::bank(uInt16 bank)
|
|||
for(uInt16 addr = 0x1000; addr < 0x2000; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
return myBankChanged = true;
|
||||
|
|
|
@ -51,7 +51,7 @@ Cartridge2K::Cartridge2K(const ByteBuffer& image, size_t size,
|
|||
mySize = System::PAGE_SIZE;
|
||||
}
|
||||
|
||||
createCodeAccessBase(mySize);
|
||||
createRomAccessArrays(mySize);
|
||||
|
||||
// Set mask for accessing the image buffer
|
||||
// This is guaranteed to work, as mySize is a power of two
|
||||
|
@ -76,7 +76,9 @@ void Cartridge2K::install(System& system)
|
|||
for(uInt16 addr = 0x1000; addr < 0x2000; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myImage[addr & myMask];
|
||||
access.codeAccessBase = &myCodeAccessBase[addr & myMask];
|
||||
access.romAccessBase = &myRomAccessBase[addr & myMask];
|
||||
access.romPeekCounter = &myRomAccessCounter[addr & myMask];
|
||||
access.romPokeCounter = &myRomAccessCounter[(addr & myMask) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ Cartridge3E::Cartridge3E(const ByteBuffer& image, size_t size,
|
|||
|
||||
// Copy the ROM image into my buffer
|
||||
std::copy_n(image.get(), mySize, myImage.get());
|
||||
createCodeAccessBase(mySize + myRAM.size());
|
||||
createRomAccessArrays(mySize + myRAM.size());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -59,7 +59,9 @@ void Cartridge3E::install(System& system)
|
|||
for(uInt16 addr = 0x1800; addr < 0x2000; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myImage[(mySize - 2048) + (addr & 0x07FF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[(mySize - 2048) + (addr & 0x07FF)];
|
||||
access.romAccessBase = &myRomAccessBase[(mySize - 2048) + (addr & 0x07FF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[(mySize - 2048) + (addr & 0x07FF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[(mySize - 2048) + (addr & 0x07FF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
|
@ -73,25 +75,19 @@ uInt8 Cartridge3E::peek(uInt16 address)
|
|||
uInt16 peekAddress = address;
|
||||
address &= 0x0FFF;
|
||||
|
||||
if(address < 0x0800)
|
||||
// Due to the way paging is set up, the only way to get here is a TIA read or
|
||||
// attempting to read from the RAM write port
|
||||
|
||||
if(address < 0x0040) // TIA access
|
||||
return mySystem->tia().peek(address);
|
||||
else if(myCurrentBank >= 256)
|
||||
{
|
||||
if(myCurrentBank < 256)
|
||||
return myImage[(address & 0x07FF) + (myCurrentBank << 11)];
|
||||
else
|
||||
{
|
||||
if(address < 0x0400)
|
||||
return myRAM[(address & 0x03FF) + ((myCurrentBank - 256) << 10)];
|
||||
else
|
||||
{
|
||||
// Reading from the write port triggers an unwanted write
|
||||
return peekRAM(myRAM[(address & 0x03FF) + ((myCurrentBank - 256) << 10)], peekAddress);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return myImage[(address & 0x07FF) + mySize - 2048];
|
||||
// Reading from the write port triggers an unwanted write
|
||||
return peekRAM(myRAM[(address & 0x03FF) + ((myCurrentBank - 256) << 10)], peekAddress);
|
||||
}
|
||||
|
||||
// Make compiler happy; should never get here
|
||||
return myImage[(address & 0x07FF) + mySize - 2048];
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -111,11 +107,12 @@ bool Cartridge3E::poke(uInt16 address, uInt8 value)
|
|||
|
||||
return mySystem->tia().poke(address, value);
|
||||
}
|
||||
else
|
||||
else if(myCurrentBank >= 256)
|
||||
{
|
||||
if(address & 0x0400)
|
||||
{
|
||||
pokeRAM(myRAM[(address & 0x03FF) + ((myCurrentBank - 256) << 10)], pokeAddress, value);
|
||||
pokeRAM(myRAM[(address & 0x03FF) + ((myCurrentBank - 256) << 10)],
|
||||
pokeAddress, value);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
@ -128,6 +125,7 @@ bool Cartridge3E::poke(uInt16 address, uInt8 value)
|
|||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -158,7 +156,9 @@ bool Cartridge3E::bank(uInt16 bank)
|
|||
for(uInt16 addr = 0x1000; addr < 0x1800; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myImage[offset + (addr & 0x07FF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[offset + (addr & 0x07FF)];
|
||||
access.romAccessBase = &myRomAccessBase[offset + (addr & 0x07FF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[offset + (addr & 0x07FF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[offset + (addr & 0x07FF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
}
|
||||
|
@ -174,10 +174,13 @@ bool Cartridge3E::bank(uInt16 bank)
|
|||
System::PageAccess access(this, System::PageAccessType::READ);
|
||||
|
||||
// Map read-port RAM image into the system
|
||||
// Writes are mapped to poke(), to check for write to the read port
|
||||
for(uInt16 addr = 0x1000; addr < 0x1400; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myRAM[offset + (addr & 0x03FF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[mySize + offset + (addr & 0x03FF)];
|
||||
access.romAccessBase = &myRomAccessBase[mySize + offset + (addr & 0x03FF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[mySize + offset + (addr & 0x03FF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[mySize + offset + (addr & 0x03FF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
|
@ -185,11 +188,12 @@ bool Cartridge3E::bank(uInt16 bank)
|
|||
access.type = System::PageAccessType::WRITE;
|
||||
|
||||
// Map write-port RAM image into the system
|
||||
// Map access to this class, since we need to inspect all accesses to
|
||||
// check if RWP happens
|
||||
// Reads are mapped to peek(), to check for read from write port
|
||||
for(uInt16 addr = 0x1400; addr < 0x1800; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.codeAccessBase = &myCodeAccessBase[mySize + offset + (addr & 0x03FF)];
|
||||
access.romAccessBase = &myRomAccessBase[mySize + offset + (addr & 0x03FF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[mySize + offset + (addr & 0x03FF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[mySize + offset + (addr & 0x03FF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
}
|
||||
|
@ -216,6 +220,12 @@ uInt16 Cartridge3E::bankCount() const
|
|||
return 256 + 32;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt16 Cartridge3E::bankSize(uInt16 bank) const
|
||||
{
|
||||
return 2_KB; // we cannot use bankCount() here, because it delivers wrong numbers
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool Cartridge3E::patch(uInt16 address, uInt8 value)
|
||||
{
|
||||
|
|
|
@ -111,6 +111,14 @@ class Cartridge3E : public Cartridge
|
|||
*/
|
||||
uInt16 bankCount() const override;
|
||||
|
||||
/**
|
||||
Get the size of a bank.
|
||||
|
||||
@param bank The bank to get the size for
|
||||
@return The bank's size
|
||||
*/
|
||||
virtual uInt16 bankSize(uInt16 bank = 0) const override;
|
||||
|
||||
/**
|
||||
Patch the cartridge ROM.
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ Cartridge3EPlus::Cartridge3EPlus(const ByteBuffer& image, size_t size,
|
|||
|
||||
// Copy the ROM image into my buffer
|
||||
std::copy_n(image.get(), mySize, myImage.get());
|
||||
createCodeAccessBase(mySize + myRAM.size());
|
||||
createRomAccessArrays(mySize + myRAM.size());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -143,10 +143,22 @@ bool Cartridge3EPlus::poke(uInt16 address, uInt8 value)
|
|||
|
||||
if(whichBankIsThere & BITMASK_ROMRAM)
|
||||
{
|
||||
uInt32 byteOffset = address & BITMASK_RAM_BANK;
|
||||
uInt32 baseAddress = ((whichBankIsThere & BIT_BANK_MASK) << RAM_BANK_TO_POWER) + byteOffset;
|
||||
pokeRAM(myRAM[baseAddress], address, value);
|
||||
changed = true;
|
||||
if(address & RAM_BANK_SIZE)
|
||||
{
|
||||
uInt32 byteOffset = address & BITMASK_RAM_BANK;
|
||||
uInt32 baseAddress = ((whichBankIsThere & BIT_BANK_MASK) << RAM_BANK_TO_POWER) + byteOffset;
|
||||
pokeRAM(myRAM[baseAddress], address, value);
|
||||
changed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Writing to the read port should be ignored, but trigger a break if option enabled
|
||||
uInt8 dummy;
|
||||
|
||||
pokeRAM(dummy, address, value);
|
||||
myRamWriteAccess = address;
|
||||
changed = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -202,7 +214,7 @@ void Cartridge3EPlus::bankRAMSlot(uInt16 bank)
|
|||
if(!upper)
|
||||
access.directPeekBase = &myRAM[startCurrentBank + (addr & (RAM_BANK_SIZE - 1))];
|
||||
|
||||
access.codeAccessBase = &myCodeAccessBase[mySize + startCurrentBank + (addr & (RAM_BANK_SIZE - 1))];
|
||||
access.romAccessBase = &myRomAccessBase[mySize + startCurrentBank + (addr & (RAM_BANK_SIZE - 1))];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
}
|
||||
|
@ -242,7 +254,7 @@ void Cartridge3EPlus::bankROMSlot(uInt16 bank)
|
|||
for(uInt16 addr = start; addr <= end; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myImage[startCurrentBank + (addr & (ROM_BANK_SIZE - 1))];
|
||||
access.codeAccessBase = &myCodeAccessBase[startCurrentBank + (addr & (ROM_BANK_SIZE - 1))];
|
||||
access.romAccessBase = &myRomAccessBase[startCurrentBank + (addr & (ROM_BANK_SIZE - 1))];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ Cartridge3F::Cartridge3F(const ByteBuffer& image, size_t size,
|
|||
|
||||
// Copy the ROM image into my buffer
|
||||
std::copy_n(image.get(), mySize, myImage.get());
|
||||
createCodeAccessBase(mySize);
|
||||
createRomAccessArrays(mySize);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -57,7 +57,9 @@ void Cartridge3F::install(System& system)
|
|||
for(uInt16 addr = 0x1800; addr < 0x2000; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myImage[(mySize - 2048) + (addr & 0x07FF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[(mySize - 2048) + (addr & 0x07FF)];
|
||||
access.romAccessBase = &myRomAccessBase[(mySize - 2048) + (addr & 0x07FF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[(mySize - 2048) + (addr & 0x07FF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[(mySize - 2048) + (addr & 0x07FF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
|
@ -117,7 +119,9 @@ bool Cartridge3F::bank(uInt16 bank)
|
|||
for(uInt16 addr = 0x1000; addr < 0x1800; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myImage[offset + (addr & 0x07FF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[offset + (addr & 0x07FF)];
|
||||
access.romAccessBase = &myRomAccessBase[offset + (addr & 0x07FF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[offset + (addr & 0x07FF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[offset + (addr & 0x07FF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
return myBankChanged = true;
|
||||
|
|
|
@ -34,14 +34,14 @@ Cartridge4A50::Cartridge4A50(const ByteBuffer& image, size_t size,
|
|||
for(uInt32 slice = 0; slice < 128_KB / size; ++slice)
|
||||
std::copy_n(image.get(), size, myImage.begin() + (slice*size));
|
||||
|
||||
// We use System::PageAccess.codeAccessBase, but don't allow its use
|
||||
// We use System::PageAccess.romAccessBase, but don't allow its use
|
||||
// through a pointer, since the address space of 4A50 carts can change
|
||||
// at the instruction level, and PageAccess is normally defined at an
|
||||
// interval of 64 bytes
|
||||
//
|
||||
// Instead, access will be through the getAccessFlags and setAccessFlags
|
||||
// methods below
|
||||
createCodeAccessBase(myImage.size() + myRAM.size());
|
||||
createRomAccessArrays(myImage.size() + myRAM.size());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -181,68 +181,70 @@ bool Cartridge4A50::poke(uInt16 address, uInt8 value)
|
|||
return myBankChanged;
|
||||
}
|
||||
|
||||
#ifdef DEBUGGER_SUPPORT
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt8 Cartridge4A50::getAccessFlags(uInt16 address) const
|
||||
Device::AccessFlags Cartridge4A50::getAccessFlags(uInt16 address) const
|
||||
{
|
||||
if((address & 0x1800) == 0x1000) // 2K region from 0x1000 - 0x17ff
|
||||
{
|
||||
if(myIsRomLow)
|
||||
return myCodeAccessBase[(address & 0x7ff) + mySliceLow];
|
||||
return myRomAccessBase[(address & 0x7ff) + mySliceLow];
|
||||
else
|
||||
return myCodeAccessBase[131072 + (address & 0x7ff) + mySliceLow];
|
||||
return myRomAccessBase[131072 + (address & 0x7ff) + mySliceLow];
|
||||
}
|
||||
else if(((address & 0x1fff) >= 0x1800) && // 1.5K region from 0x1800 - 0x1dff
|
||||
((address & 0x1fff) <= 0x1dff))
|
||||
{
|
||||
if(myIsRomMiddle)
|
||||
return myCodeAccessBase[(address & 0x7ff) + mySliceMiddle + 0x10000];
|
||||
return myRomAccessBase[(address & 0x7ff) + mySliceMiddle + 0x10000];
|
||||
else
|
||||
return myCodeAccessBase[131072 + (address & 0x7ff) + mySliceMiddle];
|
||||
return myRomAccessBase[131072 + (address & 0x7ff) + mySliceMiddle];
|
||||
}
|
||||
else if((address & 0x1f00) == 0x1e00) // 256B region from 0x1e00 - 0x1eff
|
||||
{
|
||||
if(myIsRomHigh)
|
||||
return myCodeAccessBase[(address & 0xff) + mySliceHigh + 0x10000];
|
||||
return myRomAccessBase[(address & 0xff) + mySliceHigh + 0x10000];
|
||||
else
|
||||
return myCodeAccessBase[131072 + (address & 0xff) + mySliceHigh];
|
||||
return myRomAccessBase[131072 + (address & 0xff) + mySliceHigh];
|
||||
}
|
||||
else if((address & 0x1f00) == 0x1f00) // 256B region from 0x1f00 - 0x1fff
|
||||
{
|
||||
return myCodeAccessBase[(address & 0xff) + 0x1ff00];
|
||||
return myRomAccessBase[(address & 0xff) + 0x1ff00];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void Cartridge4A50::setAccessFlags(uInt16 address, uInt8 flags)
|
||||
void Cartridge4A50::setAccessFlags(uInt16 address, Device::AccessFlags flags)
|
||||
{
|
||||
if((address & 0x1800) == 0x1000) // 2K region from 0x1000 - 0x17ff
|
||||
{
|
||||
if(myIsRomLow)
|
||||
myCodeAccessBase[(address & 0x7ff) + mySliceLow] |= flags;
|
||||
myRomAccessBase[(address & 0x7ff) + mySliceLow] |= flags;
|
||||
else
|
||||
myCodeAccessBase[131072 + (address & 0x7ff) + mySliceLow] |= flags;
|
||||
myRomAccessBase[131072 + (address & 0x7ff) + mySliceLow] |= flags;
|
||||
}
|
||||
else if(((address & 0x1fff) >= 0x1800) && // 1.5K region from 0x1800 - 0x1dff
|
||||
((address & 0x1fff) <= 0x1dff))
|
||||
{
|
||||
if(myIsRomMiddle)
|
||||
myCodeAccessBase[(address & 0x7ff) + mySliceMiddle + 0x10000] |= flags;
|
||||
myRomAccessBase[(address & 0x7ff) + mySliceMiddle + 0x10000] |= flags;
|
||||
else
|
||||
myCodeAccessBase[131072 + (address & 0x7ff) + mySliceMiddle] |= flags;
|
||||
myRomAccessBase[131072 + (address & 0x7ff) + mySliceMiddle] |= flags;
|
||||
}
|
||||
else if((address & 0x1f00) == 0x1e00) // 256B region from 0x1e00 - 0x1eff
|
||||
{
|
||||
if(myIsRomHigh)
|
||||
myCodeAccessBase[(address & 0xff) + mySliceHigh + 0x10000] |= flags;
|
||||
myRomAccessBase[(address & 0xff) + mySliceHigh + 0x10000] |= flags;
|
||||
else
|
||||
myCodeAccessBase[131072 + (address & 0xff) + mySliceHigh] |= flags;
|
||||
myRomAccessBase[131072 + (address & 0xff) + mySliceHigh] |= flags;
|
||||
}
|
||||
else if((address & 0x1f00) == 0x1f00) // 256B region from 0x1f00 - 0x1fff
|
||||
{
|
||||
myCodeAccessBase[(address & 0xff) + 0x1ff00] |= flags;
|
||||
myRomAccessBase[(address & 0xff) + 0x1ff00] |= flags;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void Cartridge4A50::checkBankSwitch(uInt16 address, uInt8 value)
|
||||
|
|
|
@ -153,20 +153,21 @@ class Cartridge4A50 : public Cartridge
|
|||
bool poke(uInt16 address, uInt8 value) override;
|
||||
|
||||
private:
|
||||
#ifdef DEBUGGER_SUPPORT
|
||||
/**
|
||||
Query the given address type for the associated disassembly flags.
|
||||
Query the given address type for the associated access flags.
|
||||
|
||||
@param address The address to query
|
||||
*/
|
||||
uInt8 getAccessFlags(uInt16 address) const override;
|
||||
Device::AccessFlags getAccessFlags(uInt16 address) const override;
|
||||
/**
|
||||
Change the given address to use the given disassembly flags.
|
||||
Change the given address to use the given access flags.
|
||||
|
||||
@param address The address to modify
|
||||
@param flags A bitfield of DisasmType directives for the given address
|
||||
@param flags A bitfield of AccessType directives for the given address
|
||||
*/
|
||||
void setAccessFlags(uInt16 address, uInt8 flags) override;
|
||||
|
||||
void setAccessFlags(uInt16 address, Device::AccessFlags flags) override;
|
||||
#endif
|
||||
/**
|
||||
Check all possible hotspots
|
||||
*/
|
||||
|
|
|
@ -25,7 +25,7 @@ Cartridge4K::Cartridge4K(const ByteBuffer& image, size_t size,
|
|||
{
|
||||
// Copy the ROM image into my buffer
|
||||
std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin());
|
||||
createCodeAccessBase(myImage.size());
|
||||
createRomAccessArrays(myImage.size());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -46,7 +46,9 @@ void Cartridge4K::install(System& system)
|
|||
for(uInt16 addr = 0x1000; addr < 0x2000; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myImage[addr & 0x0FFF];
|
||||
access.codeAccessBase = &myCodeAccessBase[addr & 0x0FFF];
|
||||
access.romAccessBase = &myRomAccessBase[addr & 0x0FFF];
|
||||
access.romPeekCounter = &myRomAccessCounter[addr & 0x0FFF];
|
||||
access.romPokeCounter = &myRomAccessCounter[(addr & 0x0FFF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ Cartridge4KSC::Cartridge4KSC(const ByteBuffer& image, size_t size,
|
|||
{
|
||||
// Copy the ROM image into my buffer
|
||||
std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin());
|
||||
createCodeAccessBase(myImage.size());
|
||||
createRomAccessArrays(myImage.size());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -49,7 +49,7 @@ void Cartridge4KSC::install(System& system)
|
|||
access.type = System::PageAccessType::WRITE;
|
||||
for(uInt16 addr = 0x1000; addr < 0x1080; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.codeAccessBase = &myCodeAccessBase[addr & 0x007F];
|
||||
access.romAccessBase = &myRomAccessBase[addr & 0x007F];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
|
@ -58,7 +58,7 @@ void Cartridge4KSC::install(System& system)
|
|||
for(uInt16 addr = 0x1080; addr < 0x1100; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myRAM[addr & 0x007F];
|
||||
access.codeAccessBase = &myCodeAccessBase[0x80 + (addr & 0x007F)];
|
||||
access.romAccessBase = &myRomAccessBase[0x80 + (addr & 0x007F)];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
|
@ -66,7 +66,7 @@ void Cartridge4KSC::install(System& system)
|
|||
for(uInt16 addr = 0x1100; addr < 0x2000; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myImage[addr & 0x0FFF];
|
||||
access.codeAccessBase = &myCodeAccessBase[addr & 0x0FFF];
|
||||
access.romAccessBase = &myRomAccessBase[addr & 0x0FFF];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,13 +35,13 @@ CartridgeAR::CartridgeAR(const ByteBuffer& image, size_t size,
|
|||
std::copy_n(ourDefaultHeader.data(), ourDefaultHeader.size(),
|
||||
myLoadImages.get()+myImage.size());
|
||||
|
||||
// We use System::PageAccess.codeAccessBase, but don't allow its use
|
||||
// We use System::PageAccess.romAccessBase, but don't allow its use
|
||||
// through a pointer, since the AR scheme doesn't support bankswitching
|
||||
// in the normal sense
|
||||
//
|
||||
// Instead, access will be through the getAccessFlags and setAccessFlags
|
||||
// methods below
|
||||
createCodeAccessBase(mySize);
|
||||
createRomAccessArrays(mySize);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -190,19 +190,21 @@ bool CartridgeAR::poke(uInt16 addr, uInt8)
|
|||
return modified;
|
||||
}
|
||||
|
||||
#ifdef DEBUGGER_SUPPORT
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt8 CartridgeAR::getAccessFlags(uInt16 address) const
|
||||
Device::AccessFlags CartridgeAR::getAccessFlags(uInt16 address) const
|
||||
{
|
||||
return myCodeAccessBase[(address & 0x07FF) +
|
||||
return myRomAccessBase[(address & 0x07FF) +
|
||||
myImageOffset[(address & 0x0800) ? 1 : 0]];
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeAR::setAccessFlags(uInt16 address, uInt8 flags)
|
||||
void CartridgeAR::setAccessFlags(uInt16 address, Device::AccessFlags flags)
|
||||
{
|
||||
myCodeAccessBase[(address & 0x07FF) +
|
||||
myRomAccessBase[(address & 0x07FF) +
|
||||
myImageOffset[(address & 0x0800) ? 1 : 0]] |= flags;
|
||||
}
|
||||
#endif
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeAR::bankConfiguration(uInt8 configuration)
|
||||
|
|
|
@ -159,19 +159,21 @@ class CartridgeAR : public Cartridge
|
|||
bool poke(uInt16 address, uInt8 value) override;
|
||||
|
||||
private:
|
||||
#ifdef DEBUGGER_SUPPORT
|
||||
/**
|
||||
Query the given address type for the associated disassembly flags.
|
||||
Query the given address type for the associated access flags.
|
||||
|
||||
@param address The address to query
|
||||
*/
|
||||
uInt8 getAccessFlags(uInt16 address) const override;
|
||||
Device::AccessFlags getAccessFlags(uInt16 address) const override;
|
||||
/**
|
||||
Change the given address to use the given disassembly flags.
|
||||
Change the given address to use the given access flags.
|
||||
|
||||
@param address The address to modify
|
||||
@param flags A bitfield of DisasmType directives for the given address
|
||||
@param flags A bitfield of AccessType directives for the given address
|
||||
*/
|
||||
void setAccessFlags(uInt16 address, uInt8 flags) override;
|
||||
void setAccessFlags(uInt16 address, Device::AccessFlags flags) override;
|
||||
#endif
|
||||
|
||||
// Handle a change to the bank configuration
|
||||
bool bankConfiguration(uInt8 configuration);
|
||||
|
|
|
@ -25,7 +25,7 @@ CartridgeBF::CartridgeBF(const ByteBuffer& image, size_t size,
|
|||
{
|
||||
// Copy the ROM image into my buffer
|
||||
std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin());
|
||||
createCodeAccessBase(myImage.size());
|
||||
createRomAccessArrays(myImage.size());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -88,7 +88,7 @@ bool CartridgeBF::bank(uInt16 bank)
|
|||
for(uInt16 addr = (0x1F80 & ~System::PAGE_MASK); addr < 0x2000;
|
||||
addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
|
@ -97,7 +97,7 @@ bool CartridgeBF::bank(uInt16 bank)
|
|||
addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
return myBankChanged = true;
|
||||
|
|
|
@ -25,7 +25,7 @@ CartridgeBFSC::CartridgeBFSC(const ByteBuffer& image, size_t size,
|
|||
{
|
||||
// Copy the ROM image into my buffer
|
||||
std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin());
|
||||
createCodeAccessBase(myImage.size());
|
||||
createRomAccessArrays(myImage.size());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -51,7 +51,7 @@ void CartridgeBFSC::install(System& system)
|
|||
access.type = System::PageAccessType::WRITE;
|
||||
for(uInt16 addr = 0x1000; addr < 0x1080; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.codeAccessBase = &myCodeAccessBase[addr & 0x007F];
|
||||
access.romAccessBase = &myRomAccessBase[addr & 0x007F];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
|
@ -60,7 +60,7 @@ void CartridgeBFSC::install(System& system)
|
|||
for(uInt16 addr = 0x1080; addr < 0x1100; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myRAM[addr & 0x007F];
|
||||
access.codeAccessBase = &myCodeAccessBase[0x80 + (addr & 0x007F)];
|
||||
access.romAccessBase = &myRomAccessBase[0x80 + (addr & 0x007F)];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
|
@ -127,7 +127,7 @@ bool CartridgeBFSC::bank(uInt16 bank)
|
|||
for(uInt16 addr = (0x1F80 & ~System::PAGE_MASK); addr < 0x2000;
|
||||
addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
|
@ -136,7 +136,7 @@ bool CartridgeBFSC::bank(uInt16 bank)
|
|||
addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
return myBankChanged = true;
|
||||
|
|
|
@ -49,7 +49,7 @@ CartridgeBUS::CartridgeBUS(const ByteBuffer& image, size_t size,
|
|||
std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin());
|
||||
|
||||
// Even though the ROM is 32K, only 28K is accessible to the 6507
|
||||
createCodeAccessBase(28_KB);
|
||||
createRomAccessArrays(28_KB);
|
||||
|
||||
// Pointer to the program ROM (28K @ 0 byte offset)
|
||||
// which starts after the 2K BUS Driver and 2K C Code
|
||||
|
@ -442,7 +442,9 @@ bool CartridgeBUS::bank(uInt16 bank)
|
|||
// Map Program ROM image into the system
|
||||
for(uInt16 addr = 0x1040; addr < 0x2000; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + 28_KB];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
return myBankChanged = true;
|
||||
|
|
|
@ -65,7 +65,7 @@ CartridgeCDF::CartridgeCDF(const ByteBuffer& image, size_t size,
|
|||
std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin());
|
||||
|
||||
// even though the ROM is 32K, only 28K is accessible to the 6507
|
||||
createCodeAccessBase(28_KB);
|
||||
createRomAccessArrays(28_KB);
|
||||
|
||||
// Pointer to the program ROM (28K @ 0 byte offset)
|
||||
// which starts after the 2K CDF Driver and 2K C Code
|
||||
|
@ -415,7 +415,9 @@ bool CartridgeCDF::bank(uInt16 bank)
|
|||
// Map Program ROM image into the system
|
||||
for(uInt16 addr = 0x1040; addr < 0x2000; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + 28_KB];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
return myBankChanged = true;
|
||||
|
|
|
@ -27,7 +27,7 @@ CartridgeCM::CartridgeCM(const ByteBuffer& image, size_t size,
|
|||
{
|
||||
// Copy the ROM image into my buffer
|
||||
std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin());
|
||||
createCodeAccessBase(myImage.size());
|
||||
createRomAccessArrays(myImage.size());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -119,7 +119,9 @@ bool CartridgeCM::bank(uInt16 bank)
|
|||
for(uInt16 addr = 0x1000; addr < 0x1800; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
|
@ -131,12 +133,16 @@ bool CartridgeCM::bank(uInt16 bank)
|
|||
if(mySWCHA & 0x10)
|
||||
{
|
||||
access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + myAccessSize];
|
||||
}
|
||||
else
|
||||
{
|
||||
access.directPeekBase = &myRAM[addr & 0x7FF];
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x07FF)];
|
||||
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x07FF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x07FF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x07FF) + myAccessSize];
|
||||
}
|
||||
|
||||
if((mySWCHA & 0x30) == 0x20)
|
||||
|
|
|
@ -28,7 +28,7 @@ CartridgeCTY::CartridgeCTY(const ByteBuffer& image, size_t size,
|
|||
{
|
||||
// Copy the ROM image into my buffer
|
||||
std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin());
|
||||
createCodeAccessBase(myImage.size());
|
||||
createRomAccessArrays(myImage.size());
|
||||
|
||||
// Default to no tune data in case user is utilizing an old ROM
|
||||
myTuneData.fill(0);
|
||||
|
@ -240,7 +240,9 @@ bool CartridgeCTY::bank(uInt16 bank)
|
|||
System::PageAccess access(this, System::PageAccessType::READ);
|
||||
for(uInt16 addr = 0x1080; addr < 0x2000; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
return myBankChanged = true;
|
||||
|
|
|
@ -40,7 +40,7 @@ CartridgeCV::CartridgeCV(const ByteBuffer& image, size_t size,
|
|||
// Copy the RAM image into a buffer for use in reset()
|
||||
std::copy_n(image.get(), myInitialRAM.size(), myInitialRAM.begin());
|
||||
}
|
||||
createCodeAccessBase(myImage.size() + myRAM.size());
|
||||
createRomAccessArrays(myImage.size() + myRAM.size());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -68,7 +68,9 @@ void CartridgeCV::install(System& system)
|
|||
for(uInt16 addr = 0x1800; addr < 0x2000; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myImage[addr & 0x07FF];
|
||||
access.codeAccessBase = &myCodeAccessBase[addr & 0x07FF];
|
||||
access.romAccessBase = &myRomAccessBase[addr & 0x07FF];
|
||||
access.romPeekCounter = &myRomAccessCounter[addr & 0x07FF];
|
||||
access.romPokeCounter = &myRomAccessCounter[(addr & 0x07FF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
|
@ -76,7 +78,7 @@ void CartridgeCV::install(System& system)
|
|||
// Map access to this class, since we need to inspect all accesses to
|
||||
// check if RWP happens
|
||||
access.directPeekBase = nullptr;
|
||||
access.codeAccessBase = nullptr;
|
||||
access.romAccessBase = nullptr;
|
||||
access.type = System::PageAccessType::WRITE;
|
||||
for(uInt16 addr = 0x1400; addr < 0x1800; addr += System::PAGE_SIZE)
|
||||
mySystem->setPageAccess(addr, access);
|
||||
|
@ -87,7 +89,9 @@ void CartridgeCV::install(System& system)
|
|||
for(uInt16 addr = 0x1000; addr < 0x1400; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myRAM[addr & 0x03FF];
|
||||
access.codeAccessBase = &myCodeAccessBase[2048 + (addr & 0x03FF)];
|
||||
access.romAccessBase = &myRomAccessBase[2048 + (addr & 0x03FF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[2048 + (addr & 0x03FF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[2048 + (addr & 0x03FF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
}
|
||||
|
@ -104,8 +108,21 @@ uInt8 CartridgeCV::peek(uInt16 address)
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeCV::poke(uInt16 address, uInt8 value)
|
||||
{
|
||||
pokeRAM(myRAM[address & 0x03FF], address, value);
|
||||
return true;
|
||||
|
||||
if(address & 0x0400)
|
||||
{
|
||||
pokeRAM(myRAM[address & 0x03FF], address, value);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Writing to the read port should be ignored, but trigger a break if option enabled
|
||||
uInt8 dummy;
|
||||
|
||||
pokeRAM(dummy, address, value);
|
||||
myRamWriteAccess = address;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
|
@ -30,7 +30,7 @@ CartridgeCVPlus::CartridgeCVPlus(const ByteBuffer& image, size_t size,
|
|||
|
||||
// Copy the ROM image into my buffer
|
||||
std::copy_n(image.get(), mySize, myImage.get());
|
||||
createCodeAccessBase(mySize + myRAM.size());
|
||||
createRomAccessArrays(mySize + myRAM.size());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -58,11 +58,13 @@ void CartridgeCVPlus::install(System& system)
|
|||
// Map access to this class, since we need to inspect all accesses to
|
||||
// check if RWP happens
|
||||
access.directPeekBase = access.directPokeBase = nullptr;
|
||||
access.codeAccessBase = nullptr;
|
||||
access.romAccessBase = nullptr;
|
||||
access.type = System::PageAccessType::WRITE;
|
||||
for(uInt16 addr = 0x1400; addr < 0x1800; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.codeAccessBase = &myCodeAccessBase[mySize + (addr & 0x03FF)];
|
||||
access.romAccessBase = &myRomAccessBase[mySize + (addr & 0x03FF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[mySize + (addr & 0x03FF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[mySize + (addr & 0x03FF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
|
@ -71,7 +73,9 @@ void CartridgeCVPlus::install(System& system)
|
|||
for(uInt16 addr = 0x1000; addr < 0x1400; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myRAM[addr & 0x03FF];
|
||||
access.codeAccessBase = &myCodeAccessBase[mySize + (addr & 0x03FF)];
|
||||
access.romAccessBase = &myRomAccessBase[mySize + (addr & 0x03FF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[mySize + (addr & 0x03FF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[mySize + (addr & 0x03FF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
|
@ -104,9 +108,22 @@ bool CartridgeCVPlus::poke(uInt16 address, uInt8 value)
|
|||
return mySystem->tia().poke(address, value);
|
||||
}
|
||||
else
|
||||
pokeRAM(myRAM[address & 0x03FF], pokeAddress, value);
|
||||
{
|
||||
if(address & 0x0400)
|
||||
{
|
||||
pokeRAM(myRAM[address & 0x03FF], pokeAddress, value);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Writing to the read port should be ignored, but trigger a break if option enabled
|
||||
uInt8 dummy;
|
||||
|
||||
return true;
|
||||
pokeRAM(dummy, pokeAddress, value);
|
||||
myRamWriteAccess = pokeAddress;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -135,7 +152,7 @@ bool CartridgeCVPlus::bank(uInt16 bank)
|
|||
for(uInt16 addr = 0x1800; addr < 0x2000; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myImage[offset + (addr & 0x07FF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[offset + (addr & 0x07FF)];
|
||||
access.romAccessBase = &myRomAccessBase[offset + (addr & 0x07FF)];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ CartridgeDASH::CartridgeDASH(const ByteBuffer& image, size_t size,
|
|||
|
||||
// Copy the ROM image into my buffer
|
||||
std::copy_n(image.get(), mySize, myImage.get());
|
||||
createCodeAccessBase(mySize + myRAM.size());
|
||||
createRomAccessArrays(mySize + myRAM.size());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -135,10 +135,22 @@ bool CartridgeDASH::poke(uInt16 address, uInt8 value)
|
|||
|
||||
if(whichBankIsThere & BITMASK_ROMRAM)
|
||||
{
|
||||
uInt32 byteOffset = address & BITMASK_RAM_BANK;
|
||||
uInt32 baseAddress = ((whichBankIsThere & BIT_BANK_MASK) << RAM_BANK_TO_POWER) + byteOffset;
|
||||
pokeRAM(myRAM[baseAddress], address, value);
|
||||
changed = true;
|
||||
if(address & RAM_BANK_SIZE)
|
||||
{
|
||||
uInt32 byteOffset = address & BITMASK_RAM_BANK;
|
||||
uInt32 baseAddress = ((whichBankIsThere & BIT_BANK_MASK) << RAM_BANK_TO_POWER) + byteOffset;
|
||||
pokeRAM(myRAM[baseAddress], address, value);
|
||||
changed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Writing to the read port should be ignored, but trigger a break if option enabled
|
||||
uInt8 dummy;
|
||||
|
||||
pokeRAM(dummy, address, value);
|
||||
myRamWriteAccess = address;
|
||||
changed = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -192,7 +204,7 @@ void CartridgeDASH::bankRAMSlot(uInt16 bank)
|
|||
if(!upper)
|
||||
access.directPeekBase = &myRAM[startCurrentBank + (addr & (RAM_BANK_SIZE - 1))];
|
||||
|
||||
access.codeAccessBase = &myCodeAccessBase[mySize + startCurrentBank + (addr & (RAM_BANK_SIZE - 1))];
|
||||
access.romAccessBase = &myRomAccessBase[mySize + startCurrentBank + (addr & (RAM_BANK_SIZE - 1))];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
}
|
||||
|
@ -235,7 +247,7 @@ void CartridgeDASH::bankROMSlot(uInt16 bank)
|
|||
for (uInt16 addr = start; addr <= end; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myImage[startCurrentBank + (addr & (ROM_BANK_SIZE - 1))];
|
||||
access.codeAccessBase = &myCodeAccessBase[startCurrentBank + (addr & (ROM_BANK_SIZE - 1))];
|
||||
access.romAccessBase = &myRomAccessBase[startCurrentBank + (addr & (ROM_BANK_SIZE - 1))];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ CartridgeDF::CartridgeDF(const ByteBuffer& image, size_t size,
|
|||
{
|
||||
// Copy the ROM image into my buffer
|
||||
std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin());
|
||||
createCodeAccessBase(myImage.size());
|
||||
createRomAccessArrays(myImage.size());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -84,7 +84,9 @@ bool CartridgeDF::bank(uInt16 bank)
|
|||
for(uInt16 addr = (0x1FC0 & ~System::PAGE_MASK); addr < 0x2000;
|
||||
addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
|
@ -93,7 +95,9 @@ bool CartridgeDF::bank(uInt16 bank)
|
|||
addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
return myBankChanged = true;
|
||||
|
|
|
@ -25,7 +25,7 @@ CartridgeDFSC::CartridgeDFSC(const ByteBuffer& image, size_t size,
|
|||
{
|
||||
// Copy the ROM image into my buffer
|
||||
std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin());
|
||||
createCodeAccessBase(myImage.size());
|
||||
createRomAccessArrays(myImage.size());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -51,7 +51,9 @@ void CartridgeDFSC::install(System& system)
|
|||
access.type = System::PageAccessType::WRITE;
|
||||
for(uInt16 addr = 0x1000; addr < 0x1080; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.codeAccessBase = &myCodeAccessBase[addr & 0x007F];
|
||||
access.romAccessBase = &myRomAccessBase[addr & 0x007F];
|
||||
access.romPeekCounter = &myRomAccessCounter[addr & 0x007F];
|
||||
access.romPokeCounter = &myRomAccessCounter[(addr & 0x007F) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
|
@ -60,7 +62,9 @@ void CartridgeDFSC::install(System& system)
|
|||
for(uInt16 addr = 0x1080; addr < 0x1100; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myRAM[addr & 0x007F];
|
||||
access.codeAccessBase = &myCodeAccessBase[0x80 + (addr & 0x007F)];
|
||||
access.romAccessBase = &myRomAccessBase[0x80 + (addr & 0x007F)];
|
||||
access.romPeekCounter = &myRomAccessCounter[0x80 + (addr & 0x007F)];
|
||||
access.romPokeCounter = &myRomAccessCounter[0x80 + (addr & 0x007F) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
|
@ -127,7 +131,9 @@ bool CartridgeDFSC::bank(uInt16 bank)
|
|||
for(uInt16 addr = (0x1FC0 & ~System::PAGE_MASK); addr < 0x2000;
|
||||
addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
|
@ -136,7 +142,9 @@ bool CartridgeDFSC::bank(uInt16 bank)
|
|||
addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
return myBankChanged = true;
|
||||
|
|
|
@ -27,7 +27,7 @@ CartridgeDPC::CartridgeDPC(const ByteBuffer& image, size_t size,
|
|||
{
|
||||
// Make a copy of the entire image
|
||||
std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin());
|
||||
createCodeAccessBase(8_KB);
|
||||
createRomAccessArrays(8_KB);
|
||||
|
||||
// Pointer to the program ROM (8K @ 0 byte offset)
|
||||
myProgramImage = myImage.data();
|
||||
|
@ -373,7 +373,9 @@ bool CartridgeDPC::bank(uInt16 bank)
|
|||
for(uInt16 addr = (0x1FF8 & ~System::PAGE_MASK); addr < 0x2000;
|
||||
addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
|
@ -382,7 +384,9 @@ bool CartridgeDPC::bank(uInt16 bank)
|
|||
addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myProgramImage[myBankOffset + (addr & 0x0FFF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
return myBankChanged = true;
|
||||
|
|
|
@ -36,7 +36,7 @@ CartridgeDPCPlus::CartridgeDPCPlus(const ByteBuffer& image, size_t size,
|
|||
if(mySize < myImage.size())
|
||||
myImage.fill(0);
|
||||
std::copy_n(image.get(), size, myImage.begin() + (myImage.size() - mySize));
|
||||
createCodeAccessBase(24_KB);
|
||||
createRomAccessArrays(24_KB);
|
||||
|
||||
// Pointer to the program ROM (24K @ 3K offset; ignore first 3K)
|
||||
myProgramImage = myImage.data() + 3_KB;
|
||||
|
@ -57,9 +57,20 @@ CartridgeDPCPlus::CartridgeDPCPlus(const ByteBuffer& image, size_t size,
|
|||
Thumbulator::ConfigureFor::DPCplus,
|
||||
this);
|
||||
|
||||
// Currently only one known DPC+ ARM driver exhibits a problem
|
||||
// with the default mask to use for DFxFRACLOW
|
||||
if(MD5::hash(image, 3_KB) == "8dd73b44fd11c488326ce507cbeb19d1")
|
||||
// Currently 4 DPC+ driver versions have been identified:
|
||||
// 17884ec14f9b1d06fe8d617a1fbdcf47 Jitter Encore Compatible
|
||||
// 5f80b5a5adbe483addc3f6e6f1b472f8 Stable Encore Compatible
|
||||
// 8dd73b44fd11c488326ce507cbeb19d1 Stable NOT Encore Compatible
|
||||
// b328dbdf787400c0f0e2b88b425872a5 Jitter Encore Compatible
|
||||
//
|
||||
// Jitter/Stable refers to the appearance of the playfield in bB games if
|
||||
// the DFxFRACINC registers are not updated before every drawscreen.
|
||||
//
|
||||
// The default mask for DFxFRACLOW implements the Jitter behavior. This
|
||||
// changes the mask to implement the Stable behavior.
|
||||
myDriverMD5 = MD5::hash(image, 3_KB);
|
||||
if(myDriverMD5 == "5f80b5a5adbe483addc3f6e6f1b472f8" ||
|
||||
myDriverMD5 == "8dd73b44fd11c488326ce507cbeb19d1" )
|
||||
myFractionalLowMask = 0x0F0000;
|
||||
|
||||
setInitialState();
|
||||
|
@ -593,7 +604,9 @@ bool CartridgeDPCPlus::bank(uInt16 bank)
|
|||
// Map Program ROM image into the system
|
||||
for(uInt16 addr = 0x1080; addr < 0x2000; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + 24_KB];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
return myBankChanged = true;
|
||||
|
|
|
@ -272,6 +272,10 @@ class CartridgeDPCPlus : public Cartridge
|
|||
// Indicates the offset into the ROM image (aligns to current bank)
|
||||
uInt16 myBankOffset{0};
|
||||
|
||||
// MD5 value of the 3K DPC+ driver. Used to determine which mask to use,
|
||||
// and shown in the Cartridge tab of the debugger
|
||||
string myDriverMD5;
|
||||
|
||||
// Older DPC+ driver code had different behaviour wrt the mask used
|
||||
// to retrieve 'DFxFRACLOW' (fractional data pointer low byte)
|
||||
// ROMs built with an old DPC+ driver and using the newer mask can
|
||||
|
|
|
@ -25,7 +25,7 @@ CartridgeE0::CartridgeE0(const ByteBuffer& image, size_t size,
|
|||
{
|
||||
// Copy the ROM image into my buffer
|
||||
std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin());
|
||||
createCodeAccessBase(myImage.size());
|
||||
createRomAccessArrays(myImage.size());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -61,13 +61,17 @@ void CartridgeE0::install(System& system)
|
|||
addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myImage[0x1C00 + (addr & 0x03FF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[0x1C00 + (addr & 0x03FF)];
|
||||
access.romAccessBase = &myRomAccessBase[0x1C00 + (addr & 0x03FF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[0x1C00 + (addr & 0x03FF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[0x1C00 + (addr & 0x03FF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
// Set the page accessing methods for the hot spots in the last segment
|
||||
access.directPeekBase = nullptr;
|
||||
access.codeAccessBase = &myCodeAccessBase[0x1FC0]; // TJ: is this the correct address (or 0x1FE0)?
|
||||
access.romAccessBase = &myRomAccessBase[0x1FC0]; // TJ: is this the correct address (or 0x1FE0)?
|
||||
access.romPeekCounter = &myRomAccessCounter[0x1FC0];
|
||||
access.romPokeCounter = &myRomAccessCounter[0x1FC0 + myAccessSize];
|
||||
access.type = System::PageAccessType::READ;
|
||||
for(uInt16 addr = (0x1FE0 & ~System::PAGE_MASK); addr < 0x2000;
|
||||
addr += System::PAGE_SIZE)
|
||||
|
@ -144,7 +148,9 @@ void CartridgeE0::segmentZero(uInt16 slice)
|
|||
for(uInt16 addr = 0x1000; addr < 0x1400; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myImage[offset + (addr & 0x03FF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[offset + (addr & 0x03FF)];
|
||||
access.romAccessBase = &myRomAccessBase[offset + (addr & 0x03FF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[offset + (addr & 0x03FF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[offset + (addr & 0x03FF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
myBankChanged = true;
|
||||
|
@ -165,7 +171,9 @@ void CartridgeE0::segmentOne(uInt16 slice)
|
|||
for(uInt16 addr = 0x1400; addr < 0x1800; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myImage[offset + (addr & 0x03FF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[offset + (addr & 0x03FF)];
|
||||
access.romAccessBase = &myRomAccessBase[offset + (addr & 0x03FF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[offset + (addr & 0x03FF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[offset + (addr & 0x03FF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
myBankChanged = true;
|
||||
|
@ -186,7 +194,9 @@ void CartridgeE0::segmentTwo(uInt16 slice)
|
|||
for(uInt16 addr = 0x1800; addr < 0x1C00; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myImage[offset + (addr & 0x03FF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[offset + (addr & 0x03FF)];
|
||||
access.romAccessBase = &myRomAccessBase[offset + (addr & 0x03FF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[offset + (addr & 0x03FF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[offset + (addr & 0x03FF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
myBankChanged = true;
|
||||
|
|
|
@ -25,7 +25,7 @@ CartridgeEF::CartridgeEF(const ByteBuffer& image, size_t size,
|
|||
{
|
||||
// Copy the ROM image into my buffer
|
||||
std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin());
|
||||
createCodeAccessBase(myImage.size());
|
||||
createRomAccessArrays(myImage.size());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -84,7 +84,9 @@ bool CartridgeEF::bank(uInt16 bank)
|
|||
for(uInt16 addr = (0x1FE0 & ~System::PAGE_MASK); addr < 0x2000;
|
||||
addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
|
@ -93,7 +95,9 @@ bool CartridgeEF::bank(uInt16 bank)
|
|||
addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
return myBankChanged = true;
|
||||
|
|
|
@ -25,7 +25,7 @@ CartridgeEFSC::CartridgeEFSC(const ByteBuffer& image, size_t size,
|
|||
{
|
||||
// Copy the ROM image into my buffer
|
||||
std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin());
|
||||
createCodeAccessBase(myImage.size());
|
||||
createRomAccessArrays(myImage.size());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -51,7 +51,9 @@ void CartridgeEFSC::install(System& system)
|
|||
access.type = System::PageAccessType::WRITE;
|
||||
for(uInt16 addr = 0x1000; addr < 0x1080; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.codeAccessBase = &myCodeAccessBase[addr & 0x007F];
|
||||
access.romAccessBase = &myRomAccessBase[addr & 0x007F];
|
||||
access.romPeekCounter = &myRomAccessCounter[addr & 0x007F];
|
||||
access.romPokeCounter = &myRomAccessCounter[(addr & 0x007F) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
|
@ -60,7 +62,9 @@ void CartridgeEFSC::install(System& system)
|
|||
for(uInt16 addr = 0x1080; addr < 0x1100; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myRAM[addr & 0x007F];
|
||||
access.codeAccessBase = &myCodeAccessBase[0x80 + (addr & 0x007F)];
|
||||
access.romAccessBase = &myRomAccessBase[0x80 + (addr & 0x007F)];
|
||||
access.romPeekCounter = &myRomAccessCounter[0x80 + (addr & 0x007F)];
|
||||
access.romPokeCounter = &myRomAccessCounter[0x80 + (addr & 0x007F) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
|
@ -127,7 +131,9 @@ bool CartridgeEFSC::bank(uInt16 bank)
|
|||
for(uInt16 addr = (0x1FE0 & ~System::PAGE_MASK); addr < 0x2000;
|
||||
addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
|
@ -136,7 +142,9 @@ bool CartridgeEFSC::bank(uInt16 bank)
|
|||
addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
return myBankChanged = true;
|
||||
|
|
|
@ -25,7 +25,7 @@ CartridgeF0::CartridgeF0(const ByteBuffer& image, size_t size,
|
|||
{
|
||||
// Copy the ROM image into my buffer
|
||||
std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin());
|
||||
createCodeAccessBase(myImage.size());
|
||||
createRomAccessArrays(myImage.size());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -91,7 +91,9 @@ bool CartridgeF0::bank(uInt16 bank)
|
|||
for(uInt16 addr = (0x1FF0 & ~System::PAGE_MASK); addr < 0x2000;
|
||||
addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
|
@ -100,7 +102,9 @@ bool CartridgeF0::bank(uInt16 bank)
|
|||
addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ CartridgeF4::CartridgeF4(const ByteBuffer& image, size_t size,
|
|||
{
|
||||
// Copy the ROM image into my buffer
|
||||
std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin());
|
||||
createCodeAccessBase(myImage.size());
|
||||
createRomAccessArrays(myImage.size());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -88,7 +88,9 @@ bool CartridgeF4::bank(uInt16 bank)
|
|||
for(uInt16 addr = (0x1FF4 & ~System::PAGE_MASK); addr < 0x2000;
|
||||
addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
|
@ -97,7 +99,9 @@ bool CartridgeF4::bank(uInt16 bank)
|
|||
addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
return myBankChanged = true;
|
||||
|
|
|
@ -25,7 +25,7 @@ CartridgeF4SC::CartridgeF4SC(const ByteBuffer& image, size_t size,
|
|||
{
|
||||
// Copy the ROM image into my buffer
|
||||
std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin());
|
||||
createCodeAccessBase(myImage.size());
|
||||
createRomAccessArrays(myImage.size());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -51,7 +51,9 @@ void CartridgeF4SC::install(System& system)
|
|||
access.type = System::PageAccessType::WRITE;
|
||||
for(uInt16 addr = 0x1000; addr < 0x1080; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.codeAccessBase = &myCodeAccessBase[addr & 0x007F];
|
||||
access.romAccessBase = &myRomAccessBase[addr & 0x007F];
|
||||
access.romPeekCounter = &myRomAccessCounter[addr & 0x007F];
|
||||
access.romPokeCounter = &myRomAccessCounter[(addr & 0x07F) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
|
@ -60,7 +62,9 @@ void CartridgeF4SC::install(System& system)
|
|||
for(uInt16 addr = 0x1080; addr < 0x1100; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myRAM[addr & 0x007F];
|
||||
access.codeAccessBase = &myCodeAccessBase[0x80 + (addr & 0x007F)];
|
||||
access.romAccessBase = &myRomAccessBase[0x80 + (addr & 0x007F)];
|
||||
access.romPeekCounter = &myRomAccessCounter[0x80 + (addr & 0x007F)];
|
||||
access.romPokeCounter = &myRomAccessCounter[0x80 + (addr & 0x007F) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
|
@ -127,7 +131,9 @@ bool CartridgeF4SC::bank(uInt16 bank)
|
|||
for(uInt16 addr = (0x1FF4 & ~System::PAGE_MASK); addr < 0x2000;
|
||||
addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
|
@ -136,7 +142,9 @@ bool CartridgeF4SC::bank(uInt16 bank)
|
|||
addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
return myBankChanged = true;
|
||||
|
|
|
@ -25,7 +25,7 @@ CartridgeF6::CartridgeF6(const ByteBuffer& image, size_t size,
|
|||
{
|
||||
// Copy the ROM image into my buffer
|
||||
std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin());
|
||||
createCodeAccessBase(myImage.size());
|
||||
createRomAccessArrays(myImage.size());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -128,7 +128,9 @@ bool CartridgeF6::bank(uInt16 bank)
|
|||
for(uInt16 addr = (0x1FF6 & ~System::PAGE_MASK); addr < 0x2000;
|
||||
addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
|
@ -137,7 +139,9 @@ bool CartridgeF6::bank(uInt16 bank)
|
|||
addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
return myBankChanged = true;
|
||||
|
|
|
@ -25,7 +25,7 @@ CartridgeF6SC::CartridgeF6SC(const ByteBuffer& image, size_t size,
|
|||
{
|
||||
// Copy the ROM image into my buffer
|
||||
std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin());
|
||||
createCodeAccessBase(myImage.size());
|
||||
createRomAccessArrays(myImage.size());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -51,7 +51,9 @@ void CartridgeF6SC::install(System& system)
|
|||
access.type = System::PageAccessType::WRITE;
|
||||
for(uInt16 addr = 0x1000; addr < 0x1080; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.codeAccessBase = &myCodeAccessBase[addr & 0x007F];
|
||||
access.romAccessBase = &myRomAccessBase[addr & 0x007F];
|
||||
access.romPeekCounter = &myRomAccessCounter[addr & 0x007F];
|
||||
access.romPokeCounter = &myRomAccessCounter[(addr & 0x07F) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
|
@ -60,7 +62,9 @@ void CartridgeF6SC::install(System& system)
|
|||
for(uInt16 addr = 0x1080; addr < 0x1100; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myRAM[addr & 0x007F];
|
||||
access.codeAccessBase = &myCodeAccessBase[0x80 + (addr & 0x007F)];
|
||||
access.romAccessBase = &myRomAccessBase[0x80 + (addr & 0x007F)];
|
||||
access.romPeekCounter = &myRomAccessCounter[0x80 + (addr & 0x007F)];
|
||||
access.romPokeCounter = &myRomAccessCounter[0x80 + (addr & 0x007F) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
|
@ -167,7 +171,9 @@ bool CartridgeF6SC::bank(uInt16 bank)
|
|||
for(uInt16 addr = (0x1FF6 & ~System::PAGE_MASK); addr < 0x2000;
|
||||
addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
|
@ -176,7 +182,9 @@ bool CartridgeF6SC::bank(uInt16 bank)
|
|||
addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
return myBankChanged = true;
|
||||
|
|
|
@ -25,7 +25,7 @@ CartridgeF8::CartridgeF8(const ByteBuffer& image, size_t size,
|
|||
{
|
||||
// Copy the ROM image into my buffer
|
||||
std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin());
|
||||
createCodeAccessBase(myImage.size());
|
||||
createRomAccessArrays(myImage.size());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -109,7 +109,9 @@ bool CartridgeF8::bank(uInt16 bank)
|
|||
for(uInt16 addr = (0x1FF8 & ~System::PAGE_MASK); addr < 0x2000;
|
||||
addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
|
@ -118,7 +120,9 @@ bool CartridgeF8::bank(uInt16 bank)
|
|||
addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
return myBankChanged = true;
|
||||
|
|
|
@ -25,7 +25,7 @@ CartridgeF8SC::CartridgeF8SC(const ByteBuffer& image, size_t size,
|
|||
{
|
||||
// Copy the ROM image into my buffer
|
||||
std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin());
|
||||
createCodeAccessBase(myImage.size());
|
||||
createRomAccessArrays(myImage.size());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -51,7 +51,9 @@ void CartridgeF8SC::install(System& system)
|
|||
access.type = System::PageAccessType::WRITE;
|
||||
for(uInt16 addr = 0x1000; addr < 0x1080; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.codeAccessBase = &myCodeAccessBase[addr & 0x007F];
|
||||
access.romAccessBase = &myRomAccessBase[addr & 0x007F];
|
||||
access.romPeekCounter = &myRomAccessCounter[addr & 0x007F];
|
||||
access.romPokeCounter = &myRomAccessCounter[(addr & 0x07F) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
|
@ -60,7 +62,9 @@ void CartridgeF8SC::install(System& system)
|
|||
for(uInt16 addr = 0x1080; addr < 0x1100; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myRAM[addr & 0x007F];
|
||||
access.codeAccessBase = &myCodeAccessBase[0x80 + (addr & 0x007F)];
|
||||
access.romAccessBase = &myRomAccessBase[0x80 + (addr & 0x007F)];
|
||||
access.romPeekCounter = &myRomAccessCounter[0x80 + (addr & 0x007F)];
|
||||
access.romPokeCounter = &myRomAccessCounter[0x80 + (addr & 0x007F) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
|
@ -147,7 +151,9 @@ bool CartridgeF8SC::bank(uInt16 bank)
|
|||
for(uInt16 addr = (0x1FF8 & ~System::PAGE_MASK); addr < 0x2000;
|
||||
addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
|
@ -156,7 +162,9 @@ bool CartridgeF8SC::bank(uInt16 bank)
|
|||
addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
return myBankChanged = true;
|
||||
|
|
|
@ -25,7 +25,7 @@ CartridgeFA::CartridgeFA(const ByteBuffer& image, size_t size,
|
|||
{
|
||||
// Copy the ROM image into my buffer
|
||||
std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin());
|
||||
createCodeAccessBase(myImage.size());
|
||||
createRomAccessArrays(myImage.size());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -51,7 +51,9 @@ void CartridgeFA::install(System& system)
|
|||
access.type = System::PageAccessType::WRITE;
|
||||
for(uInt16 addr = 0x1000; addr < 0x1100; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.codeAccessBase = &myCodeAccessBase[addr & 0x00FF];
|
||||
access.romAccessBase = &myRomAccessBase[addr & 0x00FF];
|
||||
access.romPeekCounter = &myRomAccessCounter[addr & 0x00FF];
|
||||
access.romPokeCounter = &myRomAccessCounter[(addr & 0x00FF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
|
@ -60,7 +62,9 @@ void CartridgeFA::install(System& system)
|
|||
for(uInt16 addr = 0x1100; addr < 0x1200; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myRAM[addr & 0x00FF];
|
||||
access.codeAccessBase = &myCodeAccessBase[0x100 + (addr & 0x00FF)];
|
||||
access.romAccessBase = &myRomAccessBase[0x100 + (addr & 0x00FF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[0x100 + (addr & 0x00FF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[0x100 + (addr & 0x00FF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
|
@ -157,7 +161,9 @@ bool CartridgeFA::bank(uInt16 bank)
|
|||
for(uInt16 addr = (0x1FF8 & ~System::PAGE_MASK); addr < 0x2000;
|
||||
addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
|
@ -166,7 +172,9 @@ bool CartridgeFA::bank(uInt16 bank)
|
|||
addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
return myBankChanged = true;
|
||||
|
|
|
@ -35,7 +35,7 @@ CartridgeFA2::CartridgeFA2(const ByteBuffer& image, size_t size,
|
|||
|
||||
// Copy the ROM image into my buffer
|
||||
std::copy_n(img_ptr, mySize, myImage.begin());
|
||||
createCodeAccessBase(mySize);
|
||||
createRomAccessArrays(mySize);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -61,7 +61,9 @@ void CartridgeFA2::install(System& system)
|
|||
access.type = System::PageAccessType::WRITE;
|
||||
for(uInt16 addr = 0x1000; addr < 0x1100; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.codeAccessBase = &myCodeAccessBase[addr & 0x00FF];
|
||||
access.romAccessBase = &myRomAccessBase[addr & 0x00FF];
|
||||
access.romPeekCounter = &myRomAccessCounter[addr & 0x00FF];
|
||||
access.romPokeCounter = &myRomAccessCounter[(addr & 0x00FF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
|
@ -71,7 +73,9 @@ void CartridgeFA2::install(System& system)
|
|||
for(uInt16 addr = 0x1100; addr < 0x1200; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myRAM[addr & 0x00FF];
|
||||
access.codeAccessBase = &myCodeAccessBase[0x100 + (addr & 0x00FF)];
|
||||
access.romAccessBase = &myRomAccessBase[0x100 + (addr & 0x00FF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[0x100 + (addr & 0x00FF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[0x100 + (addr & 0x00FF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
|
@ -222,7 +226,9 @@ bool CartridgeFA2::bank(uInt16 bank)
|
|||
for(uInt16 addr = (0x1FF4 & ~System::PAGE_MASK); addr < 0x2000;
|
||||
addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
|
@ -231,7 +237,9 @@ bool CartridgeFA2::bank(uInt16 bank)
|
|||
addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
return myBankChanged = true;
|
||||
|
|
|
@ -26,7 +26,7 @@ CartridgeFC::CartridgeFC(const ByteBuffer& image, size_t size,
|
|||
{
|
||||
// Copy the ROM image into my buffer
|
||||
std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin());
|
||||
createCodeAccessBase(myImage.size());
|
||||
createRomAccessArrays(myImage.size());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -113,7 +113,9 @@ bool CartridgeFC::bank(uInt16 bank)
|
|||
for (uInt16 addr = (0x1FF8 & ~System::PAGE_MASK); addr < 0x2000;
|
||||
addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
|
@ -122,7 +124,9 @@ bool CartridgeFC::bank(uInt16 bank)
|
|||
addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
myCurrentBank = myTargetBank;
|
||||
|
|
|
@ -26,7 +26,7 @@ CartridgeFE::CartridgeFE(const ByteBuffer& image, size_t size,
|
|||
{
|
||||
// Copy the ROM image into my buffer
|
||||
std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin());
|
||||
createCodeAccessBase(myImage.size());
|
||||
createRomAccessArrays(myImage.size());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -49,11 +49,6 @@ void CartridgeFE::install(System& system)
|
|||
System::PageAccess access(this, System::PageAccessType::READWRITE);
|
||||
for(uInt16 addr = 0x180; addr < 0x200; addr += System::PAGE_SIZE)
|
||||
mySystem->setPageAccess(addr, access);
|
||||
|
||||
// Map all of the cart accesses to call peek and poke
|
||||
access.type = System::PageAccessType::READ;
|
||||
for(uInt16 addr = 0x1000; addr < 0x2000; addr += System::PAGE_SIZE)
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -104,6 +99,19 @@ bool CartridgeFE::bank(uInt16 bank)
|
|||
return false;
|
||||
|
||||
myBankOffset = bank << 12;
|
||||
|
||||
System::PageAccess access(this, System::PageAccessType::READ);
|
||||
|
||||
// Setup the page access methods for the current bank
|
||||
// Map all of the cart accesses to call peek and poke
|
||||
for(uInt16 addr = 0x1000; addr < 0x2000; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
return myBankChanged = true;
|
||||
}
|
||||
|
||||
|
@ -160,7 +168,7 @@ bool CartridgeFE::load(Serializer& in)
|
|||
}
|
||||
catch(...)
|
||||
{
|
||||
cerr << "ERROR: CartridgeF8SC::load" << endl;
|
||||
cerr << "ERROR: CartridgeFE::load" << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ CartridgeMDM::CartridgeMDM(const ByteBuffer& image, size_t size,
|
|||
|
||||
// Copy the ROM image into my buffer
|
||||
std::copy_n(image.get(), mySize, myImage.get());
|
||||
createCodeAccessBase(mySize);
|
||||
createRomAccessArrays(mySize);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -111,7 +111,9 @@ bool CartridgeMDM::bank(uInt16 bank)
|
|||
for(uInt16 addr = 0x1000; addr < 0x2000; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ void CartridgeMNetwork::initialize(const ByteBuffer& image, size_t size)
|
|||
|
||||
// Copy the ROM image into my buffer
|
||||
std::copy_n(image.get(), std::min<size_t>(romSize(), size), myImage.get());
|
||||
createCodeAccessBase(romSize() + myRAM.size());
|
||||
createRomAccessArrays(romSize() + myRAM.size());
|
||||
|
||||
myRAMSlice = bankCount() - 1;
|
||||
}
|
||||
|
@ -70,7 +70,9 @@ void CartridgeMNetwork::setAccess(uInt16 addrFrom, uInt16 size,
|
|||
access.directPeekBase = &directData[directOffset + (addr & addrMask)];
|
||||
else if(type == System::PageAccessType::WRITE) // all RAM writes mapped to ::poke()
|
||||
access.directPokeBase = nullptr;
|
||||
access.codeAccessBase = &myCodeAccessBase[codeOffset + (addr & addrMask)];
|
||||
access.romAccessBase = &myRomAccessBase[codeOffset + (addr & addrMask)];
|
||||
access.romPeekCounter = &myRomAccessCounter[codeOffset + (addr & addrMask)];
|
||||
access.romPokeCounter = &myRomAccessCounter[codeOffset + (addr & addrMask) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
}
|
||||
|
@ -86,7 +88,9 @@ void CartridgeMNetwork::install(System& system)
|
|||
for(uInt16 addr = (0x1FE0 & ~System::PAGE_MASK); addr < 0x2000;
|
||||
addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.codeAccessBase = &myCodeAccessBase[0x1fc0];
|
||||
access.romAccessBase = &myRomAccessBase[0x1fc0];
|
||||
access.romPeekCounter = &myRomAccessCounter[0x1fc0];
|
||||
access.romPokeCounter = &myRomAccessCounter[0x1fc0 + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
/*setAccess(0x1FE0 & ~System::PAGE_MASK, System::PAGE_SIZE,
|
||||
|
@ -137,13 +141,42 @@ bool CartridgeMNetwork::poke(uInt16 address, uInt8 value)
|
|||
// All RAM writes are mapped here
|
||||
if((myCurrentSlice[0] == myRAMSlice) && (address < BANK_SIZE / 2))
|
||||
{
|
||||
pokeRAM(myRAM[address & (BANK_SIZE / 2 - 1)], pokeAddress, value);
|
||||
return true;
|
||||
// RAM slices
|
||||
if(!(address & 0x0400))
|
||||
{
|
||||
pokeRAM(myRAM[address & (BANK_SIZE / 2 - 1)], pokeAddress, value);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Writing to the read port should be ignored, but trigger a break if option enabled
|
||||
uInt8 dummy;
|
||||
|
||||
pokeRAM(dummy, pokeAddress, value);
|
||||
myRamWriteAccess = pokeAddress;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if((address >= 0x0800) && (address <= 0x08FF))
|
||||
else
|
||||
{
|
||||
pokeRAM(myRAM[0x0400 + (myCurrentRAM << 8) + (address & 0x00FF)], pokeAddress, value);
|
||||
return true;
|
||||
// fixed 256 bytes of RAM
|
||||
if((address >= 0x0800) && (address <= 0x09FF))
|
||||
{
|
||||
if(!(address & 0x100))
|
||||
{
|
||||
pokeRAM(myRAM[0x0400 + (myCurrentRAM << 8) + (address & 0x00FF)], pokeAddress, value);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Writing to the read port should be ignored, but trigger a break if option enabled
|
||||
uInt8 dummy;
|
||||
|
||||
pokeRAM(dummy, pokeAddress, value);
|
||||
myRamWriteAccess = pokeAddress;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
@ -29,7 +29,7 @@ CartridgeSB::CartridgeSB(const ByteBuffer& image, size_t size,
|
|||
|
||||
// Copy the ROM image into my buffer
|
||||
std::copy_n(image.get(), mySize, myImage.get());
|
||||
createCodeAccessBase(mySize);
|
||||
createRomAccessArrays(mySize);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -121,7 +121,9 @@ bool CartridgeSB::bank(uInt16 bank)
|
|||
for(uInt16 addr = 0x1000; addr < 0x2000; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
return myBankChanged = true;
|
||||
|
|
|
@ -27,7 +27,7 @@ CartridgeUA::CartridgeUA(const ByteBuffer& image, size_t size,
|
|||
{
|
||||
// Copy the ROM image into my buffer
|
||||
std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin());
|
||||
createCodeAccessBase(myImage.size());
|
||||
createRomAccessArrays(myImage.size());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -135,7 +135,9 @@ bool CartridgeUA::bank(uInt16 bank)
|
|||
for(uInt16 addr = 0x1000; addr < 0x2000; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
return myBankChanged = true;
|
||||
|
|
|
@ -37,7 +37,7 @@ CartridgeWD::CartridgeWD(const ByteBuffer& image, size_t size,
|
|||
}
|
||||
else
|
||||
std::copy_n(image.get(), mySize, myImage.begin());
|
||||
createCodeAccessBase(8_KB);
|
||||
createRomAccessArrays(8_KB);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -63,7 +63,9 @@ void CartridgeWD::install(System& system)
|
|||
for(uInt16 addr = 0x1000; addr < 0x1040; addr += System::PAGE_SIZE)
|
||||
{
|
||||
read.directPeekBase = &myRAM[addr & 0x003F];
|
||||
read.codeAccessBase = &myCodeAccessBase[addr & 0x003F];
|
||||
read.romAccessBase = &myRomAccessBase[addr & 0x003F];
|
||||
read.romPeekCounter = &myRomAccessCounter[addr & 0x003F];
|
||||
read.romPokeCounter = &myRomAccessCounter[(addr & 0x003F) + 8_KB];
|
||||
mySystem->setPageAccess(addr, read);
|
||||
}
|
||||
|
||||
|
@ -73,7 +75,9 @@ void CartridgeWD::install(System& system)
|
|||
System::PageAccess write(this, System::PageAccessType::WRITE);
|
||||
for(uInt16 addr = 0x1040; addr < 0x1080; addr += System::PAGE_SIZE)
|
||||
{
|
||||
write.codeAccessBase = &myCodeAccessBase[addr & 0x003F];
|
||||
write.romAccessBase = &myRomAccessBase[addr & 0x003F];
|
||||
write.romPeekCounter = &myRomAccessCounter[addr & 0x003F];
|
||||
write.romPokeCounter = &myRomAccessCounter[(addr & 0x003F) + 8_KB];
|
||||
mySystem->setPageAccess(addr, write);
|
||||
}
|
||||
|
||||
|
@ -177,7 +181,9 @@ void CartridgeWD::segmentZero(uInt8 slice)
|
|||
// Skip first 128 bytes; it is always RAM
|
||||
for(uInt16 addr = 0x1080; addr < 0x1400; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.codeAccessBase = &myCodeAccessBase[offset + (addr & 0x03FF)];
|
||||
access.romAccessBase = &myRomAccessBase[offset + (addr & 0x03FF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[offset + (addr & 0x03FF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[offset + (addr & 0x03FF) + 8_KB];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
myOffset[0] = offset;
|
||||
|
@ -191,7 +197,9 @@ void CartridgeWD::segmentOne(uInt8 slice)
|
|||
|
||||
for(uInt16 addr = 0x1400; addr < 0x1800; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.codeAccessBase = &myCodeAccessBase[offset + (addr & 0x03FF)];
|
||||
access.romAccessBase = &myRomAccessBase[offset + (addr & 0x03FF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[offset + (addr & 0x03FF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[offset + (addr & 0x03FF) + 8_KB];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
myOffset[1] = offset;
|
||||
|
@ -205,7 +213,9 @@ void CartridgeWD::segmentTwo(uInt8 slice)
|
|||
|
||||
for(uInt16 addr = 0x1800; addr < 0x1C00; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.codeAccessBase = &myCodeAccessBase[offset + (addr & 0x03FF)];
|
||||
access.romAccessBase = &myRomAccessBase[offset + (addr & 0x03FF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[offset + (addr & 0x03FF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[offset + (addr & 0x03FF) + 8_KB];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
myOffset[2] = offset;
|
||||
|
@ -225,7 +235,9 @@ void CartridgeWD::segmentThree(uInt8 slice)
|
|||
|
||||
for(uInt16 addr = 0x1C00; addr < 0x2000; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.codeAccessBase = &myCodeAccessBase[offset + (addr & 0x03FF)];
|
||||
access.romAccessBase = &myRomAccessBase[offset + (addr & 0x03FF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[offset + (addr & 0x03FF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[offset + (addr & 0x03FF) + 8_KB];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
myOffset[3] = offset;
|
||||
|
|
|
@ -27,7 +27,7 @@ CartridgeX07::CartridgeX07(const ByteBuffer& image, size_t size,
|
|||
{
|
||||
// Copy the ROM image into my buffer
|
||||
std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin());
|
||||
createCodeAccessBase(myImage.size());
|
||||
createRomAccessArrays(myImage.size());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -115,7 +115,9 @@ bool CartridgeX07::bank(uInt16 bank)
|
|||
for(uInt16 addr = 0x1000; addr < 0x2000; addr += System::PAGE_SIZE)
|
||||
{
|
||||
access.directPeekBase = &myImage[offset + (addr & 0x0FFF)];
|
||||
access.codeAccessBase = &myCodeAccessBase[offset + (addr & 0x0FFF)];
|
||||
access.romAccessBase = &myRomAccessBase[offset + (addr & 0x0FFF)];
|
||||
access.romPeekCounter = &myRomAccessCounter[offset + (addr & 0x0FFF)];
|
||||
access.romPokeCounter = &myRomAccessCounter[offset + (addr & 0x0FFF) + myAccessSize];
|
||||
mySystem->setPageAccess(addr, access);
|
||||
}
|
||||
return myBankChanged = true;
|
||||
|
|
|
@ -745,7 +745,7 @@ void Console::updateVcenter(Int32 vcenter)
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void Console::changeScanlineAdjust(int direction)
|
||||
{
|
||||
Int32 newAdjustVSize = myTIA->adjustVSize();;
|
||||
Int32 newAdjustVSize = myTIA->adjustVSize();
|
||||
|
||||
if (direction != -1 && direction != +1) return;
|
||||
|
||||
|
@ -923,6 +923,11 @@ unique_ptr<Controller> Console::getControllerPort(const Controller::Type type,
|
|||
swapAxis = true;
|
||||
else if(type == Controller::Type::PaddlesIAxDr)
|
||||
swapAxis = swapDir = true;
|
||||
|
||||
Paddles::setAnalogXCenter(BSPF::stringToInt(myProperties.get(PropType::Controller_PaddlesXCenter)));
|
||||
Paddles::setAnalogYCenter(BSPF::stringToInt(myProperties.get(PropType::Controller_PaddlesYCenter)));
|
||||
Paddles::setAnalogSensitivity(myOSystem.settings().getInt("psense"));
|
||||
|
||||
controller = make_unique<Paddles>(port, myEvent, *mySystem,
|
||||
swapPaddles, swapAxis, swapDir);
|
||||
break;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -32,6 +32,39 @@ class System;
|
|||
*/
|
||||
class Device : public Serializable
|
||||
{
|
||||
public:
|
||||
enum AccessType {
|
||||
NONE = 0,
|
||||
REFERENCED = 1 << 0, /* 0x01, code somewhere in the program references it,
|
||||
i.e. LDA $F372 referenced $F372 */
|
||||
VALID_ENTRY = 1 << 1, /* 0x02, addresses that can have a label placed in front of it.
|
||||
A good counterexample would be "FF00: LDA $FE00"; $FF01
|
||||
would be in the middle of a multi-byte instruction, and
|
||||
therefore cannot be labelled. */
|
||||
|
||||
// The following correspond to specific types that can be set within the
|
||||
// debugger, or specified in a Distella cfg file, and are listed in order
|
||||
// of increasing hierarchy
|
||||
//
|
||||
ROW = 1 << 2, // 0x004, all other addresses
|
||||
DATA = 1 << 3, // 0x008, addresses loaded into registers other than GRPx / PFx / COLUxx, AUDxx
|
||||
AUD = 1 << 4, // 0x010, addresses loaded into audio registers
|
||||
BCOL = 1 << 5, // 0x020, addresses loaded into COLUBK register
|
||||
PCOL = 1 << 6, // 0x040, addresses loaded into COLUPF register
|
||||
COL = 1 << 7, // 0x080, addresses loaded into COLUPx registers
|
||||
PGFX = 1 << 8, // 0x100, addresses loaded into PFx registers
|
||||
GFX = 1 << 9, // 0x200, addresses loaded into GRPx registers
|
||||
TCODE = 1 << 10, // 0x400, (tentative) disassemble-able code segments
|
||||
CODE = 1 << 11, // 0x800, disassemble-able code segments
|
||||
// special bits for address
|
||||
HADDR = 1 << 13 | 1 << 14 | 1 << 15, // 0xe000, // highest 3 address bits
|
||||
// special type for poke()
|
||||
WRITE = TCODE // 0x200, address written to
|
||||
};
|
||||
using AccessFlags = uInt16;
|
||||
|
||||
using AccessCounter = uInt32;
|
||||
|
||||
public:
|
||||
Device() = default;
|
||||
virtual ~Device() = default;
|
||||
|
@ -97,20 +130,36 @@ class Device : public Serializable
|
|||
*/
|
||||
virtual bool poke(uInt16 address, uInt8 value) { return false; }
|
||||
|
||||
#ifdef DEBUGGER_SUPPORT
|
||||
/**
|
||||
Query the given address for its disassembly flags
|
||||
Query the given address for its access flags
|
||||
|
||||
@param address The address to modify
|
||||
*/
|
||||
virtual uInt8 getAccessFlags(uInt16 address) const { return 0; }
|
||||
virtual AccessFlags getAccessFlags(uInt16 address) const { return AccessType::NONE; }
|
||||
|
||||
/**
|
||||
Change the given address type to use the given disassembly flags
|
||||
Change the given address type to use the given access flags
|
||||
|
||||
@param address The address to modify
|
||||
@param flags A bitfield of DisasmType directives for the given address
|
||||
@param flags A bitfield of AccessType directives for the given address
|
||||
*/
|
||||
virtual void setAccessFlags(uInt16 address, uInt8 flags) { }
|
||||
virtual void setAccessFlags(uInt16 address, AccessFlags flags) { }
|
||||
|
||||
/**
|
||||
Increase the given address's access counter
|
||||
|
||||
@param address The address to modify
|
||||
*/
|
||||
virtual void increaseAccessCounter(uInt16 address, bool isWrite = false) { }
|
||||
|
||||
/**
|
||||
Query the access counters
|
||||
|
||||
@return The access counters as comma separated string
|
||||
*/
|
||||
virtual string getAccessCounters() const { return ""; }
|
||||
#endif
|
||||
|
||||
protected:
|
||||
/// Pointer to the system the device is installed in or the null pointer
|
||||
|
|
|
@ -55,7 +55,7 @@ class DispatchResult
|
|||
if (myStatus != status) throw runtime_error("invalid status for operation");
|
||||
}
|
||||
|
||||
template<class ...Ts> void assertStatus(Status status, Ts... more) const
|
||||
template<typename ...Ts> void assertStatus(Status status, Ts... more) const
|
||||
{
|
||||
if (myStatus == status) return;
|
||||
|
||||
|
|
|
@ -49,10 +49,6 @@ Driving::Driving(Jack jack, const Event& event, const System& system)
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void Driving::update()
|
||||
{
|
||||
// Make sure direct gray codes from Stelladaptor stay in sync with
|
||||
// simulated gray codes generated by PC keyboard or PC joystick
|
||||
myCounter = (myGrayIndex << 2) | (myCounter & 3);
|
||||
|
||||
// Digital events (from keyboard or joystick hats & buttons)
|
||||
setPin(DigitalPin::Six, myEvent.get(myFireEvent) == 0);
|
||||
int d_axis = myEvent.get(myXAxisValue);
|
||||
|
@ -92,8 +88,7 @@ void Driving::update()
|
|||
}
|
||||
|
||||
// Only consider the lower-most bits (corresponding to pins 1 & 2)
|
||||
myCounter &= 0x0f;
|
||||
myGrayIndex = myCounter >> 2;
|
||||
myGrayIndex = Int32(myCounter * SENSITIVITY / 4.0F) & 0b11;
|
||||
|
||||
// Stelladaptor is the only controller that should set this
|
||||
int yaxis = myEvent.get(myYAxisValue);
|
||||
|
@ -111,6 +106,10 @@ void Driving::update()
|
|||
myGrayIndex = 2; // up + down
|
||||
else /* if(yaxis < 16384-4096) */
|
||||
myGrayIndex = 0; // no movement
|
||||
|
||||
// Make sure direct gray codes from Stelladaptor stay in sync with
|
||||
// simulated gray codes generated by PC keyboard or PC joystick
|
||||
myCounter = myGrayIndex / SENSITIVITY * 4.0F;
|
||||
}
|
||||
|
||||
// Gray codes for rotation
|
||||
|
@ -154,3 +153,13 @@ bool Driving::setMouseControl(
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void Driving::setSensitivity(int sensitivity)
|
||||
{
|
||||
BSPF::clamp(sensitivity, 1, 20, 10);
|
||||
SENSITIVITY = sensitivity / 10.0F;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
float Driving::SENSITIVITY = 1.0;
|
||||
|
|
|
@ -76,9 +76,18 @@ class Driving : public Controller
|
|||
bool setMouseControl(
|
||||
Controller::Type xtype, int xid, Controller::Type ytype, int yid) override;
|
||||
|
||||
/**
|
||||
Sets the sensitivity for digital emulation of driving controlle movement
|
||||
using a keyboard.
|
||||
|
||||
@param sensitivity Value from 1 to 20, with larger values causing
|
||||
more movement (10 represents the baseline)
|
||||
*/
|
||||
static void setSensitivity(int sensitivity);
|
||||
|
||||
private:
|
||||
// Counter to iterate through the gray codes
|
||||
uInt32 myCounter{0};
|
||||
Int32 myCounter{0};
|
||||
|
||||
// Index into the gray code table
|
||||
uInt32 myGrayIndex{0};
|
||||
|
@ -98,6 +107,10 @@ class Driving : public Controller
|
|||
// Controllers to emulate in 'specific' mouse axis mode
|
||||
int myControlIDX{-1}, myControlIDY{-1};
|
||||
|
||||
// User-defined sensitivity; adjustable since end-users may prefer different
|
||||
// speeds
|
||||
static float SENSITIVITY;
|
||||
|
||||
private:
|
||||
// Following constructors and assignment operators not supported
|
||||
Driving() = delete;
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "Paddles.hxx"
|
||||
#include "Lightgun.hxx"
|
||||
#include "PointingDevice.hxx"
|
||||
#include "Driving.hxx"
|
||||
#include "PropsSet.hxx"
|
||||
#include "Settings.hxx"
|
||||
#include "Sound.hxx"
|
||||
|
@ -97,6 +98,7 @@ void EventHandler::initialize()
|
|||
Paddles::setDigitalSensitivity(myOSystem.settings().getInt("dsense"));
|
||||
Paddles::setMouseSensitivity(myOSystem.settings().getInt("msense"));
|
||||
PointingDevice::setSensitivity(myOSystem.settings().getInt("tsense"));
|
||||
Driving::setSensitivity(myOSystem.settings().getInt("dcsense"));
|
||||
|
||||
#ifdef GUI_SUPPORT
|
||||
// Set quick select delay when typing characters in listwidgets
|
||||
|
|
|
@ -36,9 +36,14 @@
|
|||
#ifdef GUI_SUPPORT
|
||||
#include "Font.hxx"
|
||||
#include "StellaFont.hxx"
|
||||
#include "ConsoleMediumBFont.hxx"
|
||||
#include "StellaMediumFont.hxx"
|
||||
#include "StellaLargeFont.hxx"
|
||||
#include "Stella12x24tFont.hxx"
|
||||
#include "Stella14x28tFont.hxx"
|
||||
#include "Stella16x32tFont.hxx"
|
||||
#include "ConsoleFont.hxx"
|
||||
#include "ConsoleBFont.hxx"
|
||||
#include "Launcher.hxx"
|
||||
#include "Menu.hxx"
|
||||
#include "CommandMenu.hxx"
|
||||
|
@ -106,27 +111,42 @@ bool FrameBuffer::initialize()
|
|||
// This font is used in a variety of situations when a really small
|
||||
// font is needed; we let the specific widget/dialog decide when to
|
||||
// use it
|
||||
mySmallFont = make_unique<GUI::Font>(GUI::stellaDesc);
|
||||
mySmallFont = make_unique<GUI::Font>(GUI::stellaDesc); // 6x10
|
||||
|
||||
// The general font used in all UI elements
|
||||
// This is determined by the size of the framebuffer
|
||||
if(myOSystem.settings().getBool("minimal_ui"))
|
||||
myFont = make_unique<GUI::Font>(GUI::stellaLargeDesc);
|
||||
{
|
||||
myFont = make_unique<GUI::Font>(GUI::stella12x24tDesc); // 12x24
|
||||
// The info font used in all UI elements
|
||||
// This is determined by the size of the framebuffer
|
||||
myInfoFont = make_unique<GUI::Font>(GUI::stellaLargeDesc); // 10x20
|
||||
}
|
||||
else
|
||||
myFont = make_unique<GUI::Font>(GUI::stellaMediumDesc);
|
||||
{
|
||||
myFont = make_unique<GUI::Font>(GUI::stellaMediumDesc); // 9x18
|
||||
// The info font used in all UI elements
|
||||
// This is determined by the size of the framebuffer
|
||||
myInfoFont = make_unique<GUI::Font>(GUI::consoleDesc); // 8x13
|
||||
}
|
||||
|
||||
// The info font used in all UI elements
|
||||
// This is determined by the size of the framebuffer
|
||||
myInfoFont = make_unique<GUI::Font>(GUI::consoleDesc);
|
||||
|
||||
// The font used by the ROM launcher
|
||||
const string& lf = myOSystem.settings().getString("launcherfont");
|
||||
if(lf == "small")
|
||||
myLauncherFont = make_unique<GUI::Font>(GUI::consoleDesc);
|
||||
myLauncherFont = make_unique<GUI::Font>(GUI::consoleBDesc); // 8x13
|
||||
else if(lf == "low_medium")
|
||||
myLauncherFont = make_unique<GUI::Font>(GUI::consoleMediumBDesc); // 9x15
|
||||
else if(lf == "medium")
|
||||
myLauncherFont = make_unique<GUI::Font>(GUI::stellaMediumDesc);
|
||||
else
|
||||
myLauncherFont = make_unique<GUI::Font>(GUI::stellaLargeDesc);
|
||||
myLauncherFont = make_unique<GUI::Font>(GUI::stellaMediumDesc); // 9x18
|
||||
else if(lf == "large" || lf == "large10")
|
||||
myLauncherFont = make_unique<GUI::Font>(GUI::stellaLargeDesc); // 10x20
|
||||
else if(lf == "large12")
|
||||
myLauncherFont = make_unique<GUI::Font>(GUI::stella12x24tDesc); // 12x24
|
||||
else if(lf == "large14")
|
||||
myLauncherFont = make_unique<GUI::Font>(GUI::stella14x28tDesc); // 14x28
|
||||
else // "large16"
|
||||
myLauncherFont = make_unique<GUI::Font>(GUI::stella16x32tDesc); // 16x32
|
||||
#endif
|
||||
|
||||
// Determine possible TIA windowed zoom levels
|
||||
|
|
|
@ -381,6 +381,16 @@ class FrameBuffer
|
|||
*/
|
||||
virtual void clear() = 0;
|
||||
|
||||
/**
|
||||
Transform from window to renderer coordinates, x direction
|
||||
*/
|
||||
virtual int scaleX(int x) const { return x; }
|
||||
|
||||
/**
|
||||
Transform from window to renderer coordinates, y direction
|
||||
*/
|
||||
virtual int scaleY(int y) const { return y; }
|
||||
|
||||
protected:
|
||||
/**
|
||||
This method is called to query and initialize the video hardware
|
||||
|
|
|
@ -18,26 +18,20 @@
|
|||
#ifdef DEBUGGER_SUPPORT
|
||||
#include "Debugger.hxx"
|
||||
#include "Expression.hxx"
|
||||
#include "CartDebug.hxx"
|
||||
#include "Device.hxx"
|
||||
#include "Base.hxx"
|
||||
|
||||
// Flags for disassembly types
|
||||
#define DISASM_CODE CartDebug::CODE
|
||||
// #define DISASM_GFX CartDebug::GFX
|
||||
// #define DISASM_PGFX CartDebug::PGFX
|
||||
#define DISASM_DATA CartDebug::DATA
|
||||
// #define DISASM_ROW CartDebug::ROW
|
||||
#define DISASM_WRITE CartDebug::WRITE
|
||||
#define DISASM_NONE 0
|
||||
// Flags for access types
|
||||
#define DISASM_CODE Device::CODE
|
||||
#define DISASM_DATA Device::DATA
|
||||
#define DISASM_WRITE Device::WRITE
|
||||
#define DISASM_NONE Device::NONE
|
||||
#else
|
||||
// Flags for disassembly types
|
||||
// Flags for access types
|
||||
#define DISASM_CODE 0
|
||||
// #define DISASM_GFX 0
|
||||
// #define DISASM_PGFX 0
|
||||
#define DISASM_DATA 0
|
||||
// #define DISASM_ROW 0
|
||||
#define DISASM_NONE 0
|
||||
#define DISASM_WRITE 0
|
||||
#define DISASM_NONE 0
|
||||
#endif
|
||||
#include "Settings.hxx"
|
||||
#include "Vec.hxx"
|
||||
|
@ -104,7 +98,7 @@ void M6502::reset()
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
inline uInt8 M6502::peek(uInt16 address, uInt8 flags)
|
||||
inline uInt8 M6502::peek(uInt16 address, Device::AccessFlags flags)
|
||||
{
|
||||
handleHalt();
|
||||
|
||||
|
@ -144,7 +138,7 @@ inline uInt8 M6502::peek(uInt16 address, uInt8 flags)
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
inline void M6502::poke(uInt16 address, uInt8 value, uInt8 flags)
|
||||
inline void M6502::poke(uInt16 address, uInt8 value, Device::AccessFlags flags)
|
||||
{
|
||||
////////////////////////////////////////////////
|
||||
// TODO - move this logic directly into CartAR
|
||||
|
@ -300,8 +294,8 @@ inline void M6502::_execute(uInt64 cycles, DispatchResult& result)
|
|||
mySystem->cart().clearAllRAMAccesses();
|
||||
#endif // DEBUGGER_SUPPORT
|
||||
|
||||
// Reset the peek/poke address pointers
|
||||
myLastPeekAddress = myLastPokeAddress = myDataAddressForPoke = 0;
|
||||
// Reset the data poke address pointer
|
||||
myDataAddressForPoke = 0;
|
||||
|
||||
try {
|
||||
uInt16 operandAddress = 0, intermediateAddress = 0;
|
||||
|
|
|
@ -34,6 +34,7 @@ class DispatchResult;
|
|||
#endif
|
||||
|
||||
#include "bspf.hxx"
|
||||
#include "Device.hxx"
|
||||
#include "Serializable.hxx"
|
||||
|
||||
/**
|
||||
|
@ -156,13 +157,27 @@ class M6502 : public Serializable
|
|||
|
||||
@return The address of the last read
|
||||
*/
|
||||
uInt16 lastReadBaseAddress() const { return myLastPeekBaseAddress; }
|
||||
uInt16 lastReadAddress() const { return myLastPeekAddress; }
|
||||
|
||||
/**
|
||||
Return the last address that was part of a write/poke.
|
||||
|
||||
@return The address of the last write
|
||||
*/
|
||||
uInt16 lastWriteAddress() const { return myLastPokeAddress; }
|
||||
|
||||
/**
|
||||
Return the last (non-mirrored) address that was part of a read/peek.
|
||||
|
||||
@return The address of the last read
|
||||
*/
|
||||
uInt16 lastReadBaseAddress() const { return myLastPeekBaseAddress; }
|
||||
|
||||
/**
|
||||
Return the last (non-mirrored) address that was part of a write/poke.
|
||||
|
||||
@return The address of the last write
|
||||
*/
|
||||
uInt16 lastWriteBaseAddress() const { return myLastPokeBaseAddress; }
|
||||
|
||||
/**
|
||||
|
@ -255,7 +270,7 @@ class M6502 : public Serializable
|
|||
|
||||
@return The byte at the specified address
|
||||
*/
|
||||
uInt8 peek(uInt16 address, uInt8 flags);
|
||||
uInt8 peek(uInt16 address, Device::AccessFlags flags);
|
||||
|
||||
/**
|
||||
Change the byte at the specified address to the given value and
|
||||
|
@ -264,7 +279,7 @@ class M6502 : public Serializable
|
|||
@param address The address where the value should be stored
|
||||
@param value The value to be stored at the address
|
||||
*/
|
||||
void poke(uInt16 address, uInt8 value, uInt8 flags = 0);
|
||||
void poke(uInt16 address, uInt8 value, Device::AccessFlags flags = Device::NONE);
|
||||
|
||||
/**
|
||||
Get the 8-bit value of the Processor Status register.
|
||||
|
@ -377,7 +392,7 @@ class M6502 : public Serializable
|
|||
/// accessed specifically by a peek or poke command
|
||||
uInt16 myLastPeekBaseAddress{0}, myLastPokeBaseAddress{0};
|
||||
// Indicates the type of the last access
|
||||
uInt8 myFlags{0};
|
||||
uInt16 myFlags{0};
|
||||
|
||||
/// Indicates the last address used to access data by a peek command
|
||||
/// for the CPU registers (S/A/X/Y)
|
||||
|
|
|
@ -3770,9 +3770,9 @@ case 0x40:
|
|||
}
|
||||
{
|
||||
peek(0x0100 + SP++, DISASM_NONE);
|
||||
PS(peek(0x0100 + SP++, DISASM_NONE));
|
||||
PC = peek(0x0100 + SP++, DISASM_NONE);
|
||||
PC |= (uInt16(peek(0x0100 + SP, DISASM_NONE)) << 8);
|
||||
PS(peek(0x0100 + SP++, DISASM_DATA));
|
||||
PC = peek(0x0100 + SP++, DISASM_DATA);
|
||||
PC |= (uInt16(peek(0x0100 + SP, DISASM_DATA)) << 8);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -3784,8 +3784,8 @@ case 0x60:
|
|||
}
|
||||
{
|
||||
peek(0x0100 + SP++, DISASM_NONE);
|
||||
PC = peek(0x0100 + SP++, DISASM_NONE);
|
||||
PC |= (uInt16(peek(0x0100 + SP, DISASM_NONE)) << 8);
|
||||
PC = peek(0x0100 + SP++, DISASM_DATA);
|
||||
PC |= (uInt16(peek(0x0100 + SP, DISASM_DATA)) << 8);
|
||||
peek(PC++, DISASM_NONE);
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -885,15 +885,15 @@ define(M6502_RRA, `{
|
|||
|
||||
define(M6502_RTI, `{
|
||||
peek(0x0100 + SP++, DISASM_NONE);
|
||||
PS(peek(0x0100 + SP++, DISASM_NONE));
|
||||
PC = peek(0x0100 + SP++, DISASM_NONE);
|
||||
PC |= (uInt16(peek(0x0100 + SP, DISASM_NONE)) << 8);
|
||||
PS(peek(0x0100 + SP++, DISASM_DATA));
|
||||
PC = peek(0x0100 + SP++, DISASM_DATA);
|
||||
PC |= (uInt16(peek(0x0100 + SP, DISASM_DATA)) << 8);
|
||||
}')
|
||||
|
||||
define(M6502_RTS, `{
|
||||
peek(0x0100 + SP++, DISASM_NONE);
|
||||
PC = peek(0x0100 + SP++, DISASM_NONE);
|
||||
PC |= (uInt16(peek(0x0100 + SP, DISASM_NONE)) << 8);
|
||||
PC = peek(0x0100 + SP++, DISASM_DATA);
|
||||
PC |= (uInt16(peek(0x0100 + SP, DISASM_DATA)) << 8);
|
||||
peek(PC++, DISASM_NONE);
|
||||
}')
|
||||
|
||||
|
|
|
@ -21,9 +21,7 @@
|
|||
#include "Settings.hxx"
|
||||
#include "Switches.hxx"
|
||||
#include "System.hxx"
|
||||
#ifdef DEBUGGER_SUPPORT
|
||||
#include "CartDebug.hxx"
|
||||
#endif
|
||||
#include "Base.hxx"
|
||||
|
||||
#include "M6532.hxx"
|
||||
|
||||
|
@ -460,14 +458,17 @@ uInt32 M6532::timerClocks() const
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void M6532::createAccessBases()
|
||||
{
|
||||
myRAMAccessBase.fill(CartDebug::NONE);
|
||||
myStackAccessBase.fill(CartDebug::NONE);
|
||||
myIOAccessBase.fill(CartDebug::NONE);
|
||||
myRAMAccessBase.fill(Device::NONE);
|
||||
myStackAccessBase.fill(Device::NONE);
|
||||
myIOAccessBase.fill(Device::NONE);
|
||||
myRAMAccessCounter.fill(0);
|
||||
myStackAccessCounter.fill(0);
|
||||
myIOAccessCounter.fill(0);
|
||||
myZPAccessDelay.fill(ZP_DELAY);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt8 M6532::getAccessFlags(uInt16 address) const
|
||||
Device::AccessFlags M6532::getAccessFlags(uInt16 address) const
|
||||
{
|
||||
if (address & IO_BIT)
|
||||
return myIOAccessBase[address & IO_MASK];
|
||||
|
@ -478,10 +479,10 @@ uInt8 M6532::getAccessFlags(uInt16 address) const
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void M6532::setAccessFlags(uInt16 address, uInt8 flags)
|
||||
void M6532::setAccessFlags(uInt16 address, Device::AccessFlags flags)
|
||||
{
|
||||
// ignore none flag
|
||||
if (flags != CartDebug::NONE) {
|
||||
if (flags != Device::NONE) {
|
||||
if (address & IO_BIT)
|
||||
myIOAccessBase[address & IO_MASK] |= flags;
|
||||
else {
|
||||
|
@ -495,4 +496,63 @@ void M6532::setAccessFlags(uInt16 address, uInt8 flags)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void M6532::increaseAccessCounter(uInt16 address, bool isWrite)
|
||||
{
|
||||
if (address & IO_BIT)
|
||||
myIOAccessCounter[(isWrite ? IO_SIZE : 0) + (address & IO_MASK)]++;
|
||||
else {
|
||||
// the first access, either by direct RAM or stack access is assumed as initialization
|
||||
if (myZPAccessDelay[address & RAM_MASK])
|
||||
myZPAccessDelay[address & RAM_MASK]--;
|
||||
else if (address & STACK_BIT)
|
||||
myStackAccessCounter[(isWrite ? STACK_SIZE : 0) + (address & STACK_MASK)]++;
|
||||
else
|
||||
myRAMAccessCounter[(isWrite ? RAM_SIZE : 0) + (address & RAM_MASK)]++;
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
string M6532::getAccessCounters() const
|
||||
{
|
||||
ostringstream out;
|
||||
|
||||
out << "RAM reads:\n";
|
||||
for(uInt16 addr = 0x00; addr < RAM_SIZE; ++addr)
|
||||
out << Common::Base::HEX4 << (addr | 0x80) << ","
|
||||
<< Common::Base::toString(myRAMAccessCounter[addr], Common::Base::Fmt::_10_8) << ", ";
|
||||
out << "\n";
|
||||
out << "RAM writes:\n";
|
||||
for(uInt16 addr = 0x00; addr < RAM_SIZE; ++addr)
|
||||
out << Common::Base::HEX4 << (addr | 0x80) << ","
|
||||
<< Common::Base::toString(myRAMAccessCounter[RAM_SIZE + addr], Common::Base::Fmt::_10_8) << ", ";
|
||||
out << "\n";
|
||||
|
||||
|
||||
out << "Stack reads:\n";
|
||||
for(uInt16 addr = 0x00; addr < STACK_SIZE; ++addr)
|
||||
out << Common::Base::HEX4 << (addr | 0x180) << ","
|
||||
<< Common::Base::toString(myStackAccessCounter[addr], Common::Base::Fmt::_10_8) << ", ";
|
||||
out << "\n";
|
||||
out << "Stack writes:\n";
|
||||
for(uInt16 addr = 0x00; addr < STACK_SIZE; ++addr)
|
||||
out << Common::Base::HEX4 << (addr | 0x180) << ","
|
||||
<< Common::Base::toString(myStackAccessCounter[STACK_SIZE + addr], Common::Base::Fmt::_10_8) << ", ";
|
||||
out << "\n";
|
||||
|
||||
out << "IO reads:\n";
|
||||
for(uInt16 addr = 0x00; addr < IO_SIZE; ++addr)
|
||||
out << Common::Base::HEX4 << (addr | 0x280) << ","
|
||||
<< Common::Base::toString(myIOAccessCounter[addr], Common::Base::Fmt::_10_8) << ", ";
|
||||
out << "\n";
|
||||
out << "IO writes:\n";
|
||||
for(uInt16 addr = 0x00; addr < IO_SIZE; ++addr)
|
||||
out << Common::Base::HEX4 << (addr | 0x280) << ","
|
||||
<< Common::Base::toString(myIOAccessCounter[IO_SIZE + addr], Common::Base::Fmt::_10_8) << ", ";
|
||||
out << "\n";
|
||||
|
||||
return out.str();
|
||||
}
|
||||
|
||||
#endif // DEBUGGER_SUPPORT
|
||||
|
|
|
@ -130,12 +130,21 @@ class M6532 : public Device
|
|||
*/
|
||||
const uInt8* getRAM() const { return myRAM.data(); }
|
||||
|
||||
#ifdef DEBUGGER_SUPPORT
|
||||
/**
|
||||
Query the access counters
|
||||
|
||||
@return The access counters as comma separated string
|
||||
*/
|
||||
string getAccessCounters() const override;
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
void setTimerRegister(uInt8 data, uInt8 interval);
|
||||
void setPinState(bool shcha);
|
||||
|
||||
#ifdef DEBUGGER_SUPPORT
|
||||
#ifdef DEBUGGER_SUPPORT
|
||||
// The following are used by the debugger to read INTIM/TIMINT
|
||||
// We need separate methods to do this, so the state of the system
|
||||
// isn't changed
|
||||
|
@ -147,19 +156,26 @@ class M6532 : public Device
|
|||
void createAccessBases();
|
||||
|
||||
/**
|
||||
Query the given address type for the associated disassembly flags.
|
||||
Query the given address type for the associated access flags.
|
||||
|
||||
@param address The address to query
|
||||
*/
|
||||
uInt8 getAccessFlags(uInt16 address) const override;
|
||||
Device::AccessFlags getAccessFlags(uInt16 address) const override;
|
||||
/**
|
||||
Change the given address to use the given disassembly flags.
|
||||
Change the given address to use the given access flags.
|
||||
|
||||
@param address The address to modify
|
||||
@param flags A bitfield of DisasmType directives for the given address
|
||||
@param flags A bitfield of AccessType directives for the given address
|
||||
*/
|
||||
void setAccessFlags(uInt16 address, uInt8 flags) override;
|
||||
#endif // DEBUGGER_SUPPORT
|
||||
void setAccessFlags(uInt16 address, Device::AccessFlags flags) override;
|
||||
|
||||
/**
|
||||
Increase the given address's access counter
|
||||
|
||||
@param address The address to modify
|
||||
*/
|
||||
void increaseAccessCounter(uInt16 address, bool isWrite) override;
|
||||
#endif // DEBUGGER_SUPPORT
|
||||
|
||||
private:
|
||||
// Reference to the console
|
||||
|
@ -221,13 +237,18 @@ class M6532 : public Device
|
|||
RAM_SIZE = 0x80, RAM_MASK = RAM_SIZE - 1,
|
||||
STACK_SIZE = RAM_SIZE, STACK_MASK = RAM_MASK, STACK_BIT = 0x100,
|
||||
IO_SIZE = 0x20, IO_MASK = IO_SIZE - 1, IO_BIT = 0x200,
|
||||
ZP_DELAY = 1;
|
||||
ZP_DELAY = 1 * 2;
|
||||
|
||||
// The arrays containing information about every byte of RIOT
|
||||
// indicating whether and how (RW) it is used.
|
||||
std::array<uInt8, RAM_SIZE> myRAMAccessBase;
|
||||
std::array<uInt8, STACK_SIZE> myStackAccessBase;
|
||||
std::array<uInt8, IO_SIZE> myIOAccessBase;
|
||||
std::array<Device::AccessFlags, RAM_SIZE> myRAMAccessBase;
|
||||
std::array<Device::AccessFlags, STACK_SIZE> myStackAccessBase;
|
||||
std::array<Device::AccessFlags, IO_SIZE> myIOAccessBase;
|
||||
// The arrays containing information about every byte of RIOT
|
||||
// indicating how often it is accessed.
|
||||
std::array<Device::AccessCounter, RAM_SIZE * 2> myRAMAccessCounter;
|
||||
std::array<Device::AccessCounter, STACK_SIZE * 2> myStackAccessCounter;
|
||||
std::array<Device::AccessCounter, IO_SIZE * 2> myIOAccessCounter;
|
||||
// The array used to skip the first ZP access tracking
|
||||
std::array<uInt8, RAM_SIZE> myZPAccessDelay;
|
||||
#endif // DEBUGGER_SUPPORT
|
||||
|
|
|
@ -268,6 +268,9 @@ void OSystem::setConfigPaths()
|
|||
|
||||
buildDirIfRequired(myStateDir, myBaseDir + "state");
|
||||
buildDirIfRequired(myNVRamDir, myBaseDir + "nvram");
|
||||
#ifdef DEBUGGER_SUPPORT
|
||||
buildDirIfRequired(myCfgDir, myBaseDir + "cfg");
|
||||
#endif
|
||||
|
||||
#ifdef PNG_SUPPORT
|
||||
mySnapshotSaveDir = mySettings->getString("snapsavedir");
|
||||
|
@ -292,6 +295,7 @@ void OSystem::setConfigPaths()
|
|||
dbgPath("base dir ", myBaseDir);
|
||||
dbgPath("state dir ", myStateDir);
|
||||
dbgPath("nvram dir ", myNVRamDir);
|
||||
dbgPath("cfg dir ", myCfgDir);
|
||||
dbgPath("ssave dir ", mySnapshotSaveDir);
|
||||
dbgPath("sload dir ", mySnapshotLoadDir);
|
||||
dbgPath("cheat file", myCheatFile);
|
||||
|
@ -600,6 +604,8 @@ unique_ptr<Console> OSystem::openConsole(const FilesystemNode& romfile, string&
|
|||
CMDLINE_PROPS_UPDATE("vcenter", PropType::Display_VCenter);
|
||||
CMDLINE_PROPS_UPDATE("pp", PropType::Display_Phosphor);
|
||||
CMDLINE_PROPS_UPDATE("ppblend", PropType::Display_PPBlend);
|
||||
CMDLINE_PROPS_UPDATE("pxcenter", PropType::Controller_PaddlesXCenter);
|
||||
CMDLINE_PROPS_UPDATE("pycenter", PropType::Controller_PaddlesYCenter);
|
||||
|
||||
// Finally, create the cart with the correct properties
|
||||
if(cart)
|
||||
|
|
|
@ -270,6 +270,13 @@ class OSystem
|
|||
const string& cheatFile() const { return myCheatFile; }
|
||||
#endif
|
||||
|
||||
#ifdef DEBUGGER_SUPPORT
|
||||
/**
|
||||
Return the full/complete directory name for storing Distella cfg files.
|
||||
*/
|
||||
const string& cfgDir() const { return myCfgDir; }
|
||||
#endif
|
||||
|
||||
#ifdef PNG_SUPPORT
|
||||
/**
|
||||
Return the full/complete directory name for saving and loading
|
||||
|
@ -529,6 +536,7 @@ class OSystem
|
|||
string mySnapshotSaveDir;
|
||||
string mySnapshotLoadDir;
|
||||
string myNVRamDir;
|
||||
string myCfgDir;
|
||||
string myDefaultSaveDir;
|
||||
string myDefaultLoadDir;
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue