mirror of https://github.com/stella-emu/stella.git
Added SB scheme to the debugger ROM tab.
Improved keyboard and mouse navigation for PopupWidget and associated ContextMenu dialogs. Tweaked bankswitch autodetection for 29K ROMs; the only possibilities are ARM (FA2) or DPC+. git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@2692 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
parent
2872b6be03
commit
b97b643d17
|
@ -15,6 +15,11 @@
|
|||
3.8.1 to 3.9: (XXXXX xxx, 2013)
|
||||
|
||||
* Greatly extended functionality of the debugger disassembly:
|
||||
- There is now a new tab which lists information specific to the
|
||||
cartridge bankswitching scheme in use. This includes the ability
|
||||
to modify internal state even for esoteric ROMs which don't
|
||||
follow the standard layout of 4K per bank.
|
||||
|
||||
- The debugger now generates DASM-compatible disassembled code,
|
||||
which can be saved to an external file. This disassembly is
|
||||
based on both a static and runtime analysis, and is extremely
|
||||
|
@ -46,6 +51,10 @@
|
|||
match the one used for line selection. This makes it easier to
|
||||
see for those with problems seeing lighter colours.
|
||||
|
||||
* Improved functionality of the various pop-up dialogs and context
|
||||
menus in the UI; they can now be navigated more fully by the keyboard
|
||||
and mouse.
|
||||
|
||||
* Updated included PNG library to latest stable version.
|
||||
|
||||
-Have fun!
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
//============================================================================
|
||||
//
|
||||
// SSSS tt lll lll
|
||||
// SS SS tt ll ll
|
||||
// SS tttttt eeee ll ll aaaa
|
||||
// SSSS tt ee ee ll ll aa
|
||||
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
|
||||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2013 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//
|
||||
// $Id$
|
||||
//============================================================================
|
||||
|
||||
#include "CartSB.hxx"
|
||||
#include "PopUpWidget.hxx"
|
||||
#include "CartSBWidget.hxx"
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
CartridgeSBWidget::CartridgeSBWidget(
|
||||
GuiObject* boss, const GUI::Font& font,
|
||||
int x, int y, int w, int h, CartridgeSB& cart)
|
||||
: CartDebugWidget(boss, font, x, y, w, h),
|
||||
myCart(cart)
|
||||
{
|
||||
uInt32 size = myCart.mySize;
|
||||
|
||||
StringMap items;
|
||||
ostringstream info, bank;
|
||||
info << "SB SUPERbanking, 32 or 64 4K banks\n"
|
||||
<< "Hotspots are from $800 to $"
|
||||
<< HEX2 << (0x800 + myCart.bankCount() - 1) << ", including\n"
|
||||
<< "mirrors ($900, $A00, $B00, ...)\n"
|
||||
<< "Startup bank = " << dec << cart.myStartBank << "\n";
|
||||
|
||||
// Eventually, we should query this from the debugger/disassembler
|
||||
for(uInt32 i = 0, offset = 0xFFC, spot = 0x800; i < myCart.bankCount();
|
||||
++i, offset += 0x1000, ++spot)
|
||||
{
|
||||
uInt16 start = (cart.myImage[offset+1] << 8) | cart.myImage[offset];
|
||||
start -= start % 0x1000;
|
||||
info << "Bank " << dec << i << " @ $" << HEX4 << start << " - "
|
||||
<< "$" << (start + 0xFFF) << " (hotspot = $" << spot << ")\n";
|
||||
|
||||
bank << dec << setw(2) << setfill(' ') << i << " ($" << HEX2 << spot << ")";
|
||||
items.push_back(bank.str(), BSPF_toString(i));
|
||||
bank.str("");
|
||||
}
|
||||
|
||||
int xpos = 10,
|
||||
ypos = addBaseInformation(size, "Fred X. Quimby", info.str()) + myLineHeight;
|
||||
|
||||
myBank =
|
||||
new PopUpWidget(boss, font, xpos, ypos-2, font.getStringWidth("XX ($800) "),
|
||||
myLineHeight, items, "Set bank: ",
|
||||
font.getStringWidth("Set bank: "), kBankChanged);
|
||||
myBank->setTarget(this);
|
||||
addFocusWidget(myBank);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeSBWidget::loadConfig()
|
||||
{
|
||||
myBank->setSelected(myCart.myCurrentBank);
|
||||
|
||||
CartDebugWidget::loadConfig();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartridgeSBWidget::handleCommand(CommandSender* sender,
|
||||
int cmd, int data, int id)
|
||||
{
|
||||
if(cmd == kBankChanged)
|
||||
{
|
||||
myCart.unlockBank();
|
||||
myCart.bank(myBank->getSelected());
|
||||
myCart.lockBank();
|
||||
invalidate();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
//============================================================================
|
||||
//
|
||||
// SSSS tt lll lll
|
||||
// SS SS tt ll ll
|
||||
// SS tttttt eeee ll ll aaaa
|
||||
// SSSS tt ee ee ll ll aa
|
||||
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
|
||||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2013 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//
|
||||
// $Id$
|
||||
//============================================================================
|
||||
|
||||
#ifndef CARTRIDGESB_WIDGET_HXX
|
||||
#define CARTRIDGESB_WIDGET_HXX
|
||||
|
||||
class CartridgeSB;
|
||||
class PopUpWidget;
|
||||
|
||||
#include "CartDebugWidget.hxx"
|
||||
|
||||
class CartridgeSBWidget : public CartDebugWidget
|
||||
{
|
||||
public:
|
||||
CartridgeSBWidget(GuiObject* boss, const GUI::Font& font,
|
||||
int x, int y, int w, int h,
|
||||
CartridgeSB& cart);
|
||||
virtual ~CartridgeSBWidget() { }
|
||||
|
||||
void loadConfig();
|
||||
void handleCommand(CommandSender* sender, int cmd, int data, int id);
|
||||
|
||||
private:
|
||||
CartridgeSB& myCart;
|
||||
PopUpWidget* myBank;
|
||||
|
||||
enum { kBankChanged = 'bkCH' };
|
||||
};
|
||||
|
||||
#endif
|
|
@ -37,6 +37,7 @@ MODULE_OBJS := \
|
|||
src/debugger/gui/CartF4SCWidget.o \
|
||||
src/debugger/gui/CartF6SCWidget.o \
|
||||
src/debugger/gui/CartF8SCWidget.o \
|
||||
src/debugger/gui/CartSBWidget.o \
|
||||
src/debugger/gui/CartUAWidget.o \
|
||||
src/debugger/gui/CartX07Widget.o \
|
||||
src/debugger/gui/JoystickWidget.o \
|
||||
|
|
|
@ -430,12 +430,10 @@ string Cartridge::autodetectType(const uInt8* image, uInt32 size)
|
|||
}
|
||||
else if(size == 29*1024) // 29K
|
||||
{
|
||||
if(isProbablyDPCplus(image, size))
|
||||
type = "DPC+";
|
||||
else if(isProbablyARM(image, size))
|
||||
if(isProbablyARM(image, size))
|
||||
type = "FA2";
|
||||
else
|
||||
type = "4K"; // probably a bad ROM
|
||||
else /*if(isProbablyDPCplus(image, size))*/
|
||||
type = "DPC+";
|
||||
}
|
||||
else if(size == 32*1024) // 32K
|
||||
{
|
||||
|
|
|
@ -37,7 +37,7 @@ CartridgeSB::CartridgeSB(const uInt8* image, uInt32 size,
|
|||
createCodeAccessBase(mySize);
|
||||
|
||||
// Remember startup bank
|
||||
myStartBank = (mySize >> 12) - 1;
|
||||
myStartBank = bankCount() - 1;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -87,7 +87,7 @@ void CartridgeSB::install(System& system)
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt8 CartridgeSB::peek(uInt16 address)
|
||||
{
|
||||
address = address & (0x17FF + (mySize >> 12));
|
||||
address &= (0x17FF + (mySize >> 12));
|
||||
|
||||
// Switch banks if necessary
|
||||
if ((address & 0x1800) == 0x0800)
|
||||
|
@ -107,7 +107,7 @@ uInt8 CartridgeSB::peek(uInt16 address)
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartridgeSB::poke(uInt16 address, uInt8 value)
|
||||
{
|
||||
address = address & (0x17FF + (mySize >> 12));
|
||||
address &= (0x17FF + (mySize >> 12));
|
||||
|
||||
// Switch banks if necessary
|
||||
if((address & 0x1800) == 0x0800)
|
||||
|
|
|
@ -23,15 +23,22 @@
|
|||
#include "bspf.hxx"
|
||||
#include "Cart.hxx"
|
||||
#include "System.hxx"
|
||||
#ifdef DEBUGGER_SUPPORT
|
||||
#include "CartSBWidget.hxx"
|
||||
#endif
|
||||
|
||||
/**
|
||||
Cartridge class used for SB "SUPERbanking" 128k-256k bankswitched games.
|
||||
There are either 32 or 64 4K banks.
|
||||
There are either 32 or 64 4K banks, accessible at hotspots $800 - $81F
|
||||
(32 banks) and $800 - $83F (64 banks). All mirrors up to $FFF are
|
||||
also used ($900, $A00, ...).
|
||||
|
||||
@author Fred X. Quimby
|
||||
*/
|
||||
class CartridgeSB : public Cartridge
|
||||
{
|
||||
friend class CartridgeSBWidget;
|
||||
|
||||
public:
|
||||
/**
|
||||
Create a new cartridge using the specified image
|
||||
|
@ -118,6 +125,18 @@ class CartridgeSB : public Cartridge
|
|||
*/
|
||||
string name() const { return "CartridgeSB"; }
|
||||
|
||||
#ifdef DEBUGGER_SUPPORT
|
||||
/**
|
||||
Get debugger widget responsible for accessing the inner workings
|
||||
of the cart.
|
||||
*/
|
||||
CartDebugWidget* debugWidget(GuiObject* boss,
|
||||
const GUI::Font& font, int x, int y, int w, int h)
|
||||
{
|
||||
return new CartridgeSBWidget(boss, font, x, y, w, h, *this);
|
||||
}
|
||||
#endif
|
||||
|
||||
public:
|
||||
/**
|
||||
Get the byte at the specified address.
|
||||
|
|
|
@ -88,6 +88,7 @@ void ContextMenu::show(uInt32 x, uInt32 y, int item)
|
|||
recalc(instance().frameBuffer().imageRect());
|
||||
parent().addDialog(this);
|
||||
setSelected(item);
|
||||
moveToSelected();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -194,6 +195,50 @@ const string& ContextMenu::getSelectedTag() const
|
|||
return (_selectedItem >= 0) ? _entries[_selectedItem].second : EmptyString;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool ContextMenu::sendSelectionUp()
|
||||
{
|
||||
if(isVisible() || _selectedItem <= 0)
|
||||
return false;
|
||||
|
||||
_selectedItem--;
|
||||
sendCommand(_cmd ? _cmd : kCMenuItemSelectedCmd, _selectedItem, -1);
|
||||
return true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool ContextMenu::sendSelectionDown()
|
||||
{
|
||||
if(isVisible() || _selectedItem >= (int)_entries.size() - 1)
|
||||
return false;
|
||||
|
||||
_selectedItem++;
|
||||
sendCommand(_cmd ? _cmd : kCMenuItemSelectedCmd, _selectedItem, -1);
|
||||
return true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool ContextMenu::sendSelectionFirst()
|
||||
{
|
||||
if(isVisible())
|
||||
return false;
|
||||
|
||||
_selectedItem = 0;
|
||||
sendCommand(_cmd ? _cmd : kCMenuItemSelectedCmd, _selectedItem, -1);
|
||||
return true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool ContextMenu::sendSelectionLast()
|
||||
{
|
||||
if(isVisible())
|
||||
return false;
|
||||
|
||||
_selectedItem = _entries.size() - 1;
|
||||
sendCommand(_cmd ? _cmd : kCMenuItemSelectedCmd, _selectedItem, -1);
|
||||
return true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void ContextMenu::handleMouseDown(int x, int y, int button, int clickCount)
|
||||
{
|
||||
|
@ -287,6 +332,18 @@ void ContextMenu::handleEvent(Event::Type e)
|
|||
case Event::UIRight:
|
||||
moveDown();
|
||||
break;
|
||||
case Event::UIPgUp:
|
||||
movePgUp();
|
||||
break;
|
||||
case Event::UIPgDown:
|
||||
movePgDown();
|
||||
break;
|
||||
case Event::UIHome:
|
||||
moveToFirst();
|
||||
break;
|
||||
case Event::UIEnd:
|
||||
moveToLast();
|
||||
break;
|
||||
case Event::UICancel:
|
||||
close();
|
||||
break;
|
||||
|
@ -382,6 +439,69 @@ void ContextMenu::moveDown()
|
|||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void ContextMenu::movePgUp()
|
||||
{
|
||||
if(_firstEntry == 0)
|
||||
moveToFirst();
|
||||
else
|
||||
scrollUp(_numEntries);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void ContextMenu::movePgDown()
|
||||
{
|
||||
if(_firstEntry == (int)(_entries.size() - _numEntries))
|
||||
moveToLast();
|
||||
else
|
||||
scrollDown(_numEntries);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void ContextMenu::moveToFirst()
|
||||
{
|
||||
_firstEntry = 0;
|
||||
_scrollUpColor = kColor;
|
||||
_scrollDnColor = kScrollColor;
|
||||
|
||||
drawCurrentSelection(_firstEntry + (_showScroll ? 1 : 0));
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void ContextMenu::moveToLast()
|
||||
{
|
||||
_firstEntry = _entries.size() - _numEntries;
|
||||
_scrollUpColor = kScrollColor;
|
||||
_scrollDnColor = kColor;
|
||||
|
||||
drawCurrentSelection(_numEntries - (_showScroll ? 0 : 1));
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void ContextMenu::moveToSelected()
|
||||
{
|
||||
if(_selectedItem < 0 || _selectedItem >= (int)_entries.size())
|
||||
return;
|
||||
|
||||
// First jump immediately to the item
|
||||
_firstEntry = _selectedItem;
|
||||
int offset = 0;
|
||||
|
||||
// Now check if we've gone past the current 'window' size, and scale
|
||||
// back accordingly
|
||||
int max_offset = _entries.size() - _numEntries;
|
||||
if(_firstEntry > max_offset)
|
||||
{
|
||||
offset = _firstEntry - max_offset;
|
||||
_firstEntry -= offset;
|
||||
}
|
||||
|
||||
_scrollUpColor = _firstEntry > 0 ? kScrollColor : kColor;
|
||||
_scrollDnColor = _firstEntry < max_offset ? kScrollColor : kColor;
|
||||
|
||||
drawCurrentSelection(offset + (_showScroll ? 1 : 0));
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void ContextMenu::scrollUp(int distance)
|
||||
{
|
||||
|
@ -404,7 +524,7 @@ void ContextMenu::scrollDown(int distance)
|
|||
|
||||
_firstEntry = BSPF_min(_firstEntry + distance, max_offset);
|
||||
_scrollUpColor = kScrollColor;
|
||||
_scrollDnColor = (_firstEntry < max_offset) ? kScrollColor : kColor;
|
||||
_scrollDnColor = _firstEntry < max_offset ? kScrollColor : kColor;
|
||||
|
||||
setDirty();
|
||||
}
|
||||
|
|
|
@ -37,6 +37,9 @@ enum {
|
|||
*
|
||||
* Implementation wise, when the user selects an item, then the given 'cmd'
|
||||
* is broadcast, with data being equal to the tag value of the selected entry.
|
||||
*
|
||||
* There are also several utility methods (named as sendSelectionXXX) that
|
||||
* allow to cycle through the current items without actually opening the dialog.
|
||||
*/
|
||||
class ContextMenu : public Dialog, public CommandSender
|
||||
{
|
||||
|
@ -71,6 +74,16 @@ class ContextMenu : public Dialog, public CommandSender
|
|||
/** This dialog uses its own positioning, so we override Dialog::center() */
|
||||
void center();
|
||||
|
||||
/** The following methods are used when we want to select *and*
|
||||
send a command for the new selection. They are only to be used
|
||||
when the dialog *isn't* open, and are basically a shortcut so
|
||||
that a PopUpWidget has some basic functionality without forcing
|
||||
to open its associated ContextMenu. */
|
||||
bool sendSelectionUp();
|
||||
bool sendSelectionDown();
|
||||
bool sendSelectionFirst();
|
||||
bool sendSelectionLast();
|
||||
|
||||
protected:
|
||||
void handleMouseDown(int x, int y, int button, int clickCount);
|
||||
void handleMouseMoved(int x, int y, int button);
|
||||
|
@ -92,6 +105,11 @@ class ContextMenu : public Dialog, public CommandSender
|
|||
|
||||
void moveUp();
|
||||
void moveDown();
|
||||
void movePgUp();
|
||||
void movePgDown();
|
||||
void moveToFirst();
|
||||
void moveToLast();
|
||||
void moveToSelected();
|
||||
void scrollUp(int distance = 1);
|
||||
void scrollDown(int distance = 1);
|
||||
void sendSelection();
|
||||
|
|
|
@ -91,6 +91,18 @@ void PopUpWidget::handleMouseDown(int x, int y, int button, int clickCount)
|
|||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void PopUpWidget::handleMouseWheel(int x, int y, int direction)
|
||||
{
|
||||
if(isEnabled() && !myMenu->isVisible())
|
||||
{
|
||||
if(direction < 0)
|
||||
myMenu->sendSelectionUp();
|
||||
else
|
||||
myMenu->sendSelectionDown();
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool PopUpWidget::handleEvent(Event::Type e)
|
||||
{
|
||||
|
@ -102,6 +114,18 @@ bool PopUpWidget::handleEvent(Event::Type e)
|
|||
case Event::UISelect:
|
||||
handleMouseDown(0, 0, 1, 0);
|
||||
return true;
|
||||
case Event::UIUp:
|
||||
case Event::UILeft:
|
||||
case Event::UIPgUp:
|
||||
return myMenu->sendSelectionUp();
|
||||
case Event::UIDown:
|
||||
case Event::UIRight:
|
||||
case Event::UIPgDown:
|
||||
return myMenu->sendSelectionDown();
|
||||
case Event::UIHome:
|
||||
return myMenu->sendSelectionFirst();
|
||||
case Event::UIEnd:
|
||||
return myMenu->sendSelectionLast();
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -68,6 +68,7 @@ class PopUpWidget : public Widget, public CommandSender
|
|||
|
||||
protected:
|
||||
void handleMouseDown(int x, int y, int button, int clickCount);
|
||||
void handleMouseWheel(int x, int y, int direction);
|
||||
bool handleEvent(Event::Type e);
|
||||
void handleCommand(CommandSender* sender, int cmd, int data, int id);
|
||||
void drawWidget(bool hilite);
|
||||
|
|
Loading…
Reference in New Issue