"Fossies" - the Fresh Open Source Software Archive

Member "stella-6.0.2/src/emucore/PropsSet.cxx" (11 Oct 2019, 6278 Bytes) of package /linux/privat/stella-6.0.2-src.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "PropsSet.cxx" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 6.0.1_vs_6.0.2.

    1 //============================================================================
    2 //
    3 //   SSSS    tt          lll  lll
    4 //  SS  SS   tt           ll   ll
    5 //  SS     tttttt  eeee   ll   ll   aaaa
    6 //   SSSS    tt   ee  ee  ll   ll      aa
    7 //      SS   tt   eeeeee  ll   ll   aaaaa  --  "An Atari 2600 VCS Emulator"
    8 //  SS  SS   tt   ee      ll   ll  aa  aa
    9 //   SSSS     ttt  eeeee llll llll  aaaaa
   10 //
   11 // Copyright (c) 1995-2019 by Bradford W. Mott, Stephen Anthony
   12 // and the Stella Team
   13 //
   14 // See the file "License.txt" for information on usage and redistribution of
   15 // this file, and for a DISCLAIMER OF ALL WARRANTIES.
   16 //============================================================================
   17 
   18 #include <map>
   19 
   20 #include "bspf.hxx"
   21 #include "FSNode.hxx"
   22 #include "DefProps.hxx"
   23 #include "Props.hxx"
   24 #include "PropsSet.hxx"
   25 
   26 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
   27 PropertiesSet::PropertiesSet(const string& propsfile)
   28 {
   29   load(propsfile);
   30 }
   31 
   32 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
   33 void PropertiesSet::load(const string& filename)
   34 {
   35   ifstream in(filename);
   36 
   37   Properties prop;
   38   while(in >> prop)
   39     insert(prop);
   40 }
   41 
   42 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
   43 bool PropertiesSet::save(const string& filename) const
   44 {
   45   ofstream out(filename);
   46   if(!out)
   47     return false;
   48 
   49   // Only save those entries in the external list
   50   for(const auto& i: myExternalProps)
   51     out << i.second;
   52 
   53   return true;
   54 }
   55 
   56 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
   57 bool PropertiesSet::getMD5(const string& md5, Properties& properties,
   58                            bool useDefaults) const
   59 {
   60   properties.setDefaults();
   61   bool found = false;
   62 
   63   // There are three lists to search when looking for a properties entry,
   64   // which must be done in the following order
   65   // If 'useDefaults' is specified, only use the built-in list
   66   //
   67   //  'save': entries previously inserted that are saved on program exit
   68   //  'temp': entries previously inserted that are discarded
   69   //  'builtin': the defaults compiled into the program
   70 
   71   // First check properties from external file
   72   if(!useDefaults)
   73   {
   74     // Check external list
   75     auto ext = myExternalProps.find(md5);
   76     if(ext != myExternalProps.end())
   77     {
   78       properties = ext->second;
   79       found = true;
   80     }
   81     else  // Search temp list
   82     {
   83       auto tmp = myTempProps.find(md5);
   84       if(tmp != myTempProps.end())
   85       {
   86         properties = tmp->second;
   87         found = true;
   88       }
   89     }
   90   }
   91 
   92   // Otherwise, search the internal database using binary search
   93   if(!found)
   94   {
   95     int low = 0, high = DEF_PROPS_SIZE - 1;
   96     while(low <= high)
   97     {
   98       int i = (low + high) / 2;
   99       int cmp = BSPF::compareIgnoreCase(md5, DefProps[i][Cartridge_MD5]);
  100 
  101       if(cmp == 0)  // found it
  102       {
  103         for(int p = 0; p < LastPropType; ++p)
  104           if(DefProps[i][p][0] != 0)
  105             properties.set(PropertyType(p), DefProps[i][p]);
  106 
  107         found = true;
  108         break;
  109       }
  110       else if(cmp < 0)
  111         high = i - 1; // look at lower range
  112       else
  113         low = i + 1;  // look at upper range
  114     }
  115   }
  116 
  117   return found;
  118 }
  119 
  120 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  121 void PropertiesSet::getMD5WithInsert(const FilesystemNode& rom,
  122                                      const string& md5, Properties& properties)
  123 {
  124   if(!getMD5(md5, properties))
  125   {
  126     properties.set(Cartridge_MD5, md5);
  127     // Create a name suitable for using in properties
  128     properties.set(Cartridge_Name, rom.getNameWithExt(""));
  129 
  130     insert(properties, false);
  131   }
  132 }
  133 
  134 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  135 void PropertiesSet::insert(const Properties& properties, bool save)
  136 {
  137   // Note that the following code is optimized for insertion when an item
  138   // doesn't already exist, and when the external properties file is
  139   // relatively small (which is the case with current versions of Stella,
  140   // as the properties are built-in)
  141   // If an item does exist, it will be removed and insertion done again
  142   // This shouldn't be a speed issue, as insertions will only fail with
  143   // duplicates when you're changing the current ROM properties, which
  144   // most people tend not to do
  145 
  146   // Since the PropSet is keyed by md5, we can't insert without a valid one
  147   const string& md5 = properties.get(Cartridge_MD5);
  148   if(md5 == "")
  149     return;
  150 
  151   // Make sure the exact entry isn't already in any list
  152   Properties defaultProps;
  153   if(getMD5(md5, defaultProps, false) && defaultProps == properties)
  154     return;
  155   else if(getMD5(md5, defaultProps, true) && defaultProps == properties)
  156   {
  157     myExternalProps.erase(md5);
  158     return;
  159   }
  160 
  161   // The status of 'save' determines which list to save to
  162   PropsList& list = save ? myExternalProps : myTempProps;
  163 
  164   auto ret = list.emplace(md5, properties);
  165   if(ret.second == false)
  166   {
  167     // Remove old item and insert again
  168     list.erase(ret.first);
  169     list.emplace(md5, properties);
  170   }
  171 }
  172 
  173 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  174 void PropertiesSet::print() const
  175 {
  176   // We only look at the external properties and the built-in ones;
  177   // the temp properties are ignored
  178   // Also, any properties entries in the external file override the built-in
  179   // ones
  180   // The easiest way to merge the lists is to create another temporary one
  181   // This isn't fast, but I suspect this method isn't used too often (or at all)
  182 
  183   // First insert all external props
  184   PropsList list = myExternalProps;
  185 
  186   // Now insert all the built-in ones
  187   // Note that if we try to insert a duplicate, the insertion will fail
  188   // This is fine, since a duplicate in the built-in list means it should
  189   // be overrided anyway (and insertion shouldn't be done)
  190   Properties properties;
  191   for(int i = 0; i < DEF_PROPS_SIZE; ++i)
  192   {
  193     properties.setDefaults();
  194     for(int p = 0; p < LastPropType; ++p)
  195       if(DefProps[i][p][0] != 0)
  196         properties.set(PropertyType(p), DefProps[i][p]);
  197 
  198     list.emplace(DefProps[i][Cartridge_MD5], properties);
  199   }
  200 
  201   // Now, print the resulting list
  202   Properties::printHeader();
  203   for(const auto& i: list)
  204     i.second.print();
  205 }