Cleaned up the DebuggerParser class in preparation for user-interrupible

commands.  It's not quite working right now.

Added preliminary GP2X framebuffer class, so the GP2X can optimize
for that system.  It's based on FrameBufferSoft, and doesn't really
do much differently right now.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1167 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2006-12-02 23:25:55 +00:00
parent 78f33efe78
commit 8ef6d7032e
14 changed files with 2462 additions and 1514 deletions

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: Debugger.cxx,v 1.104 2005-10-27 19:15:14 stephena Exp $
// $Id: Debugger.cxx,v 1.105 2006-12-02 23:25:53 stephena Exp $
//============================================================================
#include "bspf.hxx"
@ -334,6 +334,12 @@ const string Debugger::run(const string& command)
return myParser->run(command);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Debugger::cancel()
{
myParser->cancel();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const string Debugger::valueToString(int value, BaseFormat outputBase)
{

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: Debugger.hxx,v 1.82 2005-10-22 15:43:16 stephena Exp $
// $Id: Debugger.hxx,v 1.83 2006-12-02 23:25:53 stephena Exp $
//============================================================================
#ifndef DEBUGGER_HXX
@ -79,7 +79,7 @@ typedef uInt16 (Debugger::*DEBUGGER_WORD_METHOD)();
for all debugging operations in Stella (parser, 6502 debugger, etc).
@author Stephen Anthony
@version $Id: Debugger.hxx,v 1.82 2005-10-22 15:43:16 stephena Exp $
@version $Id: Debugger.hxx,v 1.83 2006-12-02 23:25:53 stephena Exp $
*/
class Debugger : public DialogContainer
{
@ -169,6 +169,11 @@ class Debugger : public DialogContainer
*/
const string run(const string& command);
/**
Cancel the currently running debugger command.
*/
void cancel();
/**
Give the contents of the CPU registers and disassembly of
next instruction.
@ -211,46 +216,49 @@ class Debugger : public DialogContainer
{ return myParser->decipher_arg(stringval); }
const string valueToString(int value, BaseFormat outputBase = kBASE_DEFAULT);
/** Convenience methods to convert to hexidecimal values */
static char *to_hex_4(int i)
/** Convenience methods to convert to/from base values */
static char* to_hex_4(int i)
{
static char out[2];
sprintf(out, "%1x", i);
return out;
}
static char *to_hex_8(int i)
static char* to_hex_8(int i)
{
static char out[3];
sprintf(out, "%02x", i);
return out;
}
static char *to_hex_16(int i)
static char* to_hex_16(int i)
{
static char out[5];
sprintf(out, "%04x", i);
return out;
}
static char *to_bin(int dec, int places, char *buf) {
static char* to_bin(int dec, int places, char *buf) {
int bit = 1;
buf[places] = '\0';
while(--places >= 0) {
if(dec & bit)
buf[places] = '1';
else
buf[places] = '0';
if(dec & bit) buf[places] = '1';
else buf[places] = '0';
bit <<= 1;
}
return buf;
}
static char *to_bin_8(int dec) {
static char* to_bin_8(int dec) {
static char buf[9];
return to_bin(dec, 8, buf);
}
static char *to_bin_16(int dec) {
static char* to_bin_16(int dec) {
static char buf[17];
return to_bin(dec, 16, buf);
}
static int conv_hex_digit(char d) {
if(d >= '0' && d <= '9') return d - '0';
else if(d >= 'a' && d <= 'f') return d - 'a' + 10;
else if(d >= 'A' && d <= 'F') return d - 'A' + 10;
else return -1;
}
/**
This is used when we want the debugger from a class that can't

File diff suppressed because it is too large Load Diff

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: DebuggerParser.hxx,v 1.43 2005-11-11 21:44:19 stephena Exp $
// $Id: DebuggerParser.hxx,v 1.44 2006-12-02 23:25:53 stephena Exp $
//============================================================================
#ifndef DEBUGGER_PARSER_HXX
@ -39,76 +39,116 @@ class DebuggerParser
DebuggerParser(Debugger* debugger);
~DebuggerParser();
/** Run the given command, and return the result */
string run(const string& command);
int decipher_arg(const string &str);
void setBase(BaseFormat base) { defaultBase = base; }
BaseFormat base() { return defaultBase; }
/** Cancel the currently running command, if any */
void cancel();
string showWatches();
string addWatch(string watch);
string delWatch(int which);
void delAllWatches();
/** Execute parser commands given in 'file' */
string exec(const string& file, bool verbose = true);
/** Given a substring, determine matching substrings from the list
of available commands. Used in the debugger prompt for tab-completion */
int countCompletions(const char *in);
const char *getCompletions();
const char *getCompletionPrefix();
string exec(const string& cmd, bool verbose=true);
static inline string red(string msg ="")
/** Evaluate the given expression using operators, current base, etc */
int decipher_arg(const string &str);
/** String representation of all watches currently defined */
string showWatches();
/** Get/set the number base when parsing numeric values */
void setBase(BaseFormat base) { defaultBase = base; }
BaseFormat base() { return defaultBase; }
static inline string red(const string& msg = "")
{
// This is TIA color 0x34. The octal value is 0x80+(0x34>>1).
return "\232" + msg;
}
static inline string inverse(string msg ="")
static inline string inverse(const string& msg = "")
{
// ASCII DEL char, decimal 127
return "\177" + msg;
}
private:
bool getArgs(const string& command);
bool getArgs(const string& command, string& verb);
bool validateArgs(int cmd);
int conv_hex_digit(char d);
bool subStringMatch(const string& needle, const string& haystack);
string disasm();
string listBreaks();
string listTraps();
string eval();
string dump();
string trapStatus(int addr);
bool saveScriptFile(string file);
private:
enum {
kNumCommands = 59,
kMAX_ARG_TYPES = 10 // TODO: put in separate header file Command.hxx
};
// Constants for argument processing
enum {
kIN_COMMAND,
kIN_SPACE,
kIN_BRACE,
kIN_ARG
};
typedef enum {
kARG_WORD, // single 16-bit value
kARG_MULTI_WORD, // multiple 16-bit values (must occur last)
kARG_BYTE, // single 8-bit value
kARG_MULTI_BYTE, // multiple 8-bit values (must occur last)
kARG_BOOL, // 0 or 1 only
kARG_LABEL, // label (need not be defined, treated as string)
kARG_FILE, // filename
kARG_BASE_SPCL, // base specifier: 2, 10, or 16 (or "bin" "dec" "hex")
kARG_END_ARGS // sentinel, occurs at end of list
} parameters;
// Pointer to DebuggerParser instance method, no args, returns void.
typedef void (DebuggerParser::*METHOD)();
struct Command {
string cmdString;
string description;
bool parmsRequired;
bool refreshRequired;
parameters parms[kMAX_ARG_TYPES];
METHOD executor;
};
// Pointer to our debugger object
Debugger* debugger;
bool done;
// Flag indicating whether a currently running command should be cancelled
bool cancelCommand;
string verb;
// The results of the currently running command
string commandResult;
// Arguments in 'int' and 'string' format for the currently running command
IntArray args;
StringList argStrings;
int argCount;
BaseFormat defaultBase;
StringList watches;
static Command commands[];
// Used in 'tab-completion', holds list of commands related to a substring
string completions;
string compPrefix;
bool saveScriptFile(string file);
// List of available command methods
void executeA();
void executeBank();
void executeBase();
void executeBreak();
void executeBreakif();
void executeC();
#ifdef CHEATCODE_SUPPORT
void executeCheat();
#endif
void executeClearbreaks();
void executeCleartraps();
void executeClearwatches();
@ -129,12 +169,12 @@ class DebuggerParser
void executeListtraps();
void executeListwatches();
void executeLoadlist();
void executeLoadsym();
void executeLoadstate();
void executeLoadsym();
void executeN();
void executePc();
void executePrint();
void executeRam();
void executeRam(); // also implements 'poke' command
void executeReload();
void executeReset();
void executeRiot();
@ -160,38 +200,9 @@ class DebuggerParser
void executeX();
void executeY();
void executeZ();
};
// TODO: put in separate header file Command.hxx
#define kMAX_ARG_TYPES 10
// These next two deserve English explanations:
// pointer to DebuggerParser instance method, no args, returns void.
typedef void (DebuggerParser::*METHOD)();
// call the pointed-to method on the this object. Whew.
#define CALL_METHOD(method) ( (this->*method)() )
typedef enum {
kARG_WORD, // single 16-bit value
kARG_MULTI_WORD, // multiple 16-bit values (must occur last)
kARG_BYTE, // single 8-bit value
kARG_MULTI_BYTE, // multiple 8-bit values (must occur last)
kARG_BOOL, // 0 or 1 only
kARG_LABEL, // label (need not be defined, treated as string)
kARG_FILE, // filename
kARG_BASE_SPCL, // base specifier: 2, 10, or 16 (or "bin" "dec" "hex")
kARG_END_ARGS // sentinel, occurs at end of list
} parameters;
struct Command {
string cmdString;
string description;
bool parmsRequired;
bool refreshRequired;
parameters parms[kMAX_ARG_TYPES];
METHOD executor;
// List of commands available
static Command commands[kNumCommands];
};
#endif

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: PromptWidget.cxx,v 1.9 2006-05-04 17:45:24 stephena Exp $
// $Id: PromptWidget.cxx,v 1.10 2006-12-02 23:25:53 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
@ -529,6 +529,11 @@ void PromptWidget::specialKeys(int keycode)
handled = true;
break;
case 'c':
cancelLastCommand();
handled = true;
break;
case 'd':
killChar(+1);
handled = true;
@ -638,6 +643,12 @@ void PromptWidget::killLastWord()
_promptEndPos -= cnt;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PromptWidget::cancelLastCommand()
{
instance()->debugger().cancel();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PromptWidget::addToHistory(const char *str)
{

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: PromptWidget.hxx,v 1.5 2006-03-25 00:34:17 stephena Exp $
// $Id: PromptWidget.hxx,v 1.6 2006-12-02 23:25:53 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
@ -70,6 +70,7 @@ class PromptWidget : public Widget, public CommandSender
void killChar(int direction);
void killLine(int direction);
void killLastWord();
void cancelLastCommand();
// History
void addToHistory(const char *str);

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: EventHandler.cxx,v 1.177 2006-12-02 00:43:50 stephena Exp $
// $Id: EventHandler.cxx,v 1.178 2006-12-02 23:25:53 stephena Exp $
//============================================================================
#include <sstream>
@ -1523,8 +1523,9 @@ void EventHandler::setJoyHatMap()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool EventHandler::addKeyMapping(Event::Type event, EventMode mode, int key)
{
// These keys cannot be remapped.
if(key == SDLK_TAB || eventIsAnalog(event))
// These keys cannot be remapped
if(key == SDLK_TAB || (key > SDLK_F15 && key < SDLK_HELP) ||
eventIsAnalog(event))
return false;
else
{

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: FrameBuffer.cxx,v 1.101 2006-12-02 00:43:50 stephena Exp $
// $Id: FrameBuffer.cxx,v 1.102 2006-12-02 23:25:54 stephena Exp $
//============================================================================
#include <sstream>
@ -426,13 +426,8 @@ void FrameBuffer::setCursorState()
case EventHandler::S_EMULATE:
showCursor(false);
break;
default:
#if !defined(GP2X)
showCursor(true);
#else
showCursor(false);
#endif
}
}

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: FrameBuffer.hxx,v 1.75 2006-11-18 13:29:11 stephena Exp $
// $Id: FrameBuffer.hxx,v 1.76 2006-12-02 23:25:54 stephena Exp $
//============================================================================
#ifndef FRAMEBUFFER_HXX
@ -96,7 +96,7 @@ struct Scaler {
All GUI elements (ala ScummVM) are drawn here as well.
@author Stephen Anthony
@version $Id: FrameBuffer.hxx,v 1.75 2006-11-18 13:29:11 stephena Exp $
@version $Id: FrameBuffer.hxx,v 1.76 2006-12-02 23:25:54 stephena Exp $
*/
class FrameBuffer
{
@ -223,7 +223,7 @@ class FrameBuffer
/**
Shows or hides the cursor based on the given boolean value.
*/
void showCursor(bool show);
virtual void showCursor(bool show);
/**
Grabs or ungrabs the mouse based on the given boolean value.

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: MediaFactory.cxx,v 1.4 2006-02-05 19:59:22 stephena Exp $
// $Id: MediaFactory.cxx,v 1.5 2006-12-02 23:25:54 stephena Exp $
//============================================================================
////////////////////////////////////////////////////////////////////
@ -25,15 +25,18 @@
#include "OSystem.hxx"
#include "FrameBuffer.hxx"
#include "FrameBufferSoft.hxx"
#ifdef DISPLAY_OPENGL
#include "FrameBufferGL.hxx"
#endif
#if defined(PSP)
#if defined(GP2X)
#include "FrameBufferGP2X.hxx"
#elif defined(PSP)
#include "FrameBufferPSP.hxx"
#elif defined (_WIN32_WCE)
#include "FrameBufferWinCE.hxx"
#else
#include "FrameBufferSoft.hxx"
#endif
#include "Sound.hxx"
@ -65,7 +68,9 @@ FrameBuffer* MediaFactory::createVideo(OSystem* osystem)
// software framebuffer
if(!fb)
{
#if defined (PSP)
#if defined (GP2X)
fb = new FrameBufferGP2X(osystem);
#elif defined (PSP)
fb = new FrameBufferPSP(osystem);
#elif defined (_WIN32_WCE)
fb = new FrameBufferWinCE(osystem);

View File

@ -0,0 +1,559 @@
//============================================================================
//
// 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-2005 by Bradford W. Mott and the Stella team
//
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: FrameBufferGP2X.cxx,v 1.1 2006-12-02 23:25:54 stephena Exp $
//============================================================================
#include <SDL.h>
#include <SDL_syswm.h>
#include <sstream>
#include "Console.hxx"
#include "FrameBuffer.hxx"
#include "FrameBufferGP2X.hxx"
#include "MediaSrc.hxx"
#include "Settings.hxx"
#include "OSystem.hxx"
#include "Font.hxx"
#include "GuiUtils.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FrameBufferGP2X::FrameBufferGP2X(OSystem* osystem)
: FrameBuffer(osystem),
myRectList(NULL),
myOverlayRectList(NULL)
{
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FrameBufferGP2X::~FrameBufferGP2X()
{
delete myRectList;
delete myOverlayRectList;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FrameBufferGP2X::initSubsystem()
{
// Set up the rectangle list to be used in the dirty update
delete myRectList;
myRectList = new RectList();
delete myOverlayRectList;
myOverlayRectList = new RectList();
if(!myRectList || !myOverlayRectList)
{
cerr << "ERROR: Unable to get memory for SDL rects" << endl;
return false;
}
// Create the screen
return createScreen();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferGP2X::setAspectRatio()
{
// Aspect ratio correction not yet available in software mode
theAspectRatio = 1.0;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferGP2X::setScaler(Scaler scaler)
{
// Not supported, we always use 1x zoom
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FrameBufferGP2X::createScreen()
{
myScreenDim.x = myScreenDim.y = 0;
myScreenDim.w = myBaseDim.w;
myScreenDim.h = myBaseDim.h;
// In software mode, the image and screen dimensions are always the same
myImageDim = myScreenDim;
myScreen = SDL_SetVideoMode(myScreenDim.w, myScreenDim.h, 16, mySDLFlags);
if(myScreen == NULL)
{
cerr << "ERROR: Unable to open SDL window: " << SDL_GetError() << endl;
return false;
}
// Erase old rects, since they've probably been scaled for
// a different sized screen
myRectList->start();
myOverlayRectList->start();
return true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferGP2X::drawMediaSource()
{
MediaSource& mediasrc = myOSystem->console().mediaSource();
uInt8* currentFrame = mediasrc.currentFrameBuffer();
uInt8* previousFrame = mediasrc.previousFrameBuffer();
uInt16 screenMultiple = 1; // remove this, and everything that refers to it
uInt32 width = mediasrc.width();
uInt32 height = mediasrc.height();
// switch((int)myRenderType) // use switch/case, since we'll eventually have filters
// {
if(!myUsePhosphor)
{
struct Rectangle
{
uInt8 color;
uInt16 x, y, width, height;
} rectangles[2][160];
// This array represents the rectangles that need displaying
// on the current scanline we're processing
Rectangle* currentRectangles = rectangles[0];
// This array represents the rectangles that are still active
// from the previous scanlines we have processed
Rectangle* activeRectangles = rectangles[1];
// Indicates the number of active rectangles
uInt16 activeCount = 0;
// This update procedure requires theWidth to be a multiple of four.
// This is validated when the properties are loaded.
for(uInt16 y = 0; y < height; ++y)
{
// Indicates the number of current rectangles
uInt16 currentCount = 0;
// Look at four pixels at a time to see if anything has changed
uInt32* current = (uInt32*)(currentFrame);
uInt32* previous = (uInt32*)(previousFrame);
for(uInt16 x = 0; x < width; x += 4, ++current, ++previous)
{
// Has something changed in this set of four pixels?
if((*current != *previous) || theRedrawTIAIndicator)
{
uInt8* c = (uInt8*)current;
uInt8* p = (uInt8*)previous;
// Look at each of the bytes that make up the uInt32
for(uInt16 i = 0; i < 4; ++i, ++c, ++p)
{
// See if this pixel has changed
if((*c != *p) || theRedrawTIAIndicator)
{
// Can we extend a rectangle or do we have to create a new one?
if((currentCount != 0) &&
(currentRectangles[currentCount - 1].color == *c) &&
((currentRectangles[currentCount - 1].x +
currentRectangles[currentCount - 1].width) == (x + i)))
{
currentRectangles[currentCount - 1].width += 1;
}
else
{
currentRectangles[currentCount].x = x + i;
currentRectangles[currentCount].y = y;
currentRectangles[currentCount].width = 1;
currentRectangles[currentCount].height = 1;
currentRectangles[currentCount].color = *c;
currentCount++;
}
}
}
}
}
// Merge the active and current rectangles flushing any that are of no use
uInt16 activeIndex = 0;
for(uInt16 t = 0; (t < currentCount) && (activeIndex < activeCount); ++t)
{
Rectangle& current = currentRectangles[t];
Rectangle& active = activeRectangles[activeIndex];
// Can we merge the current rectangle with an active one?
if((current.x == active.x) && (current.width == active.width) &&
(current.color == active.color))
{
current.y = active.y;
current.height = active.height + 1;
++activeIndex;
}
// Is it impossible for this active rectangle to be merged?
else if(current.x >= active.x)
{
// Flush the active rectangle
SDL_Rect temp;
temp.x = active.x * screenMultiple << 1;
temp.y = active.y * screenMultiple;
temp.w = active.width * screenMultiple << 1;
temp.h = active.height * screenMultiple;
myRectList->add(&temp);
SDL_FillRect(myScreen, &temp, myDefPalette[active.color]);
++activeIndex;
}
}
// Flush any remaining active rectangles
for(uInt16 s = activeIndex; s < activeCount; ++s)
{
Rectangle& active = activeRectangles[s];
SDL_Rect temp;
temp.x = active.x * screenMultiple << 1;
temp.y = active.y * screenMultiple;
temp.w = active.width * screenMultiple << 1;
temp.h = active.height * screenMultiple;
myRectList->add(&temp);
SDL_FillRect(myScreen, &temp, myDefPalette[active.color]);
}
// We can now make the current rectangles into the active rectangles
Rectangle* tmp = currentRectangles;
currentRectangles = activeRectangles;
activeRectangles = tmp;
activeCount = currentCount;
currentFrame += width;
previousFrame += width;
}
// Flush any rectangles that are still active
for(uInt16 t = 0; t < activeCount; ++t)
{
Rectangle& active = activeRectangles[t];
SDL_Rect temp;
temp.x = active.x * screenMultiple << 1;
temp.y = active.y * screenMultiple;
temp.w = active.width * screenMultiple << 1;
temp.h = active.height * screenMultiple;
myRectList->add(&temp);
SDL_FillRect(myScreen, &temp, myDefPalette[active.color]);
}
}
else
// case kPhosphor_16:
{
// Since phosphor mode updates the whole screen,
// we might as well use SDL_Flip (see postFrameUpdate)
myUseDirtyRects = false;
SDL_Rect temp;
temp.x = temp.y = temp.w = temp.h = 0;
myRectList->add(&temp);
uInt16* buffer = (uInt16*)myScreen->pixels;
uInt32 bufofsY = 0;
uInt32 screenofsY = 0;
for(uInt32 y = 0; y < height; ++y )
{
uInt32 ystride = 1; // optimize this away
while(ystride--)
{
uInt32 pos = screenofsY;
for(uInt32 x = 0; x < width; ++x )
{
const uInt32 bufofs = bufofsY + x;
uInt32 xstride = 1; // optimize this away
uInt8 v = currentFrame[bufofs];
uInt8 w = previousFrame[bufofs];
while(xstride--)
{
buffer[pos++] = (uInt16) myAvgPalette[v][w];
buffer[pos++] = (uInt16) myAvgPalette[v][w];
}
}
screenofsY += myPitch;
}
bufofsY += width;
}
}
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferGP2X::preFrameUpdate()
{
// Start a new rectlist on each display update
myRectList->start();
// Add all previous overlay rects, then erase
SDL_Rect* dirtyOverlayRects = myOverlayRectList->rects();
for(unsigned int i = 0; i < myOverlayRectList->numRects(); ++i)
myRectList->add(&dirtyOverlayRects[i]);
myOverlayRectList->start();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferGP2X::postFrameUpdate()
{
SDL_Flip(myScreen);
myRectList->start();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferGP2X::scanline(uInt32 row, uInt8* data)
{
// Make sure no pixels are being modified
SDL_LockSurface(myScreen);
uInt32 bpp = myScreen->format->BytesPerPixel;
uInt8* start = (uInt8*) myScreen->pixels;
uInt32 yoffset = row * myScreen->pitch;
uInt32 pixel = 0;
uInt8 *p, r, g, b;
for(Int32 x = 0; x < myScreen->w; x++)
{
p = (Uint8*) (start + // Start at top of RAM
(yoffset) + // Go down 'row' lines
(x * bpp)); // Go in 'x' pixels
pixel = *(Uint16*) p;
SDL_GetRGB(pixel, myScreen->format, &r, &g, &b);
data[x * 3 + 0] = r;
data[x * 3 + 1] = g;
data[x * 3 + 2] = b;
}
SDL_UnlockSurface(myScreen);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferGP2X::toggleFilter()
{
// Not supported
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferGP2X::hLine(uInt32 x, uInt32 y, uInt32 x2, int color)
{
SDL_Rect tmp;
// Horizontal line
tmp.x = x;
tmp.y = y;
tmp.w = (x2 - x + 1);
tmp.h = 1;
SDL_FillRect(myScreen, &tmp, myDefPalette[color]);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferGP2X::vLine(uInt32 x, uInt32 y, uInt32 y2, int color)
{
SDL_Rect tmp;
// Vertical line
tmp.x = x;
tmp.y = y;
tmp.w = 1;
tmp.h = (y2 - y + 1);
SDL_FillRect(myScreen, &tmp, myDefPalette[color]);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferGP2X::fillRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h,
int color)
{
SDL_Rect tmp;
// Fill the rectangle
tmp.x = x;
tmp.y = y;
tmp.w = w;
tmp.h = h;
SDL_FillRect(myScreen, &tmp, myDefPalette[color]);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferGP2X::drawChar(const GUI::Font* FONT, uInt8 chr,
uInt32 xorig, uInt32 yorig, int color)
{
GUI::Font* font = (GUI::Font*)FONT;
const FontDesc& desc = font->desc();
// If this character is not included in the font, use the default char.
if(chr < desc.firstchar || chr >= desc.firstchar + desc.size)
{
if (chr == ' ')
return;
chr = desc.defaultchar;
}
const Int32 w = font->getCharWidth(chr);
const Int32 h = font->getFontHeight();
chr -= desc.firstchar;
const uInt16* tmp = desc.bits + (desc.offset ? desc.offset[chr] : (chr * h));
SDL_Rect rect;
for(int y = 0; y < h; y++)
{
const uInt16 buffer = *tmp++;
uInt16 mask = 0x8000;
for(int x = 0; x < w; x++, mask >>= 1)
{
if ((buffer & mask) != 0)
{
rect.x = x + xorig;
rect.y = y + yorig;
rect.w = rect.h = 1;
SDL_FillRect(myScreen, &rect, myDefPalette[color]);
}
}
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferGP2X::drawBitmap(uInt32* bitmap, Int32 xorig, Int32 yorig,
int color, Int32 h)
{
SDL_Rect rect;
for(int y = 0; y < h; y++)
{
uInt32 mask = 0xF0000000;
for(int x = 0; x < 8; x++, mask >>= 4)
{
if(bitmap[y] & mask)
{
rect.x = x + xorig;
rect.y = y + yorig;
rect.w = rect.h = 1;
SDL_FillRect(myScreen, &rect, myDefPalette[color]);
}
}
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferGP2X::translateCoords(Int32* x, Int32* y)
{
// Coordinates don't change
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferGP2X::addDirtyRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h)
{
// Add a dirty rect to the overlay rectangle list
// They will actually be added to the main rectlist in preFrameUpdate()
// TODO - intelligent merging of rectangles, to avoid overlap
SDL_Rect temp;
temp.x = x;
temp.y = y;
temp.w = w;
temp.h = h;
myOverlayRectList->add(&temp);
// cerr << "addDirtyRect(): "
// << "x=" << temp.x << ", y=" << temp.y << ", w=" << temp.w << ", h=" << temp.h << endl;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferGP2X::enablePhosphor(bool enable, int blend)
{
myUsePhosphor = enable;
myPhosphorBlend = blend;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferGP2X::cls()
{
if(myScreen)
{
SDL_FillRect(myScreen, NULL, 0);
SDL_UpdateRect(myScreen, 0, 0, 0, 0);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferGP2X::showCursor(bool show)
{
// Never show the cursor
SDL_ShowCursor(SDL_DISABLE);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
RectList::RectList(Uint32 size)
{
currentSize = size;
currentRect = 0;
rectArray = new SDL_Rect[currentSize];
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
RectList::~RectList()
{
delete[] rectArray;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void RectList::add(SDL_Rect* newRect)
{
if(currentRect >= currentSize)
{
currentSize = currentSize * 2;
SDL_Rect *temp = new SDL_Rect[currentSize];
for(Uint32 i = 0; i < currentRect; ++i)
temp[i] = rectArray[i];
delete[] rectArray;
rectArray = temp;
}
rectArray[currentRect].x = newRect->x;
rectArray[currentRect].y = newRect->y;
rectArray[currentRect].w = newRect->w;
rectArray[currentRect].h = newRect->h;
++currentRect;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SDL_Rect* RectList::rects()
{
return rectArray;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Uint32 RectList::numRects()
{
return currentRect;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void RectList::start()
{
currentRect = 0;
}

View File

@ -0,0 +1,244 @@
//============================================================================
//
// 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-2005 by Bradford W. Mott and the Stella team
//
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: FrameBufferGP2X.hxx,v 1.1 2006-12-02 23:25:55 stephena Exp $
//============================================================================
#ifndef FRAMEBUFFER_GP2X_HXX
#define FRAMEBUFFER_GP2X_HXX
#include <SDL.h>
#include <SDL_syswm.h>
class OSystem;
class GUI::Font;
class RectList;
#include "bspf.hxx"
#include "GuiUtils.hxx"
#include "FrameBuffer.hxx"
/**
This class implements an SDL hardware framebuffer.
@author Stephen Anthony
@version $Id: FrameBufferGP2X.hxx,v 1.1 2006-12-02 23:25:55 stephena Exp $
*/
class FrameBufferGP2X : public FrameBuffer
{
public:
/**
Creates a new software framebuffer
*/
FrameBufferGP2X(OSystem* osystem);
/**
Destructor
*/
virtual ~FrameBufferGP2X();
//////////////////////////////////////////////////////////////////////
// The following methods are derived from FrameBuffer.hxx
//////////////////////////////////////////////////////////////////////
/**
This method is called to initialize software video mode.
Return false if any operation fails, otherwise return true.
*/
virtual bool initSubsystem();
/**
This method is called to query the type of the FrameBuffer.
*/
virtual BufferType type() { return kSoftBuffer; }
/**
This method is called to set the aspect ratio of the screen.
*/
virtual void setAspectRatio();
/**
This method is called to change to the given scaler type.
@param scaler The scaler to use for rendering the mediasource
*/
virtual void setScaler(Scaler scaler);
/**
This method is called whenever the screen needs to be recreated.
It updates the global screen variable.
*/
virtual bool createScreen();
/**
Switches between the filtering options in software mode.
Currently, none exist.
*/
virtual void toggleFilter();
/**
This method should be called anytime the MediaSource needs to be redrawn
to the screen.
*/
virtual void drawMediaSource();
/**
This method is called before any drawing is done (per-frame).
*/
virtual void preFrameUpdate();
/**
This method is called after any drawing is done (per-frame).
*/
virtual void postFrameUpdate();
/**
This method is called to get the specified scanline data.
@param row The row we are looking for
@param data The actual pixel data (in bytes)
*/
virtual void scanline(uInt32 row, uInt8* data);
/**
This method is called to map a given r,g,b triple to the screen palette.
@param r The red component of the color.
@param g The green component of the color.
@param b The blue component of the color.
*/
virtual Uint32 mapRGB(Uint8 r, Uint8 g, Uint8 b)
{ return SDL_MapRGB(myScreen->format, r, g, b); }
/**
This method is called to draw a horizontal line.
@param x The first x coordinate
@param y The y coordinate
@param x2 The second x coordinate
@param color The color of the line
*/
virtual void hLine(uInt32 x, uInt32 y, uInt32 x2, int color);
/**
This method is called to draw a vertical line.
@param x The x coordinate
@param y The first y coordinate
@param y2 The second y coordinate
@param color The color of the line
*/
virtual void vLine(uInt32 x, uInt32 y, uInt32 y2, int color);
/**
This method is called to draw a filled rectangle.
@param x The x coordinate
@param y The y coordinate
@param w The width of the area
@param h The height of the area
@param color The color of the area
*/
virtual void fillRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h,
int color);
/**
This method is called to draw the specified character.
@param font The font to use to draw the character
@param c The character to draw
@param x The x coordinate
@param y The y coordinate
@param color The color of the character
*/
virtual void drawChar(const GUI::Font* font, uInt8 c, uInt32 x, uInt32 y,
int color);
/**
This method is called to draw the bitmap image.
@param bitmap The data to draw
@param x The x coordinate
@param y The y coordinate
@param color The color of the character
@param h The height of the data image
*/
virtual void drawBitmap(uInt32* bitmap, Int32 x, Int32 y, int color,
Int32 h = 8);
/**
This method translates the given coordinates to their
unzoomed/unscaled equivalents.
@param x X coordinate to translate
@param y Y coordinate to translate
*/
inline virtual void translateCoords(Int32* x, Int32* y);
/**
This method adds a dirty rectangle
(ie, an area of the screen that has changed)
@param x The x coordinate
@param y The y coordinate
@param w The width of the area
@param h The height of the area
*/
virtual void addDirtyRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h);
/**
Enable/disable phosphor effect.
*/
virtual void enablePhosphor(bool enable, int blend);
/**
Completely erase contents of the screen.
*/
virtual void cls();
/**
Shows or hides the cursor based on the given boolean value.
*/
virtual void showCursor(bool show);
private:
int myPitch;
// Used in the dirty update of the SDL surface
RectList* myRectList;
// Used in the dirty update of the overlay surface
RectList* myOverlayRectList;
};
class RectList
{
public:
RectList(Uint32 size = 512);
~RectList();
void add(SDL_Rect* rect);
SDL_Rect* rects();
Uint32 numRects();
void start();
private:
Uint32 currentSize, currentRect;
SDL_Rect* rectArray;
};
#endif

View File

@ -1,6 +1,7 @@
MODULE := src/gp2x
MODULE_OBJS := \
src/gp2x/FrameBufferGP2X.o \
src/gp2x/FSNodeGP2X.o \
src/gp2x/OSystemGP2X.o \
src/gp2x/SettingsGP2X.o

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: LauncherDialog.cxx,v 1.57 2006-11-28 21:48:56 stephena Exp $
// $Id: LauncherDialog.cxx,v 1.58 2006-12-02 23:25:55 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
@ -154,6 +154,7 @@ LauncherDialog::LauncherDialog(OSystem* osystem, DialogContainer* parent,
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
LauncherDialog::~LauncherDialog()
{
cerr << "LauncherDialog::~LauncherDialog()\n";
delete myOptions;
delete myGameList;
}