]> www.vanbest.org Git - sasc-ng.git/commitdiff
release 0.8.6 0.8.6
authorleslie <unknown>
Thu, 27 Dec 2007 21:01:45 +0000 (22:01 +0100)
committerleslie <unknown>
Thu, 27 Dec 2007 21:01:45 +0000 (22:01 +0100)
47 files changed:
HISTORY
README
cam.c
crypto-bn.h
crypto.c
data.c
data.h
filter.c
log.h
misc.h
parse.c
po/de_DE.po
po/fi_FI.po
po/fr_FR.po
po/hu_HU.po
po/it_IT.po
po/nl_NL.po
po/pl_PL.po
po/ru_RU.po
po/sc.pot
po/sv_SE.po
sc.c
smartcard.c
system-common.c
system.c
systems/cardclient/camd.c
systems/cryptoworks/cryptoworks.c
systems/irdeto/irdeto.c
systems/nagra/cpu.c
systems/nagra/cpu.h
systems/nagra/nagra.c
systems/nagra/nagra1.c
systems/nagra/nagra2-0101.c
systems/nagra/nagra2-0501.c
systems/nagra/nagra2-4101.c
systems/nagra/nagra2-map57.c [deleted file]
systems/nagra/nagra2.c
systems/sc-irdeto/sc-irdeto.c
systems/sc-videoguard2/sc-videoguard2.c
systems/seca/seca.c
systems/viaccess/st20.c
systems/viaccess/tps.c
testing/Makefile
testing/compat.c
testing/testECM.c
testing/testN2Emu.c
version.h

diff --git a/HISTORY b/HISTORY
index 126ee561dc6b437bfdd7e20ab930fa2c38f759db..f41595da10f725523f826c3ef486cc8f535d6786 100644 (file)
--- a/HISTORY
+++ b/HISTORY
@@ -1,6 +1,22 @@
 VDR Plugin 'sc' Revision History
 --------------------------------
 
+21.12.2007: Version 0.8.6
+- Added Nagra2 0501 dyn. AU execution fix.
+- Added Nagra2 4101 map58 AU (though already outdated). Using unified ECC code
+  for map57 & map58.
+- Added instruction cycle counter to Nagra ST7/19 cpu emulation.
+- Added support for recent Nagra2 0101/0901 ECM (including map4e/22/3e cycle
+  calculation, timer/CRC hardware simulation, DES map, EEPROM updates, dynamic
+  ECM code, auxserver V2 call).
+- Added Nagra2 config option to drop EMM-S packets.
+- Added Nagra1 UK reg05 fix (i.e. moved it from N2 to N1).
+- Added TPS AU fix.
+- Added SVDR commands to inject keys and to configure logging to file.
+- Removed some gcc'isims (case ranges, named variadic macros, variable length
+  arrays).
+- Updated finnish translations.
+
 10.11.2007: Version 0.8.5
 - Added new Nagra2 0501 AU sheme.
 - Added Nagra2 NA 'temporarily' fixes.
diff --git a/README b/README
index 90ad096e6f273001b926c591c3e16fd7f742a1d2..c1c78b6cd601f6c5f06f9c9df25c84de46ffa89b 100644 (file)
--- a/README
+++ b/README
@@ -214,7 +214,7 @@ right. The plugin searches for these files in the "nagra" subdirectory.
 
 For Nagra2 AU some providers need binary Rom and Eeprom files. The files have to
 be named "ROMxxx.bin" and "EEPyy_xxx.bin", where xxx is the ROM version (e.g.
-102) and yy is the upper part of the provider ID (e.g. 08 for BEV). The files
+102) and yy is the upper part of the provider ID (e.g. 09 for BEV). The files
 must contain the joined contents of all Rom/Eeprom pages. The plugin searches
 for these files in the "nagra" subdirectory.
 
@@ -332,14 +332,21 @@ SVDR interface
 
 The plugin implements a SVDR interface. Supported commands are:
    RELOAD
-     reload all configuration files (only if the softcam isn't active at the
+     Reload all configuration files (only if the softcam isn't active at the
      moment).
      Return codes: 550 - Softcam active, can't reload files.
                    901 - Reloading files not entirely successfull. Most of the
                          time this will leave you with an unusable softcam.
                    900 - Reload successfull.
 
-   LOG [on|off] module.option[,module.option][,...]
+   KEY string
+     Parse the given string and add the key to the key database (as if it was
+     received from EMM stream).
+     Return codes: 501 - Syntax error.
+                   900 - Key added.
+                   901 - Invalid key format or key already known.
+
+   LOG <on|off> module.option[,module.option][,...]
      Enables or disables all given message classes.
      Return codes: 501 - Syntax error or unknown message class.
                    900 - Options set and saved.
@@ -350,3 +357,8 @@ The plugin implements a SVDR interface. Supported commands are:
      message classes.
      Return codes: 901 - No message classes available.
                    900 - Message class status (multi line reply).
+
+   LOGFILE <on|off> [filename]
+     Enables or disables logging to file and optionaly sets the filename.",
+     Return codes: 501 - Syntax error.
+                   900 - Logfile option set and saved.
diff --git a/cam.c b/cam.c
index 63195bed96a6d930177af892709b57ea90b7095b..fbe81db5dfdf47f4e5a9bb65d03484e9a4ff3ffd 100644 (file)
--- a/cam.c
+++ b/cam.c
@@ -602,7 +602,7 @@ bool cEcmData::Parse(const char *buf)
     SetName(Name);
     const char *line=buf+num;
     if(nu>0 && *line++==':') {
-      unsigned char dat[nu];
+      unsigned char *dat=AUTOMEM(nu);
       if(GetHex(line,dat,nu,true)==nu) AddData(dat,nu);
       }
     return true;
@@ -614,7 +614,7 @@ bool cEcmData::Save(FILE *f)
 {
   fprintf(f,"%d:%x:%x:%s:%x/%x:%x:%x/%x",prgId,source,transponder,name,caId,emmCaId,provId,ecm_pid,ecm_table);
   if(data) {
-    char str[dataLen*2+2];
+    char *str=AUTOARRAY(char,dataLen*2+2);
     fprintf(f,":%d:%s\n",dataLen,HexStr(str,data,dataLen));
     }
   else
index 14ce54d38f86b35804b50f5d42e422c4a4d7e255..0168d9483eca2559e0270a4bc60101aac0af3998 100644 (file)
@@ -36,6 +36,7 @@ public:
   cBN(void) { BN_init(&big); }
   ~cBN() { BN_free(&big); }
   operator BIGNUM* () { return &big; }
+  BIGNUM *operator->() { return &big; }
   bool Get(const unsigned char *in, int n);
   bool GetLE(const unsigned char *in, int n);
   int Put(unsigned char *out, int n) const;
index ed1e12a800c3c4b25b15bc15bae19ddd016bc3af..c1e64cc267233807862969b1eaa117a794e0def4 100644 (file)
--- a/crypto.c
+++ b/crypto.c
@@ -58,7 +58,7 @@ int cBN::Put(unsigned char *out, int n) const
 {
   int s=BN_num_bytes(&big);
   if(s>n) {
-    unsigned char buff[s];
+    unsigned char *buff=AUTOMEM(s);
     BN_bn2bin(&big,buff);
     memcpy(out,buff+s-n,n);
     }
@@ -73,7 +73,7 @@ int cBN::Put(unsigned char *out, int n) const
 
 bool cBN::GetLE(const unsigned char *in, int n)
 {
-  unsigned char tmp[n];
+  unsigned char *tmp=AUTOMEM(n);
   RotateBytes(tmp,in,n);
   return BN_bin2bn(tmp,n,&big)!=0;
 }
diff --git a/data.c b/data.c
index 897368627fee0a7d33f6a27b2d4012746bc4f392..332ec0b40848672e83d2d03e6c02f33958542a4d 100644 (file)
--- a/data.c
+++ b/data.c
@@ -763,6 +763,21 @@ void cPlainKeys::ExternalUpdate(void)
     }
 }
 
+bool cPlainKeys::NewKeyParse(const char *line)
+{
+  cPlainKey *nk=NewFromType(toupper(line[0]));
+  if(nk && nk->Parse(line)) {
+    cPlainKey *k=0;
+    while((k=FindKeyNoTrig(nk->type,nk->id,nk->keynr,-1,k)))
+      if(k->Cmp(nk)) break;
+    if(!k) {
+      AddNewKey(nk,2,true);
+      return true;
+      }
+    }
+  return false;
+}
+
 void cPlainKeys::Action(void)
 {
   last.Set(EXT_AU_MIN);
@@ -774,17 +789,7 @@ void cPlainKeys::Action(void)
     while(fgets(buff,sizeof(buff),pipe)) {
       char *line=skipspace(stripspace(buff));
       if(line[0]==0 || line[0]==';' || line[0]=='#') continue;
-      cPlainKey *nk=NewFromType(toupper(line[0]));
-      if(nk && nk->Parse(line)) {
-        cPlainKey *k=0;
-        while((k=FindKeyNoTrig(nk->type,nk->id,nk->keynr,-1,k)))
-          if(k->Cmp(nk)) break;
-        if(!k) {
-          AddNewKey(nk,2,true);
-          nk=0;
-          }
-        }
-      delete nk;
+      NewKeyParse(line);
       }
     }
   pipe.Close();
diff --git a/data.h b/data.h
index 02ca51d5d032601c2d91ae5aabc6b371036d50d0..26500648473884248bb436d7e8f1575c09c29921 100644 (file)
--- a/data.h
+++ b/data.h
@@ -263,6 +263,7 @@ public:
   cPlainKey *FindKey(int Type, int Id, int Keynr, int Size, cPlainKey *key=0);
   cPlainKey *FindKeyNoTrig(int Type, int Id, int Keynr, int Size, cPlainKey *key=0);
   bool NewKey(int Type, int Id, int Keynr, void *Key, int Keylen);
+  bool NewKeyParse(const char *line);
   void HouseKeeping(void);
   };
 
