Reorganized random number generation code in each Cart class. There

was duplicate code in many Cart classes and in M6532 class, and since all
these classes are subclasses of Device, it made sense to move the
functionality there instead.

Carts 3E and E7 now return a random value when attempting to read from
the write port.  Still TODO is determine what happens to the value at
that address (is it randomized or zeroed?).  Thanks to Batari for
suggestions and sample code.

Fixed bug in E7 carts when entering the debugger; bankswitch was being
inadvertantly triggered which caused emulation to fail.

Overall, I need to figure out exactly what happens when reading from
the write port for all carts with extended RAM.  There are two things
to consider: what value is written to the address, and what value
is returned.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1892 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2009-11-05 00:41:44 +00:00
parent 917f766a6d
commit 5ce401e6a4
16 changed files with 51 additions and 47 deletions

View File

@ -19,7 +19,6 @@
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>
#include "Random.hxx"
#include "System.hxx" #include "System.hxx"
#include "TIA.hxx" #include "TIA.hxx"
#include "Cart3E.hxx" #include "Cart3E.hxx"
@ -50,9 +49,8 @@ Cartridge3E::~Cartridge3E()
void Cartridge3E::reset() void Cartridge3E::reset()
{ {
// Initialize RAM with random values // Initialize RAM with random values
class Random random;
for(uInt32 i = 0; i < 32768; ++i) for(uInt32 i = 0; i < 32768; ++i)
myRam[i] = random.next(); myRam[i] = myRandGenerator.next();
// We'll map bank 0 into the first segment upon reset // We'll map bank 0 into the first segment upon reset
bank(0); bank(0);
@ -97,13 +95,14 @@ void Cartridge3E::install(System& system)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 Cartridge3E::peek(uInt16 address) uInt8 Cartridge3E::peek(uInt16 address)
{ {
// TODO - determine what really happens when you read from the write port
address &= 0x0FFF; address &= 0x0FFF;
if(address < 0x0800) if(address < 0x0800)
{ {
if(myCurrentBank < 256) if(myCurrentBank < 256)
return myImage[(address & 0x07FF) + (myCurrentBank << 11)]; return myImage[(address & 0x07FF) + (myCurrentBank << 11)];
else if(address < 0x400) // Read from write port gives undefined values
return myRandGenerator.next();
else else
return myRam[(address & 0x03FF) + ((myCurrentBank - 256) << 10)]; return myRam[(address & 0x03FF) + ((myCurrentBank - 256) << 10)];
} }

View File

@ -19,7 +19,6 @@
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>
#include "Random.hxx"
#include "System.hxx" #include "System.hxx"
#include "M6532.hxx" #include "M6532.hxx"
#include "TIA.hxx" #include "TIA.hxx"
@ -46,9 +45,8 @@ Cartridge4A50::~Cartridge4A50()
void Cartridge4A50::reset() void Cartridge4A50::reset()
{ {
// Initialize RAM with random values // Initialize RAM with random values
class Random random;
for(uInt32 i = 0; i < 32768; ++i) for(uInt32 i = 0; i < 32768; ++i)
myRAM[i] = random.next(); myRAM[i] = myRandGenerator.next();
mySliceLow = mySliceMiddle = mySliceHigh = 0; mySliceLow = mySliceMiddle = mySliceHigh = 0;
myIsRomLow = myIsRomMiddle = myIsRomHigh = true; myIsRomLow = myIsRomMiddle = myIsRomHigh = true;

View File

@ -20,7 +20,6 @@
#include <cstring> #include <cstring>
#include "M6502.hxx" #include "M6502.hxx"
#include "Random.hxx"
#include "System.hxx" #include "System.hxx"
#include "CartAR.hxx" #include "CartAR.hxx"
@ -53,9 +52,8 @@ CartridgeAR::~CartridgeAR()
void CartridgeAR::reset() void CartridgeAR::reset()
{ {
// Initialize RAM with random values // Initialize RAM with random values
class Random random;
for(uInt32 i = 0; i < 6 * 1024; ++i) for(uInt32 i = 0; i < 6 * 1024; ++i)
myImage[i] = random.next(); myImage[i] = myRandGenerator.next();
// Initialize SC BIOS ROM // Initialize SC BIOS ROM
initializeROM(); initializeROM();
@ -302,8 +300,7 @@ void CartridgeAR::initializeROM()
// The accumulator should contain a random value after exiting the // The accumulator should contain a random value after exiting the
// SC BIOS code - a value placed in offset 281 will be stored in A // SC BIOS code - a value placed in offset 281 will be stored in A
class Random random; ourDummyROMCode[281] = myRandGenerator.next();
ourDummyROMCode[281] = random.next();
// Initialize ROM with illegal 6502 opcode that causes a real 6502 to jam // Initialize ROM with illegal 6502 opcode that causes a real 6502 to jam
for(uInt32 i = 0; i < 2048; ++i) for(uInt32 i = 0; i < 2048; ++i)

View File

@ -19,7 +19,6 @@
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>
#include "Random.hxx"
#include "System.hxx" #include "System.hxx"
#include "CartCV.hxx" #include "CartCV.hxx"
@ -52,9 +51,8 @@ void CartridgeCV::reset()
memcpy(myImage, myROM, 2048); memcpy(myImage, myROM, 2048);
// Initialize RAM with random values // Initialize RAM with random values
class Random random;
for(uInt32 i = 0; i < 1024; ++i) for(uInt32 i = 0; i < 1024; ++i)
myRAM[i] = random.next(); myRAM[i] = myRandGenerator.next();
} }
else if(mySize == 4096) else if(mySize == 4096)
{ {

View File

@ -19,7 +19,6 @@
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>
#include "Random.hxx"
#include "System.hxx" #include "System.hxx"
#include "CartE7.hxx" #include "CartE7.hxx"
@ -46,9 +45,8 @@ CartridgeE7::~CartridgeE7()
void CartridgeE7::reset() void CartridgeE7::reset()
{ {
// Initialize RAM with random values // Initialize RAM with random values
class Random random;
for(uInt32 i = 0; i < 2048; ++i) for(uInt32 i = 0; i < 2048; ++i)
myRAM[i] = random.next(); myRAM[i] = myRandGenerator.next();
// Install some default banks for the RAM and first segment // Install some default banks for the RAM and first segment
bankRAM(0); bankRAM(0);
@ -109,7 +107,9 @@ uInt8 CartridgeE7::peek(uInt16 address)
// NOTE: The following does not handle reading from RAM, however, // NOTE: The following does not handle reading from RAM, however,
// this function should never be called for RAM because of the // this function should never be called for RAM because of the
// way page accessing has been setup // way page accessing has been setup
// TODO - determine what really happens when you read from the write port if((bank() == 7) && (address < 0x400))
return myRandGenerator.next(); // Read from write port gives undefined values
else
return myImage[(myCurrentSlice[address >> 11] << 11) + (address & 0x07FF)]; return myImage[(myCurrentSlice[address >> 11] << 11) + (address & 0x07FF)];
} }
@ -136,6 +136,8 @@ void CartridgeE7::poke(uInt16 address, uInt8)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeE7::bankRAM(uInt16 bank) void CartridgeE7::bankRAM(uInt16 bank)
{ {
if(myBankLocked) return;
// Remember what bank we're in // Remember what bank we're in
myCurrentRAM = bank; myCurrentRAM = bank;
uInt16 offset = bank << 8; uInt16 offset = bank << 8;

View File

@ -19,7 +19,6 @@
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>
#include "Random.hxx"
#include "System.hxx" #include "System.hxx"
#include "CartEFSC.hxx" #include "CartEFSC.hxx"
@ -42,9 +41,8 @@ CartridgeEFSC::~CartridgeEFSC()
void CartridgeEFSC::reset() void CartridgeEFSC::reset()
{ {
// Initialize RAM with random values // Initialize RAM with random values
class Random random;
for(uInt32 i = 0; i < 128; ++i) for(uInt32 i = 0; i < 128; ++i)
myRAM[i] = random.next(); myRAM[i] = myRandGenerator.next();
// Upon reset we switch to bank 1 // Upon reset we switch to bank 1
bank(1); bank(1);

View File

@ -19,7 +19,6 @@
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>
#include "Random.hxx"
#include "System.hxx" #include "System.hxx"
#include "CartF4SC.hxx" #include "CartF4SC.hxx"
@ -42,9 +41,8 @@ CartridgeF4SC::~CartridgeF4SC()
void CartridgeF4SC::reset() void CartridgeF4SC::reset()
{ {
// Initialize RAM with random values // Initialize RAM with random values
class Random random;
for(uInt32 i = 0; i < 128; ++i) for(uInt32 i = 0; i < 128; ++i)
myRAM[i] = random.next(); myRAM[i] = myRandGenerator.next();
// Upon reset we switch to bank 0 // Upon reset we switch to bank 0
bank(0); bank(0);

View File

@ -19,7 +19,6 @@
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>
#include "Random.hxx"
#include "System.hxx" #include "System.hxx"
#include "CartF6SC.hxx" #include "CartF6SC.hxx"
@ -42,9 +41,8 @@ CartridgeF6SC::~CartridgeF6SC()
void CartridgeF6SC::reset() void CartridgeF6SC::reset()
{ {
// Initialize RAM with random values // Initialize RAM with random values
class Random random;
for(uInt32 i = 0; i < 128; ++i) for(uInt32 i = 0; i < 128; ++i)
myRAM[i] = random.next(); myRAM[i] = myRandGenerator.next();
// Upon reset we switch to bank 0 // Upon reset we switch to bank 0
bank(0); bank(0);

View File

@ -19,7 +19,6 @@
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>
#include "Random.hxx"
#include "System.hxx" #include "System.hxx"
#include "CartF8SC.hxx" #include "CartF8SC.hxx"
@ -42,9 +41,8 @@ CartridgeF8SC::~CartridgeF8SC()
void CartridgeF8SC::reset() void CartridgeF8SC::reset()
{ {
// Initialize RAM with random values // Initialize RAM with random values
class Random random;
for(uInt32 i = 0; i < 128; ++i) for(uInt32 i = 0; i < 128; ++i)
myRAM[i] = random.next(); myRAM[i] = myRandGenerator.next();
// Upon reset we switch to bank 1 // Upon reset we switch to bank 1
bank(1); bank(1);

View File

@ -19,7 +19,6 @@
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>
#include "Random.hxx"
#include "System.hxx" #include "System.hxx"
#include "CartFASC.hxx" #include "CartFASC.hxx"
@ -42,9 +41,8 @@ CartridgeFASC::~CartridgeFASC()
void CartridgeFASC::reset() void CartridgeFASC::reset()
{ {
// Initialize RAM with random values // Initialize RAM with random values
class Random random;
for(uInt32 i = 0; i < 256; ++i) for(uInt32 i = 0; i < 256; ++i)
myRAM[i] = random.next(); myRAM[i] = myRandGenerator.next();
// Upon reset we switch to bank 2 // Upon reset we switch to bank 2
bank(2); bank(2);
@ -124,8 +122,12 @@ uInt8 CartridgeFASC::peek(uInt16 address)
// Thanks to Kroko of AtariAge for this advice and code idea // Thanks to Kroko of AtariAge for this advice and code idea
if(address < 0x0100) // Write port is at 0xF000 - 0xF100 (256 bytes) if(address < 0x0100) // Write port is at 0xF000 - 0xF100 (256 bytes)
{ {
if(myBankLocked) return 0; if(!myBankLocked)
else return myRAM[address] = 0; {
return myRAM[address] = 0;
}
else
return 0;
} }
else else
{ {

View File

@ -19,7 +19,6 @@
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>
#include "Random.hxx"
#include "System.hxx" #include "System.hxx"
#include "CartMC.hxx" #include "CartMC.hxx"
@ -46,9 +45,8 @@ CartridgeMC::~CartridgeMC()
void CartridgeMC::reset() void CartridgeMC::reset()
{ {
// Initialize RAM with random values // Initialize RAM with random values
class Random random;
for(uInt32 i = 0; i < 32768; ++i) for(uInt32 i = 0; i < 32768; ++i)
myRAM[i] = random.next(); myRAM[i] = myRandGenerator.next();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -20,7 +20,6 @@
#include <iostream> #include <iostream>
#include "Console.hxx" #include "Console.hxx"
#include "Random.hxx"
#include "Switches.hxx" #include "Switches.hxx"
#include "System.hxx" #include "System.hxx"
@ -41,15 +40,13 @@ M6532::~M6532()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void M6532::reset() void M6532::reset()
{ {
class Random random;
// Randomize the 128 bytes of memory // Randomize the 128 bytes of memory
for(uInt32 t = 0; t < 128; ++t) for(uInt32 t = 0; t < 128; ++t)
myRAM[t] = random.next(); myRAM[t] = myRandGenerator.next();
// The timer absolutely cannot be initialized to zero; some games will // The timer absolutely cannot be initialized to zero; some games will
// loop or hang (notably Solaris and H.E.R.O.) // loop or hang (notably Solaris and H.E.R.O.)
myTimer = (0xff - (random.next() % 0xfe)) << 10; myTimer = (0xff - (myRandGenerator.next() % 0xfe)) << 10;
myIntervalShift = 10; myIntervalShift = 10;
myCyclesWhenTimerSet = 0; myCyclesWhenTimerSet = 0;
myInterruptEnabled = false; myInterruptEnabled = false;

View File

@ -17,11 +17,18 @@
//============================================================================ //============================================================================
#include <time.h> #include <time.h>
#include "OSystem.hxx" #include "OSystem.hxx"
#include "Random.hxx" #include "Random.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Random::Random() Random::Random()
{
initSeed();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Random::initSeed()
{ {
if(ourSystem) if(ourSystem)
myValue = ourSystem->getTicks(); myValue = ourSystem->getTicks();

View File

@ -40,6 +40,12 @@ class Random
Random(); Random();
public: public:
/**
Re-initialize the random number generator with a new seed,
to generate a different set of random numbers.
*/
void initSeed();
/** /**
Answer the next random number from the random number generator Answer the next random number from the random number generator

View File

@ -22,6 +22,7 @@
Device::Device() Device::Device()
: mySystem(0) : mySystem(0)
{ {
myRandGenerator.initSeed();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -35,3 +36,5 @@ void Device::systemCyclesReset()
// By default I do nothing when my system resets its cycle counter // By default I do nothing when my system resets its cycle counter
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Random Device::myRandGenerator;

View File

@ -21,6 +21,7 @@
class System; class System;
#include "Random.hxx"
#include "Serializable.hxx" #include "Serializable.hxx"
#include "bspf.hxx" #include "bspf.hxx"
@ -107,6 +108,10 @@ class Device : public Serializable
protected: protected:
/// Pointer to the system the device is installed in or the null pointer /// Pointer to the system the device is installed in or the null pointer
System* mySystem; System* mySystem;
/// Many devices need a source of random numbers, usually for emulating
/// unknown/undefined behaviour
static class Random myRandGenerator;
}; };
#endif #endif