Jump to content
  • entries
    658
  • comments
    2,707
  • views
    907,072

Internal Ram revamped


I decided to revamp my enhancement to Stella to make it easier to implement Internal RAM for additional cartridge types. In my original enhancement you needed to add 2 additional source files for each cartridge type. The 2 files would derive a new class from the base class CartRamWidget:

 

  • base class file
    • CartRamWidget.hxx
  • DPC Plus class files
    • CartRamDPCPlusWidget.cxx
    • CartRamDPCPlusWidget.hxx
  • F8SC class files
    • CartRamF8SCWidget.cxx
    • CartRamF8SCWidget.hxx
  • etc.
    • CartRam_etc_Widget.cxx
    • CartRam_etc_Widget.hxx

 

Note: Only cartridge types with internal RAM need those files, so files like Cart4KWidget.cxx and Cart4KWidget.hxx (for 4K games) would never be needed.

 

In the new routines there's just the CartRamWidget class (now using 2 files):

  • CartRamWidget.cxx
  • CartRamWidget.hxx

 

The existing CartDebugWidget base class was updated with 6 additional functions:

virtual bool internalRam() { return false; }
virtual int internalRamSize() { return 0; }
virtual string internalRamDescription(){ return ""; }
virtual ByteArray internalRamOld(int start, int count) { ByteArray ba; return ba; }
virtual ByteArray internalRamCurrent(int start, int count) { ByteArray ba; return ba; }
virtual void internalRamSetValue(int addr, uInt8 value) { };
 

Each type of cartridge has a derived class from CartDebugWidget, such as CartDPCPlusWidget for DPC+ and CartF8SCWidget for 8K with Super Chip RAM. If a cartridge does not have extra RAM, nothing needs to be done because the default internalRam() function returns false. For cartridges with extra RAM, they just need to add those 6 functions and the RAM will automatically show up in Stella's Debug Window. For DPC+ those functions are:

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeDPCPlusWidget::internalRam()
{
    return true;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int CartridgeDPCPlusWidget::internalRamSize()
{
    return 5*1024;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string CartridgeDPCPlusWidget::internalRamDescription()
{
    ostringstream desc;
    desc << "0000-0FFF - 4K display data\n"
         << "            indirectly accessible to 6507\n"
         << "            via DPC+'s Data Fetcher registers\n"
         << "1000-13FF - 1K frequency table,\n"
         << "            C variables and C stack\n"
         << "            not accessible to 6507";    
    return desc.str();
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ByteArray CartridgeDPCPlusWidget::internalRamOld(int start, int count)
{
    ByteArray ram;
    ram.clear();
    for (int i = 0;i<count;i++)
        ram.push_back(myOldState.internalram[start + i]);
    return ram;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ByteArray CartridgeDPCPlusWidget::internalRamCurrent(int start, int count)
{
    ByteArray ram;
    ram.clear();
    for (int i = 0;i<count;i++)
        ram.push_back(myCart.myDisplayImage[start + i]);
    return ram;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeDPCPlusWidget::internalRamSetValue(int addr, uInt8 value)
{
    myCart.myDisplayImage[addr] = value;
}
 

Here's an example of hacking the score to ABCDEF in Frantic:

blogentry-3056-0-68561300-1394324932_thumb.png

 

New score (look at the TIA Display in top-left)

blogentry-3056-0-27923100-1394324938_thumb.png

 

The new CartRamWidget can also handle RAM quantities of less than 256. It does that by shrinking the RAM grid:

blogentry-3056-0-51924900-1394324943_thumb.png

 

There's plenty more to do, but I'm quite happy with the results so far.

  • Like 1

2 Comments


Recommended Comments

Thanks!

 

this was definitely a gap.

For a number of carts you could already see the Cartridge RAM by using the scrollbars that become enabled just to the right of the ZP RAM grid. In the above Defender II screenshot I'd scrolled the upper RAM display so I could compare it with the output from my new routines.

 

The upper display gets enabled when the cartridge class calls function registerRamArea(). The F8SC cartridge used by Defender II calls it like this:

 

registerRamArea(0x1000, 128, 0x80, 0x00);
The parameters are base address, size of RAM, read offset, write offset. If you edit the upper grid the routines use 6507 "poke" and "peek" to update the RAM and confirm the change.

 

The reason I added the new tab is registerRamArea() doesn't work for DPC+. The 5K of RAM exists outside of the 6507's addressing space, so the 6507 "poke" and "peek" cannot access it.

 

Last night I figured out how to get the label field updated so that when you click on a grid cell the appropriate name shows up in the label field. I then started to add the Undo, Revert, Search, Compare and Reset buttons. The buttons show up, but the callback functions haven't been implemented yet so clicking on them doesn't do anything.

 

Right now you can change RAM in either grid, but the change won't appear in the other grid. Since that could be confusing, I plan to remove the calls to registerRamArea() when I update a cartridge to use the new Cartridge RAM grid.

  • Like 1
Guest
Add a comment...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...