index e8a8f9fb52a332d6468ee050dac189b31d5a182e..9f92029038f7deb1524c12b60a5cededc8c20761 100644 (file)
--- a/filter.c
+++ b/filter.c
@@ -222,19 +222,23 @@ void cAction::Priority(int Pri)
 void cAction::Action(void)
 {
   if(pri>0) SetPriority(pri);
+  struct pollfd *pfd=0;
   while(Running()) {
-    int num=filters.Count();
-    if(num<=0) {
+    if(filters.Count()<=0) {
       cCondWait::SleepMs(100);
       }
     else {
       // first build pfd data
       Lock();
+      delete pfd; pfd=new struct pollfd[filters.Count()];
+      if(!pfd) {
+        PRINTF(L_GEN_ERROR,"action %s: pollfd: out of memory",id);
+        break;
+        }
+      int num=0;
       cPidFilter *filter;
-      struct pollfd pfd[num];
-      num=0;
-      memset(pfd,0,sizeof(pfd));
       for(filter=filters.First(); filter; filter=filters.Next(filter)) {
+        memset(&pfd[num],0,sizeof(struct pollfd));
         pfd[num].fd=filter->fd;
         pfd[num].events=POLLIN;
         num++;
@@ -289,4 +293,5 @@ void cAction::Action(void)
       Unlock();
       }
     }
+  delete pfd;
 }
diff --git a/log.h b/log.h
index 7f4a4f6d16a53026f6ad7b6fe6a600414d4185c0..38fa86b644586e0c12be711e94c6e027a5bd44c1 100644 (file)
--- a/log.h
+++ b/log.h
 
 #define ADD_MODULE(MOD,NAME) static bool __add_mod_ ## NAME = cLogging::AddModule(MOD,&NAME);
 
-#define PRINTF(c,t...)      cLogging::Printf((c),t)
+#define PRINTF(c,...)       cLogging::Printf((c),__VA_ARGS__)
 #define PUTS(c,t)           cLogging::Puts((c),(t))
 #define PUTLB(c,lb)         cLogging::PutLB((c),(lb))
-#define HEXDUMP(c,d,n,t...) cLogging::Dump((c),(d),(n),t)
-#define LDUMP(c,d,n,t...)   cLogging::LineDump((c),(d),(n),t)
+#define HEXDUMP(c,d,n,...)  cLogging::Dump((c),(d),(n),__VA_ARGS__)
+#define LDUMP(c,d,n,...)    cLogging::LineDump((c),(d),(n),__VA_ARGS__)
 #define LOG(c)              cLogging::Enabled((c))
 
 // backward compatibility
@@ -50,7 +50,7 @@
 
 #define LBSTART(c)          do { int __c=(c); if(LOG(__c)) { cLogLineBuff __llb(__c)
 #define LBSTARTF(c)         do { int __c=(c); { cLogLineBuff __llb(__c)
-#define LBPUT(t...)         __llb.Printf(t)
+#define LBPUT(...)          __llb.Printf(__VA_ARGS__)
 #define LBFLUSH()           __llb.Flush()
 #define LBEND( )            } } while(0)
 
diff --git a/misc.h b/misc.h
index d6404a1c0c7181c77b0b6d03bf31cdf9e696b4ba..f24f1ff346b5ff36b8924373148d9a2afd7f87d0 100644 (file)
--- a/misc.h
+++ b/misc.h
 #define WORD(buffer,index,mask) (((buffer[(index)]<<8) + buffer[(index)+1]) & mask)
 #define SCT_LEN(sct) (3+(((sct)[1]&0x0f)<<8)+(sct)[2])
 
+// replacement for variable-sized arrays
+#define AUTOARRAY(type,size) (type *)alloca(sizeof(type)*(size))
+#define AUTOMEM(size)        (unsigned char *)alloca(size)
+
 // ----------------------------------------------------------------
 
 #define DEV_DVB_FRONTEND "frontend"
diff --git a/parse.c b/parse.c
index 856a674305f46a4915b90c258c32e546968879f5..429f1442e4c579b531e3edbe51ae14d02ae68616 100644 (file)
--- a/parse.c
+++ b/parse.c
@@ -406,7 +406,7 @@ int cProviderViaccess::Assemble(cAssembleData *ad)
 
     case 0x8E:
       if(sharedEmm) {
-        unsigned char tmp[len+sharedLen];
+        unsigned char *tmp=AUTOMEM(len+sharedLen);
         unsigned char *ass=(unsigned char *)cParseViaccess::NanoStart(data);
         len-=(ass-data);
         if((data[6]&2)==0) {
@@ -635,7 +635,7 @@ int cCardCryptoworks::Assemble(cAssembleData *ad)
     case 0x86:
       if(sharedEmm) {
         int alen=len-5 + sharedLen-12;
-        unsigned char tmp[alen];
+        unsigned char *tmp=AUTOMEM(alen);
         memcpy(tmp,&data[5],len-5);
         memcpy(tmp+len-5,&sharedEmm[12],sharedLen-12);
 
index cb87c2793a33d115bc09fda3fc19b024ce84fbd5..6b231b96c1974bbaff44558c31e89fc32273c8b1 100644 (file)
@@ -6,7 +6,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: VDR 1.5.9\n"
 "Report-Msgid-Bugs-To: <noone@nowhere.org>\n"
-"POT-Creation-Date: 2007-10-27 17:16+0200\n"
+"POT-Creation-Date: 2007-12-19 18:49+0100\n"
 "PO-Revision-Date: 2007-08-27 12:45+0200\n"
 "Last-Translator: somebody\n"
 "Language-Team: somebody\n"
@@ -160,6 +160,21 @@ msgstr "Cardclient: sofort verbinden"
 msgid "Nagra: min. ECM processing time"
 msgstr "Nagra: min. ECM Bearbeitungszeit"
 
+msgid "Nagra2: drop EMM-S packets"
+msgstr "Nagra2: EMM-S Pakete verwerfen"
+
+msgid "Nagra2: Enable AUXserver"
+msgstr "Nagra2: AUXserver aktivieren"
+
+msgid "Nagra2: AUXserver hostname"
+msgstr "Nagra2: AUXserver Hostname"
+
+msgid "Nagra2: AUXserver port"
+msgstr "Nagra2: AUXserver Port"
+
+msgid "Nagra2: AUXserver password"
+msgstr "Nagra2: AUXserver Passwort"
+
 msgid "don't touch"
 msgstr "nicht ändern"
 
index cfbfad2e46043c2ace70c73e6d6a09d622fe8040..2447c7dc1ec19b4a2e306867017db9f63b026e5c 100644 (file)
@@ -6,7 +6,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: VDR 1.5.9\n"
 "Report-Msgid-Bugs-To: <noone@nowhere.org>\n"
-"POT-Creation-Date: 2007-10-27 17:16+0200\n"
+"POT-Creation-Date: 2007-12-19 18:52+0100\n"
 "PO-Revision-Date: 2007-08-27 12:45+0200\n"
 "Last-Translator: somebody\n"
 "Language-Team: somebody\n"
@@ -116,7 +116,7 @@ msgid "Update keys (AU)"
 msgstr "Tilausten päivitys (AU)"
 
 msgid "Start AU on EPG scan"
-msgstr ""
+msgstr "Aloita AU EPG-päivityksessä"
 
 msgid "Concurrent FF streams"
 msgstr "Yhtäaikainen salauksenpurku (FF)"
@@ -160,6 +160,21 @@ msgstr "Korttiasiakas: yhdist
 msgid "Nagra: min. ECM processing time"
 msgstr "Nagra: Min. ECM-prosessointiaika"
 
+msgid "Nagra2: drop EMM-S packets"
+msgstr ""
+
+msgid "Nagra2: Enable AUXserver"
+msgstr ""
+
+msgid "Nagra2: AUXserver hostname"
+msgstr ""
+
+msgid "Nagra2: AUXserver port"
+msgstr ""
+
+msgid "Nagra2: AUXserver password"
+msgstr ""
+
 msgid "don't touch"
 msgstr "älä koske"
 
index fb682c62d09142e9e6c682b07574b8b3414855cb..6fd88fe809e1f6b86bdb80869ab1f827a715dced 100644 (file)
@@ -6,7 +6,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: VDR 1.5.9\n"
 "Report-Msgid-Bugs-To: <noone@nowhere.org>\n"
-"POT-Creation-Date: 2007-10-27 17:16+0200\n"
+"POT-Creation-Date: 2007-12-19 18:52+0100\n"
 "PO-Revision-Date: 2007-08-27 12:45+0200\n"
 "Last-Translator: somebody\n"
 "Language-Team: somebody\n"
@@ -160,6 +160,21 @@ msgstr "Cardclient: connecter immediatement"
 msgid "Nagra: min. ECM processing time"
 msgstr "Nagra: min. durée du processus ECM"
 
+msgid "Nagra2: drop EMM-S packets"
+msgstr ""
+
+msgid "Nagra2: Enable AUXserver"
+msgstr ""
+
+msgid "Nagra2: AUXserver hostname"
+msgstr ""
+
+msgid "Nagra2: AUXserver port"
+msgstr ""
+
+msgid "Nagra2: AUXserver password"
+msgstr ""
+
 msgid "don't touch"
 msgstr "Ne pas modifier"
 
index d608902968750d25a4d83304e800afa8c22bc55d..9744b77e20bf83cd1fb84f9ff4f4aeee53c18dbd 100644 (file)
@@ -6,7 +6,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: VDR 1.5.11\n"
 "Report-Msgid-Bugs-To: <noone@nowhere.org>\n"
-"POT-Creation-Date: 2007-11-08 12:39+0100\n"
+"POT-Creation-Date: 2007-12-19 18:52+0100\n"
 "PO-Revision-Date: 2007-11-01 16:45+0200\n"
 "Last-Translator: jv\n"
 "Language-Team: somebody\n"
@@ -160,6 +160,21 @@ msgstr "Kliens: csatlakozzon azonnal"
 msgid "Nagra: min. ECM processing time"
 msgstr "Nagra: min. ECM feldolgozási idő"
 
+msgid "Nagra2: drop EMM-S packets"
+msgstr ""
+
+msgid "Nagra2: Enable AUXserver"
+msgstr ""
+
+msgid "Nagra2: AUXserver hostname"
+msgstr ""
+
+msgid "Nagra2: AUXserver port"
+msgstr ""
+
+msgid "Nagra2: AUXserver password"
+msgstr ""
+
 msgid "don't touch"
 msgstr "ne bántsd"
 
index dc64af78f2e691344141354ebcff815d4421ea35..273b6dc70f6a414dd433c00e6e8d4a2cb2e69e83 100644 (file)
@@ -6,7 +6,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: VDR 1.5.9\n"
 "Report-Msgid-Bugs-To: <noone@nowhere.org>\n"
-"POT-Creation-Date: 2007-10-27 17:16+0200\n"
+"POT-Creation-Date: 2007-12-19 18:52+0100\n"
 "PO-Revision-Date: 2007-08-27 12:45+0200\n"
 "Last-Translator: somebody\n"
 "Language-Team: somebody\n"
@@ -160,6 +160,21 @@ msgstr ""
 msgid "Nagra: min. ECM processing time"
 msgstr ""
 
+msgid "Nagra2: drop EMM-S packets"
+msgstr ""
+
+msgid "Nagra2: Enable AUXserver"
+msgstr ""
+
+msgid "Nagra2: AUXserver hostname"
+msgstr ""
+
+msgid "Nagra2: AUXserver port"
+msgstr ""
+
+msgid "Nagra2: AUXserver password"
+msgstr ""
+
 msgid "don't touch"
 msgstr ""
 
index 143180ba8971d5873e6300066dd9c215171f8628..5cc85db35e56c6321c92f01a1a3c80d7059bf685 100644 (file)
@@ -6,7 +6,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: VDR 1.5.9\n"
 "Report-Msgid-Bugs-To: <noone@nowhere.org>\n"
-"POT-Creation-Date: 2007-10-27 17:16+0200\n"
+"POT-Creation-Date: 2007-12-19 18:52+0100\n"
 "PO-Revision-Date: 2007-08-27 12:45+0200\n"
 "Last-Translator: somebody\n"
 "Language-Team: somebody\n"
@@ -160,6 +160,21 @@ msgstr "Cardclient: direct contact maken"
 msgid "Nagra: min. ECM processing time"
 msgstr "Nagra: min. ECM bewerkingstijd"
 
+msgid "Nagra2: drop EMM-S packets"
+msgstr ""
+
+msgid "Nagra2: Enable AUXserver"
+msgstr ""
+
+msgid "Nagra2: AUXserver hostname"
+msgstr ""
+
+msgid "Nagra2: AUXserver port"
+msgstr ""
+
+msgid "Nagra2: AUXserver password"
+msgstr ""
+
 msgid "don't touch"
 msgstr "niet wijzigen"
 
index 5e5e4d7c2ba69f5bc3f37965d1839c6d19b95a15..184cb325227e411d30e5bb6a68b638252b9dd746 100644 (file)
@@ -6,7 +6,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: VDR 1.5.9\n"
 "Report-Msgid-Bugs-To: <noone@nowhere.org>\n"
-"POT-Creation-Date: 2007-10-27 17:16+0200\n"
+"POT-Creation-Date: 2007-12-19 18:52+0100\n"
 "PO-Revision-Date: 2007-08-27 12:45+0200\n"
 "Last-Translator: somebody\n"
 "Language-Team: somebody\n"
@@ -160,6 +160,21 @@ msgstr "Klient karty: pod
 msgid "Nagra: min. ECM processing time"
 msgstr "Nagra: min. czas przetwarzania ECM"
 
+msgid "Nagra2: drop EMM-S packets"
+msgstr ""
+
+msgid "Nagra2: Enable AUXserver"
+msgstr ""
+
+msgid "Nagra2: AUXserver hostname"
+msgstr ""
+
+msgid "Nagra2: AUXserver port"
+msgstr ""
+
+msgid "Nagra2: AUXserver password"
+msgstr ""
+
 msgid "don't touch"
 msgstr "nie dotykaj"
 
index 785adc1ea3d564f3da522430f4857eff0d51f2cb..3dad9031df5267d2b42f32581fbbf02feb57b556 100644 (file)
@@ -6,7 +6,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: VDR 1.5.9\n"
 "Report-Msgid-Bugs-To: <noone@nowhere.org>\n"
-"POT-Creation-Date: 2007-10-27 17:16+0200\n"
+"POT-Creation-Date: 2007-12-19 18:52+0100\n"
 "PO-Revision-Date: 2007-09-17 23:03+0200\n"
 "Last-Translator: <bikalexander@gmail.com>\n"
 "Language-Team: ru\n"
@@ -161,6 +161,21 @@ msgstr "Cardclient: 
 msgid "Nagra: min. ECM processing time"
 msgstr "Nagra: ÜØÝ. ÒàÕÜï ÞÑàÐÑÞâÚØ ECM"
 
+msgid "Nagra2: drop EMM-S packets"
+msgstr ""
+
+msgid "Nagra2: Enable AUXserver"
+msgstr ""
+
+msgid "Nagra2: AUXserver hostname"
+msgstr ""
+
+msgid "Nagra2: AUXserver port"
+msgstr ""
+
+msgid "Nagra2: AUXserver password"
+msgstr ""
+
 msgid "don't touch"
 msgstr "ÝÕ Ø×ÜÕÝïâì"
 
index 31df669ca62cff16bd02e6cf897ffd6c76b62af8..1fb168cd0b590836e5cdfd9f26cfbc1e77e0450b 100644 (file)
--- a/po/sc.pot
+++ b/po/sc.pot
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: <noone@nowhere.org>\n"
-"POT-Creation-Date: 2007-11-08 12:39+0100\n"
+"POT-Creation-Date: 2007-12-19 18:52+0100\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -162,6 +162,21 @@ msgstr ""
 msgid "Nagra: min. ECM processing time"
 msgstr ""
 
+msgid "Nagra2: drop EMM-S packets"
+msgstr ""
+
+msgid "Nagra2: Enable AUXserver"
+msgstr ""
+
+msgid "Nagra2: AUXserver hostname"
+msgstr ""
+
+msgid "Nagra2: AUXserver port"
+msgstr ""
+
+msgid "Nagra2: AUXserver password"
+msgstr ""
+
 msgid "don't touch"
 msgstr ""
 
index 11458380ba5b855d54ea102c4a13de7b93029572..04fcf04f53574d2a100d848c6f16895bffa1cafb 100644 (file)
@@ -6,7 +6,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: VDR 1.5.9\n"
 "Report-Msgid-Bugs-To: <noone@nowhere.org>\n"
-"POT-Creation-Date: 2007-10-27 17:16+0200\n"
+"POT-Creation-Date: 2007-12-19 18:52+0100\n"
 "PO-Revision-Date: 2007-08-27 12:45+0200\n"
 "Last-Translator: somebody\n"
 "Language-Team: somebody\n"
@@ -160,6 +160,21 @@ msgstr ""
 msgid "Nagra: min. ECM processing time"
 msgstr ""
 
+msgid "Nagra2: drop EMM-S packets"
+msgstr ""
+
+msgid "Nagra2: Enable AUXserver"
+msgstr ""
+
+msgid "Nagra2: AUXserver hostname"
+msgstr ""
+
+msgid "Nagra2: AUXserver port"
+msgstr ""
+
+msgid "Nagra2: AUXserver password"
+msgstr ""
+
 msgid "don't touch"
 msgstr ""
 
diff --git a/sc.c b/sc.c
index b76b6874ce973f39771047e4d85456cce0646919..a207da4cb5cad1630ae420def13418677fd6e286 100644 (file)
--- a/sc.c
+++ b/sc.c
@@ -1369,10 +1369,14 @@ const char **cScPlugin::SVDRPHelpPages(void)
   static const char *HelpPages[] = {
     "RELOAD\n"
     "    Reload all configuration files.",
+    "KEY <string>\n",
+    "    Add key to the key database (as if it was received from EMM stream).",
     "LOG <on|off> <class>[,<class>...]\n"
     "    Turn the given message class(es) on or off.",
     "LOGCFG\n"
     "    Display available message classes and their status.",
+    "LOGFILE <on|off> [<filename>]\n"
+    "    Enables/disables logging to file and optionaly sets the filename.",
     NULL
     };
   return HelpPages;
@@ -1394,9 +1398,22 @@ cString cScPlugin::SVDRPCommand(const char *Command, const char *Option, int &Re
         }
       }
     }
+  else if(!strcasecmp(Command,"KEY")) {
+    if(Option && *Option) {
+      if(keys.NewKeyParse(skipspace(Option)))
+        return "Key update successfull";
+      else {
+        ReplyCode=901;
+        return "Key already known or invalid key format";
+        }
+      }
+    else { ReplyCode=501; return "Missing args"; }
+    }
   else if(!strcasecmp(Command,"LOG")) {
     if(Option && *Option) {
-      char *opt=strdup(Option);
+      char tmp[1024];
+      strn0cpy(tmp,Option,sizeof(tmp));
+      char *opt=tmp;
       opt=skipspace(opt);
       bool mode;
       if(!strncasecmp(opt,"ON ",3)) { mode=true; opt+=3; }
@@ -1436,6 +1453,35 @@ cString cScPlugin::SVDRPCommand(const char *Command, const char *Option, int &Re
     if(lb.Length()>0) return lb.Line();
     ReplyCode=901; return "No config available";
     }
+  else if(!strcasecmp(Command,"LOGFILE")){
+    if(Option && *Option) {
+      char tmp[1024];
+      strn0cpy(tmp,Option,sizeof(tmp));
+      char *opt=tmp;
+      opt=skipspace(opt);
+      bool mode;
+      if(!strncasecmp(opt,"ON",2)) { mode=true; opt+=2; }
+      else if(!strncasecmp(opt,"OFF",3)) { mode=false; opt+=3; }
+      else { ReplyCode=501; return "Bad mode, valid: on off"; }
+      cLineBuff lb(256);
+      if(mode) {
+        logcfg.logFile=true;
+        if(*opt==' ' || *opt=='\t') {
+          opt=stripspace(skipspace(opt));
+          strn0cpy(logcfg.logFilename,opt,sizeof(logcfg.logFilename));
+          }
+        lb.Printf("logging to file enabled, file %s",logcfg.logFilename);
+        }
+      else {
+        logcfg.logFile=false;
+        lb.Printf("logging to file disabled");
+        }
+      ScSetup.Store(true);
+      Setup.Save();
+      return lb.Line();
+      }
+    else { ReplyCode=501; return "Missing args"; }
+    }
   return NULL;
 }
 
index 5391daa52815be116d7bab4484ce691e5f165791..50d43a34392858daa8415470283f66433932e18c 100644 (file)
@@ -961,7 +961,7 @@ int cSmartCard::Read(unsigned char *data, int len, int to)
 
 int cSmartCard::Write(const unsigned char *data, int len)
 {
-  unsigned char tmp[len];
+  unsigned char *tmp=AUTOMEM(len);
   if(atr->convention==SM_INDIRECT) {
     memcpy(tmp,data,len);
     Invert(tmp,len);
@@ -969,7 +969,7 @@ int cSmartCard::Write(const unsigned char *data, int len)
     }
   int r=ser->Write(data,len);
   if(r>0) {
-    unsigned char buff[r];
+    unsigned char *buff=AUTOMEM(r);
     int rr=ser->Read(buff,r,cfg->serTO);
     if(rr<0) r=rr;
     }
index 3011bcc1fdcb55cf9af075ff6e7f50942b447409..eec12fe98fcc706892bd5ea726378f7c6afbc966 100644 (file)
@@ -121,7 +121,7 @@ void cBNKey::Get(void *mem)
 
 cString cBNKey::Print(void)
 {
-  unsigned char mem[keylen];
+  unsigned char *mem=AUTOMEM(keylen);
   if(rotate) key->PutLE(mem,keylen); else key->Put(mem,keylen);
   char *str=(char *)malloc(keylen*2+2);
   if(str) HexStr(str,mem,keylen);
index 32e93254591741c77556e1cdc2bd11617d4c4e20..8b77b91922fd7ef44ab62ca74153e29d9e5f6779 100644 (file)
--- a/system.c
+++ b/system.c
@@ -525,20 +525,20 @@ int cMsgCache::Get(const unsigned char *msg, int len, unsigned char *store)
     }
   else {
     id=(s-&caches[0])+1;
-    switch(s->mode) {
-      case GOOD:
-        if(store && storeSize>0)
-          memcpy(store,&stores[(id-1)*storeSize],storeSize);
-        PRINTF(L_CORE_MSGCACHE,"%d/%p: msg is cached as GOOD (%d)",getpid(),this,id);
-        return 0;
-      case FAIL1...FAIL2:
-        PRINTF(L_CORE_MSGCACHE,"%d/%p: msg is cached as FAIL%d (%d)",getpid(),this,s->mode,id);
-        s->mode|=QUEUED;
-        return id;
-      case FAILN:
-      default:
-        PRINTF(L_CORE_MSGCACHE,"%d/%p: msg is cached as FAILN (%d)",getpid(),this,id);
-        return -1;
+    if(s->mode==GOOD) {
+      if(store && storeSize>0)
+        memcpy(store,&stores[(id-1)*storeSize],storeSize);
+      PRINTF(L_CORE_MSGCACHE,"%d/%p: msg is cached as GOOD (%d)",getpid(),this,id);
+      return 0;
+      }
+    else if(s->mode>=FAIL1 && s->mode<=FAIL2) {
+      PRINTF(L_CORE_MSGCACHE,"%d/%p: msg is cached as FAIL%d (%d)",getpid(),this,s->mode,id);
+      s->mode|=QUEUED;
+      return id;
+      }
+    else {
+      PRINTF(L_CORE_MSGCACHE,"%d/%p: msg is cached as FAILN (%d)",getpid(),this,id);
+      return -1;
       }
     }
 }
@@ -559,23 +559,18 @@ int cMsgCache::Cache(int id, bool result, const unsigned char *store)
     return 0;
     }
   else {
-    switch(s->mode&MASK) {
-      case GOOD:
-        s->mode=FREE;
-        // fall through
-      case FREE:
-      case FAIL1...FAIL2:
-        s->mode=(s->mode&MASK)+1;
-        if(s->mode<maxFail) {
-          LBPUT("(FAIL%d)",s->mode);
-          break;
-          }
-        // fall through
-      case FAILN:
-        s->mode=FAILN;
-        LBPUT("(FAILN)");
-        break;
+    int m=s->mode&MASK;
+    if(m==GOOD)
+      m=s->mode=FREE;
+    if(m==FREE || (m>=FAIL1 && m<=FAIL2)) {
+      s->mode=(s->mode&MASK)+1;
+      if(s->mode<maxFail)
+        LBPUT("(FAIL%d)",s->mode);
+      else
+        m=s->mode=FAILN;
       }
+    if(m==FAILN)
+      LBPUT("(FAILN)");
     return s->mode;
     }
   LBEND();
index 212f786200d25fc6daf6dd909dd602ac298c36c4..7d5c09623a41ea5aa6c81c30c57a83079b3bd775 100644 (file)
@@ -100,13 +100,13 @@ bool cCardClientCommon::ParseKeyConfig(const char *config, int *num)
 
 bool cCardClientCommon::SendMsg(cNetSocket *so, const unsigned char *data, int len)
 {
-  unsigned char buff2[minMsgLen];
+  unsigned char *buff2=AUTOMEM(minMsgLen);
   if(len<minMsgLen) {
     memcpy(buff2,data,len);
     memset(buff2+len,0,minMsgLen-len);
     data=buff2; len=minMsgLen;
     }
-  unsigned char buff[len+16];
+  unsigned char *buff=AUTOMEM(len+16);
   const int l=Encrypt(data,len,buff);
   if(l>0) { data=buff; len=l; }
   return cCardClient::SendMsg(so,data,len);
@@ -177,7 +177,7 @@ bool cCardClientCommon::ProcessEMM(int caSys, const unsigned char *source)
       const int length=SCT_LEN(source);
       int id=msEMM.Get(source,length,0);
       if(id>0) {
-        unsigned char buff[length+32];
+        unsigned char *buff=AUTOMEM(length+32);
         buff[0]=0x03;
         buff[1]=(caSys>>8);
         buff[2]=(caSys&0xFF);
@@ -201,7 +201,7 @@ bool cCardClientCommon::ProcessECM(const cEcmInfo *ecm, const unsigned char *sou
   while(exclusive) sleepCond.Wait(*this);
   if((so.Connected() || Login()) && (!emmProcessing || CanHandle(ecm->caId))) {
     const int length=SCT_LEN(source);
-    unsigned char buff[length+32];
+    unsigned char *buff=AUTOMEM(length+32);
     int n;
     while((n=RecvMsg(&so,buff,16,0))>0) HandleEMMRequest(buff,n);
     buff[0]=0x02;
@@ -467,7 +467,7 @@ bool cCardClientCamd35::SendBlock(struct CmdBlock *cb, int datalen)
   cb->udp_header.len=datalen;
   cb->udp_header.crc=bswap_32(crc32_le(0,&cb->data[0],datalen));
   datalen+=CBSIZE(cb);
-  unsigned char buff[datalen+UCSIZE(cb)+16];
+  unsigned char *buff=AUTOMEM(datalen+UCSIZE(cb)+16);
   *((unsigned int *)buff)=ucrc;
   HEXDUMP(L_CC_CAMDEXTR,cb,datalen+UCSIZE(cb),"send:");
   const int l=Encrypt((unsigned char *)cb+UCSIZE(cb),datalen,buff+UCSIZE(cb));
index c807d33c801136573d20590279b2fad8bb21edcc..c68ca6317036e17a8d1e6ec65c243a0ece9732ba 100644 (file)
@@ -281,7 +281,7 @@ void cCryptoworks::DecryptDES(unsigned char *data, unsigned char algo, const uns
 
 bool cCryptoworks::DecryptRSA(unsigned char *data, int len, unsigned char algo, const unsigned char *key22, BIGNUM *mod)
 {
-  unsigned char buf[64], mask[len];
+  unsigned char buf[64], *mask=AUTOMEM(len);
 
   LDUMP(L_SYS_VERBOSE,data+len,8,"rsa in:");
   memcpy(buf,data+len,8);
@@ -379,7 +379,7 @@ bool cPlainKeyCryptoworks::Parse(const char *line)
       keylen=IsBNKey() ? PLAINLEN_CW_R : PLAINLEN_CW_D;
       }
     if(ok) {
-      unsigned char skey[keylen];
+      unsigned char *skey=AUTOMEM(keylen);
       if(GetHex(line,skey,keylen)) {
         SetBinKey(skey,keylen);
         return true;
index 98dc7f85092f97fdb8c08b545d2e46e29dab89ed..9f180730db0ea5e39d64f86747b97587e807b244 100644 (file)
@@ -428,6 +428,7 @@ void cSystemIrd::ProcessEMM(int pid, int caid, unsigned char *buffer)
   if((numKeys>0 && (id[0]!=lastKey || numKeys>1)) || mk) {
     memcpy(savebuf,buffer,n); // save the buffer
     cIrdCardInfo *ci=Icards.First();
+    unsigned char *chkkey=AUTOMEM(max(sizeof(ci->PMK),sizeof(ci->HMK)));
     while(ci) {
       ci->hexBase=cParseIrdeto::AddrBase(buffer);
       if((numKeys>0         && (ci->cProviderIrdeto::MatchEMM(buffer) || CheckNull(ci->provId,sizeof(ci->provId)) )) ||
@@ -439,7 +440,6 @@ void cSystemIrd::ProcessEMM(int pid, int caid, unsigned char *buffer)
           lastKey=id[i];
           SessionKeyCrypt(pk[i],ci->PMK,date);
           }
-        unsigned char chkkey[max(sizeof(ci->PMK),sizeof(ci->HMK))];
         int keylen;
         if(mk) {
           memcpy(chkkey,ci->HMK,sizeof(ci->HMK)); // key is modified in decryptIrd()
index b283b00a40e9ef34146ee3d36894bfe451e12465..054920ec2ace7dfc3135562cd72993c922d334c5 100644 (file)
@@ -25,8 +25,8 @@
 #include "cpu.h"
 #include "log-nagra.h"
 
-#define LOGLBPUT(t...)  loglb->Printf(t)
-#define CCLOGLBPUT(t...)  do { if(doDisAsm) loglb->Printf(t); } while(0)
+#define LOGLBPUT(...)   loglb->Printf(__VA_ARGS__)
+#define CCLOGLBPUT(...) do { if(doDisAsm) loglb->Printf(__VA_ARGS__); } while(0)
 
 // -- cMapMem ------------------------------------------------------------------
 
@@ -79,7 +79,7 @@ cMapRom::~cMapRom()
 
 bool cMapRom::IsFine(void)
 {
-  return (addr!=0);
+  return addr!=0 && size>0;
 }
 
 unsigned char cMapRom::Get(unsigned short ea)
@@ -146,6 +146,7 @@ c6805::c6805(void) {
   hasReadHandler=hasWriteHandler=false;
   ClearBreakpoints();
   InitMapper();
+  ResetCycles();
   memset(stats,0,sizeof(stats));
   loglb=new cLineBuff(128);
 }
@@ -180,7 +181,7 @@ bool c6805::AddMapper(cMap *map, unsigned short start, int size, unsigned char s
       }
     else PRINTF(L_SYS_EMU,"6805: too many mappers");
     }
-  else PRINTF(L_SYS_EMU,"6805: mapper not ready");
+  else PRINTF(L_SYS_EMU,"6805: mapper not ready (start=%02x:%04x size=%04x)",seg,start,size);
   delete map;
   return false;
 }
@@ -270,6 +271,11 @@ void c6805::PopCr(void)
   cr=pop();
 }
 
+void c6805::Push(unsigned char c)
+{
+  push(c);
+}
+
 void c6805::AddBreakpoint(unsigned short addr)
 {
   if(numBp<MAX_BREAKPOINTS) {
@@ -285,6 +291,19 @@ void c6805::ClearBreakpoints(void)
   memset(bp,0,sizeof(bp));
 }
 
+void c6805::AddCycles(unsigned int num)
+{
+  if(num>0) {
+    clockcycles+=num;
+    TimerHandler(num);
+    }
+}
+
+void c6805::ResetCycles(void)
+{
+  clockcycles=0;
+}
+
 static const char * const ops[] = {
 //         0x00    0x01    0x02    0x03    0x04    0x05    0x06    0x07    0x08    0x09    0x0a    0x0b    0x0c    0x0d    0x0e    0x0f
 /* 0x00 */ "BRSET","BRCLR","BRSET","BRCLR","BRSET","BRCLR","BRSET","BRCLR","BRSET","BRCLR","BRSET","BRCLR","BRSET","BRCLR","BRSET","BRCLR",
@@ -333,6 +352,26 @@ static const char opFlags[] = {
 /* 0xf0 */  0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x05, 0x05, 0x05, 0x05, 0x00, 0x00, 0x05, 0x06,
   };
 
+static const unsigned char clock_cycles[] = {
+//         00  01  02  03  04  05  06  07  08  09  0a  0b  0c  0d  0e  0f
+/* 0x00 */  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  0,  0,  0,  0,  0,  0,
+/* 0x10 */  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  0,  0,  0,  0,  0,  0,
+/* 0x20 */  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,
+/* 0x30 */  5,  0,  0,  5,  5,  0,  5,  5,  5,  5,  5,  0,  5,  4,  5,  5,
+/* 0x40 */  3,  0, 11,  3,  3,  0,  3,  3,  3,  3,  3,  0,  3,  3,  3,  3,
+/* 0x50 */  3,  0,  0,  3,  3,  0,  3,  3,  3,  3,  3,  0,  3,  3,  3,  3,
+/* 0x60 */  6,  0,  0,  6,  6,  0,  6,  6,  6,  6,  6,  0,  6,  5,  6,  6,
+/* 0x70 */  5,  0,  0,  5,  5,  0,  5,  5,  5,  5,  5,  0,  5,  4,  5,  5,
+/* 0x80 */  9,  6,  0, 10,  4,  4,  4,  0,  3,  3,  3,  0,  0,  0,  2,  2,
+/* 0x90 */  1,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
+/* 0xa0 */  2,  2,  2,  2,  2,  2,  2,  0,  2,  2,  2,  2,  0,  6,  2,  0,
+/* 0xb0 */  3,  3,  3,  3,  3,  3,  3,  4,  3,  3,  3,  3,  2,  5,  3,  4,
+/* 0xc0 */  4,  4,  4,  4,  4,  4,  4,  5,  4,  4,  4,  4,  3,  6,  4,  5,
+/* 0xd0 */  5,  5,  5,  5,  5,  5,  5,  6,  5,  5,  5,  5,  4,  7,  5,  6,
+/* 0xe0 */  4,  4,  4,  4,  4,  4,  4,  5,  4,  4,  4,  4,  3,  6,  4,  5,
+/* 0xf0 */  3,  3,  3,  3,  3,  3,  3,  4,  3,  3,  3,  3,  2,  5,  3,  4, 
+  };
+
 char * c6805::PADDR(unsigned char s, unsigned short ea)
 {
   snprintf(addrBuff,sizeof(addrBuff),((ea&0x8000) && s>0)?"%2$x:%1$04x":"%04x",ea,s);
@@ -368,7 +407,7 @@ int c6805::Run(int max_count)
     count++;
 
     if(!LOG(L_SYS_DISASM) && LOG(L_SYS_DISASM80)) {
-      bool flag=(pc>=0x80 && pc<0xE0);
+      bool flag=(pc>=0x80 && pc<0x200);
       if(doDisAsm && !flag) PRINTF(disAsmLogClass,"[...]");
       doDisAsm=flag;
       }
@@ -389,47 +428,72 @@ int c6805::Run(int max_count)
     bool paged=false, vbra=false;
     unsigned char ins=Get(pc++);
     char xs='X', xi='X';
+    int cycles=0;
  
     // check pre-bytes
     switch(ins) {
       case 0x31: // use SP indexed or indirect paged mode (ST19)
+        cycles+=2;
         ins=Get(pc++);
         switch(ins) {
-          case 0x22 ... 0x27: vbra=true; PRINTF(L_SYS_EMU,"WARN: V-flag not yet calculated"); break;
+          case 0x22: case 0x23: case 0x24: case 0x25:
+          case 0x26: case 0x27:
+            vbra=true; PRINTF(L_SYS_EMU,"WARN: V-flag not yet calculated"); break;
           case 0x75:
           case 0x8D:
-          case 0xC0 ... 0xCB:
-          case 0xCE ... 0xCF:
-          case 0xD0 ... 0xDB:
-          case 0xDE ... 0xDF: paged=true; indirect=true; break;
-          case 0xE0 ... 0xEB:
-          case 0xEE ... 0xEF: idx=sp; xi='S'; break;
+          case 0xC0: case 0xC1: case 0xC2: case 0xC3:
+          case 0xC4: case 0xC5: case 0xC6: case 0xC7:
+          case 0xC8: case 0xC9: case 0xCA: case 0xCB:
+          case 0xCE: case 0xCF:
+          case 0xD0: case 0xD1: case 0xD2: case 0xD3:
+          case 0xD4: case 0xD5: case 0xD6: case 0xD7:
+          case 0xD8: case 0xD9: case 0xDA: case 0xDB:
+          case 0xDE: case 0xDF:
+            paged=true; indirect=true; break;
+          case 0xE0: case 0xE1: case 0xE2: case 0xE3:
+          case 0xE4: case 0xE5: case 0xE6: case 0xE7:
+          case 0xE8: case 0xE9: case 0xEA: case 0xEB:
+          case 0xEE: case 0xEF:
+            idx=sp; xi='S'; break;
           }
         break;
       case 0x32: // use indirect SP indexed or indirect paged Y indexed mode (ST19)
+        cycles+=2;
         ins=Get(pc++);
         switch(ins) {
-          case 0x22 ... 0x27: vbra=true; PRINTF(L_SYS_EMU,"WARN: V-flag not yet calculated"); indirect=true; break;
+          case 0x22: case 0x23: case 0x24: case 0x25:
+          case 0x26: case 0x27:
+            vbra=true; PRINTF(L_SYS_EMU,"WARN: V-flag not yet calculated"); indirect=true; break;
           case 0xC3:
-          case 0xCE ... 0xCF:
-          case 0xD0 ... 0xDB:
-          case 0xDE ... 0xDF: paged=true; indirect=true; ex=&y; idx=*ex; xs='Y'; xi='Y'; break;
-          case 0xE0 ... 0xEB:
-          case 0xEE ... 0xEF: indirect=true; idx=sp; xi='S'; break;
+          case 0xCE: case 0xCF:
+          case 0xD0: case 0xD1: case 0xD2: case 0xD3:
+          case 0xD4: case 0xD5: case 0xD6: case 0xD7:
+          case 0xD8: case 0xD9: case 0xDA: case 0xDB:
+          case 0xDE: case 0xDF:
+            paged=true; indirect=true; ex=&y; idx=*ex; xs='Y'; xi='Y'; break;
+          case 0xE0: case 0xE1: case 0xE2: case 0xE3:
+          case 0xE4: case 0xE5: case 0xE6: case 0xE7:
+          case 0xE8: case 0xE9: case 0xEA: case 0xEB:
+          case 0xEE: case 0xEF:
+            indirect=true; idx=sp; xi='S'; break;
           }
         break;
       case 0x91: // use Y register with indirect addr mode (ST7)
+        cycles++;
         indirect=true;
         // fall through
       case 0x90: // use Y register (ST7)
+        cycles++;
         ex=&y; idx=*ex; xs='Y'; xi='Y';
         ins=Get(pc++);
         break;
       case 0x92: // use indirect addr mode (ST7)
+        cycles+=2;
         indirect=true;
         ins=Get(pc++);
         break;
       }
+    AddCycles(cycles+clock_cycles[ins]);
 
     if(doDisAsm) {
       char str[8];
@@ -759,7 +823,11 @@ int c6805::Run(int max_count)
       case 0x6E:
       case 0x7E:
         op=(op<<4)|(op>>4); tst(op); break;
-      case 0x00 ... 0x0F: // BRSET BRCLR
+      //case 0x00 ... 0x0F: // BRSET BRCLR
+      case 0x00: case 0x01: case 0x02: case 0x03:
+      case 0x04: case 0x05: case 0x06: case 0x07:
+      case 0x08: case 0x09: case 0x0A: case 0x0B:
+      case 0x0C: case 0x0D: case 0x0E: case 0x0F:
         {
         int bit=(ins&0x0F)>>1;
         CCLOGLBPUT(",#%x,",bit);
@@ -767,7 +835,11 @@ int c6805::Run(int max_count)
         branch((ins&0x01) ? !cc.c:cc.c);
         break;
         }
-      case 0x10 ... 0x1F: // BSET BCLR
+      //case 0x10 ... 0x1F: // BSET BCLR
+      case 0x10: case 0x11: case 0x12: case 0x13:
+      case 0x14: case 0x15: case 0x16: case 0x17:
+      case 0x18: case 0x19: case 0x1A: case 0x1B:
+      case 0x1C: case 0x1D: case 0x1E: case 0x1F:
         {
         int bit=(ins&0x0F)>>1;
         CCLOGLBPUT(",#%x",bit);
index 9cf78523ac82abbf0da14273ff2eb79fb1385181..f8fedaa1fc0e8b07b75c24765c35512735027333 100644 (file)
@@ -88,7 +88,7 @@ public:
 
 // ----------------------------------------------------------------
 
-#define MAX_BREAKPOINTS 4
+#define MAX_BREAKPOINTS 24
 #define MAX_MAPPER      8
 #define MAX_PAGES       4
 #define PAGE_SIZE       32*1024
@@ -107,6 +107,7 @@ private:
   int nextMapper;
   int pageMap[256];
   bool indirect;
+  unsigned int clockcycles;
   //
   void InitMapper(void);
   void ClearMapper(void);
@@ -144,9 +145,14 @@ protected:
   unsigned short GetPc(void) const { return pc; }
   void PopPc(void);
   void PopCr(void);
+  void Push(unsigned char c);
+  void ResetCycles(void);
+  void AddCycles(unsigned int num);
+  unsigned int Cycles(void) { return clockcycles; }
   virtual void Stepper(void)=0;
   virtual void WriteHandler(unsigned char seg, unsigned short ea, unsigned char &op) {}
   virtual void ReadHandler(unsigned char seg, unsigned short ea, unsigned char &op) {}
+  virtual void TimerHandler(unsigned int num) {}
 private:
   unsigned int stats[256];
   char addrBuff[32];
index 185e67ed8fbebd43c4d88c1269c0f35dd00e24b1..392a837ca3176ad509ed6c73a5a848c24bc23016 100644 (file)
@@ -35,8 +35,6 @@ ADD_MODULE(L_SYS,lm_sys)
 
 int minEcmTime=400; // ms
 
-#ifndef TESTER
-
 // -- cPlainKeyNagra -----------------------------------------------------------
 
 #define PLAINLEN_NAGRA_H 8
@@ -197,8 +195,6 @@ cString cPlainKeyNagra::PrintKeyNr(void)
   return nr;
 }
 
-#endif // TESTER
-
 // -- cNagra -------------------------------------------------------------------
 
 cNagra::cNagra(void)
index b50b764d08a5b64cbd7ca24c8c90decccb27eaaa..a2c4e0a77489db68058ce33c2c0fec38e7704fe3 100644 (file)
@@ -186,22 +186,50 @@ bool cEmu::MathMapHandler(void)
 // -- cEmuRom3Core -------------------------------------------------------------
 
 class cEmuRom3Core : public cEmu {
+private:
+  bool special05;
 protected:
   virtual void Stepper(void);
+  virtual void WriteHandler(unsigned char seg, unsigned short ea, unsigned char &op);
+  virtual void ReadHandler(unsigned char seg, unsigned short ea, unsigned char &op);
   bool CoreInitSetup(void);
   bool DoMaps(bool hasExt);
+public:
+  cEmuRom3Core(void);
   };
 
-void cEmuRom3Core::Stepper(void)
+cEmuRom3Core::cEmuRom3Core(void)
 {
-  int rnd=random();
-  unsigned char mem4=Get(0x04);
-  if(!bitset(mem4,2)) {
-    Set(0x06,(rnd&0xff00)>>8);
-    Set(0x07,rnd&0xff);
+  special05=false;
+}
+
+void cEmuRom3Core::WriteHandler(unsigned char seg, unsigned short ea, unsigned char &op)
+{
+  if(ea==0x05) special05=(op&0x40)!=0;
+}
+
+void cEmuRom3Core::ReadHandler(unsigned char seg, unsigned short ea, unsigned char &op)
+{
+  if(special05) {
+    special05=false; // prevent loop
+    unsigned short start=Get(0x30C0);
+    unsigned short end=Get(0x30C1);
+    if(((ea>>8)>=start) && ((ea>>8)<=end)) op=0x00; // dataspace
+    else op=0x01;                                   // codespace
+    special05=true;
     }
+  else
+    switch(ea) {
+      case 0x06:
+      case 0x07:
+        if(!(Get(0x04)&4)) op=random()&0xFF;
+        break;
+      }
 }
 
+void cEmuRom3Core::Stepper(void)
+{}
+
 bool cEmuRom3Core::CoreInitSetup(void)
 {
   ForceSet(0x0001,1<<3,true);
@@ -403,7 +431,9 @@ bool cEmuRom10::MathMapHandler(void)
         }
       return true;
 
-    case 0x0e ... 0x10:
+    case 0x0e:
+    case 0x0F:
+    case 0x10:
       {
       const unsigned short addr=(Get(0x4d)<<8)|Get(0x4e);
       unsigned char tmp[64];
@@ -705,7 +735,7 @@ bool cSystemNagra::ProcessECM(const cEcmInfo *ecm, unsigned char *data)
   pk->Get(sessionKey);
 
   const int desLen=(ecmLen-9) & ~7; // datalen - signature - ks byte
-  unsigned char decrypted[desLen];
+  unsigned char *decrypted=AUTOMEM(desLen);
   for(int i=(desLen/8)-1; decrypt && i>=0; i--) {
     const int off=i*8;
     Decrypt(data+11+off,sessionKey,decrypted+off);
@@ -769,7 +799,7 @@ bool cSystemNagra::ProcessECM(const cEcmInfo *ecm, unsigned char *data)
       hasVerifyKey=true;
       }
     else if(doLog) PRINTF(L_SYS_KEY,"missing %04x V TYP%d key (non-fatal)",mecmProvId,keyType);
-    unsigned char decrMecmData[mecmRSALen];
+    unsigned char *decrMecmData=AUTOMEM(mecmRSALen);
     if(!DecryptECM(&mecmData[4],decrMecmData,hasVerifyKey?verifyKey:0,mecmRSALen,e1,n1,n2))
       return false;
 
@@ -870,7 +900,14 @@ void cSystemNagra::ProcessEMM(int pid, int caid, unsigned char *buffer)
     switch(emmdata[i]) { // Check filter type
       case 0x00: // One card
         i+=7; break;
-      case 0x01 ... 0x20: // Group of cards
+      case 0x01: case 0x02: case 0x03: case 0x04: // Group of cards
+      case 0x05: case 0x06: case 0x07: case 0x08:
+      case 0x09: case 0x0A: case 0x0B: case 0x0C:
+      case 0x0D: case 0x0E: case 0x0F: case 0x10:
+      case 0x11: case 0x12: case 0x13: case 0x14:
+      case 0x15: case 0x16: case 0x17: case 0x18:
+      case 0x19: case 0x1A: case 0x1B: case 0x1C:
+      case 0x1D: case 0x1E: case 0x1F: case 0x20:
         i+=emmdata[i]+0x7; break;
       case 0x3e:
         i+=6; break;
index bb3065ef77ccbe47bdd7ac72d3e6f7f68b02c854..8369d8b0a8187adb5759cfee5d06e60c1be9b9b9 100644 (file)
 
 // -- cAuxSrv ------------------------------------------------------------------
 
-/*
-#define HAS_AUXSRV
+//#define HAS_AUXSRV
 
+#ifdef HAS_AUXSRV
+#define AUX_PROTOCOL_VERSION 2
+static int auxEnabled=0;
 static int auxPort=7777;
 static char auxAddr[80]="localhost";
 static char auxPassword[250]="auxserver";
@@ -33,7 +35,7 @@ private:
   bool Login(void);
 public:
   cAuxSrv(void);
-  bool Map(int map, unsigned char *data, int len, int outlen);
+  int Map(int map, unsigned char *data, int len, int outlen);
   };
 
 cAuxSrv::cAuxSrv(void)
@@ -52,16 +54,23 @@ bool cAuxSrv::Login()
     buff[3]=l;
     memcpy(&buff[4],auxPassword,l);
     buff[4+l]=0xFF;
-    if(so.Write(buff,l+5)==l+5) return true;
+    if(so.Write(buff,l+5)==l+5 &&
+       so.Read(buff,sizeof(buff))>=9 &&
+       buff[0]==0x7A && buff[1]==0xA7 && buff[2]==0x00 && buff[3]==0x04 && buff[8]==0xff &&
+       ((buff[4]<<8)|buff[5])==AUX_PROTOCOL_VERSION) return true;
     PRINTF(L_SYS_MAP,"auxsrv: login write failed");
     }
   so.Disconnect();
   return false;
 }
 
-bool cAuxSrv::Map(int map, unsigned char *data, int len, int outlen)
+int cAuxSrv::Map(int map, unsigned char *data, int len, int outlen)
 {
-  if(len>500 || outlen>500) return false;
+  if(!auxEnabled) {
+    PRINTF(L_SYS_MAP,"auxsrv: AUXserver is disabled!");
+    return -1;
+    }
+  if(len>500 || outlen>500) return -1;
   cMutexLock lock(this);
   if(!so.Connected() && !Login()) return false;
   PRINTF(L_SYS_MAP,"auxsrv: calling map%02x",map);
@@ -77,15 +86,16 @@ bool cAuxSrv::Map(int map, unsigned char *data, int len, int outlen)
     if((len=so.Read(buff,sizeof(buff)))>0) {
       if(buff[0]==0x7A && buff[1]==0xA7) {
         if(buff[4]==0x00) {
+          int cycles=(buff[5]<<16)|(buff[6]<<8)|buff[7];
           int l=buff[2]*256+buff[3];
-          if(len>=l+5 && l==outlen+1) {
+          if(len>=l+5 && l==outlen+4) {
             if(buff[l+4]==0xFF) {
-              memcpy(data,buff+5,outlen);
-              return true;
+              memcpy(data,buff+8,outlen);
+              return cycles;
               }
             else PRINTF(L_SYS_MAP,"auxsrv: bad footer in map%02x response",map);
             }
-          else PRINTF(L_SYS_MAP,"auxsrv: bad length in map%02x response (got=%d want=%d)",map,l-1,outlen);
+          else PRINTF(L_SYS_MAP,"auxsrv: bad length in map%02x response (got=%d,%d want=%d,%d)",map,l-4,len,outlen,l+8);
           }
         else PRINTF(L_SYS_MAP,"auxsrv: map%02x not successfull (unsupported?)",map);
         }
@@ -95,22 +105,29 @@ bool cAuxSrv::Map(int map, unsigned char *data, int len, int outlen)
     }
   else  PRINTF(L_SYS_MAP,"auxsrv: map%02x write failed",map);
   so.Disconnect();
-  return false;
+  return -1;
 }
-*/
+#endif //HAS_AUXSRV
 
 // -- cMap0101 ----------------------------------------------------------------
 
-#include "nagra2-map57.c"
-
 class cMap0101 : public cMapCore {
 private:
   static const unsigned char primes[];
-  unsigned char residues[53];
-//  cAuxSrv aux;
-  cN2Map57 map57;
+  static const unsigned short coef22[][32];
+  static const unsigned short msbtbl3e[];
+  unsigned int cycles;
+#ifdef HAS_AUXSRV
+  cAuxSrv aux;
+#endif
+  //
+  void GenCRC16Table(void);
+  void MakePrime(BIGNUM *n, unsigned char *residues);
 protected:
+  unsigned short crc16table[256];
+  //
   void DoMap(int f, unsigned char *data=0, int l=0);
+  unsigned int MapCycles() { return cycles; }
 public:
   cMap0101(void);
   };
@@ -122,43 +139,416 @@ const unsigned char cMap0101::primes[] = {
   0xE5,0xE9,0xEF,0xF1,0xFB
   };
 
+const unsigned short cMap0101::coef22[256][32] = {
+  {0,1,1,0,1,0,1,1,0,11,10,11,10,10,11,10,11,21,22,22,21,22,21,22,22,32,33,32,33,33,32,33},
+  {3,1,0,1,1,0,1,0,1,10,11,11,10,11,10,11,11,21,22,21,22,22,21,22,21,33,33,33,33,32,33,33},
+  {5,1,0,1,1,0,1,0,1,10,11,11,10,11,10,11,11,21,22,21,22,22,21,22,21,33,33,33,33,32,33,33},
+  {7,1,1,1,0,1,1,1,1,10,11,10,11,11,10,11,10,22,22,22,22,21,22,22,22,33,32,33,33,33,33,32},
+  {9,1,1,1,0,1,1,1,1,10,11,10,11,11,10,11,10,22,22,22,22,21,22,22,22,33,32,33,33,33,33,32},
+  {12,0,1,1,1,1,0,1,1,11,11,11,11,10,11,11,11,22,21,22,22,22,22,21,22,33,33,33,34,33,33,33},
+  {14,0,1,1,1,1,0,1,1,11,11,11,11,10,11,11,11,22,21,22,22,22,22,21,22,33,33,33,34,33,33,33},
+  {16,1,1,2,1,1,1,1,2,11,10,11,11,11,11,10,11,22,22,22,23,22,22,22,22,34,33,33,33,33,34,33},
+  {0,1,1,2,1,1,1,1,2,11,10,11,11,11,11,10,11,22,22,22,23,22,22,22,22,34,33,33,33,33,34,33},
+  {3,1,1,1,1,2,1,1,1,11,11,11,12,11,11,11,11,23,22,22,22,22,23,22,22,33,33,34,33,34,33,33},
+  {5,1,1,1,1,2,1,1,1,11,11,11,12,11,11,11,11,23,22,22,22,22,23,22,22,33,33,34,33,34,33,33},
+  {7,1,2,1,2,1,1,2,1,12,11,11,11,11,12,11,11,22,22,23,22,23,22,22,23,33,34,33,33,34,33,34},
+  {9,1,2,1,2,1,1,2,1,12,11,11,11,11,12,11,11,22,22,23,22,23,22,22,23,33,34,33,33,34,33,34},
+  {12,2,1,1,2,1,2,1,1,11,11,12,11,12,11,11,12,22,23,22,22,23,22,23,22,34,34,33,34,33,34,34},
+  {14,2,1,1,2,1,2,1,1,11,11,12,11,12,11,11,12,22,23,22,22,23,22,23,22,34,34,33,34,33,34,34},
+  {16,2,1,2,1,2,2,1,2,11,12,11,11,12,11,12,11,23,23,22,23,22,23,23,22,34,33,34,34,33,34,33},
+  {0,2,1,2,1,2,2,1,2,11,12,11,11,12,11,12,11,23,23,22,23,22,23,23,22,34,33,34,34,33,34,33},
+  {3,1,2,2,1,2,1,2,2,12,12,11,12,11,12,12,11,23,22,23,23,22,23,22,23,34,34,34,33,34,34,34},
+  {5,1,2,2,1,2,1,2,2,12,12,11,12,11,12,12,11,23,22,23,23,22,23,22,23,34,34,34,33,34,34,34},
+  {7,2,2,1,2,2,2,2,1,12,11,12,12,11,12,11,12,23,23,23,22,23,23,23,23,33,34,34,34,34,33,34},
+  {9,2,2,1,2,2,2,2,1,12,11,12,12,11,12,11,12,23,23,23,22,23,23,23,23,33,34,34,34,34,33,34},
+  {12,2,2,2,2,1,2,2,2,12,12,12,11,12,12,12,12,22,23,23,23,23,22,23,23,34,34,35,34,34,34,34},
+  {14,2,2,2,2,1,2,2,2,12,12,12,11,12,12,12,12,22,23,23,23,23,22,23,23,34,34,35,34,34,34,34},
+  {16,2,3,2,2,2,2,3,2,11,12,12,12,12,11,12,12,23,23,24,23,23,23,23,24,34,34,34,34,35,34,34},
+  {0,2,3,2,2,2,2,3,2,11,12,12,12,12,11,12,12,23,23,24,23,23,23,23,24,34,34,34,34,35,34,34},
+  {3,2,2,2,3,2,2,2,2,12,12,13,12,12,12,12,13,23,23,23,23,24,23,23,23,34,35,34,35,34,34,35},
+  {5,2,2,2,3,2,2,2,2,12,12,13,12,12,12,12,13,23,23,23,23,24,23,23,23,34,35,34,35,34,34,35},
+  {7,3,2,3,2,2,3,2,3,12,12,12,12,13,12,12,12,23,24,23,24,23,23,24,23,35,34,34,35,34,35,34},
+  {9,3,2,3,2,2,3,2,3,12,12,12,12,13,12,12,12,23,24,23,24,23,23,24,23,35,34,34,35,34,35,34},
+  {12,2,2,3,2,3,2,2,3,12,13,12,13,12,12,13,12,24,23,23,24,23,24,23,23,35,34,35,34,35,35,34},
+  {14,2,2,3,2,3,2,2,3,12,13,12,13,12,12,13,12,24,23,23,24,23,24,23,23,35,34,35,34,35,35,34},
+  {16,2,3,2,3,3,2,3,2,13,12,12,13,12,13,12,12,24,23,24,23,24,24,23,24,34,35,35,34,35,34,35},
+  {0,2,3,2,3,3,2,3,2,13,12,12,13,12,13,12,12,24,23,24,23,24,24,23,24,34,35,35,34,35,34,35},
+  {3,3,3,2,3,2,3,3,2,13,12,13,12,13,13,12,13,23,24,24,23,24,23,24,24,35,35,34,35,35,35,35},
+  {5,3,3,2,3,2,3,3,2,13,12,13,12,13,13,12,13,23,24,24,23,24,23,24,24,35,35,34,35,35,35,35},
+  {7,3,2,3,3,3,3,2,3,12,13,13,12,13,12,13,13,24,24,23,24,24,24,24,23,35,35,35,35,34,35,35},
+  {9,3,2,3,3,3,3,2,3,12,13,13,12,13,12,13,13,24,24,23,24,24,24,24,23,35,35,35,35,34,35,35},
+  {12,3,3,3,2,3,3,3,3,13,13,12,13,13,13,13,12,24,24,24,24,23,24,24,24,35,36,35,35,35,35,36},
+  {14,3,3,3,2,3,3,3,3,13,13,12,13,13,13,13,12,24,24,24,24,23,24,24,24,35,36,35,35,35,35,36},
+  {16,4,3,3,3,3,4,3,3,13,13,13,13,12,13,13,13,24,25,24,24,24,24,25,24,35,35,35,36,35,35,35},
+  {0,4,3,3,3,3,4,3,3,13,13,13,13,12,13,13,13,24,25,24,24,24,24,25,24,35,35,35,36,35,35,35},
+  {3,3,3,4,3,3,3,3,4,13,14,13,13,13,13,14,13,24,24,24,25,24,24,24,24,36,35,36,35,35,36,35},
+  {5,3,3,4,3,3,3,3,4,13,14,13,13,13,13,14,13,24,24,24,25,24,24,24,24,36,35,36,35,35,36,35},
+  {7,3,4,3,3,4,3,4,3,13,13,13,14,13,13,13,13,25,24,25,24,24,25,24,25,35,35,36,35,36,35,35},
+  {9,3,4,3,3,4,3,4,3,13,13,13,14,13,13,13,13,25,24,25,24,24,25,24,25,35,35,36,35,36,35,35},
+  {12,3,4,3,4,3,3,4,3,14,13,14,13,13,14,13,14,24,24,25,24,25,24,24,25,35,36,35,36,36,35,36},
+  {14,3,4,3,4,3,3,4,3,14,13,14,13,13,14,13,14,24,24,25,24,25,24,24,25,35,36,35,36,36,35,36},
+  {16,4,3,4,4,3,4,3,4,13,13,14,13,14,13,13,14,24,25,24,25,25,24,25,24,36,36,35,36,35,36,36},
+  {0,4,3,4,4,3,4,3,4,13,13,14,13,14,13,13,14,24,25,24,25,25,24,25,24,36,36,35,36,35,36,36},
+  {3,4,3,4,3,4,4,3,4,13,14,13,14,14,13,14,13,25,25,24,25,24,25,25,24,36,35,36,36,36,36,35},
+  {5,4,3,4,3,4,4,3,4,13,14,13,14,14,13,14,13,25,25,24,25,24,25,25,24,36,35,36,36,36,36,35},
+  {7,3,4,4,4,4,3,4,4,14,14,13,14,13,14,14,13,25,24,25,25,25,25,24,25,36,36,36,35,36,36,36},
+  {9,3,4,4,4,4,3,4,4,14,14,13,14,13,14,14,13,25,24,25,25,25,25,24,25,36,36,36,35,36,36,36},
+  {12,4,4,3,4,4,4,4,3,14,13,14,14,14,14,13,14,25,25,25,24,25,25,25,25,37,36,36,36,36,37,36},
+  {14,4,4,3,4,4,4,4,3,14,13,14,14,14,14,13,14,25,25,25,24,25,25,25,25,37,36,36,36,36,37,36},
+  {16,4,4,4,4,5,4,4,4,14,14,14,13,14,14,14,14,26,25,25,25,25,26,25,25,36,36,37,36,36,36,36},
+  {0,4,4,4,4,5,4,4,4,14,14,14,13,14,14,14,14,26,25,25,25,25,26,25,25,36,36,37,36,36,36,36},
+  {3,4,5,4,4,4,4,5,4,15,14,14,14,14,15,14,14,25,25,26,25,25,25,25,26,36,37,36,36,37,36,37},
+  {5,4,5,4,4,4,4,5,4,15,14,14,14,14,15,14,14,25,25,26,25,25,25,25,37,36,37,36,36,37,36,37},
+  {7,5,4,4,5,4,5,4,4,14,14,15,14,14,14,14,15,25,26,25,25,26,25,26,36,36,37,36,37,36,36,37},
+  {9,5,4,4,5,4,5,4,4,14,14,15,14,14,14,14,26,25,26,25,25,26,25,26,36,36,37,36,37,36,36,37},
+  {12,5,4,5,4,4,5,4,5,14,15,14,14,15,14,15,25,25,26,25,26,25,25,26,36,37,36,37,37,36,37,36},
+  {14,5,4,5,4,4,5,4,15,14,15,14,14,15,14,15,25,25,26,25,26,25,25,26,36,37,36,37,37,36,37,36},
+  {16,4,5,5,4,5,4,5,14,14,15,14,15,14,14,15,25,26,25,26,26,25,26,25,37,37,36,37,36,37,37,36},
+  {40,4,5,5,4,5,4,5,14,14,15,14,15,14,14,15,25,26,25,26,26,25,26,25,37,37,36,37,36,37,37,36},
+  {44,4,5,4,5,5,4,5,14,15,14,15,15,14,15,14,26,26,25,26,25,26,26,25,37,36,37,37,37,37,36,37},
+  {44,4,5,4,5,5,4,5,14,15,14,15,15,14,15,14,26,26,25,26,25,26,26,25,37,36,37,37,37,37,36,37},
+  {47,5,5,5,5,4,5,5,15,15,14,15,14,15,15,14,26,25,26,26,26,26,25,26,37,37,37,36,37,37,37,37},
+  {47,5,5,5,5,4,5,5,15,15,14,15,14,15,15,14,26,25,26,26,26,26,25,26,37,37,37,36,37,37,37,37},
+  {52,5,4,5,5,5,5,4,15,14,15,15,15,15,14,15,26,26,26,25,26,26,26,26,38,37,37,37,37,38,37,37},
+  {52,5,4,5,5,5,5,4,15,14,15,15,15,15,14,15,26,26,26,25,26,26,26,26,38,37,37,37,37,38,37,37},
+  {56,5,5,5,6,5,5,5,15,15,15,14,15,15,15,15,27,26,26,26,26,27,26,26,37,37,38,37,37,37,37,38},
+  {56,5,5,5,6,5,5,5,15,15,15,14,15,15,15,15,27,26,26,26,26,27,26,26,37,37,38,37,37,37,37,38},
+  {60,6,5,5,5,5,6,5,16,15,15,15,15,16,15,15,26,26,27,26,26,26,26,27,37,38,37,37,38,37,38,37},
+  {60,6,5,5,5,5,6,5,16,15,15,15,15,16,15,15,26,26,27,26,26,26,26,27,37,38,37,37,38,37,38,37},
+  {65,5,5,6,5,6,5,5,15,15,16,15,15,15,15,16,26,27,26,26,27,26,27,26,37,38,37,38,37,37,38,37},
+  {65,5,5,6,5,6,5,5,15,15,16,15,15,15,15,16,26,27,26,26,27,26,27,26,37,38,37,38,37,37,38,37},
+  {69,5,6,5,5,6,5,6,15,16,15,15,16,15,16,15,26,27,26,27,26,26,27,26,38,37,38,38,37,38,37,38},
+  {69,5,6,5,5,6,5,6,15,16,15,15,16,15,16,15,26,27,26,27,26,26,27,26,38,37,38,38,37,38,37,38},
+  {72,6,6,5,6,5,6,6,15,16,15,16,15,15,16,15,27,26,27,27,26,27,26,27,38,37,38,37,38,38,37,38},
+  {72,6,6,5,6,5,6,6,15,16,15,16,15,15,16,15,27,26,27,27,26,27,26,27,38,37,38,37,38,38,37,38},
+  {76,6,5,6,6,5,6,5,16,15,16,16,15,16,15,16,27,26,27,26,27,27,26,27,37,38,38,38,38,37,38,38},
+  {76,6,5,6,6,5,6,5,16,15,16,16,15,16,15,16,27,26,27,26,27,27,26,27,37,38,38,38,38,37,38,38},
+  {81,6,6,6,5,6,6,6,16,15,16,15,16,16,15,16,26,27,27,27,27,26,27,27,38,38,37,38,38,38,38,37},
+  {81,6,6,6,5,6,6,6,16,15,16,15,16,16,15,16,26,27,27,27,27,26,27,27,38,38,37,38,38,38,38,37},
+  {85,5,6,6,6,6,5,6,15,16,16,16,16,15,16,16,27,27,26,27,27,27,27,26,38,38,38,38,39,38,38,38},
+  {85,5,6,6,6,6,5,6,15,16,16,16,16,15,16,16,27,27,26,27,27,27,27,26,38,38,38,38,39,38,38,38},
+  {89,6,6,7,6,6,6,6,16,16,15,16,16,16,16,15,27,27,27,27,28,27,27,27,38,39,38,38,38,38,39,38},
+  {89,6,6,7,6,6,6,6,16,16,15,16,16,16,16,15,27,27,27,27,28,27,27,27,38,39,38,38,38,38,39,38},
+  {94,6,6,6,6,7,6,6,16,16,16,16,17,16,16,16,27,28,27,27,27,27,28,27,39,38,38,39,38,39,38,38},
+  {94,6,6,6,6,7,6,6,16,16,16,16,17,16,16,16,27,28,27,27,27,27,28,27,39,38,38,39,38,39,38,38},
+  {97,6,7,6,7,6,6,7,16,17,16,16,16,16,17,16,28,27,27,28,27,28,27,27,39,38,39,38,38,39,38,39},
+  {97,6,7,6,7,6,6,7,16,17,16,16,16,16,17,16,28,27,27,28,27,28,27,27,39,38,39,38,38,39,38,39},
+  {101,7,6,6,7,6,7,6,17,16,16,17,16,17,16,16,28,27,28,27,27,28,27,28,38,39,39,38,39,38,39,39},
+  {101,7,6,6,7,6,7,6,17,16,16,17,16,17,16,16,28,27,28,27,27,28,27,28,38,39,39,38,39,38,39,39},
+  {106,7,6,7,6,7,7,6,17,16,17,16,16,17,16,17,27,28,28,27,28,27,28,28,38,39,38,39,39,38,39,38},
+  {106,7,6,7,6,7,7,6,17,16,17,16,16,17,16,17,27,28,28,27,28,27,28,28,38,39,38,39,39,38,39,38},
+  {110,6,7,7,6,7,6,7,16,17,17,16,17,16,17,17,27,28,27,28,28,27,28,27,39,39,39,39,38,39,39,39},
+  {110,6,7,7,6,7,6,7,16,17,17,16,17,16,17,17,27,28,27,28,28,27,28,27,39,39,39,39,38,39,39,39},
+  {114,7,7,6,7,7,7,7,16,17,16,17,17,16,17,16,28,28,28,28,27,28,28,28,39,38,39,39,39,39,38,39},
+  {114,7,7,6,7,7,7,7,16,17,16,17,17,16,17,16,28,28,28,28,27,28,28,28,39,38,39,39,39,39,38,39},
+  {117,7,7,7,7,6,7,7,17,17,17,17,16,17,17,17,28,27,28,28,28,28,27,28,39,39,39,40,39,39,39,39},
+  {117,7,7,7,7,6,7,7,17,17,17,17,16,17,17,17,28,27,28,28,28,28,27,28,39,39,39,40,39,39,39,39},
+  {122,7,8,7,7,7,7,8,17,16,17,17,17,17,16,17,28,28,28,29,28,28,28,28,40,39,39,39,39,40,39,39},
+  {122,7,8,7,7,7,7,8,17,16,17,17,17,17,16,17,28,28,28,29,28,28,28,28,40,39,39,39,39,40,39,39},
+  {126,7,7,7,8,7,7,7,17,17,17,18,17,17,17,17,29,28,28,28,28,29,28,28,39,39,40,39,40,39,39,40},
+  {126,7,7,7,8,7,7,7,17,17,17,18,17,17,17,17,29,28,28,28,28,29,28,28,39,39,40,39,40,39,39,40},
+  {130,8,7,8,7,7,8,7,18,17,17,17,17,18,17,17,28,28,29,28,29,28,28,29,39,40,39,39,40,39,40,39},
+  {130,8,7,8,7,7,8,7,18,17,17,17,17,18,17,17,28,28,29,28,29,28,28,29,39,40,39,39,40,39,40,39},
+  {135,7,7,8,7,8,7,7,17,17,18,17,18,17,17,18,28,29,28,28,29,28,29,28,40,40,39,40,39,40,40,39},
+  {135,7,7,8,7,8,7,7,17,17,18,17,18,17,17,18,28,29,28,28,29,28,29,28,40,40,39,40,39,40,40,39},
+  {139,7,8,7,8,8,7,8,17,18,17,17,18,17,18,17,29,29,28,29,28,29,29,28,40,39,40,40,39,40,39,40},
+  {139,7,8,7,8,8,7,8,17,18,17,17,18,17,18,17,29,29,28,29,28,29,29,28,40,39,40,40,39,40,39,40},
+  {142,8,8,7,8,7,8,8,18,18,17,18,17,18,18,17,29,28,29,29,28,29,28,29,40,40,40,39,40,40,40,40},
+  {142,8,8,7,8,7,8,8,18,18,17,18,17,18,18,17,29,28,29,29,28,29,28,29,40,40,40,39,40,40,40,40},
+  {147,8,7,8,8,8,8,7,18,17,18,18,17,18,17,18,29,29,29,28,29,29,29,29,39,40,40,40,40,39,40,40},
+  {147,8,7,8,8,8,8,7,18,17,18,18,17,18,17,18,29,29,29,28,29,29,29,29,39,40,40,40,40,39,40,40},
+  {151,8,8,8,7,8,8,8,18,18,18,17,18,18,18,18,28,29,29,29,29,28,29,29,40,40,41,40,40,40,40,41},
+  {151,8,8,8,7,8,8,8,18,18,18,17,18,18,18,18,28,29,29,29,29,28,29,29,40,40,41,40,40,40,40,41},
+  {155,9,8,8,8,8,9,8,17,18,18,18,18,17,18,18,29,29,30,29,29,29,29,30,40,40,40,40,41,40,40,40},
+  {155,9,8,8,8,8,9,8,17,18,18,18,18,17,18,18,29,29,30,29,29,29,29,30,40,40,40,40,41,40,40,40},
+  {159,8,8,9,8,8,8,8,18,18,19,18,18,18,18,19,29,29,29,29,30,29,29,29,40,41,40,41,40,40,41,40},
+  {159,8,8,9,8,8,8,8,18,18,19,18,18,18,18,19,29,29,29,29,30,29,29,29,40,41,40,41,40,40,41,40},
+  {164,8,9,8,8,9,8,9,18,18,18,18,19,18,18,18,29,30,29,30,29,29,30,29,41,40,40,41,40,41,40,40},
+  {164,8,9,8,8,9,8,9,18,18,18,18,19,18,18,18,29,30,29,30,29,29,30,29,41,40,40,41,40,41,40,40},
+  {167,8,9,8,9,8,8,9,18,19,18,19,18,18,19,18,30,29,29,30,29,30,29,29,41,40,41,40,41,41,40,41},
+  {167,8,9,8,9,8,8,9,18,19,18,19,18,18,19,18,30,29,29,30,29,30,29,29,41,40,41,40,41,41,40,41},
+  {171,9,8,9,9,8,9,8,19,18,18,19,18,19,18,18,30,29,30,29,30,30,29,30,40,41,41,40,41,40,41,41},
+  {171,9,8,9,9,8,9,8,19,18,18,19,18,19,18,18,30,29,30,29,30,30,29,30,40,41,41,40,41,40,41,41},
+  {176,9,8,9,8,9,9,8,19,18,19,18,19,19,18,19,29,30,30,29,30,29,30,30,41,41,40,41,41,41,41,40},
+  {176,9,8,9,8,9,9,8,19,18,19,18,19,19,18,19,29,30,30,29,30,29,30,30,41,41,40,41,41,41,41,40},
+  {180,8,9,9,9,9,8,9,18,19,19,18,19,18,19,19,30,30,29,30,30,30,30,29,41,41,41,41,40,41,41,41},
+  {180,8,9,9,9,9,8,9,18,19,19,18,19,18,19,19,30,30,29,30,30,30,30,29,41,41,41,41,40,41,41,41},
+  {184,9,9,8,9,9,9,9,19,19,18,19,19,19,19,18,30,30,30,30,29,30,30,30,41,42,41,41,41,41,42,41},
+  {184,9,9,8,9,9,9,9,19,19,18,19,19,19,19,18,30,30,30,30,29,30,30,30,41,42,41,41,41,41,42,41},
+  {189,9,9,9,9,10,9,9,19,19,19,19,18,19,19,19,30,31,30,30,30,30,31,30,41,41,41,42,41,41,41,41},
+  {189,9,9,9,9,10,9,9,19,19,19,19,18,19,19,19,30,31,30,30,30,30,31,30,41,41,41,42,41,41,41,41},
+  {192,9,10,9,9,9,9,10,19,20,19,19,19,19,20,19,30,30,30,31,30,30,30,30,42,41,42,41,41,42,41,42},
+  {192,9,10,9,9,9,9,10,19,20,19,19,19,19,20,19,30,30,30,31,30,30,30,30,42,41,42,41,41,42,41,42},
+  {196,10,9,9,10,9,10,9,19,19,19,20,19,19,19,19,31,30,31,30,30,31,30,31,41,41,42,41,42,41,41,42},
+  {196,10,9,9,10,9,10,9,19,19,19,20,19,19,19,19,31,30,31,30,30,31,30,31,41,41,42,41,42,41,41,42},
+  {200,10,9,10,9,9,10,9,20,19,20,19,19,20,19,20,30,30,31,30,31,30,30,31,41,42,41,42,42,41,42,41},
+  {200,10,9,10,9,9,10,9,20,19,20,19,19,20,19,20,30,30,31,30,31,30,30,31,41,42,41,42,42,41,42,41},
+  {205,9,10,10,9,10,9,10,19,19,20,19,20,19,19,20,30,31,30,31,31,30,31,30,42,42,41,42,41,42,42,41},
+  {205,9,10,10,9,10,9,10,19,19,20,19,20,19,19,20,30,31,30,31,31,30,31,30,42,42,41,42,41,42,42,41},
+  {209,9,10,9,10,10,9,10,19,20,19,20,20,19,20,19,31,31,30,31,30,31,31,30,42,41,42,42,42,42,41,42},
+  {209,9,10,9,10,10,9,10,19,20,19,20,20,19,20,19,31,31,30,31,30,31,31,30,42,41,42,42,42,42,41,42},
+  {212,10,10,10,10,9,10,10,20,20,19,20,19,20,20,19,31,30,31,31,31,31,30,31,42,42,42,41,42,42,42,42},
+  {212,10,10,10,10,9,10,10,20,20,19,20,19,20,20,19,31,30,31,31,31,31,30,31,42,42,42,41,42,42,42,42},
+  {217,10,9,10,10,10,10,9,20,19,20,20,20,20,19,20,31,31,31,30,31,31,31,31,43,42,42,42,42,43,42,42},
+  {217,10,9,10,10,10,10,9,20,19,20,20,20,20,19,20,31,31,31,30,31,31,31,31,43,42,42,42,42,43,42,42},
+  {221,10,10,10,11,10,10,10,20,20,20,19,20,20,20,20,32,31,31,31,31,32,31,31,42,42,43,42,42,42,42,43},
+  {221,10,10,10,11,10,10,10,20,20,20,19,20,20,20,20,32,31,31,31,31,32,31,31,42,42,43,42,42,42,42,43},
+  {225,11,10,10,10,10,11,10,21,20,20,20,20,21,20,20,31,31,32,31,31,31,31,32,42,43,42,42,43,42,43,42},
+  {225,11,10,10,10,10,11,10,21,20,20,20,20,21,20,20,31,31,32,31,31,31,31,32,42,43,42,42,43,42,43,42},
+  {230,10,10,11,10,11,10,10,20,20,21,20,20,20,20,21,31,32,31,31,32,31,32,31,42,43,42,43,42,42,43,42},
+  {230,10,10,11,10,11,10,10,20,20,21,20,20,20,20,21,31,32,31,31,32,31,32,31,42,43,42,43,42,42,43,42},
+  {234,10,11,10,10,11,10,11,20,21,20,20,21,20,21,20,31,32,31,32,31,31,32,31,43,42,43,43,42,43,42,43},
+  {234,10,11,10,10,11,10,11,20,21,20,20,21,20,21,20,31,32,31,32,31,31,32,31,43,42,43,43,42,43,42,43},
+  {237,11,11,10,11,10,11,11,20,21,20,21,20,20,21,20,32,31,32,32,31,32,31,32,43,42,43,42,43,43,42,43},
+  {237,11,11,10,11,10,11,11,20,21,20,21,20,20,21,20,32,31,32,32,31,32,31,32,43,42,43,42,43,43,42,43},
+  {241,11,10,11,11,10,11,10,21,20,21,21,20,21,20,21,32,31,32,31,32,32,31,32,42,43,43,43,43,42,43,43},
+  {241,11,10,11,11,10,11,10,21,20,21,21,20,21,20,21,32,31,32,31,32,32,31,32,42,43,43,43,43,42,43,43},
+  {246,11,11,11,10,11,11,11,21,20,21,20,21,21,20,21,31,32,32,32,32,31,32,32,43,43,42,43,43,43,43,42},
+  {246,11,11,11,10,11,11,11,21,20,21,20,21,21,20,21,31,32,32,32,32,31,32,32,43,43,42,43,43,43,43,42},
+  {250,10,11,11,11,11,10,11,20,21,21,21,21,20,21,21,32,32,31,32,32,32,32,31,43,43,43,43,44,43,43,43},
+  {250,10,11,11,11,11,10,11,20,21,21,21,21,20,21,21,32,32,31,32,32,32,32,31,43,43,43,43,44,43,43,43},
+  {254,11,11,12,11,11,11,11,21,21,20,21,21,21,21,20,32,32,32,32,33,32,32,32,43,44,43,43,43,43,44,43},
+  {254,11,11,12,11,11,11,11,21,21,20,21,21,21,21,20,32,32,32,32,33,32,32,32,43,44,43,43,43,43,44,43},
+  {259,11,11,11,11,12,11,11,21,21,21,21,22,21,21,21,32,33,32,32,32,32,33,32,44,43,43,44,43,44,43,43},
+  {259,11,11,11,11,12,11,11,21,21,21,21,22,21,21,21,32,33,32,32,32,32,33,32,44,43,43,44,43,44,43,43},
+  {262,11,12,11,12,11,11,12,21,22,21,21,21,21,22,21,33,32,32,33,32,33,32,32,44,43,44,43,43,44,43,44},
+  {262,11,12,11,12,11,11,12,21,22,21,21,21,21,22,21,33,32,32,33,32,33,32,32,44,43,44,43,43,44,43,44},
+  {266,12,11,11,12,11,12,11,22,21,21,22,21,22,21,21,33,32,33,32,32,33,32,33,43,44,44,43,44,43,44,44},
+  {266,12,11,11,12,11,12,11,22,21,21,22,21,22,21,21,33,32,33,32,32,33,32,33,43,44,44,43,44,43,44,44},
+  {271,12,11,12,11,12,12,11,22,21,22,21,21,22,21,22,32,33,33,32,33,32,33,33,43,44,43,44,44,43,44,43},
+  {271,12,11,12,11,12,12,11,22,21,22,21,21,22,21,22,32,33,33,32,33,32,33,33,43,44,43,44,44,43,44,43},
+  {275,11,12,12,11,12,11,12,21,22,22,21,22,21,22,22,32,33,32,33,33,32,33,32,44,44,44,44,43,44,44,44},
+  {275,11,12,12,11,12,11,12,21,22,22,21,22,21,22,22,32,33,32,33,33,32,33,32,44,44,44,44,43,44,44,44},
+  {279,12,12,11,12,12,12,12,21,22,21,22,22,21,22,21,33,33,33,33,32,33,33,33,44,43,44,44,44,44,43,44},
+  {279,12,12,11,12,12,12,12,21,22,21,22,22,21,22,21,33,33,33,33,32,33,33,33,44,43,44,44,44,44,43,44},
+  {282,12,12,12,12,11,12,12,22,22,22,22,21,22,22,22,33,32,33,33,33,33,32,33,44,44,44,45,44,44,44,44},
+  {282,12,12,12,12,11,12,12,22,22,22,22,21,22,22,22,33,32,33,33,33,33,32,33,44,44,44,45,44,44,44,44},
+  {287,12,13,12,12,12,12,13,22,21,22,22,22,22,21,22,33,33,33,34,33,33,33,33,45,44,44,44,44,45,44,44},
+  {287,12,13,12,12,12,12,13,22,21,22,22,22,22,21,22,33,33,33,34,33,33,33,33,45,44,44,44,44,45,44,44},
+  {291,12,12,12,13,12,12,12,22,22,22,23,22,22,22,22,34,33,33,33,33,34,33,33,44,44,45,44,45,44,44,45},
+  {291,12,12,12,13,12,12,12,22,22,22,23,22,22,22,22,34,33,33,33,33,34,33,33,44,44,45,44,45,44,44,45},
+  {295,13,12,13,12,12,13,12,23,22,22,22,22,23,22,22,33,33,34,33,34,33,33,34,44,45,44,44,45,44,45,44},
+  {295,13,12,13,12,12,13,12,23,22,22,22,22,23,22,22,33,33,34,33,34,33,33,34,44,45,44,44,45,44,45,44},
+  {300,12,12,13,12,13,12,12,22,22,23,22,23,22,22,23,33,34,33,33,34,33,34,33,45,45,44,45,44,45,45,44},
+  {300,12,12,13,12,13,12,12,22,22,23,22,23,22,22,23,33,34,33,33,34,33,34,33,45,45,44,45,44,45,45,44},
+  {304,12,13,12,13,13,12,13,22,23,22,22,23,22,23,22,34,34,33,34,33,34,34,33,45,44,45,45,44,45,44,45},
+  {304,12,13,12,13,13,12,13,22,23,22,22,23,22,23,22,34,34,33,34,33,34,34,33,45,44,45,45,44,45,44,45},
+  {307,13,13,12,13,12,13,13,23,23,22,23,22,23,23,22,34,33,34,34,33,34,33,34,45,45,45,44,45,45,45,45},
+  {307,13,13,12,13,12,13,13,23,23,22,23,22,23,23,22,34,33,34,34,33,34,33,34,45,45,45,44,45,45,45,45},
+  {312,13,12,13,13,13,13,12,23,22,23,23,22,23,22,23,34,34,34,33,34,34,34,34,44,45,45,45,45,44,45,45},
+  {312,13,12,13,13,13,13,12,23,22,23,23,22,23,22,23,34,34,34,33,34,34,34,34,44,45,45,45,45,44,45,45},
+  {316,13,13,13,12,13,13,13,23,23,23,22,23,23,23,23,33,34,34,34,34,33,34,34,45,45,46,45,45,45,45,46},
+  {316,13,13,13,12,13,13,13,23,23,23,22,23,23,23,23,33,34,34,34,34,33,34,34,45,45,46,45,45,45,45,46},
+  {320,14,13,13,13,13,14,13,22,23,23,23,23,22,23,23,34,34,35,34,34,34,34,35,45,45,45,45,46,45,45,45},
+  {320,14,13,13,13,13,14,13,22,23,23,23,23,22,23,23,34,34,35,34,34,34,34,35,45,45,45,45,46,45,45,45},
+  {324,13,13,14,13,13,13,13,23,23,24,23,23,23,23,24,34,34,34,34,35,34,34,34,45,46,45,46,45,45,46,45},
+  {324,13,13,14,13,13,13,13,23,23,24,23,23,23,23,24,34,34,34,34,35,34,34,34,45,46,45,46,45,45,46,45},
+  {329,13,14,13,13,14,13,14,23,23,23,23,24,23,23,23,34,35,34,35,34,34,35,34,46,45,45,46,45,46,45,45},
+  {329,13,14,13,13,14,13,14,23,23,23,23,24,23,23,23,34,35,34,35,34,34,35,34,46,45,45,46,45,46,45,45},
+  {332,13,14,13,14,13,13,14,23,24,23,24,23,23,24,23,35,34,34,35,34,35,34,34,46,45,46,45,46,46,45,46},
+  {332,13,14,13,14,13,13,14,23,24,23,24,23,23,24,23,35,34,34,35,34,35,34,34,46,45,46,45,46,46,45,46},
+  {336,14,13,14,14,13,14,13,24,23,23,24,23,24,23,23,35,34,35,34,35,35,34,35,45,46,46,45,46,45,46,46},
+  {336,14,13,14,14,13,14,13,24,23,23,24,23,24,23,23,35,34,35,34,35,35,34,35,45,46,46,45,46,45,46,46},
+  {341,14,13,14,13,14,14,13,24,23,24,23,24,24,23,24,34,35,35,34,35,34,35,35,46,46,45,46,46,46,46,45},
+  {341,14,13,14,13,14,14,13,24,23,24,23,24,24,23,24,34,35,35,34,35,34,35,35,46,46,45,46,46,46,46,45},
+  {345,13,14,14,14,14,13,14,23,24,24,23,24,23,24,24,35,35,34,35,35,35,35,34,46,46,46,46,45,46,46,46},
+  {345,13,14,14,14,14,13,14,23,24,24,23,24,23,24,24,35,35,34,35,35,35,35,34,46,46,46,46,45,46,46,46},
+  {349,14,14,13,14,14,14,14,24,24,23,24,24,24,24,23,35,35,35,35,34,35,35,35,46,47,46,46,46,46,47,46},
+  {349,14,14,13,14,14,14,14,24,24,23,24,24,24,24,23,35,35,35,35,34,35,35,35,46,47,46,46,46,46,47,46},
+  {354,14,14,14,14,15,14,14,24,24,24,24,23,24,24,24,35,36,35,35,35,35,36,35,46,46,46,47,46,46,46,46},
+  {354,14,14,14,14,15,14,14,24,24,24,24,23,24,24,24,35,36,35,35,35,35,36,35,46,46,46,47,46,46,46,46},
+  {357,14,15,14,14,14,14,15,24,25,24,24,24,24,25,24,35,35,35,36,35,35,35,35,47,46,47,46,46,47,46,47},
+  {357,14,15,14,14,14,14,15,24,25,24,24,24,24,25,24,35,35,35,36,35,35,35,35,47,46,47,46,46,47,46,47},
+  {361,15,14,14,15,14,15,14,24,24,24,25,24,24,24,24,36,35,36,35,35,36,35,36,46,46,47,46,47,46,46,47},
+  {361,15,14,14,15,14,15,14,24,24,24,25,24,24,24,24,36,35,36,35,35,36,35,36,46,46,47,46,47,46,46,47},
+  {365,15,14,15,14,14,15,14,25,24,25,24,24,25,24,25,35,35,36,35,36,35,35,36,46,47,46,47,47,46,47,46},
+  {365,15,14,15,14,14,15,14,25,24,25,24,24,25,24,25,35,35,36,35,36,35,35,36,46,47,46,47,47,46,47,46},
+  {370,14,15,15,14,15,14,15,24,24,25,24,25,24,24,25,35,36,35,36,36,35,36,35,47,47,46,47,46,47,47,46},
+  {370,14,15,15,14,15,14,15,24,24,25,24,25,24,24,25,35,36,35,36,36,35,36,35,47,47,46,47,46,47,47,46},
+  {374,14,15,14,15,15,14,15,24,25,24,25,25,24,25,24,36,36,35,36,35,36,36,35,47,46,47,47,47,47,46,47},
+  {374,14,15,14,15,15,14,15,24,25,24,25,25,24,25,24,36,36,35,36,35,36,36,35,47,46,47,47,47,47,46,47},
+  {377,15,15,15,15,14,15,15,25,25,24,25,24,25,25,24,36,35,36,36,36,36,35,36,47,47,47,46,47,47,47,47},
+  {377,15,15,15,15,14,15,15,25,25,24,25,24,25,25,24,36,35,36,36,36,36,35,36,47,47,47,46,47,47,47,47},
+  {382,15,14,15,15,15,15,14,25,24,25,25,25,25,24,25,36,36,36,35,36,36,36,36,48,47,47,47,47,48,47,47},
+  {382,15,14,15,15,15,15,14,25,24,25,25,25,25,24,25,36,36,36,35,36,36,36,36,48,47,47,47,47,48,47,47},
+  {386,15,15,15,16,15,15,15,25,25,25,24,25,25,25,25,37,36,36,36,36,37,36,36,47,47,48,47,47,47,47,48},
+  {386,15,15,15,16,15,15,15,25,25,25,24,25,25,25,25,37,36,36,36,36,37,36,36,47,47,48,47,47,47,47,48},
+  {390,16,15,15,15,15,16,15,26,25,25,25,25,26,25,25,36,36,37,36,36,36,36,37,47,48,47,47,48,47,48,47},
+  {390,16,15,15,15,15,16,15,26,25,25,25,25,26,25,25,36,36,37,36,36,36,36,37,47,48,47,47,48,47,48,47},
+  {395,15,15,16,15,16,15,15,25,25,26,25,25,25,25,26,36,37,36,36,37,36,37,36,47,48,47,48,47,47,48,47},
+  {395,15,15,16,15,16,15,15,25,25,26,25,25,25,25,26,36,37,36,36,37,36,37,36,47,48,47,48,47,47,48,47},
+  {399,15,16,15,15,16,15,16,25,26,25,25,26,25,26,25,36,37,36,37,36,36,37,36,48,47,48,48,47,48,47,48},
+  {399,15,16,15,15,16,15,16,25,26,25,25,26,25,26,25,36,37,36,37,36,36,37,36,48,47,48,48,47,48,47,48},
+  {402,16,16,15,16,15,16,16,25,26,25,26,25,25,26,25,37,36,37,37,36,37,36,37,48,47,48,47,48,48,47,48},
+  {402,16,16,15,16,15,16,16,25,26,25,26,25,25,26,25,37,36,37,37,36,37,36,37,48,47,48,47,48,48,47,48},
+  {406,16,15,16,16,15,16,15,26,25,26,26,25,26,25,26,37,36,37,36,37,37,36,37,47,48,48,48,48,47,48,48},
+  {406,16,15,16,16,15,16,15,26,25,26,26,25,26,25,26,37,36,37,36,37,37,36,37,47,48,48,48,48,47,48,48},
+  {411,16,16,16,15,16,16,16,26,25,26,25,26,26,25,26,36,37,37,37,37,36,37,37,48,48,47,48,48,48,48,47},
+  {411,16,16,16,15,16,16,16,26,25,26,25,26,26,25,26,36,37,37,37,37,36,37,37,48,48,47,48,48,48,48,47},
+  {415,15,16,16,16,16,15,16,25,26,26,26,26,25,26,26,37,37,36,37,37,37,37,36,48,48,48,48,49,48,48,48},
+  {415,15,16,16,16,16,15,16,25,26,26,26,26,25,26,26,37,37,36,37,37,37,37,36,48,48,48,48,49,48,48,48},
+  {419,16,16,17,16,16,16,16,26,26,25,26,26,26,26,25,37,37,37,37,38,37,37,37,48,49,48,48,48,48,49,48},
+  {419,16,16,17,16,16,16,16,26,26,25,26,26,26,26,25,37,37,37,37,38,37,37,37,48,49,48,48,48,48,49,48},
+  {424,16,16,16,16,17,16,16,26,26,26,26,27,26,26,26,37,38,37,37,37,37,38,37,49,48,48,49,48,49,48,48},
+  {424,16,16,16,16,17,16,16,26,26,26,26,27,26,26,26,37,38,37,37,37,37,38,37,49,48,48,49,48,49,48,48},
+  {427,16,17,16,17,16,16,17,26,27,26,26,26,26,27,26,38,37,37,38,37,38,37,37,49,48,49,48,48,49,48,49},
+  {427,16,17,16,17,16,16,17,26,27,26,26,26,26,27,26,38,37,37,38,37,38,37,37,49,48,49,48,48,49,48,49},
+  {431,17,16,16,17,16,17,16,27,26,26,27,26,27,26,26,38,37,38,37,37,38,37,38,48,49,49,48,49,48,49,49},
+  {431,17,16,16,17,16,17,16,27,26,26,27,26,27,26,26,38,37,38,37,37,38,37,38,48,49,49,48,49,48,49,49},
+  {436,17,16,17,16,17,17,16,27,26,27,26,26,27,26,27,37,38,38,37,38,37,38,38,48,49,48,49,49,48,49,48},
+  };
+
+const unsigned short cMap0101::msbtbl3e[] = {
+//      0    1    2    3    4    5    6    7    8    9    a    b    c    d    e    f
+/*0*/   0,  88, 148, 236, 224, 312, 312, 400, 302, 390, 390, 476, 390, 476, 476, 566,
+/*1*/ 378, 466, 466, 554, 466, 554, 554, 642, 466, 554, 554, 642, 554, 642, 642, 730,
+/*2*/ 448, 536, 536, 624, 536, 624, 624, 712, 536, 624, 624, 712, 624, 712, 712, 796,
+/*3*/ 536, 624, 624, 712, 624, 712, 712, 796, 624, 712, 712, 796, 712, 796, 796, 884,
+/*4*/ 524, 612, 612, 700, 612, 700, 700, 790, 612, 700, 700, 790, 700, 790, 790, 878,
+/*5*/ 612, 700, 700, 790, 700, 790, 790, 878, 700, 790, 790, 878, 790, 878, 878, 966,
+/*6*/ 612, 700, 700, 790, 700, 790, 790, 878, 700, 790, 790, 878, 790, 878, 878, 966,
+/*7*/ 700, 790, 790, 878, 790, 878, 878, 966, 790, 878, 878, 966, 878, 966, 966,1054,
+/*8*/ 602, 690, 690, 778, 690, 778, 778, 862, 690, 778, 778, 862, 778, 862, 862, 950,
+/*9*/ 690, 778, 778, 862, 778, 862, 862, 950, 778, 862, 862, 950, 862, 950, 950,1038,
+/*a*/ 690, 778, 778, 862, 778, 862, 862, 950, 778, 862, 862, 950, 862, 950, 950,1038,
+/*b*/ 778, 862, 862, 950, 862, 950, 950,1038, 862, 950, 950,1038, 950,1038,1038,1126,
+/*c*/ 690, 778, 778, 862, 778, 862, 862, 950, 778, 862, 862, 950, 862, 950, 950,1038,
+/*d*/ 778, 862, 862, 950, 862, 950, 950,1038, 862, 950, 950,1038, 950,1038,1038,1126,
+/*e*/ 778, 862, 862, 950, 862, 950, 950,1038, 862, 950, 950,1038, 950,1038,1038,1126,
+/*f*/ 862, 950, 950,1038, 950,1038,1038,1126, 950,1038,1038,1126,1038,1126,1126,1214
+  };
+
 cMap0101::cMap0101(void)
 {
+  GenCRC16Table();
+}
+
+void cMap0101::GenCRC16Table(void)
+{
+  unsigned char hi[256];
+    for(int i=0; i<256; ++i) {
+      unsigned short c = i;
+      for(int j=0; j<8; ++j) c = (c>>1) ^ ((c&1) ? 0x8408 : 0); // ccitt poly
+      crc16table[0xff-i] = c & 0xff;
+      hi[i] = c>>8;
+      }
+    for(int i=0; i<32; ++i)
+      for(int j=0; j<8; ++j)
+        crc16table[i*8+j] |= hi[(0x87+(i*8)-j)&0xff]<<8;
+}
+
+void cMap0101::MakePrime(BIGNUM *n, unsigned char *residues)
+{
+  bool isPrime;
+  cycles+=1290;
+  do {
+    cycles+=1465;
+    BN_add_word(n,2);
+    isPrime=true;
+    for(int i=0; i<53; i++) {
+      residues[i]+=2;
+      unsigned char num=residues[i];
+      unsigned char denom=primes[i];
+      if(num>denom) {
+        unsigned char r=0;
+        while(denom>=r) { cycles+=1; r=(r<<1)|((num&0x80)>>7); num<<=1; }
+        }
+      residues[i]%=primes[i];
+      if(residues[i]==0) { cycles+=13; isPrime=false; }
+      }
+    } while(!isPrime);
 }
 
 void cMap0101::DoMap(int f, unsigned char *data, int l)
 {
   PRINTF(L_SYS_MAP,"0101: calling function %02X",f);
+  cycles=0;
   switch(f) {
+    case 0x22:
+      {
+      int shift=((-l)&0xFF00)>>8, exp=(-l)&0x1F;
+      BN_zero(B);
+      BN_set_bit(B,wordsize<<6);
+      BN_sub(B,B,D);
+      BN_set_word(I,exp*2);
+      BN_mod_exp(B,B,I,D,ctx);
+      BN_mod_lshift(B,B,shift,D,ctx);
+      if(exp) cycles=559 + 2112*exp + 16*((shift+1)>>1) + 4*coef22[shift][exp] - 6;
+      else    cycles=931 +                                4*coef22[shift][0]   - 6;
+      break;
+      }
     case 0x3b:
-      MakeJ();
-      BN_zero(R);
-      BN_set_bit(R,132); // or 66*wordsize ?
-      BN_mod(H,R,D,ctx);
-      for(int i=0; i<4; i++) MonMul(H,H,H);
-      MonMul(B,A,H);
+      MonInit(132); // or 66*wordsize ?
+      MonMul(B,A,B);
+      break;
+    case 0x3e:
+      {
+      I.GetLE(data,(l?l:wordsize)<<3);
+      BN_mod_exp(B,A,I,D,ctx);
+      BN_one(A);
+      int end=(BN_num_bits(I)-1)/8;
+      cycles=3848 + end*650 + msbtbl3e[data[end]] - 13;
+      for(int i=end*8; --i>=0;) if(BN_is_bit_set(I,i)) cycles+=88;
       break;
+      }
     case 0x4d:
-      for(int i=0; i<53; i++) residues[i]=BN_mod_word(A,primes[i]);
+      if(-0x018000==l)
+        //for(int i=64; i<(wordsize<<6); i++) BN_clear_bit(B,i);
+        BN_mask_bits(B,64);
+      else {
+        BN_set_bit(B,(wordsize<<6)-1);
+        if(-0x028000==l) BN_set_bit(B,(wordsize<<6)-2);
+        }
+      BN_set_bit(B,0);
+      for(int i=0; i<53; i++) data[i]=BN_mod_word(B,primes[i]);
       break;
     case 0x4e:
+      MakePrime(B,data);
+      break;
+    case 0x57:
       {
-      bool isPrime;
-      do {
-        BN_add_word(A,2);
-        isPrime=true;
-        for(int i=0; i<53; i++) {
-          residues[i]+=2;
-          residues[i]%=primes[i];
-          if(residues[i]==0) isPrime=false;
+      cBN a, b, x, y, scalar;
+      D.GetLE(data+0x60,16);
+      x.GetLE(data+0x00,16);
+      y.GetLE(data+0x30,16);
+      b.GetLE(data+0x10,16);
+      a.GetLE(data+0x70,16);
+      scalar.GetLE(data+0x50,16);
+      int scalarbits=BN_num_bits(scalar);
+      if(scalarbits>=2 && !BN_is_zero(x) && !BN_is_zero(y) && !BN_is_zero(b)) {
+        CurveInit(a);
+        ToProjective(0,x,y);
+        BN_copy(Qx,Px);
+        BN_copy(Qy,Py);
+        for(int i=scalarbits-2; i>=0; i--) {
+          DoubleP(0);
+          if(BN_is_bit_set(scalar,i)) {
+            BN_copy(A,Pz);
+            if(BN_is_zero(Pz)) {
+              BN_copy(Px,Qx);
+              BN_copy(Py,Qy);
+              BN_copy(Pz,Qz);
+              AddP(1);
+              }
+            else {
+              BN_mask_bits(Px,32);
+              BN_lshift(b,Qz,32);
+              BN_add(Px,Px,b);
+              BN_mask_bits(Px,128);
+              AddP(0);
+              }
+            }
           }
-        } while(!isPrime);
+        ToAffine();
+        }
+      memset(data+0x20,0,64);
+      Px.PutLE(&data[0x20],16);
+      unsigned char tmp[16];
+      Qz.PutLE(tmp,16);
+      memcpy(&data[0x30],&tmp[0x0C],4);
+      Py.PutLE(&data[0x40],16);
       break;
       }
-    case 0x57:
-      map57.Map57(data);
-      //aux.Map(0x57,data,l,l);
-      break;
     default:
       if(!cMapCore::DoMap(f,data,l))
         PRINTF(L_SYS_MAP,"0101: unsupported call %02x",f);
@@ -166,36 +556,191 @@ void cMap0101::DoMap(int f, unsigned char *data, int l)
     }
 }
 
+// -- cN2Timer -----------------------------------------------------------------
+
+enum { tmCONTINUOUS=0x01, tmRUNNING=0x02, tmLATCHED=0x04 };
+
+class cN2Timer {
+private:
+  int ctrl, divisor, cycles, remainder;
+  unsigned int latch;
+public:
+  cN2Timer(void);
+  void AddCycles(int count);
+  unsigned int GetCycles(void) { return (unsigned int)cycles; }
+  void SetLatch(int val);
+  void Stop(void);
+  void Start(int mode, int div);
+  bool Running(void) { return ctrl&tmRUNNING; }
+  };
+
+cN2Timer::cN2Timer(void)
+{
+  cycles=0; ctrl=0; divisor=1; remainder=-1; latch=0xFF;
+}
+
+void cN2Timer::AddCycles(int count)
+{
+  remainder+=count;
+  if(remainder>=divisor) {
+    cycles-=remainder/divisor;
+    remainder%=divisor;
+    }
+  if(ctrl&tmCONTINUOUS) {
+    while(cycles<0) cycles+=latch+1;
+    }
+  else if(cycles<0 || (cycles==0 && remainder>=4)) {
+    cycles=0;
+    Stop();
+    }
+}
+
+void cN2Timer::SetLatch(int val)
+{
+  val&=0xFF; if(val==0) val=0x100;
+  latch=val; cycles=val; remainder=0;
+  ctrl|=tmLATCHED;
+}
+
+void cN2Timer::Start(int mode, int div)
+{
+  ctrl=(ctrl&~tmCONTINUOUS) | (mode&tmCONTINUOUS) | tmRUNNING;
+  divisor=div;
+  if(!(ctrl&tmLATCHED)) cycles=(unsigned int)(cycles-1)&0xFF;
+  remainder=-1;
+  if(!mode && cycles==0) ctrl&=~tmRUNNING;
+}
+
+void cN2Timer::Stop(void)
+{
+  ctrl&=~(tmRUNNING|tmLATCHED);
+}
+
 // -- cN2Prov0101 ----------------------------------------------------------------
 
+#define MAX_TIMERS 3
+#define TIMER_NUM(x) (((x)>>2)&3) // timer order doesn't match HW order
+
 class cN2Prov0101 : public cN2Prov, public cN2Emu, private cMap0101 {
 private:
-  bool special05;
+  int desSize;
+  DES_key_schedule desks1, desks2;
+  unsigned char desblock[8];
+  IdeaKS ks;
+  // memory mapped HW
+  enum {
+    HW_IO=0x00, HW_SECURITY,
+    HW_TIMER0_DATA=0x08, HW_TIMER0_LATCH, HW_TIMER0_CONTROL,
+    HW_CRC_CONTROL=0x0e, HW_CRC_DATA,
+    HW_TIMER1_DATA=0x10, HW_TIMER1_LATCH, HW_TIMER1_CONTROL,
+    HW_TIMER2_DATA=0x14, HW_TIMER2_LATCH, HW_TIMER2_CONTROL
+    };
+  cN2Timer timer[MAX_TIMERS];
+  enum { CRCCALC_DELAY=9, CRC_BUSY=1, CRC_DISABLED=2 };
+  unsigned short CRCvalue;
+  unsigned char CRCpos;
+  unsigned int CRCstarttime;
+  //
+  void AddRomCallbacks(void);
+  bool RomCallbacks(void);
+  bool ProcessMap(int f);
+  bool ProcessDESMap(int f);
 protected:
-  int hwCount;
+  int mecmAddr[2];
+  int mecmKeyId;
   //
-  virtual bool Algo(int algo, const unsigned char *hd, unsigned char *hw);
+  virtual bool Algo(int algo, unsigned char *hd, const unsigned char *ed, unsigned char *hw);
+  virtual bool RomInit(void);
   virtual void Stepper(void);
   virtual void WriteHandler(unsigned char seg, unsigned short ea, unsigned char &op);
   virtual void ReadHandler(unsigned char seg, unsigned short ea, unsigned char &op);
+  virtual void TimerHandler(unsigned int num);
 public:
   cN2Prov0101(int Id, int Flags);
+  virtual bool PostProcAU(int id, unsigned char *data);
   virtual int ProcessBx(unsigned char *data, int len, int pos);
+  virtual int ProcessEx(unsigned char *data, int len, int pos);
   };
 
-static cN2ProvLinkReg<cN2Prov0101,0x0101,(N2FLAG_MECM|N2FLAG_Bx)> staticPL0101;
+static cN2ProvLinkReg<cN2Prov0101,0x0101,(N2FLAG_MECM|N2FLAG_POSTAU|N2FLAG_Bx|N2FLAG_Ex)> staticPL0101;
 
 cN2Prov0101::cN2Prov0101(int Id, int Flags)
 :cN2Prov(Id,Flags)
 {
   hasWriteHandler=hasReadHandler=true;
-  special05=false;
-  hwCount=4;
+  mecmAddr[0]=0x91d7; mecmAddr[1]=0x92d7; mecmKeyId=0x106;
+  seedSize=10;
+
+  desSize=16;
+  CRCvalue=0; CRCpos=0; CRCstarttime=0;
 }
 
-bool cN2Prov0101::Algo(int algo, const unsigned char *hd, unsigned char *hw)
+bool cN2Prov0101::Algo(int algo, unsigned char *hd, const unsigned char *ed, unsigned char *hw)
 {
+  if(algo!=0x40 && algo!=0x60) {
+    PRINTF(L_SYS_ECM,"%04X: unknown MECM algo %02x",id,algo);
+    return false;
+    }
+  if(!Init(id,102)) {
+    PRINTF(L_SYS_ECM,"%04X: failed to initialize ROM",id);
+    return false;
+    }
+
+  unsigned char keyNr=(algo>>5)&0x01;
+  unsigned char mecmCode[256];
+  GetMem(mecmAddr[keyNr],mecmCode,256,0x80);
+  cPlainKey *pk;
+  unsigned char ideaKey[16];
+  if(!(pk=keys.FindKey('N',mecmKeyId,keyNr,sizeof(ideaKey)))) {
+    PRINTF(L_SYS_KEY,"missing %04x %02x MECM key",mecmKeyId,keyNr);
+    return false;
+    }
+  pk->Get(ideaKey);
+  idea.SetEncKey(ideaKey,&ks);
+  for(int i=0x100-8; i>=8; i-=8) {
+    idea.Encrypt(mecmCode+i,8,mecmCode+i,&ks,0);
+    xxor(mecmCode+i,8,mecmCode+i,mecmCode+i-8);
+    }
+  idea.Encrypt(mecmCode,8,mecmCode,&ks,0);
+  HEXDUMP(L_SYS_RAWECM,mecmCode,sizeof(mecmCode),"decrypted MECM code");
+  // check signature
+  unsigned char data[256];
+  memcpy(data,mecmCode,sizeof(data));
+  RotateBytes(data,sizeof(data));
+  SHA1(data,sizeof(data)-8,data);
+  RotateBytes(data,20);
+  if(memcmp(data,mecmCode,8)) {
+     PRINTF(L_SYS_ECM,"%04X: MECM %02x decrypt signature failed",id,keyNr);
+     return false;
+    }
+
+  // dynamic expand
+  hd[5]=ed[5];
+  hd[6]=(ed[7]&0xEF) | ((ed[6]&0x40)>>2);
+  hd[7]=ed[8];
+  hd[8]=(ed[9]&0x7F) | ((ed[6]&0x20)<<2);
+  hd[9]=ed[6]&0x80;
+  memcpy(hw,hd,seedSize);
+  ExpandInput(hw);
+
+  SetSp(0x0FFF,0x0EF8);
+  ClearBreakpoints();
+  SetMem(0x0100,mecmCode+8,0x100-8);
+  SetMem(0x0ba2,hw,0x80);
+  AddBreakpoint(0x0000);
+  AddRomCallbacks();
+  SetPc(0x0100);
+  while(!Run(10000)) {
+    if(GetPc()==0x0000) {
+      GetMem(0x0ba2,hw,0x80);
+      return true;
+      }
+    else if(!RomCallbacks()) return false;
+    }
+
+/*
   if(algo==0x40) {
+    const int hwCount=2;
     memcpy(hw,hd,hwCount+1);
     ExpandInput(hw);
     hw[0x18]|=1; hw[0x40]|=1;
@@ -216,8 +761,6 @@ bool cN2Prov0101::Algo(int algo, const unsigned char *hd, unsigned char *hw)
     return true;
     }
   else if(algo==0x60) { // map 4D/4E/57
-    memcpy(hw,hd,5);
-    ExpandInput(hw);
     hw[127]|=0x80; hw[0]|=0x01;
     DoMap(SETSIZE,0,16);
     DoMap(IMPORT_A,hw);
@@ -228,81 +771,376 @@ bool cN2Prov0101::Algo(int algo, const unsigned char *hd, unsigned char *hw)
     DoMap(IMPORT_A,hw);
     DoMap(0x4e);
     DoMap(EXPORT_A,hw);
-    DoMap(0x57,hw,128);
+    DoMap(0x57,hw);
     return true;
     }
 
   PRINTF(L_SYS_ECM,"%04X: unknown MECM algo %02x",id,algo);
+*/
+  return false;
+}
+
+bool cN2Prov0101::PostProcAU(int id, unsigned char *data)
+{
+  if(data[1]&0x5f) return false;
+  return true;
+}
+
+bool cN2Prov0101::RomInit(void)
+{
+  SetPc(0x4000);
+  SetSp(0x0FFF,0x0FE0);
+  ClearBreakpoints();
+  AddBreakpoint(0x537d);
+  AddBreakpoint(0x8992);
+  AddBreakpoint(0xA822);
+  while(!Run(5000)) {
+    switch(GetPc()) {
+      case 0x537d:
+        PRINTF(L_SYS_EMU,"%04x: ROM init successfull",id);
+        return true;
+      default:
+        PRINTF(L_SYS_EMU,"%04x: ROM init failed: unexpected breakpoint",id);
+        break;
+      }
+    }
   return false;
 }
 
+bool cN2Prov0101::ProcessMap(int f)
+{
+  unsigned short addr;
+  int size=wordsize<<3;
+  unsigned char tmp[256];
+
+  switch(f) {
+    case SETSIZE: // set map size 
+      DoMap(f,0,Get(0x48));
+      if((wordsize<<3)>256) {
+        PRINTF(L_SYS_EMU,"%04x: MAP word size too large: %d",id,wordsize);
+        return false;
+        }
+      break;
+    case IMPORT_J: //Import Ram at [44:45] to Map Registers A-E, E is 0x03 the rest in sequence
+    case IMPORT_A:
+    case IMPORT_B:
+    case IMPORT_C:
+    case IMPORT_D:
+    case IMPORT_LAST:
+      addr=HILO(0x44);
+      GetMem(addr,tmp,size,0); DoMap(f,tmp);
+      break;
+    case EXPORT_J: //Export Registers A-E with 44:45: 0x09 is E
+    case EXPORT_A:
+    case EXPORT_B:
+    case EXPORT_C:
+    case EXPORT_D:
+    case EXPORT_LAST:
+      addr=HILO(0x44);
+      DoMap(f,tmp); SetMem(addr,tmp,size,0);
+      break;
+    case SWAP_A: //Swap Registers A-D with 44:45
+    case SWAP_B:
+    case SWAP_C:
+    case SWAP_D:
+      addr=HILO(0x44);
+      GetMem(addr,tmp,size,0); DoMap(f,tmp); SetMem(addr,tmp,size,0);
+      break;
+    case CLEAR_A:
+    case CLEAR_B:
+    case CLEAR_C:
+    case CLEAR_D:
+    case COPY_A_B:
+    case COPY_B_A:
+    case COPY_A_C:
+    case COPY_C_A:
+    case COPY_C_D:
+    case COPY_D_C:
+      DoMap(f); break;
+    case 0x22:
+      DoMap(f,tmp,-((Get(0x48)<<16)|(Get(0x49)<<8)|Get(0x4a)));
+      AddCycles(MapCycles());
+      break;
+    case 0x3e:
+      GetMem(HILO(0x44),tmp,size,0);
+      DoMap(f,tmp,Get(0x48));
+      AddCycles(MapCycles());
+      break;
+    case 0x4d:
+      DoMap(f,tmp,-((Get(0x48)<<16)|(Get(0x49)<<8)|Get(0x4a)));
+      SetMem(0x400,tmp,53,0);
+      break;
+    case 0x4e:
+      GetMem(0x400,tmp,53,0);
+      DoMap(f,tmp);
+      SetMem(0x400,tmp,53,0);
+      AddCycles(MapCycles());
+      break;
+    default:
+      PRINTF(L_SYS_EMU,"%04x: map call %02x not emulated",id,f);
+      return false;
+    }
+  return true;
+}
+
+bool cN2Prov0101::ProcessDESMap(int f)
+{
+  unsigned char data[16];
+  switch(f) {
+    case 0x05:  // 3DES encrypt
+      DES_ecb2_encrypt(DES_CAST(desblock),DES_CAST(desblock),&desks1,&desks2,DES_ENCRYPT);
+      break;
+    case 0x06:  // 3DES decrypt
+      DES_ecb2_encrypt(DES_CAST(desblock),DES_CAST(desblock),&desks1,&desks2,DES_DECRYPT);
+      break;
+    case 0x0b:  // load DES data block from memory
+      GetMem(HILO(0x25),desblock,8,Get(0x24));
+      break;
+    case 0x0c:  // store DES data block to memory
+      SetMem(HILO(0x2b),desblock,8,Get(0x2a));
+      break;
+    case 0x0e:  // get DES key1 and key2
+      GetMem(HILO(0x25),data,8,Get(0x24));
+      DES_key_sched(DES_CAST(data),&desks1);
+      GetMem(HILO(0x28),data,8,Get(0x27));
+      DES_key_sched(DES_CAST(data),&desks2);
+      break;
+    case 0x0f:  // set DES size
+      desSize=Get(0x2d);
+      if(desSize!=0x10 && desSize!=0x18) {
+        PRINTF(L_SYS_EMU,"%04x: invalid DES key size %02x",id,desSize);
+        return false;
+        }
+      break;
+    default:
+      PRINTF(L_SYS_EMU,"%04x: DES map call %02x not emulated",id,f);
+      return false;
+  }
+  return true;
+}
+
+bool cN2Prov0101::RomCallbacks(void)
+{
+  unsigned int ea=GetPc();
+  if(ea&0x8000) ea|=(cr<<16);
+  switch(ea) {
+    case 0x3840: //MAP Handler
+    case 0x00A822:
+      if(!ProcessMap(a)) return false;
+      break;
+    case 0x3844: //DES Handler
+      if(!ProcessDESMap(a)) return false;
+      break;
+    case 0x5F23: //Erase_RAM_and_Hang
+    case 0x5F27: //Erase_RAM_and_Hang_Lp
+    case 0x5F5E: //BrainDead
+      PRINTF(L_SYS_EMU,"%04x: emu hung at %04x",id,ea);
+      return false;
+    case 0x70A6: //Write_Row_EEP_RC2_Len_A_To_RC1
+      {
+      unsigned short rc1=HILO(0x47);
+      unsigned short rc2=HILO(0x4a);
+      for(int i=0; i<a; i++) Set(0x80,rc1++,Get(dr,rc2++));
+      Set(0x4a,rc2>>8);
+      Set(0x4b,rc2&0xff);
+      break;
+      }
+    case 0x7BFE: //Write_Row_EEPROM_A_from_X_to_RC1
+      {
+      unsigned short rc1=HILO(0x47);
+      unsigned short rc2=c6805::x;
+      for(int i=0; i<a; i++) Set(0x80,rc1++,Get(rc2++));
+      break;
+      }
+    case 0x7CFF: //UPDATE_USW_03DD_03DE
+      Set(0x30E8,Get(0x03DD));
+      Set(0x30E9,Get(0x03DE));
+      break;
+    case 0x00A23C: //IDEA_Generate_Expanded_Key
+      {
+      unsigned char key[16];
+      GetMem(0x0a20,key,16);
+      idea.SetEncKey(key,&ks);
+      break;
+      }
+    case 0x00A2E9: //IDEA_Cypher
+      {
+      unsigned char data[8];
+      GetMem(0x070,data,8);
+      idea.Encrypt(data,8,data,&ks,0);
+      SetMem(0x070,data,8);
+      break;
+      }
+    default:
+      PRINTF(L_SYS_EMU,"%04X: unknown ROM breakpoint %04x",id,ea);
+      return false;
+    }
+  if(ea>=0x8000) PopCr();
+  PopPc();
+  return true;
+}
+
+void cN2Prov0101::AddRomCallbacks(void)
+{
+  AddBreakpoint(0xA822); // map handler
+  AddBreakpoint(0x3840);
+  AddBreakpoint(0x3844);
+  AddBreakpoint(0xA23C); //IDEA 
+  AddBreakpoint(0xA2E9);
+  AddBreakpoint(0x70A6);
+  AddBreakpoint(0x7BFE);
+  AddBreakpoint(0x7CFF);
+  AddBreakpoint(0x5F23);
+  AddBreakpoint(0x5F27);
+  AddBreakpoint(0x5F5E);
+}
+
 int cN2Prov0101::ProcessBx(unsigned char *data, int len, int pos)
 {
   if(Init(id,102)) {
     SetMem(0x80,data,len);
     SetPc(0x80+pos);
-    SetSp(0x0FFF,0x0FF0);
+    SetSp(0x0FFF,0x0EF8);
     ClearBreakpoints();
-    ForceSet(0x0001,0x0f,true); // fix xor 80
-    AddBreakpoint(0x0000);
     AddBreakpoint(0x9569);
-    AddBreakpoint(0xA822); // map handler
+    AddBreakpoint(0x0000);
+    AddRomCallbacks();
     while(!Run(1000)) {
       if(GetPc()==0x9569) {
         GetMem(0x80,data,len);
         return max((int)a,6);
         }
-      if(GetPc()==0x0000)
-        break;
-      if(GetPc()==0xA822) {
-        int size=wordsize<<3;
-        unsigned char tmp[size];
-        unsigned short addr=(Get(0x44)<<8)+Get(0x45);
-        switch(a) {
-          case 0x02:
-            DoMap(a,0,Get(0x48)); break;
-          case IMPORT_J ... IMPORT_LAST:
-            GetMem(addr,tmp,size,0); DoMap(a,tmp); break;
-          case EXPORT_J ... EXPORT_LAST:
-            DoMap(a,tmp); SetMem(addr,tmp,size,0); break;
-          case SWAP_A ... SWAP_D:
-            GetMem(addr,tmp,size,0); DoMap(a,tmp); SetMem(addr,tmp,size,0); break;
-          case CLEAR_A ... CLEAR_D:
-          case COPY_A_B ... COPY_D_C:
-            DoMap(a); break;
-          default:
-            PRINTF(L_SYS_EMM,"%04X: unrecognized map call %02x",id,a);
-            return -1;
-          }
-        PopCr(); PopPc();
+      else if(GetPc()==0x0000) break;
+      else if(!RomCallbacks()) break;
+      }
+    }
+  return -1;
+}
+
+int cN2Prov0101::ProcessEx(unsigned char *data, int len, int pos)
+{
+  if(Init(id,102)) {
+    SetMem(0x80,data,len);
+    SetPc(0x9591);
+    SetSp(0x0FFF,0x0EF8);
+    Push(0x99); //push the bug-table return onto the stack
+    Push(0x95);
+    Push(0x00);
+    Set(0x00,0x62,0x26);
+    Set(0x00,0x63,0x02);
+    Set(0x00,0x03d3,len-0x12);
+    ClearBreakpoints();
+    AddBreakpoint(0x9569);
+    AddBreakpoint(0x9599);
+    AddRomCallbacks();
+    while(!Run(10000)) {
+      if(GetPc()==0x9569) {
+        GetMem(0x80,data,len);
+        return max((int)a,6);
         }
+      else if(GetPc()==0x9599) break;
+      else if(!RomCallbacks()) break;
       }
     }
   return -1;
 }
 
+void cN2Prov0101::TimerHandler(unsigned int num)
+{
+  for(int i=0; i<MAX_TIMERS; i++) 
+    if(timer[i].Running()) timer[i].AddCycles(num);
+}
+
 void cN2Prov0101::WriteHandler(unsigned char seg, unsigned short ea, unsigned char &op)
 {
-  if(cr==0x00) {
-    if(ea==0x05) {
-      special05=(op&0x40)!=0;
+  switch(ea) {
+    case HW_SECURITY:
+      if(cr==0x00) op=Get(ea);
+      break;
+    case HW_TIMER0_CONTROL:
+    case HW_TIMER1_CONTROL:
+    case HW_TIMER2_CONTROL:
+      {
+      int num=TIMER_NUM(ea);
+      // The value of a Control Register for a timer (i.e. here $16 for the 3rd timer)
+      // can't be changed if the timer is running (i.e. old and 2 <> 0 ) : you can only
+      // stop it (i.e. op and 2 = 0).
+      if(timer[num].Running()) {
+        op=(Get(ea)&~tmRUNNING) | (op&tmRUNNING);
+        if(!(op&tmRUNNING)) timer[num].Stop();
+        }
+      else if(op&tmRUNNING) {
+        unsigned int div;
+        if((op&0xc0)==0x40) div=1 << (2 *(1 + ((op & 0x38) >> 3)));
+        else div=4; // This is wrong, but we haven't figured the right value out yet
+        timer[num].Start(op,div);
+        }
+      break;
       }
-    else if(ea==0x0a || ea==0x12 || ea==0x16) {
-      unsigned char old=Get(ea);
-      if(old&2) op=(old&~0x02) | (op&0x02);
+    case HW_TIMER0_LATCH:
+    case HW_TIMER1_LATCH:
+    case HW_TIMER2_LATCH:
+      {
+      int num=TIMER_NUM(ea);
+      if(!timer[num].Running()) timer[num].SetLatch(op);
+      break;
       }
+    case HW_CRC_CONTROL:
+      // $0e is to program the CRC unit.  $0f is the data to CRC
+      // assumes:
+      //   bit 1 disables/enables CRCing
+      if(!(op&CRC_DISABLED)) {
+        // disable -> reset CRC
+        CRCvalue=0; CRCpos=0;
+        CRCstarttime=Cycles()-CRCCALC_DELAY;
+        }
+      break;
+     case HW_CRC_DATA:
+      if(!(Get(HW_CRC_CONTROL)&CRC_DISABLED)) {
+        if(Cycles()-CRCstarttime>=CRCCALC_DELAY) {
+          // accept new data if not busy
+          CRCvalue=(CRCvalue>>8)^crc16table[(CRCvalue^op)&0xff];
+          CRCpos=0;
+          CRCstarttime=Cycles();
+          }
+        }
+      break;
     }
 }
 
 void cN2Prov0101::ReadHandler(unsigned char seg, unsigned short ea, unsigned char &op)
 {
-  if(special05) {
-    special05=false; // prevent loop
-    unsigned short start=Get(0x00,0x30C0);
-    unsigned short end=Get(0x00,0x30C1);
-    if(((ea>>8)>=start) && ((ea>>8)<=end)) op=0x00; // dataspace
-    else op=0x01;                                   // codespace
-    special05=true;
+  switch(ea) {
+    case HW_SECURITY:
+      if(cr==0) op=0x0F; break;
+    case HW_TIMER0_CONTROL:
+    case HW_TIMER1_CONTROL:
+    case HW_TIMER2_CONTROL:
+      {
+      int num=TIMER_NUM(ea);
+      op=timer[num].Running() ? op|tmRUNNING : op&~tmRUNNING;
+      break;
+      }
+    case HW_TIMER0_DATA:
+    case HW_TIMER1_DATA:
+    case HW_TIMER2_DATA:
+      {
+      int num=TIMER_NUM(ea);
+      op=timer[num].GetCycles();
+      break;
+      }
+    case HW_CRC_CONTROL:
+      if(!(op&CRC_DISABLED)) {
+        //CRC takes 10 cycles to generate
+        if(Cycles()-CRCstarttime>=CRCCALC_DELAY) op&=~CRC_BUSY; // not busy
+        else op|=CRC_BUSY; // busy
+        }
+      else op&=~CRC_BUSY; // clear busy bit
+      break;
+    case HW_CRC_DATA:
+      op=CRCvalue>>((CRCpos&1)<<3);
+      CRCpos=!CRCpos;
+      break;
     }
 }
 
@@ -348,10 +1186,10 @@ public:
   cN2Prov0901(int Id, int Flags);
   };
 
-static cN2ProvLinkReg<cN2Prov0901,0x0901,(N2FLAG_MECM|N2FLAG_Bx)> staticPL0901;
+static cN2ProvLinkReg<cN2Prov0901,0x0901,(N2FLAG_MECM|N2FLAG_POSTAU|N2FLAG_Bx|N2FLAG_Ex)> staticPL0901;
 
 cN2Prov0901::cN2Prov0901(int Id, int Flags)
 :cN2Prov0101(Id,Flags)
 {
-  hwCount=4;
+  mecmAddr[0]=0x91f5; mecmAddr[1]=0x92f5; mecmKeyId=0x907;
 }
index 5c0f4bf69b3fc66cad215622b72aa341dad663a2..6821da14b2a11795ca9e169b12cf3d2843657330 100644 (file)
@@ -39,16 +39,12 @@ void cMap0501::DoMap(int f, unsigned char *data, int l)
   switch(f) {
     case 0x37:
       l=(l?l:wordsize)<<3;
-      H.GetLE(data,l);
-      MonMul(B,H,A);
+      B.GetLE(data,l);
+      MonMul(B,B,A);
       break;
     case 0x3a:
-      MakeJ();
-      BN_zero(R);
-      BN_set_bit(R,68*wordsize);
-      BN_mod(H,R,D,ctx);
-      for(int i=0; i<4; i++) MonMul(H,H,H);
-      MonMul(B,A,H);
+      MonInit();
+      MonMul(B,A,B);
       MonMul(B,A,B);
       break;
     default:
@@ -62,7 +58,7 @@ void cMap0501::DoMap(int f, unsigned char *data, int l)
 
 class cN2Prov0501 : public cN2Prov, private cMap0501, public cN2Emu {
 protected:
-  virtual bool Algo(int algo, const unsigned char *hd, unsigned char *hw);
+  virtual bool Algo(int algo, unsigned char *hd, const unsigned char *ed, unsigned char *hw);
   virtual bool NeedsCwSwap(void) { return true; }
 public:
   cN2Prov0501(int Id, int Flags);
@@ -76,7 +72,7 @@ cN2Prov0501::cN2Prov0501(int Id, int Flags)
 ,cMap0501(Id)
 {}
 
-bool cN2Prov0501::Algo(int algo, const unsigned char *hd, unsigned char *hw)
+bool cN2Prov0501::Algo(int algo, unsigned char *hd, const unsigned char *ed, unsigned char *hw)
 {
   if(algo==0x60) {
     hw[0]=hd[0];
@@ -113,6 +109,7 @@ int cN2Prov0501::ProcessBx(unsigned char *data, int len, int pos)
     SetSp(0x0FFF,0x0FE0);
     Set(0x0001,0xFF);
     Set(0x000E,0xFF);
+    Set(0x0000,0x04);
     ClearBreakpoints();
     AddBreakpoint(0x821f);
     while(!Run(5000)) {
index d2d81877b07776fae3dd0237bff4bbb25a2c9e02..7366ccba16c76736ae4ec9bd86a092bb41850b88 100644 (file)
  * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
  */
 
+// -- cMap4101 -----------------------------------------------------------------
+
+class cMap4101 : public cMapCore {
+private:
+  int mId;
+protected:
+  void DoMap(int f, unsigned char *data=0, int l=0);
+public:
+  cMap4101(int Id);
+  };
+
+cMap4101::cMap4101(int Id)
+{
+  mId=Id|0x100;
+}
+
+void cMap4101::DoMap(int f, unsigned char *data, int l)
+{
+  PRINTF(L_SYS_MAP,"%04x: calling function %02X",mId,f);
+  switch(f) {
+    case 0x58:
+      {
+      cBN a, b, x, y, scalar;
+      D.GetLE(data+0x00,16);
+      x.GetLE(data+0x10,16);
+      y.GetLE(data+0x20,16);
+      b.GetLE(data+0x30,16);
+      a.GetLE(data+0x40,16);
+      scalar.GetLE(data+0x50,16);
+      int scalarbits=BN_num_bits(scalar);
+      if(scalarbits>=2 && !BN_is_zero(x) && !BN_is_zero(y) && !BN_is_zero(b)) {
+        CurveInit(a);
+        ToProjective(0,x,y);
+        BN_copy(Qx,Px);
+        BN_copy(Qy,Py);
+        for(int i=scalarbits-2; i>=0; i--) {
+          DoubleP(0);
+          if(BN_is_bit_set(scalar,i)) AddP(0);
+          }
+        ToAffine();
+        }
+      memset(data,0,64);
+      Px.PutLE(&data[0],16);
+      Py.PutLE(&data[32],16);
+      break;
+      }
+    case 0x44:
+      sctx.h4=UINT32_LE(data);
+      sctx.h3=UINT32_LE(data+4);
+      sctx.h2=UINT32_LE(data+8);
+      sctx.h1=UINT32_LE(data+12);
+      sctx.h0=UINT32_LE(data+16);
+      cMapCore::DoMap(0x44,data);
+      break;
+    default:
+      if(!cMapCore::DoMap(f,data,l))
+        PRINTF(L_SYS_MAP,"%04x: unsupported call %02x",mId,f);
+      break;
+    }
+}
+
 // -- cN2Prov4101 ----------------------------------------------------------------
 
-class cN2Prov4101 : public cN2Prov, public cN2Emu {
+class cN2Prov4101 : public cN2Prov, public cMap4101, public cN2Emu {
 protected:
   virtual void WriteHandler(unsigned char seg, unsigned short ea, unsigned char &op);
 public:
@@ -32,6 +93,7 @@ static cN2ProvLinkReg<cN2Prov4101,0x4101,(N2FLAG_POSTAU|N2FLAG_Bx)> staticPL4101
 
 cN2Prov4101::cN2Prov4101(int Id, int Flags)
 :cN2Prov(Id,Flags)
+,cMap4101(Id)
 {
   hasWriteHandler=true;
 }
@@ -64,6 +126,7 @@ int cN2Prov4101::ProcessBx(unsigned char *data, int len, int pos)
     ClearBreakpoints();
     AddBreakpoint(0xACDD);
     AddBreakpoint(0x9BDD);
+    AddBreakpoint(0x7EC5);
     while(!Run(5000)) {
       switch(GetPc()) {
         case 0xACDD:
@@ -71,6 +134,30 @@ int cN2Prov4101::ProcessBx(unsigned char *data, int len, int pos)
         case 0x9BDD:
           GetMem(0x80,data,len);
           return a;
+        case 0x7EC5:
+          {
+          PopPc();
+          unsigned short args=GetPc();
+          int clen=Get(args+4);
+          unsigned short ptr=(Get(args)<<8)+Get(args+1);
+          if(clen+pos-1>len) return -1; // sanity
+          GetMem(ptr,&data[pos-1],clen);
+          ptr=(Get(args+2)<<8)+Get(args+3)-0x0CED+0x00B4-0x0080; // wild hack
+          if(ptr<7 || ptr+8>len || data[ptr-1]!=0x10 || data[ptr-7]!=0x42) // sanity
+            return -1;
+          unsigned char tmp[96];
+          memcpy(&tmp[0],&data[ptr],8);
+          ptr=(((data[ptr]&0x3F)|0x40)<<8)+(data[ptr+1]&0x7F);
+          GetMem(ptr,&tmp[8],sizeof(tmp)-8);
+          DoMap(0x02,0,2);
+          DoMap(0x58,tmp);
+          DoMap(0x43);
+          DoMap(0x44,tmp);
+          SetMem(0x0440,tmp,20);
+          SetMem(0x80,data,len);
+          SetPc(0x80+pos);
+          break;
+          }
         }
       }
     }
diff --git a/systems/nagra/nagra2-map57.c b/systems/nagra/nagra2-map57.c
deleted file mode 100644 (file)
index a1408a9..0000000
+++ /dev/null
@@ -1,677 +0,0 @@
-/*
- * Softcam plugin to VDR (C++)
- *
- * This code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-// -- cN2Map57 ----------------------------------------------------------------
-
-class cN2Map57 {
-private:
-  void mod_add(BIGNUM *arg1, BIGNUM *arg2, BIGNUM *arg3, BIGNUM *arg4);
-  void bn_cmplx1(BIGNUM *arg1, BIGNUM *arg2, BIGNUM *arg3, BIGNUM *arg4, BIGNUM *arg5);
-  void bn_cmplx1a(BIGNUM *arg1, BIGNUM *arg2, BIGNUM *arg3, BIGNUM *arg4, BIGNUM *arg5);
-  void mod_sub(void);
-  void bn_func1(BIGNUM *arg0);
-  void bn_func2(int arg0);
-  void bn_func3(int arg0);
-  void bn_cmplx7(void);
-  void bn_cmplx2(BIGNUM *var1, BIGNUM *var2, BIGNUM *var3, BIGNUM *var4, BIGNUM *var5, BIGNUM *var6);
-  BIGNUM *bn_glb0, *bn_glb1, *bn_glb3, *bn_glb5, *bn_glb6, *bn_glb7;
-  BIGNUM *bn_glb_a, *bn_glb_b, *bn_glb_c, *bn_glb_d, *bn_glb_e, *bn_glb_f, *bn_glb_g;
-  BIGNUM *bn_glb_h, *bn_glb_i, *bn_glb_j, *bn_glb_k, *bn_glb_l, *bn_glb_m;
-  BIGNUM *glb2pow128, *mask128, *glb2pow64, *mask64;
-  BN_CTX *t1;
-public:
-  void Map57(unsigned char *data);
-  };
-
-void cN2Map57::mod_add(BIGNUM *arg1, BIGNUM *arg2, BIGNUM *arg3, BIGNUM *arg4)
-{
-  BN_add(arg1, arg2, arg3);
-  if(BN_cmp(arg1, arg4) >= 0) {
-    BN_sub(arg1, arg1, arg4);
-  }
-  BN_mask_bits(arg1, 128);
-}
-
-void cN2Map57::bn_cmplx1(BIGNUM *arg1, BIGNUM *arg2, BIGNUM *arg3, BIGNUM *arg4, BIGNUM *arg5)
-{
-  int j;
-  BIGNUM *var44, *var64, *var84, *vara4;
-  var44 = BN_new();
-  var64 = BN_new();
-  var84 = BN_new();
-  vara4 = BN_new();
-  BN_copy(var44, arg2);
-  BN_copy(var64, arg3);
-  BN_clear(vara4);
-  for(j=0; j<2; j++) {
-    BN_copy(var84, var64);
-    BN_mask_bits(var84, 64);
-    BN_rshift(var64, var64, 64);
-    BN_mul(var84, var84, var44, t1);
-    BN_add(vara4, vara4, var84);
-    BN_copy(var84, vara4);
-    BN_mask_bits(var84, 128);
-    BN_mul(var84, vara4, arg4, t1);
-    BN_mask_bits(var84, 64);
-    BN_mul(var84, var84, arg5, t1);
-    BN_add(vara4, vara4, var84);
-    BN_rshift(vara4, vara4, 64);
-    if(BN_cmp(vara4, arg5) >= 0) {
-      BN_sub(vara4, vara4, arg5);
-    }
-    BN_mask_bits(vara4, 128);
-  }
-  BN_copy(arg1, vara4);
-  BN_free(var44);
-  BN_free(var64);
-  BN_free(var84);
-  BN_free(vara4);
-}
-
-void cN2Map57::bn_cmplx1a(BIGNUM *arg1, BIGNUM *arg2, BIGNUM *arg3, BIGNUM *arg4, BIGNUM *arg5)
-{
-  int j;
-  BIGNUM *var44, *var64, *var84, *vara4;
-  var44 = BN_new();
-  var64 = BN_new();
-  var84 = BN_new();
-  vara4 = BN_new();
-  BN_copy(var44, arg2);
-  BN_copy(var64, arg3);
-  BN_clear(vara4);
-  for(j=0; j<2; j++) {
-    BN_copy(var84, var64);
-    BN_mask_bits(var84, 64);
-    BN_rshift(var64, var64, 64);
-    BN_mul(var84, var84, var44, t1);
-    BN_add(vara4, vara4, var84);
-    BN_copy(var84, vara4);
-    BN_mask_bits(var84, 128);
-    BN_mul(var84, vara4, arg4, t1);
-    BN_mask_bits(var84, 64);
-    BN_mul(var84, var84, arg5, t1);
-    BN_add(vara4, vara4, var84);
-    BN_rshift(vara4, vara4, 64);
-    if(j==0 && BN_cmp(vara4, arg5) >= 0) {
-      BN_sub(vara4, vara4, arg5);
-    }
-    BN_mask_bits(vara4, 128);
-  }
-  BN_copy(arg1, vara4);
-  BN_free(var44);
-  BN_free(var64);
-  BN_free(var84);
-  BN_free(vara4);
-}
-
-//uses 3, 1, glb2pow128
-//sets 1, 0 (unused)
-void cN2Map57::mod_sub()
-{
-  BN_copy(bn_glb0, bn_glb3);
-  BN_mod_sub(bn_glb1, bn_glb3, bn_glb1, glb2pow128, t1);
-  BN_mask_bits(bn_glb1, 128);
-}
-
-//uses 1, 3, 6
-//sets  1, 0 (unused), 7(unused)
-void cN2Map57::bn_func1(BIGNUM *arg0)
-{
-  BIGNUM *var30 = BN_new();
-  BIGNUM *var50 = BN_new();
-  BN_copy(var30,arg0);
-  BN_mask_bits(var30, 8);
-  unsigned int x = BN_get_word(var30);
-  BN_copy(var30,arg0);
-  if( x != 0) {
-    BN_clear(var50);
-    BN_set_word(var50, 2);
-    BN_sub(var30, var30, var50);
-  } else {
-    BN_clear(var50);
-    BN_set_word(var50, 0xfe);
-    BN_add(var30, var30, var50);
-  }
-  BN_copy(bn_glb7, bn_glb1);
-  if(BN_is_zero(arg0)) {
-    BN_clear(bn_glb7);
-    BN_set_word(bn_glb7, 1);
-    BN_clear(bn_glb0);
-
-    mod_add(bn_glb1, bn_glb7, bn_glb0, bn_glb3);
-    BN_free(var30);
-    BN_free(var50);
-    return;
-  } else {
-    int msb = BN_num_bits(var30) -1;
-    while (msb > 0) {
-
-      bn_cmplx1(bn_glb1, bn_glb1, bn_glb1, bn_glb6, bn_glb3);
-      msb--;
-      if(BN_is_bit_set(var30, msb)) {
-
-        bn_cmplx1(bn_glb1, bn_glb1, bn_glb7, bn_glb6, bn_glb3);
-      }
-    }
-    BN_clear(bn_glb7);
-    BN_set_word(bn_glb7, 1);
-
-    bn_cmplx1(bn_glb1, bn_glb1, bn_glb7, bn_glb6, bn_glb3);
-    BN_clear(bn_glb0);
-  }
-  BN_free(var30);
-  BN_free(var50);
-}
-
-//uses 3, 6, a, b, c, l, glb2pow128
-//sets 0, 1, 5, 7, a, b, c, f, g
-void cN2Map57::bn_func2(int arg0)
-{
-  BN_copy(bn_glb1, bn_glb_b);
-
-  mod_add(bn_glb1, bn_glb1, bn_glb1, bn_glb3);
-  BN_copy(bn_glb7, bn_glb1);
-  BN_copy(bn_glb5, bn_glb_c);
-  BN_mask_bits(bn_glb1, 128);
-
-  bn_cmplx1(bn_glb1, bn_glb1, bn_glb5, bn_glb6, bn_glb3);
-  BN_copy(bn_glb_g, bn_glb1);
-  BN_copy(bn_glb1, bn_glb7);
-
-  bn_cmplx1(bn_glb1, bn_glb1, bn_glb1, bn_glb6, bn_glb3);
-  BN_copy(bn_glb7, bn_glb_a);
-
-  bn_cmplx1(bn_glb1, bn_glb1, bn_glb7, bn_glb6, bn_glb3);
-  mod_sub();
-  BN_copy(bn_glb_f, bn_glb1);
-  BN_copy(bn_glb1, bn_glb7);
-
-  bn_cmplx1(bn_glb1, bn_glb1, bn_glb1, bn_glb6, bn_glb3);
-  BN_copy(bn_glb7, bn_glb1);
-
-  mod_add(bn_glb1, bn_glb1, bn_glb1, bn_glb3);
-
-  mod_add(bn_glb1, bn_glb1, bn_glb7, bn_glb3);
-  BN_copy(bn_glb7, bn_glb1);
-  BN_copy(bn_glb1, bn_glb_c);
-
-  bn_cmplx1(bn_glb1, bn_glb1, bn_glb1, bn_glb6, bn_glb3);
-
-  bn_cmplx1(bn_glb1, bn_glb1, bn_glb1, bn_glb6, bn_glb3);
-  BN_copy(bn_glb5, bn_glb_l);
-
-  bn_cmplx1(bn_glb1, bn_glb1, bn_glb5, bn_glb6, bn_glb3);
-
-  mod_add(bn_glb1, bn_glb1, bn_glb7, bn_glb3);
-  BN_copy(bn_glb7, bn_glb1);
-
-  bn_cmplx1(bn_glb1, bn_glb1, bn_glb1, bn_glb6, bn_glb3);
-  BN_copy(bn_glb0, bn_glb_f);
-
-  mod_add(bn_glb1, bn_glb0, bn_glb1, bn_glb3);
-  mod_add(bn_glb1, bn_glb0, bn_glb1, bn_glb3);
-  if(arg0 == 0) {
-    BN_copy(bn_glb_a, bn_glb1);
-  } else {
-    BN_copy(bn_glb_f, bn_glb1);
-  }
-
-  mod_add(bn_glb1, bn_glb0, bn_glb1, bn_glb3);
-
-  bn_cmplx1(bn_glb1, bn_glb1, bn_glb7, bn_glb6, bn_glb3);
-  BN_copy(bn_glb7, bn_glb1);
-  BN_copy(bn_glb1, bn_glb_b);
-
-  bn_cmplx1(bn_glb1, bn_glb1, bn_glb1, bn_glb6, bn_glb3);
-
-  mod_add(bn_glb1, bn_glb1, bn_glb1, bn_glb3);
-
-  bn_cmplx1(bn_glb1, bn_glb1, bn_glb1, bn_glb6, bn_glb3);
-
-  mod_add(bn_glb1, bn_glb1, bn_glb1, bn_glb3);
-
-  mod_add(bn_glb1, bn_glb1, bn_glb7, bn_glb3);
-  mod_sub();
-  if(arg0 == 0) {
-    BN_copy(bn_glb_b, bn_glb1);
-    BN_copy(bn_glb_c, bn_glb_g);
-  } else {
-    BN_copy(bn_glb_f, bn_glb1);
-    BN_copy(bn_glb_f, bn_glb_g);
-  }
-}
-
-//uses 3, 6, a, b, c, d, e, k
-//sets 0, 1, 5, 7, a, b, c, f, g, h, i, j
-void cN2Map57::bn_func3(int arg0)
-{
-  BN_copy(bn_glb1, bn_glb_c);
-  BN_copy(bn_glb7, bn_glb1);
-
-  bn_cmplx1(bn_glb1, bn_glb1, bn_glb1, bn_glb6, bn_glb3);
-
-  bn_cmplx1(bn_glb0, bn_glb1, bn_glb7, bn_glb6, bn_glb3);
-  BN_copy(bn_glb_f, bn_glb0);
-  BN_copy(bn_glb5, bn_glb_d);
-
-  bn_cmplx1(bn_glb1, bn_glb1, bn_glb5, bn_glb6, bn_glb3);
-  BN_copy(bn_glb7, bn_glb1);
-  mod_sub();
-  BN_copy(bn_glb0, bn_glb_a);
-
-  mod_add(bn_glb1, bn_glb0, bn_glb1, bn_glb3);
-  BN_copy(bn_glb_g, bn_glb1);
-  BN_copy(bn_glb5, bn_glb_c);
-
-  bn_cmplx1(bn_glb0, bn_glb1, bn_glb5, bn_glb6, bn_glb3);
-  if(arg0 == 0) {
-    BN_copy(bn_glb_c, bn_glb0);
-  } else {
-    BN_copy(bn_glb_g, bn_glb0);
-  }
-
-  bn_cmplx1(bn_glb1, bn_glb1, bn_glb1, bn_glb6, bn_glb3);
-  BN_copy(bn_glb_h, bn_glb1);
-  BN_copy(bn_glb0, bn_glb_a);
-
-  mod_add(bn_glb0, bn_glb0, bn_glb7, bn_glb3);
-  BN_copy(bn_glb7, bn_glb0);
-
-  //NOTE: don't 'mod' bn_glb1, but DO 'mod' glb_i
-  bn_cmplx1(bn_glb7, bn_glb1, bn_glb7, bn_glb6, bn_glb3);
-  bn_cmplx1a(bn_glb1, bn_glb1, bn_glb7, bn_glb6, bn_glb3);
-  BN_copy(bn_glb_i, bn_glb7);
-  BN_copy(bn_glb1, bn_glb_e);
-  BN_copy(bn_glb5, bn_glb_f);
-
-  bn_cmplx1(bn_glb1, bn_glb1, bn_glb5, bn_glb6, bn_glb3);
-  BN_copy(bn_glb_f, bn_glb1);
-  mod_sub();
-  BN_copy(bn_glb0, bn_glb_b);
-
-  mod_add(bn_glb1, bn_glb0, bn_glb1, bn_glb3);
-  BN_copy(bn_glb_j, bn_glb1);
-
-  bn_cmplx1(bn_glb1, bn_glb1, bn_glb1, bn_glb6, bn_glb3);
-  BN_copy(bn_glb0, bn_glb1);
-  BN_copy(bn_glb1, bn_glb7);
-  BN_copy(bn_glb7, bn_glb0);
-  mod_sub();
-
-  mod_add(bn_glb1, bn_glb1, bn_glb7, bn_glb3);
-  if(arg0 == 0) {
-    BN_copy(bn_glb_a, bn_glb1);
-  } else {
-    BN_copy(bn_glb_f, bn_glb1);
-  }
-
-  mod_add(bn_glb1, bn_glb1, bn_glb1, bn_glb3);
-  mod_sub();
-  BN_copy(bn_glb7, bn_glb_i);
-
-  mod_add(bn_glb1, bn_glb1, bn_glb7, bn_glb3);
-  BN_copy(bn_glb5, bn_glb_j);
-
-  bn_cmplx1(bn_glb0, bn_glb1, bn_glb5, bn_glb6, bn_glb3);
-  BN_copy(bn_glb1, bn_glb_f);
-  BN_copy(bn_glb_f, bn_glb0);
-  BN_copy(bn_glb7, bn_glb_b);
-
-  mod_add(bn_glb1, bn_glb1, bn_glb7, bn_glb3);
-  BN_copy(bn_glb7, bn_glb1);
-  BN_copy(bn_glb1, bn_glb_g);
-  BN_copy(bn_glb5, bn_glb_h);
-
-  bn_cmplx1(bn_glb1, bn_glb1, bn_glb5, bn_glb6, bn_glb3);
-
-  bn_cmplx1(bn_glb1, bn_glb1, bn_glb7, bn_glb6, bn_glb3);
-  mod_sub();
-  BN_copy(bn_glb7, bn_glb_f);
-
-  mod_add(bn_glb1, bn_glb1, bn_glb7, bn_glb3);
-  BN_copy(bn_glb5, bn_glb_k);
-
-  bn_cmplx1(bn_glb1, bn_glb1, bn_glb5, bn_glb6, bn_glb3);
-  if(arg0 == 0) {
-    BN_copy(bn_glb_b, bn_glb1);
-  } else {
-    BN_copy(bn_glb_f, bn_glb1);
-  }
-}
-
-//uses c, d, e, m
-//sets 0, a, b, c
-void cN2Map57::bn_cmplx7()
-{
-  BIGNUM *var1;
-  var1 = BN_new();
-  BN_copy(bn_glb0, bn_glb_c);
-  if(BN_is_zero(bn_glb_c)) {
-    BN_copy(bn_glb_a, bn_glb_d);
-    BN_copy(bn_glb_b, bn_glb_e);
-    BN_copy(bn_glb_c, bn_glb_m);
-    bn_func3(1);
-  } else {
-    BN_clear(var1);
-    BN_set_word(var1, 0xFFFFFFFF);
-    BN_mask_bits(bn_glb_a, 32);
-    BN_lshift(var1, bn_glb_m, 0x20);
-    BN_add(bn_glb_a, bn_glb_a, var1);
-    BN_mask_bits(bn_glb_a, 128);
-    bn_func3(0);
-  }
-  BN_free(var1);
-}
-
-void cN2Map57::bn_cmplx2(BIGNUM *var1, BIGNUM *var2, BIGNUM *var3, BIGNUM *var4, BIGNUM *var5, BIGNUM *var6)
-{
-  BIGNUM *var48;
-  int len = BN_num_bits(var6);
-  int i;
-  if(len < 2)
-    return;
-
-  if(BN_is_zero(var2) && BN_is_zero(var3) && BN_is_zero(var4))
-    return;
-  var48 = BN_new();
-  BN_copy(bn_glb3, var1);
-
-  BN_copy(bn_glb6, bn_glb3);
-  BN_set_bit(bn_glb6, 0);
-  BN_sub(bn_glb6, glb2pow128, bn_glb6);
-  BN_mod_inverse(bn_glb6, bn_glb6, glb2pow64, t1);
-  BN_clear(bn_glb0);
-  //
-  if(! BN_is_zero(bn_glb3)) {
-    BN_clear(bn_glb1);
-    BN_set_word(bn_glb1, 2);
-    BN_clear(bn_glb_k);
-    BN_set_word(bn_glb_k, 0x88);
-    BN_mod_exp(bn_glb1, bn_glb1, bn_glb_k, bn_glb3, t1);
-  }
-  //
-  for(i=0; i < 4; i++) {
-
-    bn_cmplx1(bn_glb1, bn_glb1, bn_glb1, bn_glb6, bn_glb3);
-  }
-  //
-  BN_clear(bn_glb7);
-  BN_set_word(bn_glb7, 1);
-  BN_add(bn_glb0, bn_glb3, bn_glb7);
-  BN_copy(bn_glb_k, bn_glb0);
-  BN_rshift(bn_glb_k, bn_glb_k, 1);
-  BN_copy(bn_glb7, bn_glb1);
-  BN_copy(bn_glb5, bn_glb_k);
-  BN_mask_bits(bn_glb5, 128);
-
-  bn_cmplx1(bn_glb1, bn_glb1, bn_glb5, bn_glb6, bn_glb3);
-  BN_copy(bn_glb_k, bn_glb1);
-
-  BN_copy(bn_glb1, var5);
-  BN_mask_bits(bn_glb1, 128);
-
-  bn_cmplx1(bn_glb1, bn_glb1, bn_glb7, bn_glb6, bn_glb3);
-  BN_copy(bn_glb_l, bn_glb1);
-  BN_copy(bn_glb1, bn_glb7);
-  BN_clear(bn_glb5);
-  BN_set_word(bn_glb5, 1);
-
-  bn_cmplx1(bn_glb1, bn_glb1, bn_glb5, bn_glb6, bn_glb3);
-  BN_copy(bn_glb_c, bn_glb1);
-  BN_copy(bn_glb_m, bn_glb1);
-  BN_copy(bn_glb1, bn_glb7);
-
-  BN_copy(bn_glb5, var2);
-  BN_mask_bits(bn_glb5, 128);
-
-  bn_cmplx1(bn_glb1, bn_glb1, bn_glb5, bn_glb6, bn_glb3);
-  BN_copy(bn_glb_a, bn_glb1);
-  BN_copy(bn_glb1, bn_glb7);
-
-  BN_copy(bn_glb5, var3);
-  BN_mask_bits(bn_glb5, 128);
-
-  bn_cmplx1(bn_glb1, bn_glb1, bn_glb5, bn_glb6, bn_glb3);
-  BN_copy(bn_glb_b, bn_glb1);
-  BN_copy(bn_glb_d, bn_glb_a);
-  BN_copy(bn_glb_e, bn_glb_b);
-
-  int x = len -1;
-  while(x > 0) {
-    x--;
-    bn_func2(0);
-    if(BN_is_bit_set(var6, x)) {
-      bn_cmplx7();
-    }
-  }
-
-  BN_copy(bn_glb1, bn_glb_c);
-  BN_mask_bits(bn_glb1, 128);
-  BN_copy(bn_glb7, bn_glb1);
-
-  bn_cmplx1(bn_glb1, bn_glb1, bn_glb1, bn_glb6, bn_glb3);
-
-  bn_cmplx1(bn_glb1, bn_glb1, bn_glb7, bn_glb6, bn_glb3);
-  BN_clear(bn_glb7);
-  BN_set_word(bn_glb7, 1);
-
-  bn_cmplx1(bn_glb1, bn_glb1, bn_glb7, bn_glb6, bn_glb3);
-  BN_copy(bn_glb0, bn_glb1);
-  BN_clear(bn_glb7);
-  BN_set_word(bn_glb7, 1);
-  BN_copy(bn_glb1, bn_glb0);
-  BN_clear(bn_glb0);
-  bn_func1(var1);
-  BN_copy(bn_glb5, bn_glb_b);
-  BN_mask_bits(bn_glb5, 128);
-
-  bn_cmplx1(bn_glb0, bn_glb1, bn_glb5, bn_glb6, bn_glb3);
-
-  BN_copy(bn_glb7, bn_glb0);
-  BN_copy(bn_glb5, bn_glb_c);
-  BN_mask_bits(bn_glb5, 128);
-
-  bn_cmplx1(bn_glb1, bn_glb1, bn_glb5, bn_glb6, bn_glb3);
-
-  BN_copy(bn_glb5, bn_glb_a);
-  BN_mask_bits(bn_glb5, 128);
-
-  bn_cmplx1(bn_glb1, bn_glb1, bn_glb5, bn_glb6, bn_glb3);
-
-  BN_clear(bn_glb5);
-  BN_set_word(bn_glb5, 1);
-
-  bn_cmplx1(bn_glb0, bn_glb1, bn_glb5, bn_glb6, bn_glb3);
-  BN_copy(bn_glb_a, bn_glb0);
-  BN_copy(bn_glb1, bn_glb7);
-
-  BN_clear(bn_glb5);
-  BN_set_word(bn_glb5, 1);
-
-  bn_cmplx1(bn_glb0, bn_glb1, bn_glb5, bn_glb6, bn_glb3);
-  BN_copy(bn_glb_b, bn_glb0);
-  BN_free(var48);
-}
-void cN2Map57::Map57(unsigned char *data)
-{
-  BIGNUM *var38, *var58, *var78, *var98, *varb8, *vard8;
-  BN_CTX *t;
-  unsigned char tmpdata[256];
-  unsigned char res[256];
-
-  t = BN_CTX_new();
-  t1 = BN_CTX_new();
-  BN_CTX_init(t);
-
-  glb2pow128 = BN_new();
-  BN_clear(glb2pow128);
-  BN_set_bit(glb2pow128, 128);
-  mask128 = BN_new();
-  BN_hex2bn(&mask128, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
-
-  glb2pow64 = BN_new();
-  BN_clear(glb2pow64);
-  BN_set_bit(glb2pow64, 64);
-  mask64 = BN_new();
-  BN_hex2bn(&mask64, "FFFFFFFFFFFFFFFF");
-  
-  bn_glb0=BN_new(); BN_clear(bn_glb0);
-  bn_glb1=BN_new(); BN_clear(bn_glb1);
-  bn_glb3=BN_new(); BN_clear(bn_glb3);
-  bn_glb5=BN_new(); BN_clear(bn_glb5);
-  bn_glb6=BN_new(); BN_clear(bn_glb6);
-  bn_glb7=BN_new(); BN_clear(bn_glb7);
-
-  bn_glb_a=BN_new(); BN_clear(bn_glb_a);
-  bn_glb_b=BN_new(); BN_clear(bn_glb_b);
-  bn_glb_c=BN_new(); BN_clear(bn_glb_c);
-  bn_glb_d=BN_new(); BN_clear(bn_glb_d);
-  bn_glb_e=BN_new(); BN_clear(bn_glb_e);
-  bn_glb_f=BN_new(); BN_clear(bn_glb_f);
-  bn_glb_g=BN_new(); BN_clear(bn_glb_g);
-  bn_glb_h=BN_new(); BN_clear(bn_glb_h);
-  bn_glb_i=BN_new(); BN_clear(bn_glb_i);
-  bn_glb_j=BN_new(); BN_clear(bn_glb_j);
-  bn_glb_k=BN_new(); BN_clear(bn_glb_k);
-  bn_glb_l=BN_new(); BN_clear(bn_glb_l);
-  bn_glb_m=BN_new(); BN_clear(bn_glb_m);
-
-  var38=BN_new(); BN_clear(var38);
-  var58=BN_new(); BN_clear(var58);
-  var78=BN_new(); BN_clear(var78);
-  var98=BN_new(); BN_clear(var98);
-  varb8=BN_new(); BN_clear(varb8);
-  vard8=BN_new(); BN_clear(vard8);
-
-  memcpy(tmpdata, data, 0x80);
-  RotateBytes(tmpdata, 0x80);
-  BN_bin2bn(tmpdata, 16, var78);
-  BN_bin2bn(tmpdata+0x10, 16, varb8);
-  BN_bin2bn(tmpdata+0x20, 16, var98);
-  BN_bin2bn(tmpdata+0x40, 16, vard8);
-  BN_bin2bn(tmpdata+0x60, 16, var38);
-  BN_bin2bn(tmpdata+0x70, 16, var58);
-
-  bn_cmplx2(varb8, var58, vard8, var38, var78, var98);
-
-  memset(res, 0, 0x80);
-  unsigned int *dest = (unsigned int *)res, *src = (unsigned int *)data;
-  *dest++ = src[0x03];
-  *dest++ = src[0x02];
-  *dest++ = src[0x01];
-  *dest++ = src[0x00];
-  *dest++ = src[0x07];
-  *dest++ = src[0x06];
-  *dest++ = src[0x05];
-  *dest++ = src[0x04];
-
-  memset(tmpdata, 0, 0x20);
-  int len = BN_bn2bin(bn_glb_a, tmpdata);
-  if(len) {
-    RotateBytes(tmpdata, len);
-  }
-  src = (unsigned int *)tmpdata;
-  *dest++ = src[0x03];
-  *dest++ = src[0x02];
-  *dest++ = src[0x01];
-  *dest++ = src[0x00];
-
-  memset(tmpdata, 0, 0x20);
-  len = BN_bn2bin(bn_glb_m, tmpdata);
-  if(len) {
-    RotateBytes(tmpdata, len);
-  }
-  *dest = src[0x03];
-  dest+=4;
-
-  memset(tmpdata, 0, 0x20);
-  len = BN_bn2bin(bn_glb_b, tmpdata);
-  if(len) {
-    RotateBytes(tmpdata, len);
-  }
-  *dest++ = src[0x03];
-  *dest++ = src[0x02];
-  *dest++ = src[0x01];
-  *dest++ = src[0x00];
-
-  dest+=4;
-  src = (unsigned int *)(data+0x60);
-  *dest++ = src[0x03];
-  *dest++ = src[0x02];
-  *dest++ = src[0x01];
-  *dest++ = src[0x00];
-  *dest++ = src[0x07];
-  *dest++ = src[0x06];
-  *dest++ = src[0x05];
-  *dest++ = src[0x04];
-
-  *(unsigned int *)(data + (8<<2))= *(unsigned int *)(res + (11<<2));
-  *(unsigned int *)(data + (9<<2))= *(unsigned int *)(res + (10<<2));
-  *(unsigned int *)(data + (10<<2))= *(unsigned int *)(res + (9<<2));
-  *(unsigned int *)(data + (11<<2))= *(unsigned int *)(res + (8<<2));
-  *(unsigned int *)(data + (12<<2))= *(unsigned int *)(res + (12<<2));
-  *(unsigned int *)(data + (13<<2))= *(unsigned int *)(res + (13<<2));
-  *(unsigned int *)(data + (14<<2))= *(unsigned int *)(res + (14<<2));
-  *(unsigned int *)(data + (15<<2))= *(unsigned int *)(res + (15<<2));
-  *(unsigned int *)(data + (16<<2))= *(unsigned int *)(res + (19<<2));
-  *(unsigned int *)(data + (17<<2))= *(unsigned int *)(res + (18<<2));
-  *(unsigned int *)(data + (18<<2))= *(unsigned int *)(res + (17<<2));
-  *(unsigned int *)(data + (19<<2))= *(unsigned int *)(res + (16<<2));
-  *(unsigned int *)(data + (20<<2))= *(unsigned int *)(res + (20<<2));
-  *(unsigned int *)(data + (21<<2))= *(unsigned int *)(res + (21<<2));
-  *(unsigned int *)(data + (22<<2))= *(unsigned int *)(res + (22<<2));
-  *(unsigned int *)(data + (23<<2))= *(unsigned int *)(res + (23<<2));
-
-  BN_free(glb2pow128);
-  BN_free(mask128);
-  BN_free(glb2pow64);
-  BN_free(mask64);
-  
-  BN_free(bn_glb0);
-  BN_free(bn_glb1);
-  BN_free(bn_glb3);
-  BN_free(bn_glb5);
-  BN_free(bn_glb6);
-  BN_free(bn_glb7);
-
-  BN_free(bn_glb_a);
-  BN_free(bn_glb_b);
-  BN_free(bn_glb_c);
-  BN_free(bn_glb_d);
-  BN_free(bn_glb_e);
-  BN_free(bn_glb_f);
-  BN_free(bn_glb_g);
-  BN_free(bn_glb_h);
-  BN_free(bn_glb_i);
-  BN_free(bn_glb_j);
-  BN_free(bn_glb_k);
-  BN_free(bn_glb_l);
-  BN_free(bn_glb_m);
-
-  BN_free(var38);
-  BN_free(var58);
-  BN_free(var78);
-  BN_free(var98);
-  BN_free(varb8);
-  BN_free(vard8);
-
-  BN_CTX_free(t);
-  BN_CTX_free(t1);
-}
index 63f538676b1e0c7ad803d64fadeddf19c1396a13..d2bda22e4a5d3f904eb4928addb21f47b02f101b 100644 (file)
@@ -46,6 +46,7 @@ private:
   bool initDone;
 protected:
   bool Init(int id, int romv);
+  virtual bool RomInit(void) { return true; }
   virtual void Stepper(void) {}
 public:
   cN2Emu(void);
@@ -74,14 +75,14 @@ bool cN2Emu::Init(int id, int romv)
 
     snprintf(buff,sizeof(buff),"EEP%02X_%d.bin",(id>>8)&0xFF|0x01,romv);
     // Eeprom00 0x00:0x3000-0x37ff OTP 0x80
-    if(!AddMapper(new cMapRom(0x3000,buff,0x0000),0x3000,0x0800,0x00)) return false;
-    //XXX if(!AddMapper(new cMapEeprom(0x3000,buff,128,0x0000),0x3000,0x0800,0x00)) return false;
+    //XXX if(!AddMapper(new cMapRom(0x3000,buff,0x0000),0x3000,0x0800,0x00)) return false;
+    if(!AddMapper(new cMapEeprom(0x3000,buff,128,0x0000),0x3000,0x0800,0x00)) return false;
     // Eeprom80 0x80:0x8000-0xbfff
-    if(!AddMapper(new cMapRom(0x8000,buff,0x0800),0x8000,0x4000,0x80)) return false;
-    //XXX if(!AddMapper(new cMapEeprom(0x8000,buff,  0,0x0800),0x8000,0x4000,0x80)) return false;
-    initDone=true;
+    //XXX if(!AddMapper(new cMapRom(0x8000,buff,0x0800),0x8000,0x4000,0x80)) return false;
+    if(!AddMapper(new cMapEeprom(0x8000,buff,  0,0x0800),0x8000,0x4000,0x80)) return false;
+    initDone=RomInit();
     }
-  return true;
+  return initDone;
 }
 
 // -- cMapCore -----------------------------------------------------------------
@@ -116,17 +117,32 @@ bool cN2Emu::Init(int id, int romv)
 
 class cMapCore {
 private:
-  cBN x, y, s, j;
-  SHA_CTX sctx;
+  int last;
+  cBN *regs[5];
+  cBN x, y, s;
 protected:
-  cBN A, B, C, D, J;
-  cBN H, R;
+  int wordsize;
+  cBN A, B, C, D, J, I;
+  cBN Px, Py, Pz,Qx, Qy, Qz; // 0x00,0x20,0x40,0x60,0x80,0x180
+  cBN sA0, sC0, sE0, s100, s120, s140, s160;
   cBNctx ctx;
-  int wordsize, last;
-  cBN *regs[5];
+  SHA_CTX sctx;
+  // stateless
+  void MakeJ0(BIGNUM *j, BIGNUM *d);
+  void ModAdd(BIGNUM *r, BIGNUM *a, BIGNUM *b, BIGNUM *d);
+  void ModSub(BIGNUM *r, BIGNUM *d, BIGNUM *b);
+  void MonMul(BIGNUM *o, BIGNUM *a, BIGNUM *b, BIGNUM *c, BIGNUM *d, BIGNUM *j);
+  // statefull
+  void MonInit(int bits=0);
+  void MonMul(BIGNUM *o, BIGNUM *a, BIGNUM *b) { MonMul(o,a,b,C,D,J); }
+  void MonExpNeg(void);
+  // ECC
+  void DoubleP(int temp);
+  void AddP(int temp);
+  void ToProjective(int set, BIGNUM *x, BIGNUM *y);
+  void ToAffine(void);
+  void CurveInit(BIGNUM *a);
   //
-  void MakeJ(void);
-  void MonMul(BIGNUM *o, BIGNUM *i1, BIGNUM *i2);
   bool DoMap(int f, unsigned char *data=0, int l=0);
 public:
   cMapCore(void);
@@ -138,60 +154,215 @@ cMapCore::cMapCore(void)
   regs[0]=&J; regs[1]=&A; regs[2]=&B; regs[3]=&C; regs[4]=&D;
 }
 
-void cMapCore::MakeJ(void)
+void cMapCore::ModAdd(BIGNUM *r, BIGNUM *a, BIGNUM *b, BIGNUM *d)
+{
+  BN_add(r,a,b);
+  if(BN_cmp(r,d)>=0) BN_sub(r,r,d);
+  BN_mask_bits(r,wordsize<<6);
+}
+
+void cMapCore::ModSub(BIGNUM *r, BIGNUM *d, BIGNUM *b)
+{
+  cBN p;
+  BN_set_bit(p,wordsize<<6);
+  BN_mod_sub(r,d,b,p,ctx);
+  BN_mask_bits(r,wordsize<<6);
+}
+
+void cMapCore::MakeJ0(BIGNUM *j, BIGNUM *d)
 {
 #if OPENSSL_VERSION_NUMBER < 0x0090700fL
 #error BN_mod_inverse is probably buggy in your openssl version
 #endif
   BN_zero(x);
-  BN_sub(J,x,D);
-  BN_set_bit(J,0);
+  BN_sub(j,x,d);
+  BN_set_bit(j,0);
   BN_set_bit(x,64);
-  BN_mod_inverse(J,J,x,ctx);
+  BN_mod_inverse(j,j,x,ctx);
 }
 
-void cMapCore::MonMul(BIGNUM *o, BIGNUM *i1, BIGNUM *i2)
+void cMapCore::MonMul(BIGNUM *o, BIGNUM *a, BIGNUM *b, BIGNUM *c, BIGNUM *d, BIGNUM *j)
 {
-  int words=(BN_num_bytes(i1)+7)>>3;
+  int words=(BN_num_bytes(d)+7)>>3;
   BN_zero(s);
-  for(int i=0; i<words; i++) { 
-    BN_rshift(x,i1,i<<6);
+  for(int i=0; i<words;) {
+    BN_rshift(x,a,(i++)<<6);
     BN_mask_bits(x,64);
-    BN_mul(x,x,i2,ctx);
+    BN_mul(x,x,b,ctx);
     BN_add(s,s,x);
 
     BN_copy(x,s);
     BN_mask_bits(x,64);
-    BN_mul(x,x,J,ctx);
-    if(i==(words-1)) {
+    BN_mul(x,x,j,ctx);
+    if(i==words) {
       BN_lshift(y,x,64);
       BN_add(y,y,x);
       // Low
-      BN_rshift(C,y,2);
-      BN_add(C,C,s);
-      BN_rshift(C,C,52);
-      BN_mask_bits(C,12);
+      BN_rshift(c,y,2);
+      BN_add(c,c,s);
+      BN_rshift(c,c,52);
+      BN_mask_bits(c,12);
       }
 
     BN_mask_bits(x,64);
-    BN_mul(x,x,D,ctx);
+    BN_mul(x,x,d,ctx);
     BN_add(s,s,x);
-    if(i==(words-1)) {
+    if(i==words) {
       // High
       BN_lshift(y,s,12);
-      BN_add(C,C,y);
-      BN_mask_bits(C,wordsize<<6);
+      BN_add(c,c,y);
+      BN_mask_bits(c,wordsize<<6);
       }
 
     BN_rshift(s,s,64);
-    if(BN_cmp(s,D)==1) {
+    if(BN_cmp(s,d)==1) {
       BN_copy(x,s);
-      BN_sub(s,x,D);
+      BN_sub(s,x,d);
       }
     }
   BN_copy(o,s);
 }
 
+void cMapCore::MonInit(int bits)
+{
+  // Calculate J0 & H montgomery elements in J and B
+  MakeJ0(J,D);
+  BN_zero(I);
+  BN_set_bit(I,bits ? bits : 68*wordsize);
+  BN_mod(B,I,D,ctx);
+  for(int i=0; i<4; i++) MonMul(B,B,B);
+}
+
+void cMapCore::MonExpNeg(void)
+{
+  if(BN_is_zero(D)) { BN_set_word(A,1); return; }
+  cBN e;
+  BN_copy(e,D);
+  BN_mask_bits(e,8);           // check LSB
+  unsigned int n=BN_get_word(e);
+  BN_copy(e,D);
+  if(n) BN_sub_word(e,0x02);   // N -2
+  else  BN_add_word(e,0xFE);   // N + 254 ('carryless' -2)
+  BN_copy(A,B);
+  for(int i=BN_num_bits(e)-2; i>-1; i--) {
+    MonMul(B,B,B);
+    if(BN_is_bit_set(e,i)) MonMul(B,A,B);
+    }
+  BN_set_word(A,1);
+  MonMul(B,A,B);
+}
+
+void cMapCore::DoubleP(int temp)
+{
+  ModAdd(B,Py,Py,D);
+  MonMul(sC0,Pz,B);
+  MonMul(B,B,B);
+  MonMul(B,Px,B);
+  ModSub(sA0,D,B);
+  MonMul(B,Px,Px);
+  BN_copy(A,B);
+  ModAdd(B,B,B,D);
+  ModAdd(A,B,A,D);
+  MonMul(B,Pz,Pz);
+  MonMul(B,B,B);
+  MonMul(B,s160,B);
+  ModAdd(B,B,A,D);
+  BN_copy(A,B);
+  MonMul(B,B,B);
+  BN_copy(C,sA0);
+  ModAdd(B,C,B,D);
+  ModAdd(B,C,B,D);
+  if(temp==0) BN_copy(Px,B); else BN_copy(sA0,B);
+  ModAdd(B,C,B,D);
+  MonMul(B,A,B);
+  BN_copy(A,B);
+  MonMul(B,Py,Py);
+  ModAdd(B,B,B,D);
+  MonMul(B,B,B);
+  ModAdd(B,B,B,D);
+  ModAdd(B,B,A,D);
+  ModSub(B,D,B);
+  if(temp==0) { BN_copy(Py,B); BN_copy(Pz,sC0); }
+  else BN_copy(sA0,sC0);
+}
+
+void cMapCore::AddP(int temp)
+{
+  MonMul(B,Pz,Pz);
+  MonMul(sA0,Pz,B);
+  MonMul(B,Qx,B);
+  BN_copy(A,B);
+  ModSub(B,D,B);
+  ModAdd(B,Px,B,D);
+  BN_copy(sC0,B);
+  MonMul(I,Pz,B);
+  if(temp==0) BN_copy(Pz,I); else BN_copy(sA0,I);
+  MonMul(B,B,B);
+  BN_copy(sE0,B);
+  ModAdd(A,Px,A,D);
+  MonMul(A,A,B);
+  BN_copy(s100,A);
+  MonMul(B,sA0,Qy);
+  BN_copy(sA0,B);
+  ModSub(B,D,B);
+  ModAdd(B,Py,B,D);
+  BN_copy(s120,B);
+  MonMul(B,B,B);
+  BN_swap(A,B);
+  ModSub(B,D,B);
+  ModAdd(B,A,B,D);
+  if(temp==0) BN_copy(Px,B); else BN_copy(sA0,B);
+  ModAdd(B,B,B,D);
+  ModSub(B,D,B);
+  ModAdd(B,B,s100,D);
+  ModAdd(A,sA0,Py,D);
+  MonMul(sA0,s120,B);
+  MonMul(B,sE0,sC0);
+  MonMul(B,A,B);
+  ModSub(B,D,B);
+  ModAdd(B,B,sA0,D);
+  MonMul(B,s140,B);
+  if(temp==0) BN_copy(Py,B); else BN_copy(sA0,B);
+}
+
+void cMapCore::ToProjective(int set, BIGNUM *x, BIGNUM *y)
+{
+  if(set==0) {
+    BN_set_word(I,1); MonMul(Pz,I,B);
+    BN_copy(Qz,Pz);
+    MonMul(Px,x,B);
+    MonMul(Py,y,B);
+    }
+  else {
+    MonMul(Qx,x,B);
+    MonMul(Qy,y,B);
+    }
+}
+
+void cMapCore::ToAffine(void)
+{
+  BN_set_word(I,1);
+  MonMul(B,Pz,Pz); MonMul(B,Pz,B); MonMul(B,I,B);
+  MonExpNeg();
+  BN_set_word(I,1);
+  MonMul(A,Py,B); MonMul(Py,I,A);
+  MonMul(B,Pz,B); MonMul(B,Px,B); MonMul(Px,I,B);
+}
+
+void cMapCore::CurveInit(BIGNUM *a)
+{
+  BN_zero(Px); BN_zero(Py); BN_zero(Pz); BN_zero(Qx); BN_zero(Qy); BN_zero(Qz);
+  BN_zero(sA0); BN_zero(sC0); BN_zero(sE0); BN_zero(s100);
+  BN_zero(s120); BN_zero(s140); BN_zero(s160);
+  MonInit();
+  BN_copy(A,B);
+  BN_copy(I,D);
+  BN_add_word(I,1);
+  BN_rshift(I,I,1);
+  MonMul(s140,I,B);
+  MonMul(s160,B,a);
+}
+
 bool cMapCore::DoMap(int f, unsigned char *data, int l)
 {
   int dl=(l?l:wordsize)<<3;
@@ -283,25 +454,27 @@ bool cMapCore::DoMap(int f, unsigned char *data, int l)
 #define N2FLAG_MECM     1
 #define N2FLAG_Bx       2
 #define N2FLAG_POSTAU   4
+#define N2FLAG_Ex       8
 #define N2FLAG_INV      128
 
 class cN2Prov {
 private:
-  unsigned seed[5], cwkey[8];
+  unsigned char seed[32], cwkey[8];
   bool keyValid;
-  cIDEA idea;
 protected:
-  int id, flags;
+  int id, flags, seedSize;
+  cIDEA idea;
   //
-  virtual bool Algo(int algo, const unsigned char *hd, unsigned char *hw) { return false; }
+  virtual bool Algo(int algo, unsigned char *hd, const unsigned char *ed, unsigned char *hw) { return false; }
   virtual bool NeedsCwSwap(void) { return false; }
   void ExpandInput(unsigned char *hw);
 public:
   cN2Prov(int Id, int Flags);
   virtual ~cN2Prov() {}
-  bool MECM(unsigned char in15, int algo, unsigned char *cws);
+  bool MECM(unsigned char in15, int algo, const unsigned char *ed, unsigned char *cw);
   void SwapCW(unsigned char *cw);
   virtual int ProcessBx(unsigned char *data, int len, int pos) { return -1; }
+  virtual int ProcessEx(unsigned char *data, int len, int pos) { return -1; }
   virtual bool PostProcAU(int id, unsigned char *data) { return true; }
   bool CanHandle(int Id) { return MATCH_ID(Id,id); }
   bool HasFlags(int Flags) { return (flags&Flags)==Flags; }
@@ -310,14 +483,15 @@ public:
 
 cN2Prov::cN2Prov(int Id, int Flags)
 {
-  keyValid=false; id=Id|0x100; flags=Flags;
+  keyValid=false; id=Id|0x100; flags=Flags; seedSize=5;
 }
 
 void cN2Prov::PrintCaps(int c)
 {
-  PRINTF(c,"provider %04x capabilities%s%s%s%s",id,
+  PRINTF(c,"provider %04x capabilities%s%s%s%s%s",id,
            HasFlags(N2FLAG_MECM)    ?" MECM":"",
            HasFlags(N2FLAG_Bx)      ?" Bx":"",
+           HasFlags(N2FLAG_Ex)      ?" Ex":"",
            HasFlags(N2FLAG_POSTAU)  ?" POSTPROCAU":"",
            HasFlags(N2FLAG_INV)     ?" INVCW":"");
 }
@@ -339,27 +513,27 @@ void cN2Prov::ExpandInput(unsigned char *hw)
     }
 }
 
-bool cN2Prov::MECM(unsigned char in15, int algo, unsigned char *cw)
+bool cN2Prov::MECM(unsigned char in15, int algo, const unsigned char *ed, unsigned char *cw)
 {
-  unsigned char hd[5], hw[128+64], buf[20];
+  unsigned char hd[32], hw[128+64], buf[20];
   hd[0]=in15&0x7F;
   hd[1]=cw[14];
   hd[2]=cw[15];
   hd[3]=cw[6];
   hd[4]=cw[7];
 
-  if(keyValid && !memcmp(seed,hd,5)) { // key cached
+  if(keyValid && !memcmp(seed,hd,seedSize)) {  // key cached
     memcpy(buf,cwkey,8);
     }
   else {                               // key not cached
     memset(hw,0,sizeof(hw));
-    if(!Algo(algo,hd,hw)) return false;
+    if(!Algo(algo,hd,ed,hw)) return false;
     memcpy(&hw[128],hw,64);
     RotateBytes(&hw[64],128);
     SHA1(&hw[64],128,buf);
     RotateBytes(buf,20);
 
-    memcpy(seed,hd,5);
+    memcpy(seed,hd,seedSize);
     memcpy(cwkey,buf,8);
     keyValid=true;
     }  
@@ -578,6 +752,8 @@ bool cNagra2::DecryptEMM(const unsigned char *in, unsigned char *out, const unsi
 
 // -- cSystemNagra2 ------------------------------------------------------------
 
+static int dropEMMs=1;
+
 class cSystemNagra2 : public cSystem, protected cNagra2 {
 private:
   int lastEcmId, lastEmmId;
@@ -606,6 +782,8 @@ bool cSystemNagra2::ProcessECM(const cEcmInfo *ecm, unsigned char *data)
 {
 #define NA_SOURCE_START 0x8267 // cSource::FromString("S61.5W");
 #define NA_SOURCE_END   0x85c8 // cSource::FromString("S148W");
+  unsigned char odata[15];
+  memcpy(odata,data,sizeof(odata));
   if(ecm->source>=NA_SOURCE_START && ecm->source<=NA_SOURCE_END) {
     if(ecm->caId==0x1234) data[5]=0x09;                // NA rev 248 morph
     else data[5]=0x01;                         // I _HATE_ this provider
@@ -679,7 +857,13 @@ bool cSystemNagra2::ProcessECM(const cEcmInfo *ecm, unsigned char *data)
         break;
       case 0x00:
         i+=2; break;
-      case 0x30 ... 0x36:
+      case 0x30:
+      case 0x31:
+      case 0x32:
+      case 0x33:
+      case 0x34:
+      case 0x35:
+      case 0x36:
       case 0xB0:
         i+=buff[i+1]+2;
         break;
@@ -696,7 +880,7 @@ bool cSystemNagra2::ProcessECM(const cEcmInfo *ecm, unsigned char *data)
   if(l!=3) return false;
   if(mecmAlgo>0) {
     if(ecmP && ecmP->HasFlags(N2FLAG_MECM)) {
-      if(!ecmP->MECM(buff[15],mecmAlgo,cw)) return false;
+      if(!ecmP->MECM(buff[15],mecmAlgo,odata,cw)) return false;
       }
     else { PRINTF(L_SYS_ECM,"MECM for provider %04x not supported",id); return false; }
     }
@@ -713,6 +897,7 @@ void cSystemNagra2::ProcessEMM(int pid, int caid, unsigned char *buffer)
   int cmdLen=buffer[9]-5;
   int id=buffer[10]*256+buffer[11];
 
+  if(buffer[0]==0x83 && dropEMMs) return; // skip EMM-S if disabled
   if(cmdLen<96 || SCT_LEN(buffer)<cmdLen+15) {
     PRINTF(L_SYS_EMM,"bad EMM message msgLen=%d sctLen=%d",cmdLen,SCT_LEN(buffer));
     return;
@@ -816,7 +1001,10 @@ void cSystemNagra2::ProcessEMM(int pid, int caid, unsigned char *buffer)
         id=(emmdata[i+1]<<8)|emmdata[i+2];
         i+=3;
         break;
-      case 0xB0 ... 0xBF: // Update with ROM CPU code
+      case 0xB0: case 0xB1: case 0xB2: case 0xB3: // Update with ROM CPU code
+      case 0xB4: case 0xB5: case 0xB6: case 0xB7:
+      case 0xB8: case 0xB9: case 0xBA: case 0xBB:
+      case 0xBC: case 0xBD: case 0xBE: case 0xBF:
         {
         int bx=emmdata[i]&15;
         if(!emmP || !emmP->HasFlags(N2FLAG_Bx)) {
@@ -841,7 +1029,24 @@ void cSystemNagra2::ProcessEMM(int pid, int caid, unsigned char *buffer)
       case 0xAE: i+=11;break;
       case 0x12: i+=emmdata[i+1]+2; break;      // create tier
       case 0x20: i+=19; break;                  // modify tier
-      case 0xE3: i+=emmdata[i+4]+5; break;     // Eeprom update
+      case 0x9F: i+=6; break;
+      case 0xE3:                                // Eeprom update
+        {
+        int ex=emmdata[i]&15;
+        if(!emmP || !emmP->HasFlags(N2FLAG_Ex)) {
+          i+=emmdata[i+4]+5;
+          PRINTF(L_SYS_EMM,"E%X for provider %04x not supported",ex,id);
+          break;
+          }
+        int r;
+        if((r=emmP->ProcessEx(emmdata,cmdLen,i+1))>0)
+          i+=r;
+        else {
+          PRINTF(L_SYS_EMM,"E%X executing failed for %04x",ex,id);
+          i=cmdLen;
+          }
+        break;
+        }
       case 0xE1:
       case 0xE2:
       case 0x00: i=cmdLen; break;              // end of processing
@@ -859,52 +1064,6 @@ void cSystemNagra2::ProcessEMM(int pid, int caid, unsigned char *buffer)
 
 // -- cSystemLinkNagra2 --------------------------------------------------------
 
-static const tI18nPhrase Phrases2[] = {
-  { "Nagra2: AUXserver hostname",
-    "Nagra2: AUXserver Hostname",
-    "",
-    "",
-    "",
-    "",
-    "",
-    "",
-    "Nagra2: AUX-palvelimen osoite",
-    "",
-    "",
-    "",
-    "",
-  },
-  { "Nagra2: AUXserver port",
-    "Nagra2: AUXserver Port",
-    "",
-    "",
-    "",
-    "",
-    "",
-    "",
-    "Nagra2: AUX-palvelimen portti",
-    "",
-    "",
-    "",
-    "",
-  },
-  { "Nagra2: AUXserver password",
-    "Nagra2: AUXserver Passwort",
-    "",
-    "",
-    "",
-    "",
-    "",
-    "",
-    "Nagra2: AUX-palvelimen salasana",
-    "",
-    "",
-    "",
-    "",
-  },
-  { NULL }
-  };
-
 class cSystemLinkNagra2 : public cSystemLink {
 public:
   cSystemLinkNagra2(void);
@@ -917,13 +1076,14 @@ static cSystemLinkNagra2 staticInitN2;
 cSystemLinkNagra2::cSystemLinkNagra2(void)
 :cSystemLink(SYSTEM_NAME,SYSTEM_PRI)
 {
+  opts=new cOpts(SYSTEM_NAME,5);
+  opts->Add(new cOptBool("DropEMMS",trNOOP("Nagra2: drop EMM-S packets"),&dropEMMs));
 #ifdef HAS_AUXSRV
   static const char allowed_chars[] = "0123456789abcdefghijklmnopqrstuvwxyz-.";
-  opts=new cOpts(SYSTEM_NAME,3);
-  opts->Add(new cOptStr("AuxServerAddr","Nagra2: AUXserver hostname",auxAddr,sizeof(auxAddr),allowed_chars));
-  opts->Add(new cOptInt("AuxServerPort","Nagra2: AUXserver port",&auxPort,0,65535));
-  opts->Add(new cOptStr("AuxServerPass","Nagra2: AUXserver password",auxPassword,sizeof(auxPassword),allowed_chars));
-  Feature.AddPhrases(Phrases2);
+  opts->Add(new cOptBool("AuxServerEnable",trNOOP("Nagra2: Enable AUXserver"),&auxEnabled));
+  opts->Add(new cOptStr("AuxServerAddr",trNOOP("Nagra2: AUXserver hostname"),auxAddr,sizeof(auxAddr),allowed_chars));
+  opts->Add(new cOptInt("AuxServerPort",trNOOP("Nagra2: AUXserver port"),&auxPort,0,65535));
+  opts->Add(new cOptStr("AuxServerPass",trNOOP("Nagra2: AUXserver password"),auxPassword,sizeof(auxPassword),allowed_chars));
 #endif
   Feature.NeedsKeyFile();
 }
index ecb16592bb7d2eb6b98163403a13c0915190decf..2a316f568c76ac6af8d08c081c13a23e4b422348 100644 (file)
@@ -50,7 +50,7 @@ ADD_MODULE(L_SC,lm_sc)
 
 static void BN_complement(const unsigned char *data, int len, BIGNUM *bn)
 {
-  unsigned char buff[len];
+  unsigned char *buff=AUTOMEM(len);
   for(int i=len-1; i>=0; i--) buff[i]=~data[i];
   BN_bin2bn(buff,len,bn);
   BN_add_word(bn,1);
index 1528b7510a7a05dda14c503d8ef8a7fed1b55c08..f36639de1b4a61db30803b9b5c223c27a21c1b0e 100644 (file)
@@ -413,7 +413,7 @@ struct CmdTab {
   unsigned char size;
   unsigned char Nentries; 
   unsigned char dummy;
-  CmdTabEntry e[0];
+  CmdTabEntry e[1];
 };
 
 class CmdTable {
index 8376da2fd2a9dd1ec723558a73956e5f16685c7e..3a0fa0c49c4cf9d472392039f8815a8b3e3788f4 100644 (file)
@@ -124,7 +124,7 @@ bool cPlainKeySeca::Parse(const char *line)
                 break;
       }
     if(ok) {
-      unsigned char skey[keylen];
+      unsigned char *skey=AUTOMEM(keylen);
       len=GetHex(line,skey,keylen,false);
       if(IsBNKey()) {
         if(C2(keynr)=='E' && len==PLAINLEN_SECA_E) {
@@ -1225,8 +1225,8 @@ bool cSystemSeca::ProcessECM(const cEcmInfo *ecmD, unsigned char *data)
   bool key8=!(cParseSeca::SysMode(data)&0x10);
   cPlainKey *pk=0;
   cKeySnoop ks(this,'S',ecmD->provId,keyNr&0x0F);
+  unsigned char *buff=AUTOMEM(msgLen);
   while((pk=keys.FindKey('S',ecmD->provId,keyNr&0x0F,key8?8:16,pk))) {
-    unsigned char buff[msgLen];
     memcpy(buff,ecm,sizeof(buff)); // if decoding fails we need the original data
     
     unsigned char PK[16], signature[20];
@@ -1551,6 +1551,7 @@ void cSystemSeca::ProcessEMM(int pid, int caid, unsigned char *buffer)
       }
     }
 
+  unsigned char *buff=AUTOMEM(msgLen);
   for(cSecaCardInfo *ci=Scards.First(); ci; ci=Scards.Next(ci)) {
     if(ci->MatchEMM(buffer) || (CheckNull(ci->sa,sizeof(ci->sa)) && ci->MatchID(buffer))) {
       unsigned char MK[16];
@@ -1563,7 +1564,7 @@ void cSystemSeca::ProcessEMM(int pid, int caid, unsigned char *buffer)
         memcpy(&MK[8],ci->key,8);
         }
 
-      unsigned char buff[msgLen], signature[20];
+      unsigned char signature[20];
       memcpy(buff,emm,sizeof(buff)); // if decoding fails we need the original de-sse'd data
 
       if(!SE) {
index c619dcca03ee0e3e05f08afc2f2ab6bb2fe5a3c9..8cc3253d938baf299bceca2d6458b7c2bba5e5c0 100644 (file)
@@ -148,22 +148,22 @@ void cST20::SetReg(int reg, unsigned int val)
 
 unsigned char *cST20::Addr(unsigned int off)
 {
-  switch(off) {
-    case FLASHS ... FLASHE:
+  if(off>=FLASHS && off<=FLASHE) {
 #ifndef SAVE_DEBUG
-      return &flash[off-FLASHS];
+    return &flash[off-FLASHS];
 #else
-      off-=FLASHS; if(off<flashSize && flash) return &flash[off]; break;
+    off-=FLASHS; if(off<flashSize && flash) return &flash[off]; break;
 #endif
-    case RAMS ... RAME:
+    }
+  else if(off>=RAMS && off<=RAME) {
 #ifndef SAVE_DEBUG
-      return &ram[off-RAMS];
+    return &ram[off-RAMS];
 #else
-      off-=RAMS; if(off<ramSize && ram) return &ram[off]; break;
+    off-=RAMS; if(off<ramSize && ram) return &ram[off]; break;
 #endif
-    case IRAMS ... IRAME:
-      return &iram[off-IRAMS];
     }
+  else if(off>=IRAMS && off<=IRAME)
+    return &iram[off-IRAMS];
 #ifndef SAVE_DEBUG
   invalid=ERRORVAL; return (unsigned char *)&invalid;
 #else
index 8bc8d018a17dfcee62283125827981687662f7c3..9203b730d5a97c142ae745c89f2310e41527d4da 100644 (file)
@@ -74,7 +74,7 @@ void cRC6::SetKey(const unsigned char *Key, int len)
   key[0]=RC6_P32;
   for(int v=1; v<RC6_MAX; v++) key[v]=key[v-1]+RC6_Q32;
   len/=4;
-  unsigned int a=0, b=0, l[len];
+  unsigned int a=0, b=0, *l=AUTOARRAY(unsigned int,len);
   memcpy(l,Key,len*4);
   for(int i=0,j=0,v=3*(len>RC6_MAX ? len : RC6_MAX) ; v>0; v--) {
     a=key[i]=rol(key[i]+a+b,3);
@@ -440,7 +440,13 @@ bool cOpenTVModule::DoDecompress(unsigned char *out_ptr, const unsigned char *in
         int off=0, len=0;
         unsigned char cmd=BYTE(); in_ptr++;
         switch(cmd>>4) {
-          case 0x0 ... 0x6:
+          case 0x0:
+          case 0x1:
+          case 0x2:
+          case 0x3:
+          case 0x4:
+          case 0x5:
+          case 0x6:
             off=((cmd&0xF)<<8)+BYTE(); in_ptr++;
             len=((cmd>>4)&0x7)+3;
             break;
@@ -461,14 +467,19 @@ bool cOpenTVModule::DoDecompress(unsigned char *out_ptr, const unsigned char *in
               }
             break;
             }
-          case 0x8 ... 0xB:
+          case 0x8:
+          case 0x9:
+          case 0xA:
+          case 0xB:
             if(cmd&0x20) NIBBLE(off); else off=0;
             off=(off<<1)|(cmd&0x1F); len=2;
             break;
           case 0xC:
             off=cmd&0x0F; len=3;
             break;
-          case 0xD ... 0xF:
+          case 0xD:
+          case 0xE:
+          case 0xF:
             NIBBLE(off);
             off|=cmd&0x0F; len=((cmd>>4)&0x3)+2;
             break;
@@ -717,6 +728,9 @@ bool cTpsKeys::ProcessAu(const cOpenTVModule *mod)
           for(int j=2; j < 0xC; j++)
             if(!memcmp(&d[addr+j],scan1,sizeof(scan1))) { cb1=addr; break; }
           }
+        else if(cb1 && !cb2) cb2=addr;
+        else if(cb1 && cb2 && !cb3) cb3=addr;
+/*
         else if((d[addr]&0xF0)==0x60 && (d[addr+1]&0xF0)==0xB0) {
           int vajw = (int)(((~(d[addr]&0x0F))<<4)|(d[addr+1]&0x0F));
           unsigned char hits=0;
@@ -733,6 +747,7 @@ bool cTpsKeys::ProcessAu(const cOpenTVModule *mod)
             else if(cb3==0) cb3=addr;
             }
           }
+*/
         }
       }
     }
index 209f8e73ba03d609266e36b93be4eee70ec7bd25..fc03ea21cb6ce89e227884b9f18c7680217053a6 100644 (file)
@@ -64,3 +64,4 @@ clean:
        @-rm -f *.o core* *~
        @-rm -f testECM testEMM testN1Emu testN2Emu
        @-rm -f filterhelper
+       @-rm -f dump.txt
index 87b486fe95a24007afa92ee5d6cc0e44d3124641..bd9c397e37cd1172685a79ae7aca815385a4eef8 100644 (file)
@@ -80,7 +80,9 @@ int ReadRaw(const char *name, unsigned char *buff, int maxlen)
     int len=0;
     while(len<maxlen && fgets(line,sizeof(line),f)) {
       if(strstr(line,"dump: n=")) continue;
-      char *p=index(line,':');
+      char *p=index(line,'#');
+      if(p) *p=0;
+      p=index(line,':');
       if(p) p++; else p=line;
       while(1) {
         char *np;
index 775b86115198ee31fe0eb1896481e249b5686802..8c6e883cf5892908a428912da3ced05934a88135 100644 (file)
@@ -5,29 +5,37 @@
 #include "data.h"
 #include "system.h"
 #include "compat.h"
+#include <vdr/sources.h>
 
 int main(int argc, char *argv[])
 {
-  if(argc<5) {
-    printf("usage: %s <lib-dir> <plugin-dir> <caid> <provid> <ecm-dump>\n",argv[0]);
+  if(argc<6) {
+    printf("usage: %s <lib-dir> <plugin-dir> <caid> <provid> <source> <ecm-dump>\n",argv[0]);
     return 1;
     }
   DllsLoad(argv[1]);
   InitAll(argv[2]);
   LogAll();
+  cLogging::SetModuleOption(LCLASS(7,0x20<<2),false); // Nagra L_SYS_DISASM
+  cLogging::SetModuleOption(LCLASS(7,0x20<<4),false); // Nagra L_SYS_CPUSTATS
   unsigned char ecm[4096];
-  ReadRaw(argv[5],ecm,sizeof(ecm));
+  ReadRaw(argv[6],ecm,sizeof(ecm));
     
   int caid=strtol(argv[3],0,0);
   int provid=strtol(argv[4],0,0);
   printf("using caid %04x provid %04x\n",caid,provid);
   cEcmInfo ecmD("dummy",0x123,caid,provid);
+  ecmD.SetSource(10,cSource::FromString(argv[5]),120);
   cSystem *sys=0;
   int lastPri=0;
   while((sys=cSystems::FindBySysId(caid,false,lastPri))) {
     lastPri=sys->Pri();
     printf("processing with module '%s'\n",sys->Name());
     bool res=sys->ProcessECM(&ecmD,ecm);
+    if(res) {
+      printf("resulting CW: ");
+      SDump(sys->CW(),16);
+      }
     delete sys;
     if(res) break;
     }
index 4c0ef89f878d5a7c9beae7ae9e850e62d7cfd182..3d36e62483b1c5de41c23b204fd8cf2ca721ffd6 100644 (file)
@@ -96,11 +96,7 @@ bool Ecm(unsigned char *buff, int cmdLen, int id)
   unsigned char cw[16];
 
   cN2Prov *ecmP=cN2Providers::GetProv(id,N2FLAG_NONE);
-  if(ecmP) printf("provider %04x capabilities%s%s%s%s\n",id,
-                    ecmP->HasFlags(N2FLAG_MECM)    ?" MECM":"",
-                    ecmP->HasFlags(N2FLAG_Bx)      ?" Bx":"",
-                    ecmP->HasFlags(N2FLAG_POSTAU)  ?" POSTPROCAU":"",
-                    ecmP->HasFlags(N2FLAG_INV)     ?" INVCW":"");
+  if(ecmP) ecmP->PrintCaps(L_SYS_ECM);
 
   int l=0, mecmAlgo=0;
   for(int i=16; i<cmdLen-10 && l!=3; ) {
@@ -135,7 +131,8 @@ printf("%02x: nano %02x\n",i,buff[i]);
   if(l!=3) return false;
   if(mecmAlgo>0) {
     if(ecmP && ecmP->HasFlags(N2FLAG_MECM)) {
-      if(!ecmP->MECM(buff[15],mecmAlgo,cw)) return false;
+static unsigned char odata[15] = { 0x80,0x30,0x47,0x07,0x45,0xec,0xc1,0xee,0xc5,0x53,0x91,0x2f,0x70,0x34,0x34 };
+      if(!ecmP->MECM(buff[15],mecmAlgo,odata,cw)) return false;
       }
     else { printf("MECM for provider %04x not supported\n",id); return false; }
     }
index 6aab704ee2edabfb5696f6a23ecb214474ccf36b..61f45b71dcf5dddf6916ac9869c6aa7bf5c07891 100644 (file)
--- a/version.h
+++ b/version.h
@@ -21,8 +21,8 @@
 #define ___VERSION_H
 
 // all release versions must end with 0xFF !!
-#define SCVERSNUM 0x000805FF
-#define SCVERSION "0.8.5"
+#define SCVERSNUM 0x000806FF
+#define SCVERSION "0.8.6"
 
 extern const char *ScVersion;