Revamped the result on floating pins for TIA reads. Previously, this was

controlled by 'tiafloat', which has now been removed.  Now, all
undriven pins take on the last value on the databus.  This fixes a bug
in those reads where bit 6 or bits 6 & 7 are also undriven (previously,
these bits would always be zero, and only bits 0-5 were from lastdatabus.

Added new commandline argument 'tiadriven', which defaults to false.
In this default case, relevant bits take on values from the databus.
If true, relevant bits still take on databus values, but some are
randomly driven high as well.  This helps to expose bugs when
developers assume the values for undriven/floating bits.

Added 'uimessages' commandline argument and associated UI item.  When
disabled, messages which are normally shown in-game are disabled.
Certain messages which indicate a serious error are still shown, however.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1900 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2009-11-10 20:12:50 +00:00
parent f1e88a2d48
commit 00f8ffb686
10 changed files with 70 additions and 37 deletions

View File

@ -1927,7 +1927,8 @@ bool EventHandler::enterDebugMode()
{
myOSystem->debugger().setQuitState();
setEventState(S_EMULATE);
myOSystem->frameBuffer().showMessage("Debugger window too large");
myOSystem->frameBuffer().showMessage("Debugger window too large",
kBottomCenter, true);
return false;
}
myOverlay->reStack();
@ -1935,7 +1936,8 @@ bool EventHandler::enterDebugMode()
myOSystem->sound().mute(true);
myEvent->clear();
#else
myOSystem->frameBuffer().showMessage("Debugger unsupported");
myOSystem->frameBuffer().showMessage("Debugger unsupported",
kBottomCenter, true);
#endif
return true;

View File

@ -271,8 +271,12 @@ void FrameBuffer::update()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::showMessage(const string& message, MessagePosition position,
uInt32 color)
bool force, uInt32 color)
{
// Only show messages if they've been enabled
if(!(force || myOSystem->settings().getBool("uimessages")))
return;
// Erase old messages on the screen
if(myMsg.counter > 0)
{

View File

@ -127,10 +127,12 @@ class FrameBuffer
@param message The message to be shown
@param position Onscreen position for the message
@param force Force showing this message, even if messages are disabled
@param color Color of text in the message
*/
void showMessage(const string& message,
MessagePosition position = kBottomCenter,
bool force = false,
uInt32 color = kTextColorHi);
/**

View File

@ -437,7 +437,8 @@ fallback:
if(ret)
{
setFramerate(60);
myFrameBuffer->showMessage("OpenGL mode failed, fallback to software", kMiddleCenter);
myFrameBuffer->showMessage("OpenGL mode failed, fallback to software",
kMiddleCenter, true);
}
return ret;
}

View File

@ -57,6 +57,7 @@ Settings::Settings(OSystem* osystem)
setInternal("palette", "standard");
setInternal("colorloss", "false");
setInternal("timing", "sleep");
setInternal("uimessages", "true");
// TV filter options
setInternal("tv_tex", "off");
@ -114,7 +115,7 @@ Settings::Settings(OSystem* osystem)
// Misc options
setInternal("autoslot", "false");
setInternal("showinfo", "false");
setInternal("tiafloat", "true");
setInternal("tiadriven", "false");
setInternal("avoxport", "");
setInternal("stats", "false");
setInternal("audiofirst", "true");
@ -289,7 +290,6 @@ void Settings::validate()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Settings::usage()
{
#ifndef MAC_OSX
cout << endl
<< "Stella version " << STELLA_VERSION << endl
<< endl
@ -339,6 +339,7 @@ void Settings::usage()
<< " -colorloss <1|0> Enable PAL color-loss effect\n"
<< " -framerate <number> Display the given number of frames per second (0 to auto-calculate)\n"
<< " -timing <sleep|busy> Use the given type of wait between frames\n"
<< " -uimessages <1|0> Show onscreen UI messages for different events\n"
<< endl
#ifdef SOUND_SUPPORT
<< " -sound <1|0> Enable sound generation\n"
@ -395,7 +396,7 @@ void Settings::usage()
<< " -holdselect Start the emulator with the Game Select switch held down\n"
<< " -holdbutton0 Start the emulator with the left joystick button held down\n"
<< " -stats <1|0> Overlay console info during emulation\n"
<< " -tiafloat <1|0> Set unused TIA pins floating on a read/peek\n"
<< " -tiadriven <1|0> Drive unused TIA pins randomly value on a read/peek\n"
<< endl
<< " -bs <arg> Sets the 'Cartridge.Type' (bankswitch) property\n"
<< " -type <arg> Same as using -bs\n"
@ -415,7 +416,6 @@ void Settings::usage()
<< " -ppblend <arg> Sets the 'Display.PPBlend' property\n"
#endif
<< endl;
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -169,9 +169,8 @@ void TIA::reset()
myDumpEnabled = false;
myDumpDisabledCycle = 0;
// The mask indicates which pins should be driven high
// If a pin is floating (the default), then its mask value is 0
myOutputPinsMask = mySettings.getBool("tiafloat") ? 0x00 : 0x3F;
// Should undriven pins be randomly driven high or low?
myTIAPinsDriven = mySettings.getBool("tiadriven");
myFrameCounter = 0;
myScanlineCountForLastFrame = 0;
@ -1162,83 +1161,93 @@ uInt8 TIA::peek(uInt16 addr)
// Update frame to current color clock before we look at anything!
updateFrame(mySystem->cycles() * 3);
uInt8 value = 0x00;
// If pins are undriven, we start with the last databus value
// Otherwise, there is some randomness injected into the mix
uInt8 value = myTIAPinsDriven ? mySystem->getDataBusState(0xFF) :
mySystem->getDataBusState();
uInt16 collision = myCollision & (uInt16)myCollisionEnabledMask;
switch(addr & 0x000f)
{
case CXM0P:
value = ((collision & Cx_M0P1) ? 0x80 : 0x00) |
value = (value & 0x3F) |
((collision & Cx_M0P1) ? 0x80 : 0x00) |
((collision & Cx_M0P0) ? 0x40 : 0x00);
break;
case CXM1P:
value = ((collision & Cx_M1P0) ? 0x80 : 0x00) |
value = (value & 0x3F) |
((collision & Cx_M1P0) ? 0x80 : 0x00) |
((collision & Cx_M1P1) ? 0x40 : 0x00);
break;
case CXP0FB:
value = ((collision & Cx_P0PF) ? 0x80 : 0x00) |
value = (value & 0x3F) |
((collision & Cx_P0PF) ? 0x80 : 0x00) |
((collision & Cx_P0BL) ? 0x40 : 0x00);
break;
case CXP1FB:
value = ((collision & Cx_P1PF) ? 0x80 : 0x00) |
value = (value & 0x3F) |
((collision & Cx_P1PF) ? 0x80 : 0x00) |
((collision & Cx_P1BL) ? 0x40 : 0x00);
break;
case CXM0FB:
value = ((collision & Cx_M0PF) ? 0x80 : 0x00) |
value = (value & 0x3F) |
((collision & Cx_M0PF) ? 0x80 : 0x00) |
((collision & Cx_M0BL) ? 0x40 : 0x00);
break;
case CXM1FB:
value = ((collision & Cx_M1PF) ? 0x80 : 0x00) |
value = (value & 0x3F) |
((collision & Cx_M1PF) ? 0x80 : 0x00) |
((collision & Cx_M1BL) ? 0x40 : 0x00);
break;
case CXBLPF:
value = (collision & Cx_BLPF) ? 0x80 : 0x00;
value = (value & 0x7F) | ((collision & Cx_BLPF) ? 0x80 : 0x00);
break;
case CXPPMM:
value = ((collision & Cx_P0P1) ? 0x80 : 0x00) |
value = (value & 0x3F) |
((collision & Cx_P0P1) ? 0x80 : 0x00) |
((collision & Cx_M0M1) ? 0x40 : 0x00);
break;
case INPT0:
value = dumpedInputPort(myConsole.controller(Controller::Left).read(Controller::Nine));
value = (value & 0x7F) |
dumpedInputPort(myConsole.controller(Controller::Left).read(Controller::Nine));
break;
case INPT1:
value = dumpedInputPort(myConsole.controller(Controller::Left).read(Controller::Five));
value = (value & 0x7F) |
dumpedInputPort(myConsole.controller(Controller::Left).read(Controller::Five));
break;
case INPT2:
value = dumpedInputPort(myConsole.controller(Controller::Right).read(Controller::Nine));
value = (value & 0x7F) |
dumpedInputPort(myConsole.controller(Controller::Right).read(Controller::Nine));
break;
case INPT3:
value = dumpedInputPort(myConsole.controller(Controller::Right).read(Controller::Five));
value = (value & 0x7F) |
dumpedInputPort(myConsole.controller(Controller::Right).read(Controller::Five));
break;
case INPT4:
value = myConsole.controller(Controller::Left).read(Controller::Six) ? 0x80 : 0x00;
value = (value & 0x7F) |
(myConsole.controller(Controller::Left).read(Controller::Six) ? 0x80 : 0x00);
break;
case INPT5:
value = myConsole.controller(Controller::Right).read(Controller::Six) ? 0x80 : 0x00;
value = (value & 0x7F) |
(myConsole.controller(Controller::Right).read(Controller::Six) ? 0x80 : 0x00);
break;
default:
break;
}
// On certain CMOS EPROM chips the unused TIA pins on a read are not
// floating but pulled high. Programmers might want to check their
// games for compatibility, so we make this optional.
value |= ((mySystem->getDataBusState() | myOutputPinsMask) & 0x3F);
return value;
}

View File

@ -562,9 +562,9 @@ class TIA : public Device
bool myHMOVEBlankEnabled;
bool myAllowHMOVEBlanks;
// Indicates if unused TIA pins are floating on a peek
// Otherwise, they're forced high
uInt8 myOutputPinsMask;
// Indicates if unused TIA pins are randomly driven high or low
// Otherwise, they take on the value previously on the databus
bool myTIAPinsDriven;
// Bitmap of the objects that should be considered while drawing
uInt8 myEnabledObjects;

View File

@ -518,10 +518,11 @@ void LauncherDialog::handleCommand(CommandSender* sender, int cmd,
}
else
instance().frameBuffer().showMessage(
"Error creating console (screen too small)", kMiddleCenter);
"Error creating console (screen too small)", kMiddleCenter, true);
}
else
instance().frameBuffer().showMessage("Not a valid ROM file", kMiddleCenter);
instance().frameBuffer().showMessage("Not a valid ROM file",
kMiddleCenter, true);
}
}
break;

View File

@ -214,6 +214,12 @@ VideoDialog::VideoDialog(OSystem* osystem, DialogContainer* parent,
wid.push_back(myGrabmouseCheckbox);
ypos += lineHeight + 4;
// Show UI messages onscreen
myUIMessagesCheckbox = new CheckboxWidget(myTab, font, xpos, ypos,
"Show UI messages");
wid.push_back(myUIMessagesCheckbox);
ypos += lineHeight + 4;
// Center window (in windowed mode)
myCenterCheckbox = new CheckboxWidget(myTab, font, xpos, ypos,
"Center window (*)");
@ -413,6 +419,9 @@ void VideoDialog::loadConfig()
// Grab mouse
myGrabmouseCheckbox->setState(instance().settings().getBool("grabmouse"));
// Show UI messages
myUIMessagesCheckbox->setState(instance().settings().getBool("uimessages"));
// Center window
myCenterCheckbox->setState(instance().settings().getBool("center"));
@ -508,6 +517,9 @@ void VideoDialog::saveConfig()
instance().settings().setBool("grabmouse", myGrabmouseCheckbox->getState());
instance().frameBuffer().setCursorState();
// Show UI messages
instance().settings().setBool("uimessages", myUIMessagesCheckbox->getState());
// Center window
instance().settings().setBool("center", myCenterCheckbox->getState());
@ -552,6 +564,7 @@ void VideoDialog::setDefaults()
myGLStretchCheckbox->setState(false);
myUseVSyncCheckbox->setState(true);
myGrabmouseCheckbox->setState(false);
myUIMessagesCheckbox->setState(true);
myCenterCheckbox->setState(true);
myFastSCBiosCheckbox->setState(false);

View File

@ -71,6 +71,7 @@ class VideoDialog : public Dialog
CheckboxWidget* myColorLossCheckbox;
CheckboxWidget* myGLStretchCheckbox;
CheckboxWidget* myUseVSyncCheckbox;
CheckboxWidget* myUIMessagesCheckbox;
CheckboxWidget* myCenterCheckbox;
CheckboxWidget* myGrabmouseCheckbox;
CheckboxWidget* myFastSCBiosCheckbox;