Page 2 of 2 FirstFirst 12
Results 11 to 17 of 17

Thread: What software do i need to make Computer software

  1. #11
    Quote Originally Posted by byrnesc1 View Post
    Notepad ++ or Sublime Text 2 are my 2 "go to" code editing apps, call me old fashioned I guess
    I would suggest doing a bit of research before jumping straight into a language. You should think about what you want to make and what for platform. C++ is a very good language to learn in which there's a high chance you will actually use it in a major project.

  2. Internet, Programming and Graphics   -   #12

  3. Internet, Programming and Graphics   -   #13
    Gribley's Avatar On a hate list
    Join Date
    Sep 2008
    Location
    The turning on the left
    Posts
    2,347
    C with gcc compiler, notepad as an editor and debug the hard way. Don't mess with that Visual stuff

    Or Devpac assembler if you want to develop on an Amiga :S.... ok not very likely that one but it was just as much fun.

    For Intel\PC then I use PowerBasic as it compiles to standalone without a whole bunch of "framework" crap, little bit harder to debug that visual stuff but certain satisfaction in tracing issues with debug outputs. You don`t need automatic trash collection if you code proper like

    Oh the good old days....
    Code:
    /*********************************************************************
        File:       GoM V3.5.4  (Based all on FoM-FunSECA)
        Author:     Gribley 
        Dates:      Nov2001 - May 2002
        Purpose:    SECA emulation :p
        Compiler:   AVR-GCC + Make2
        Hardware:   FunCard 8515 or, with mod to Makefile, 8535
    **********************************************************************/
    
    
    #include <io.h>
    #include "types.h"
    
    
    // Using intelli byte we can add additional space
    // to any calls to the upper end of the eeprom
    // this therefore allows us to have a single
    // version that supports Funcard 2, 3 and 4...  this value
    // is added to the upper limit of the eeprom
    u16 Extra_Funcard_Space = 0x0000;
    
    
    // Default serial number
    //u08 DefaultSerial[3]    = {0xF2, 0xF1, 0xF0};
      
    #include "funseca.h"
    #include "funio.h"
    #include "decrip.h"
    #include "ee_ext.h"
    #include "ee_int.h"
    
    
    #define MODO_LOG  = 0x01
    
    
    u08 ECM_Count_High  = 0x00;
    u08 ECM_Count_Low   = 0x00;
    u08 ECM_LastECMInst = 0x00;
    u08 ECM_LastProviderChecked = 0x00;
    
    
    //u08 EVENT_Display[16] = {0xD3,0xC7,0xAE,0xFD,0x2B,0x8E,0x91,0x35,
    //             0xC4,0x81,0xC0,0xE4,0xB3,0x09,0xD4,0x0B};
    u08 EVENT_Display[12] =   {'C','W','P',':','0','0',' ','E',
                               'V','N','T',':'};
    
    
    //u08 ECM_Display[16]   = {0x6A,0x81,0x60,0x2A,0x12,0xA7,0x38,0x8E,
    //             0x66,0xD1,0xCB,0x82,0x6C,0xAC,0xB9,0x09};
    u08 ECM_Display[12]   =   {'I','N','S',':','0','0',' ','E',
                    'C','M','s',':'};
    
    
    // Display LOG ON in provider 4 when logging is enabled.
    u08 LOG_Method          = 0x00;
    u08 LOG_ON[6]           = {'L','o','g',' ','O','N'};
    u08 LOG_Mode_0[4]       = {'L','o','o','p'};
    u08 LOG_Mode_1[4]       = {'S','t','o','p'};
                 
    #define MAX_COMMAND_LENGHT 0x5F  // (+5 de la cabecera = 0x5f)
    // Buffer of entrance and exit
    u08 buffer[MAX_COMMAND_LENGHT];
    
    
    // This is just an experiement!
    u08 ProviderCount     = 0x00;
    // current Provider, currentKey & current Channel for info mode
    u08 currentProvider   = 0x01;
    u08 currentKey        = 0x00;
    
    
    // PPV auto - with CapturePPVEvent now watching for lack of 3c\3a receipt
    // i.e. Porn, this should then default to using SelectSelect mode.
    //u08 CapturePPVEvent   = 0x00;
    u08 EventUpdatedin3C  = FALSE;
    u08 OldStylePPV       = FALSE;
    
    
    // Data for the Inst 0x0A:  Operating system of the card
    #define TOTAL_VERSION 68 
    u08 version[TOTAL_VERSION]= {
      0x61,0x19,0xad,0xca,0x15,0x2f,0x10,0x03,
      0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,
      0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
      0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
      0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x9E,
      0xB9,0xDF,0x34,0x94,0xEF,0x3E,0x00,0x13,
      0x3A,0x57,0x12,0x53,0x84,0x1A,0xD5,0x90,
      0x14,0x10,0x31,0x2C,0xDA,0xC8,0xAD, '5',
      '4' ,'=' ,'-' ,0x00 };
    
    
    //u08 gribomatic[16] = {'G','-','o','-','M',' ','V','3',
    //                      'x','x',' ','(','N','A',')',' '};
    u08 gribomatic[16] = {0x9B,0x65,0xBB,0x32,0x07,0x10,0xF2,0x32,
                          0x36,0xB4,0xD4,0xCC,0x86,0x2B,0xB5,0x1D};
    
    
                  // Encrypted strings you easy use :)
                  // If nothing else it should stop Mr PurpleHaze
                                      
                          // Standard version 3     -> 0x9B,0x65,0xBB,0x32,0x07,0x10,0xF2,0x32,
                          // Beta\private version 3 -> 0x8E,0xDA,0xB3,0xFC,0xB0,0x6E,0x98,0x13,
                  // 353 string -> 0x14,0xCC,0x61,0xF4,0xE6,0x84,0x07,0xC9};
                  // 354 string -> 0x36,0xB4,0xD4,0xCC,0x86,0x2B,0xB5,0x1D};
                  
    // PPV BX record, generate event and session details on the fly....
    u08 ppv_record[14]      = {0xB1,0x00,0xFF,0xFF,0x01,0xFE,0x05,0x00,0x00,0xFF,0xFF,0x00,0x00,0x04};
    
    
    // Record last requested in 0x34,0x32 pair
    //u08 ppv_request[2]        = {0x00,0x00};
    
    
    #define EVENT_ID1              2
    #define EVENT_ID2              3
    #define SESSION_ID             4
    #define SESSION_DATE1          9
    #define SESSION_DATE2         10
    
    
    // Punteros a las funciones de comunicación
    void (*ptrSend)(u08);
    u08  (*ptrReceive) (void);
    
    
    // stores the last processed instruction
    u08 lastInst            = 0x00; 
    // Only show my info if last command was not a 3c or 3a request
    u08 LastNonProviderInst = 0x00;
    
    
    // Allows to use phoenix to make operations of external I/O eeprom. 
    u08 support_phoenix     = TRUE;
    
    
    // PAra the cloqueo of ticket offices
    u08 decodeX             = FALSE;
    u08 needPin             = TRUE;
    u08 pinChecked          = FALSE;
    
    
    // Answer to Reset
    // It indicates that the card is a version 4,1 (original FoM 4.0)
    u08 ATR[16]={0x3B,0xF7,0x11,0x00,0x01,0x40,0x96,0x58,
                 0x42,0x14,0x0E,0x6C,0xB6,0xD6,0x90,0x00};
    
    
    // key in use (PK + SK)
    u08 Key[8+8];
    
    
    // hash-buffers for the verification of the signature
    u08 hash[8];
    u08 initial_hash[8];
    
    
    // ControlWords desencriptadas para la 0x3A
    u08 CW[8+8];
    
    
    // command sent by 0x34 and 0x38
    u08 Comando34[5];
    
    
    // status bytes
    u08 sw1=0x90,sw2=0x00;
    
    
    // PPV Cache vars
    u08 NextEvent=0;
    u08 lLastProvider=0;
    u08 CommandCountDown=60;
    
    
    u08 EventInCache(u08 evnt1, u08 evnt2)
    {
      u08 i;
      for (i=0; i<32; i=i+2){
        if (evnt1==version[i] && evnt2==version[i+1]){
          // Event is known :)
          return 1;
        }
      }
      return 0;
    }
    
    
    void AddPPVEvent(u08 evnt1, u08 evnt2)
    {
      if (!EventInCache(evnt1,evnt2)){
        // Move the event marker onwards
        version[NextEvent++]=evnt1;
        version[NextEvent++]=evnt2;
        // Start to overwrite from the start once again
        if (NextEvent>31){
          // Back to the start
          NextEvent=0;
        }
      }
    }
    
    
    void IncrementECMCount(u08 inst)
    {
      // Only increment ECM count when card has been initalised in the STB
      if (!support_phoenix){
        ECM_LastECMInst = inst;
        if (ECM_Count_Low==0xff){
          if (ECM_Count_High<0xff){ECM_Count_High++;}
          ECM_Count_Low=0x00;
        } else
        ECM_Count_Low++;
      }
    }
    
    
    void sendString(u08 *str, u08 len)
    {
      do { (*ptrSend)(*str++); } while (--len);
    }
    
    
    void receiveString(u08 len)
    {
      u08 *dst=buffer;
    
    
      do { *dst++ = (*ptrReceive)(); } while (--len);
    }
    
    
    void fillBuffer(u08 begin_idx ,u08 end_idx, u08 fillByte)
    {
      u08 cnt;
    
    
      for (cnt=begin_idx; cnt<end_idx; cnt++)
        buffer[cnt]=fillByte;
    }
    
    
    void _memcpy(u08 *dst,u08 *src,u08 n)
    {
     while(n){
       *dst=*src;
       dst++;
       src++;
       n--;
      } 
    }
    
    
    
    
    u16 getProvAddr(u08 p1)
    {
      u16 res;
    
    
      p1 &= 0x0f;
      for (res = EE_ENTETY_0; p1; p1--)
        res += EE_ENTETY_SIZE;
    
    
      return res;
    }
    
    
    
    
    u16  getPKAddr(u08 p1, u08 p2)
    {
      u16 key_offset = getProvAddr(p1) + EE_ENT_KEY_0;
    
    
      //key_index*=8, at908515 opt, lose the bit 7 (superencription)
      p2 <<= 1; p2 <<= 1; p2 <<= 1;
    
    
      return (key_offset + p2);
    }
    
    
    
    
    void  decode(u08 p2, u08 len)
    {
      u08 *src=buffer;
      if (p2&0x80){
        while (len>8){
          decrip(Key,src);
          len-=8;
          src+=8;
        }
      }
    }
    
    
    void getKey(u08 p1, u08 p2)
    {
      u16 key_offset=getPKAddr(p1,p2);
    
    
      ee_readString(Key,key_offset,8);
      ee_readString(Key+8,(p1&0x10)?key_offset+(16*8):key_offset,8);
    }
    
    
    
    
    u08 xor_hash(u08 len, u08 r)
    {
      u08 cnt;
    
    
      decrip(Key,hash);
      len-=r;
      for (cnt=0; cnt<r; cnt++)
        hash[cnt]^=buffer[len+cnt];
    
    
      return len;
    }
    
    
    u08 signaturePresent(u08 siglen)
    {
      // Grib - Length has to be at least 9 (82 plus sig)
      if (siglen>0x08){
        if (buffer[siglen-0x09]==0x82){
          // Signature is present
          return 1;
        }
      }
      // Too short of signature missing
      return 0;
    }
    
    
    u08 signatureCheck(u08 p1, u08 len)
    {
      u08 cnt;
      u08 resto=len&7;
      u16 addr;
      
      // Grib - Length has to be at least 9 (82 plus sig)
      if (!signaturePresent(len)){
        return 0;
      }
      //if (len<9)
      //  return 0;
      
      len-=8; // indice al nano 0x82
      //if (buffer[len-1]!=0x82)
      //  return 0;
      
      _memcpy(hash,buffer+len,8);
      
      // I calculate inverse of the company/signature
      if (resto){
        len=xor_hash(len,resto);
      }
    
    
      while (len>0){
        len=xor_hash(len,8);
      }
    
    
      // To calculate initial hashbuffer
      for (cnt=0; cnt<8; cnt++){
        initial_hash[cnt]=0;
      }
    
    
      addr=getProvAddr(p1) + EE_ENT_PPUA;
      p1&=0xE0;
      if (p1==0x20){
        // UA + 00 00
        ee_readString(initial_hash, EE_NUM_TARJETA,6);
      } else if (p1==0x40){
        // PPUA + 00 00 00 00
        ee_readString(initial_hash,addr,4);
      } else if (p1==0x60){
        // SA + 00 00 00 00 00
        ee_readString(initial_hash,addr,3);
      }
    
    
      // If hash signs correct - > calculated buffer = hash initial buffer 
      for (cnt=0; cnt<8; cnt++){
        if (initial_hash[cnt]!=hash[cnt])
          return 0;
      }
      
      return 1;
    }
    
    
    void updateKey(u08 idx, u08 p1, u08 sk)
    {
      u16 addr;
    
    
      // to desencriptar the key
      _memcpy(CW,&buffer[idx+2],8);
      decrip(Key,CW);
    
    
      // to calculate direction
      addr=getPKAddr(p1,(buffer[idx+1]&0x0F));
      addr=sk?(addr+(16*8)):addr;
    
    
      // to update if it is different from the stored one
      ee_updateString(addr,CW,8);
    }
    
    
    u08 keyExist(u08 p1, u08 p2)
    {
      // 0x00 if the key does not exist
      // 0x50 if only PK
      // 0xf0 if also SK (note:  the PK can be 8*0x00)
      u08 cnt,res=0x00;
    
    
      // Cargar Pk&Sk
      getKey(p1|0x10,p2);
    
    
      for (cnt=0; cnt<16; cnt++){
        if (Key[cnt]){
          if (cnt<8)
            res=0x50;
          else res=0xf0;
       }
     }
      return res;
    }
    
    
    
    
    u08 nibble2ascii(u08 nibble)
    {
      // Changed to go lower case for the 'keylog' stuff later on
      return (nibble<0x0a)?(nibble+'0'):(nibble+('a'-0x0a));
    }
    
    
    void byte2ascii(u08 value, u08 idx)
    {
      u08 *dst=&buffer[idx];
      
      *dst++=nibble2ascii(value>>4);
      *dst=nibble2ascii(value&0x0f);
    }
    
    
    void antipurple(u08 offset, u08 repeat)
    {
      u08 i;
      // Antipurple decrypts the contents in the buffer
      // at a given offset x the number of 8byte blocks
      for (i=0; i<16; i++){
        Key[i]=i%0x0d;
      }
      for (i=0; i<repeat; i++){
        decrip(Key,buffer+(offset+(8*i)));
      }
    }   
    
    
    #ifdef MODO_LOG
    #include "log.h"
    #endif
        
    void setupInfo(u08 p1, u08 p3)
    {
      u16 addr;
      u08 i; //j,n;
    
    
      if (p1!=++ECM_LastProviderChecked){
        // Not in sequence!
        LastNonProviderInst=0x12;
      }
      
      // Check provider index ANTI-ECM method
      if ((p1 & 0x0F)>=ProviderCount && currentKey && (LastNonProviderInst!=0x3a || p3!=0x18)){
        // We are faking the number of providers.
        LastNonProviderInst=0x12;
        sw2=0x04;
        return;
      }
    
    
      // Stick in the real provider details
      addr = getProvAddr(p1);
    
    
      // Ident
      ee_readString(buffer,addr,2);
    
    
      // To fill up with spaces field names
      fillBuffer(2,(2+16),0x20);
    
    
      //addr = getProvAddr(CurrentProvider);
      // PPUA + Date
      ee_readString(buffer+(2+16),addr + EE_ENT_PPUA, 4+2);
      
      // Grib - adding region to the return
      ee_readString(buffer+(23+1),addr + EE_ENT_REGION,1);
            
      p1&=0x0f;
      if (p1==0x00 || LastNonProviderInst!=0x3a || p3!=0x18){
        LastNonProviderInst=0x12;
        // Provider name in buffer[2..18]
        ee_readString(buffer + 2, addr + EE_ENT_NAME, 16);
        // PPUA + Date
        // done above -> ee_readString(buffer+(2+16),addr + EE_ENT_PPUA,4+2);
        if (!p1){
          // Just clear the seca date....
          _memcpy(buffer+(2+16+4+1),0x00,1);
        }
      } else
      if (p1==0x01){
        _memcpy(buffer+(2),gribomatic,16);
        // Need to decrypt the my key now.... waster mr PurpleHaze
        antipurple(2,2);
        // Display the current Opkey
        byte2ascii(currentKey,14);
        // And the method of PPV
        buffer[17]=(OldStylePPV)?'M':'A';
        
      } else
      if (p1==0x02){    
        // Use provider 2 for event and custWP :)
        _memcpy(buffer+(2),EVENT_Display,12);
        //antipurple(2,2);
      
        byte2ascii(ee_read(getProvAddr(currentProvider)+(EE_ENT_PPUA + 3)),6);
        byte2ascii(ppv_record[EVENT_ID1],14);
        byte2ascii(ppv_record[EVENT_ID2],16);
    
    
      } else
      if (p1==0x03){
        // Use provider 3 as a general ECM display :)
        _memcpy(buffer+(2),ECM_Display,12);
        //antipurple(2,2);
       
        byte2ascii(ECM_LastECMInst,6);
        byte2ascii(ECM_Count_High,14);
        byte2ascii(ECM_Count_Low,16);
         
      } else
      if (p1==0x04){
        // Bit of a KeyLog rip off, show only the opkey
        // that is not in use :p
        if (modo_log){
          _memcpy(buffer+(2),LOG_ON,6);
          if (LOG_Method){
            // Loop at end of eeprom
            _memcpy(buffer+(9),LOG_Mode_1,4);
          } else {
              // Stop at end of eeprom
            _memcpy(buffer+(9),LOG_Mode_0,4);
          }
         
        } else {
          if (currentKey==0x0c){
            addr=getPKAddr(currentProvider, 0x0d);
          } else {
            addr=getPKAddr(currentProvider, 0x0c);
          }
          for(i=0; i<8; i++){
            byte2ascii(ee_read(addr + i),2+2*i);
          }
        }
      } else {
        // Provider name in buffer[2..18]
        ee_readString(buffer + 2, addr + EE_ENT_NAME, 16);   
      }  
    }
    
    
    u08 cardHasExpired(u08 p1, u08 nano_idx, u08 TestDate)
    {
      u08 expdate_h,expdate_l;
      u08 actdate_h,actdate_l;
      u08 *ptr;
      u16 addr;
        
      // get card expiration date
      addr=getProvAddr(p1) + EE_ENT_SUBS_DATE;
      expdate_h=ee_read(addr);
      expdate_l=ee_read(addr+1);
    
    
      // get ECM or EMM command date
      ptr=&buffer[nano_idx];
      actdate_h=*(ptr+1);
      actdate_l=*(ptr+2);
      
      // Do we want to check the boundery of the date?...  ECM check
      if (TestDate){
        if (!(actdate_h<expdate_h)){
          // Check out the difference between the dates
          addr=((actdate_h-expdate_h)*0xff)+(actdate_l-expdate_l);
          if (addr>=0x00){
          return 1;
          }
        }
        return 0;
      }
      // else we just see if the card has expired
      return (actdate_h>expdate_h || (actdate_h==expdate_h && actdate_l>expdate_l));
    }
    
    
    u08 isCustWPActive(u08 nanof0_idx, u08 custwp)
    {
      return rightShift(buffer[(nanof0_idx + 32) - rightShift(custwp,3)],custwp&7)&1;
    }
    
    
    u08 TestKey(u08 idx, u08 p1, u08 sk)
    {
      u16 addr;
      u08 res;
      
      // Not the current OpKey so ignore..
      // default to bad update until we know better
      res=0;
      if ((buffer[idx+1]&0x0F)==currentKey){
        // to decypt the key
        _memcpy(CW,&buffer[idx+2],8);
        decrip(Key,CW);
    
    
        // to calculate base address of the key
        addr=getPKAddr(p1,(buffer[idx+1]&0x0F));
        addr=sk?(addr+(16*8)):addr;
    
    
        // Return 1 if already set (this is the "good" result)
        res = mem2eeprom_cmp(addr, CW, 8);
        //res=ee_TestString(addr,CW,8);
      }
      return res;
    }
    
    
    u08 processNanos(u08 p1,u08 ECMorEMM, u08 TestOnly)
    {
     // Current Nano command
     u08 nano;
     // Position with "buffer"
     u08 idx=0;
     // Preview PPV or PBM check will activate
     u08 rightsAdquired = 0;
     // Does more or less the same as rights Aquired!
     u08 nanos_13_31 = 2;
     // Nbr of nanos processed, returned as part of error in 3c if required
     u08 pnanos = 0;
     // Store address of target provider
     u16 addr;
     // Disable porn channels, going via the parental warning nano
     u08 nano_2c = 1; 
     // Flag checks if a d1 nano was present in an ECM
     u08 invalid_ECM=0;
     // Reused var... various
     u08 cnt;
     
     u08 aux1;
     u08 aux2;
     
     // Set initial value for 3c check to 1 for ECM
     if (ECMorEMM==kECM){
       invalid_ECM=1;
       //EventUpdatedin3C=FALSE;
     }
     
     // Get provider address once outside loop :)
     addr = getProvAddr(p1) ;
      
     while (1){
      nano = buffer[idx];
      // Less flash space to load here instead of references later.
      aux1 = buffer[idx+1];
      aux2 = buffer[idx+2];
    
    
      if (nano==0x82){
        // ECM 3-Mar-2002
        // They are sending through signed 3c instructions
        // that do not contain valid nanos
        if (TestOnly){
          if (!invalid_ECM){
             sw2=0x09;
          }
          return invalid_ECM;
        }
        if (invalid_ECM){
          sw1 = 0x96; sw2 = pnanos;
          return 0;
        }
        pnanos++;
        return pnanos;
      } else
     
      // ECM nanos - - - - - - - - - - - - - - - - - - - - - - - - - - -   
       
      if (ECMorEMM){
    //   nano 04 : give dw for output                    OK
    //   nano 12 : parental control protection                ADDED
    //   nano 13 : verify channel id with provider bitmap package        OK
    //   nano 15 : PPV special management                    ADDED
    //   nano 19 : PPV preview control                    OK
    //   nano 27 : delete old PPV preview records                OK
    //   nano 2C : PPV tokens management                    OK
    //   nano 2D : delete old PPV event records                ADDED
    //   nano 31 : verify PPV event id, diffusion number and vision number    OK
    //   nano 82 : signature                        OK
    //   nano D1 : control word to decrypt                    OK
    //   nano F1 : bitmap regional code                    OK
    
    
      if ((nano==0x04 || nano==0x19) && !rightsAdquired){
        // free the channel
        if (nano==0x19){sw2=0x27;}
        rightsAdquired = 1;
        pnanos++;  
      } else
    
    
      if (nano==0x13 && !rightsAdquired && nanos_13_31){
        // test channel boundle identifier
        u08 pbm,bid;
        if ((bid=aux1)<64){
          //addr=getProvAddr(p1) + (EE_ENT_PBM + 7) - rightShift(bid,3);
          //pbm=ee_read(addr);
          pbm=ee_read(addr + (EE_ENT_PBM + 7) - rightShift(bid,3));
          if (rightShift(pbm,bid&7)&1){
            RED_INFO_LED_OFF;
            rightsAdquired=1;
          }
        }    
        pnanos++;
            
      } else
      
      if (nano==0x12 || nano==0x2d){
        pnanos++;
      } else
      
      if (nano==0x15){
        if (nanos_13_31>0x01){
          sw1=0x96; sw2=0;
          return 0;
        }
        pnanos++;
    
    
      } else
      
      if (nano==0x27 && !rightsAdquired){
        // test card expiration date
        pnanos++;   
        // Check for not a Null value in the 0x27
        if (aux1|aux2){
          if (cardHasExpired(p1,idx,FALSE)){
            sw1=0x93; sw2=0x01; 
            return 0;
          } 
          ppv_record[SESSION_DATE1] = aux1;
          ppv_record[SESSION_DATE2] = aux2;
        }
      } else
        
      if (nano==0x2c && !rightsAdquired){
        // x channel
        // No pin of perv channels,
        if ((aux1|aux2)==0){ // (buffer[idx+1]==0 && buffer[idx+2]==0){
          // Null event!
          sw1=0x96; sw2=0;
          return 0;
        }
        nano_2c =  decodeX;
        nanos_13_31--;
      } else
      
      if (nano==0x31 && !rightsAdquired && nanos_13_31){
        // Check that the PPV event matches the last PPV record
        // request offered in the 32/34
        if ((aux1|aux2)==0){ // (buffer[idx+1]==0 && buffer[idx+2]==0){
          // Null event!
          sw1=0x96; sw2=0;
          return 0;
        }
    
    
        // Now if the event is in the cache it is bad!
        if (CommandCountDown || EventInCache(aux1,aux2)){ // ((ppv_request[0]!=buffer[idx+1] || ppv_request[1]!=buffer[idx+2]) && (!EventInCache(buffer[idx+1],buffer[idx+2]))){
          sw2=0x1a;
        
        } else {
          ppv_record[SESSION_ID] = buffer[idx+3];
          // Add the captured event ID... need to test further!
          ppv_record[EVENT_ID1] = aux1;
          ppv_record[EVENT_ID2] = aux2;
          // Flag for the 34 to determine if an event was received
          // EventUpdatedin3C=TRUE;
        }
        // No longer it is necessary to verify 0x13, 0x31
        nanos_13_31--;
        pnanos++;   
      } else
     
      if (nano==0xD1){
        pnanos++; 
        if ((rightsAdquired || !nanos_13_31) && (nano_2c)){
          u08 *ptr;  
          ptr=&buffer[idx+1];
          decrip(Key,ptr);
          decrip(Key,ptr+8);
          _memcpy(CW,ptr,16);
          // Contains control word :)
          invalid_ECM=0;
          
        } else{
          // rights no adquired
          sw1=0x93; sw2=0x02; 
          return 0;
        }
        
      } else
    
    
      if (nano==0xf1){
        // Region nano, purpose not really understood... at least by me....
        pnanos++;
        //addr=getProvAddr(p1) + EE_ENT_REGION;
        // Can reuse the custWP check for region check, they
        // perform the same actual bit check 
        if (!isCustWPActive(idx, ee_read(addr + EE_ENT_REGION))){
          //IncrementECMCount(0xf1);
          sw1=0x93; sw2=0x05;
          return 0;
        }
      } 
      } // end of ECM nanos
      
    
    
      // EMM nanos - - - - - - - - - - - - - - - - - - - - - - - - - - -
      
      else {
    //   nano 01 : set nano 24 flag to FF
    //   nano 02 : set nano 24 flag to 00
    //   nano 03 : delete pin code
    //   nano 10 : delete given key (primary and secondary)
    //   nano 11 : delete seca record of a given type
    //   nano 17 : write regional bitmap
    //   nano 18 : delete service preview record
    //   nano 1D : set 8022 eeprom location
    //   nano 1E : set 8020 eeprom location
    //   nano 1F : set 8021 eeprom location
    //   nano 21 : set expiration date
    //   nano 22 : verify expiration date
    //   nano 23 : add new provider
    //   nano 24 : apply next nanos to given provider
    //   nano 25 : delete given provider
    //   nano 26 : modify provider space for records and flags
    //   nano 28 : delete a ppv preview record
    //   nano 30 : store special credits in ppv credits record
    //   nano 32 : seek or create record for a given event-id
    //   nano 33 : create or modify service preview record
    //   nano 40 : delete ppv event record with event-id between min-max
    //   nano 41 : set PPUA
    //   nano 42 : store data and new credits in ppv credits record
    //   nano 43 : update data and add credits in ppv credits record
    //   nano 80 : set provider bitmap package
    //   nano 82 : signature
    //   nano 87 : set provider data for ins 44
    //   nano 90 : write primary key
    //   nano 91 : write secondary key
    //   nano B0 : store seca record of a given type
    //   nano D0 : change provider name
    //   nano F0 : verify CUSTWP
    
    
      if (nano==0x17 && !TestOnly){
        // Grib - Region code update
        // addr=getProvAddr(p1) + EE_ENT_REGION;
        // Store the region code.
        ee_write(addr + EE_ENT_REGION,aux1);
      
      } else
    
    
      if (nano==0x21){
        // Check to see if we are just checking out the EMM instruction
        if (TestOnly){
          if (!cardHasExpired(p1,idx,TRUE)){
            sw2=0x09;
            return 0;
          }
    
    
        } else {
          // update expiration date
          //addr=getProvAddr(p1) + EE_ENT_SUBS_DATE;
          ee_updateString(addr + EE_ENT_SUBS_DATE,&buffer[idx+1],2);
          pnanos++;
        }
    
    
      } else
     
      if (nano==0x22 && !TestOnly){
        // test card expiration date
        if (cardHasExpired(p1,idx,FALSE)){
          sw1=0x93; sw2=0x01; 
          return 0;
        }
      } else
    
    
      if (nano==0x41 && !TestOnly){
        // update PPUA
        //addr=getProvAddr(p1)+ EE_ENT_PPUA;
        if (ee_updateString(addr + EE_ENT_PPUA,&buffer[idx+1],4)){
           sw2 = 0x19; // 90 19
        }    
      } else
    
    
      // nano 80 : set provider bitmap package
      if (nano==0x80 && TestOnly){
        // update PBM 8 bytes
        pnanos=0;
        for(cnt=0; cnt<8; cnt++){
          if (buffer[idx+1+cnt]){
            pnanos++;
          }
        }
        // If PBM is being reset then ignore packet
        if (!pnanos){
          sw2=0x09;
          return 0;
        }  
      } else 
      
      if (nano==0x90 || nano==0x91){
        // update primary or secondary key 
        if (TestOnly){
          if (TestKey(idx,p1,nano&0x01))
            invalid_ECM=1;
    
    
        } else {
          updateKey(idx,p1,nano&0x01);
        }
        
      } else 
      
      if (nano==0xF0 && !TestOnly){
        // CustWP-Bitmap
        //u08 custwp;
    
    
        //addr=getProvAddr(p1)+(EE_ENT_PPUA + 3);
        //custwp = ee_read(addr+(EE_ENT_PPUA + 3));
        // Should reuse vars like this but want the extra space
        pnanos = ee_read(addr+(EE_ENT_PPUA + 3));
        
        if (!isCustWPActive(idx, pnanos)){  // if (!isCustWPActive(idx, custwp)){
          // If this assets and are not different from zero -> 90 09
          cnt = 0x00;
          //custwp = 0xff;
          pnanos = 0xff;
          
          do{
              cnt++;
              if (isCustWPActive(idx,cnt)){
                // Found an Active CustWP!  Updating Ppua!
                ee_write(addr+(EE_ENT_PPUA + 3),cnt);
                // it ignites red LED, was extinguished in proxima 0x3c
                RED_INFO_LED_ON; 
                //custwp=cnt;
                pnanos=cnt;             
              }
            } while (cnt!=pnanos);  //(cnt!=custwp);
        }
      } // end of nano f0
      
      } // end of EMM nanos
    
    
      // next nano
      nano>>=4;
      if (nano>0xC) nano=(nano-0x0b)<<3;
      idx+=(nano+1);
     }
    }
    
    
    // Combined the sign prepares from 38, 3c and 40 Instructions
    // saves around 50 odd bytes :)
    u08 PrepareSigCheck(u08 p1, u08 p2, u08 p3, u08 checkMK)
    {
      u08 tmp;
      
      // 13-Apr-2002,
      // If not super encrypted then need to check a signature is supplied first!
      if (!(p2&0x80)){
        // Not encrypted, check signature presence
        if (!signaturePresent(p3)){
          sw2=0x02;
          goto PrepFailed;
        }
      }
    
    
      // 17-Apr-2002, to verify that it uses MK
      if (checkMK && (p2&0x0f)>0x0b){
        sw2=0x13;
        goto PrepFailed;
      }
     
      // it verifies existence of keys
      tmp = keyExist(p1, p2&0x0f);
     
      if (tmp==0x00){
        // It does not exist key primary 90 1D
        sw2=0x1D;
        goto PrepFailed;
      } else
      if (tmp==0x50 && (p1&0x10)){
        // It does not exist key secondary 90 1F
        sw2=0x1F;
        goto PrepFailed;
      }
      
      // decrypt buffer before continueing
      getKey(p1,p2);
      decode(p2,p3);        
      // Return 0 for OK...  caller will jmp to TX_Data on anything else
      return 0;
     
     PrepFailed:
      return 1;
    }
    
    
    // Secoms construction of 06 record returns....  how complicated!
    // Append Key Index and trailer for Primary\Secondary keys
    u08 *ConstructKeyRegistry(u08 tipo,u08 Prov,u08 *lista){  
      if ((tipo&0xf0)==0xf0){ // Si tenemos la primaria y secundaria
        *lista++=tipo;
        *lista++=0x80|Prov;
        *lista++=0x50|(tipo&0x0f);
        *lista++=0xc0|Prov;
      } else if ((tipo&0x50)==0x50) {// Si tenemos solo la primaria
        *lista++=tipo;
        *lista++=0x80|Prov;
      }
      return lista;
    }
    
    
    // Build a list (using log buffer) of all the records on the card
    void ConstructEEpromList(u08 ndrProviders){
      // It is used to store the list, the table that contendra the instruction to do log (to save space) 
      // The list this structured of the following form:
      // A registry is of two bytes reason why to correctly cross it habra that to jump of two in two 
      // The first field contains the type of registry and the second is the descriptive Byte 
      // Each registry of this table identifies to one virtual one in eeprom. 
      // The order of the registries is not accidental, this fact asi despues to analyze a pile of original cards 
      u08 *punt1=&log_buffer[2], ind1, ind2;
        
      // REGISTRIES RECORDS
      *punt1++=0x01; // First type of record STARTUP
      *punt1++=0xe0;
      *punt1++=0;    // Second type of record PPV
      *punt1++=0xe0;         
      punt1=ConstructKeyRegistry(keyExist(0,0),0,punt1); // Registries of mks 00
    
    
      *punt1++=0x02; // Date of Activation of card
      *punt1++=0xe0;
         
      // Extract the PBM and Keys for all the providers
      for (ind1=0;ind1<=ndrProviders;ind1++){ 
        // PBM of the supplier, single if it is not empty
        if (ind1){ 
          *punt1++=0; 
          *punt1++=0x90|ind1;
        } 
        // Loop through for current provider build list of keys in use!
        for (ind2=(ind1)?0:1;ind2<16;ind2++){
          punt1=ConstructKeyRegistry((keyExist(ind1,ind2)|ind2),ind1,punt1);
        }
        /* For the moment don`t want to support the PPV returns :)
        if (ind1) {            // Registries PPV, Single if not empty
          *punt1++=0x0;     // Registry of Credit PPV of the Supplier
          *punt1++=0xd0|ind1;                                  
          *punt1++=0x0;     // A registry of Event PPV anyone
          *punt1++=0xb0|ind1;
        }
        */
      }        
      *++punt1=0xff; // End of list
    } 
    // End of Secom 06 record construction!
    
    
    // info en KeyLeds
    void LED_Display(void)
    {
      // keyleds:
      // - 0: always off (low power supply decos) (PIN:9999)
      // - 1: show operation key in use (PIN:9998)
      // - 2: show current provider index (PIN:9997)
      u08 keyleds             = 0x00;
    
    
      keyleds = ee_read(EE_KEYLEDS + Extra_Funcard_Space);
    
    
      if (keyleds==0){
        outp(0x0F,PORTD);
      } else if (keyleds==1){
        outp(~(currentKey),PORTD);
      } else if (keyleds==2){
        outp(~(currentProvider),PORTD);
      }
    }
     
    int main(void)
    {
      u08 *ptrAux;     // Pointer used by secom code
      u16 addr_prov;   // Store the address of the current provider
            
      u08 inst=0,p1=0,p2=0,p3=0;
      u08 numProviders;
      // Don`t really need a dedicate var for this
      //u08 cla=0;
      u08 lastprovider=0;
      u08 ind=0;
      u08 aux1=0;
      u08 aux2=0;
      // Number of complete registry inst 32 interations
      u08 RegActual=0; 
      
      // Desactiva el comparador analogico :P
      sbi(ACSR,7);
    
    
      // Configura Puertos B    y D
    
    
      // El puerto B    :
      //    - leds de colores (pins 2,3,4)
      //    - i/o (pin 6)
    
    
      outp(0x1C,DDRB);    // 0b00011100   
      outp(0x1C,PORTB);   // 0b01011100
    
    
      // El puerto D    :
      //    - KeyLeds (pins 0,1,2,3)
      outp(0x0F,DDRD);   // 0b00001111
      outp(0x0F,PORTD);  // 0b00001111
    
    
      // init eeprom externa
      
      /*-----------------------------------------------------------------------------
      | Detección modo Apollo:
      | 
      | The state of bit 7 is verified and bit 5 of port B. If the 7 are to 0 and 
      | the 5 to 1, somebody to them has changed (FunStudio) - > Apollo way 
      | 
      +------------------------------------------------------------------------------------*/
      
      if(0x80 == (inp(PINB) & 0xA0))
      {   
        sbi(DDRB,6);
        sbi(PORTB,6);
        RED_INFO_LED_ON;
        ptrSend    = &SendA;
        ptrReceive = &ReceiveA;
        cbi(PORTB,6);
      }
      else
      {    
        // Modo Phoenix
        ptrSend    = &Send;
        ptrReceive = &Receive;
    
    
        // Enviamos ATR
        ORANGE_INFO_LED_ON;
        sendString(ATR,16);
        ORANGE_INFO_LED_OFF;
    //    Send(0x90);
    //    Send(0x00);
      }
      
      extee_init();
      
      // Populate the offset value depending on the type of eeprom we have in use.
      ee_SetEEPromSize();
      
      // Load the number of providers from the eeprom
      numProviders = ee_read(EE_NUM_ENTETIES) - 1;
      
      // Now loading OldStyle PPV setting from ext eeprom config
      OldStylePPV = !ee_read(EE_FULLAUTO);
      
      // Load the log style they want to use
      LOG_Method = ee_read(EE_LOGMETHOD);
    
    
      // Load up the number of providers to return when asked
      ProviderCount = ee_read(EE_PROVIDER_CNT);
      // Put an upper limit on the provider count to stop
      // users setting to higher than available!
      if (ProviderCount>numProviders){ProviderCount=numProviders + 1;}
      
      // For the decos without PIN It allows to block channels X 
      decodeX = (ee_read(EE_FLAGS) & FLG_BLOQUEAR_TX);
      
      #ifdef MODO_LOG
      // Is AutoLog enabled?...  hate it myself but.....
      modo_log = ee_read(EE_FLAGS) & FLG_AUTOLOG;
      // Set the start point in the ee_ to start the log
      leer_config_log(numProviders);
      #endif
      
      while (1){
        // Decrement the command counter (bad PPV enent cache)
        if (CommandCountDown){CommandCountDown--;}
        
        // status word by default
        sw1=0x90;
        sw2=0x00;
    
    
        GREEN_INFO_LED_OFF;     // 'busy' led    
        // Using a temp var for class...  no need to retain
        ind=(*ptrReceive)();    // C1 en SECA
        GREEN_INFO_LED_ON;      // 'busy' led
    
    
        inst=(*ptrReceive)();   // Instruction
        p1=(*ptrReceive)();     // parameter 1
        p2=(*ptrReceive)();     // parameter 2
        p3=(*ptrReceive)();     // Length of command
    
    
        // Check class in temp var
        if (ind!=0xC1){
          // Class not supported: 6E 00
          //lastInst=0;
          sw1=0x6E;
          goto TX_Data;
        }
        
        if (inst&1){
          // The first bit of inst must be zero
          sw1=0x6D;
          lastInst=0;
          goto TX_Date_MPSkip;
        }
        
        if ((!p3 && inst&2) || p3>MAX_COMMAND_LENGHT){
          // Length of incorrect entrance: 67 00
          sw1=0x67;
          lastInst=0;
          // Do not send back data for invalid length
          p3=0;
          goto TX_Date_MPSkip;
        }
    
    
        // Check p3, we do not send an ack for anything without length!
        if (p3)
          // Return ACK
          (*ptrSend)(inst);
      
        if (inst&2){
          // CARD->CAM
          fillBuffer(0,MAX_COMMAND_LENGHT,0xFF);
    
    
        } else {
          // CAM->CARD
          if (p3)
            receiveString(p3); 
          
          #ifdef MODO_LOG
          // alvamos the buffer for log
          _memcpy(&log_buffer[5],buffer,p3);
          #endif
        }
    
    
        /*-----------------------------------------------------------------------------
        | In principle, treating this possibility does not have here to produce problems 
        | With !support_phoenix we made sure to be able to send all the directions 
        | it stops INS 20 y 22
        +-----------------------------------------------------------------------------*/
        // Check provider index, not applicable to serial request.
        if (((p1 & 0x0F) > numProviders && inst!=0x0e) && (!support_phoenix)){
          // supported supplier not 90 04
          sw2=0x04;
          goto TX_Data;
        }
        
        // - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        // INSTRUCTION 0x34: Specification of the Request of Data
        if (inst==0x34){
          // Sólo soportamos dos peticiones:
          //   00 00 00 : Provider Package Bitmap Records
          //   04 00 01 : SECA Startup Records
          // The request is stored in Comando34
          
          // Check that provider is within the limit
          if ((p1&0x0F)>ProviderCount){
            // Need to validate supplier index
            sw2=0x04;
            goto TX_Data;
          }
          if (p3!=3){
            // Incorrect length of the entrance: 67 00
            sw1=0x67;
            goto TX_Data;
          }
          
          _memcpy(Comando34,buffer,3);
          //lastInst=inst;
        } else
    
    
        // - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        // INSTRUCTION 0x32: Request of Data
        // INSTRUCTION 0x36: As per 0x32 but with additional options
        //                   2Fh=d4 30h=d5 87-8Eh=a1..a8
        if (inst==0x32 || inst==0x36){
          /*
          ; Ins 32 : output data requested
          ; data from ins 34  d1 = 29h  d2 = 2Dh  d3 = 2Eh
          ; d1 d2 d3
          ; 0  0  0    Provider package bitmap record   C1 32 xx 00 0A  83 data 04
          ; 1  0  0    Provider PPV credits record      C1 32 xx 00 0A  84 data 04
          ' 2 .......  a check on something??
          ; 3  x  x    Provider PPV event record        C1 32 xx 00 0D  B1 data 04
          ; 4  0  x    Seca record                      C1 32 00 00 0D  B1 data 04
          ; 6  x  x    Given record (number)            C1 32 xx 00 12  D2 data 03
          */
          
          // Store the command 34 stuff into vars, takes a little less
          // space than references in the code
          ind = Comando34[0];
          aux1 = Comando34[1];
          aux2 = Comando34[2];
          
          if (p2){
            // incorrect value of p2 (p2!=0) 94 02
            sw1=0x94;
            sw2=0x02;
            goto TX_Data;
          
          // Check last instruction was a 36 or 38  
          } else if (lastInst!=inst && lastInst!=0x38 && lastInst!=0x34){
        sw2=0x14;
            goto TX_Data;
          
          } else if (inst==0x36){
            // ins 36 error in parameter P1
            if (lastprovider!=p1){
              sw1=0x94; sw2=0x01;
          goto TX_Data;
        }
    
    
          } else {
            // Works on a MOSC but not documented...
            if (ind==0x02 && (lastprovider)){
              sw2=0x15;
              goto TX_Data;
            }
          }
          
          // Default for returned records is 0x04      
          buffer[0]=0x04;
          
          // Command 00 - - - - - - - - - - - - - - - - - - - - 
          if (ind==0x00){
            // Command 00
            // Data:  00 00 -> Provider Package Bitmap Records
            if (p3<0x0A){
              // It does not fit, to send 0x03
              buffer[0]=0x03;
    
    
            } else if (p1){
              // ok, all except SECA
              buffer[0]=0x83;
              ee_readString(buffer + 1, getProvAddr(p1) + EE_ENT_PBM, 8);
              buffer[0x0A-1]=0x04;
            }
            
          } else if (ind==0x01){
            if (p3<0x0A){
              // It does not fit, to send 0x03
              buffer[0]=0x03;
            }
    
    
          } else if (ind==0x03){
            // Command 03
            // Data:   xx xx -> Provider PPV Records (xx xx = EventID)
            if(p3<0x0e){
              buffer[0] = 0x03;
            } else {
              // buffer[0]=0x04;
              if (EventInCache(aux1, aux2) || CommandCountDown || p3!=0x20){
                // Bad record
                AddPPVEvent(aux1,aux2);
            IncrementECMCount(inst);
            
              } else {
                // Store last PPV request, need to check the 31 nano in 3c 
                // to ensure they match
                // Hoping for an auto purchase
                //if (OldStylePPV || CapturePPVEvent>1 || EventUpdatedin3C){// || (ppv_record[EVENT_ID1]==Comando34[1] && ppv_record[EVENT_ID2]==Comando34[2])){
                //if ((OldStylePPV || EventUpdatedin3C) && (ppv_request[0]==aux1 && ppv_request[0]==aux2)){
                needPin = FALSE;
                if (OldStylePPV || EventUpdatedin3C){
                  // needPin = FALSE;
                  ppv_record[EVENT_ID1] = aux1;
                  ppv_record[EVENT_ID2] = aux2;
                  // Return the BX record requested
                  _memcpy(buffer,ppv_record,14);            
                  
                  EventUpdatedin3C = FALSE;
                } else {
                  EventUpdatedin3C=TRUE;
                }
              }
            }
          
          } else if (ind==0x04){
            // Data:   00 00 -> SECA PPV Records
            //         00 01 -> SECA Startup Records
            //         00 02 -> SECA Records de Activación
            // This one will not get caught by main increment
            IncrementECMCount(inst);
            // 12-Apr-2002, we have move the size check outside
            // the check on record number
            if (p3<0x0d){
              // Not enough space for result! 0x03
              buffer[0]=0x03;
             
            // SECA Startup Records
            } else {
              // Only information on Seca p1=0 can be requested
              if (aux2<=0x02 && !p1){
                // Build the output record
                buffer[0]=0xb2;
                if (aux2==0x00){
                  ee_readString(buffer + 1, EE_SECA_PPVSTARTUP, 11);
                } else {
                  if (aux2==0x01){
                    ee_readString(buffer + 1, EE_STARTUP_STR, 11);
                  } else {
                    ee_readString(buffer + 1, EE_SECA_ACTIVATE, 11);
                  }
                }
                buffer[0x0D-1]=0x04;
              }
            }
          
          } else if (ind==0x06){
            // If it is the first request to initialize the registry
            // to the first item to send
             if (lastInst==0x34) RegActual=aux2; 
               
            // We constructed the Virtual List of eeprom records (only need
            // to build upto the current provider each time - required for
            // record position information :()
               ConstructEEpromList(p1);
          
        // We initialized leader of construction of answer             
             aux2=0;
                     
             // Loop for construction of answer
             while (1) { 
             // Memorizamos type of registry (RegActual*2)
             ind = log_buffer[RegActual<<1];     
               // Description Memorizamos of Registry
               aux1= log_buffer[(RegActual<<1)+1]; 
    
    
             // If to the registries or the Supplier of the present
             // Registry finished it is greater than the requested supplier 
               if ((aux1==0xff)||((aux1&0x0f)>(p1&0x0f))){ 
                 buffer[aux2]=0x04;
                 goto TX_Data;
               }     
    
    
            // If the Supplier of the Present Registry is minor who the asked for supplier 
               if ((aux1&0x0f)<(p1&0x0f)){          
                 RegActual++; // We increased I number of registry
                 continue;    // We return to verify
            }
                                                  
               // If the following registry does not fit in the answer message
               if ((aux2+18)>p3){
                 buffer[aux2]=0x03;
                 goto TX_Data;
               }     
                         
              // First part of the answer
               buffer[aux2]  = 0xd2;
          buffer[aux2+1]= 0;
          buffer[aux2+2]= RegActual;
                      
            // We initialized this part of the answer to 0
          fillBuffer(aux2+12,aux2+17,0x00);
                    
          // We assigned leader for saving of space
          ptrAux   = &buffer[aux2+3]; 
              addr_prov = getProvAddr(p1);
                
               // Following Part of the Answer depending on the type of registry to send
               // SECA - PPV
               if ((ind==0x00)&&(p1==0)) { 
            ee_readString(ptrAux, EE_SECA_PPVSTARTUP, 11);
              
               // SECA - Start-up
          } else if (ind==0x01) {   
                 // We read startup record of eeprom
                 ee_readString(ptrAux, EE_STARTUP_STR, 11);
                 
               // SECA - Registry of activation of the card
               } else if (ind==0x02) {   
            ee_readString(ptrAux, EE_SECA_ACTIVATE, 11);
                 
               // Registry of suppliers - Package BitMap (PBM)
               } else if (((aux1&0xf0)==0x90)&&(p1)) {  
                 *ptrAux=0x00;
             // We read PBM of the supplier
             ee_readString(&buffer[aux2+4],addr_prov + EE_ENT_PBM ,8);
            
          // Registry of suppliers - Key
               } else if (((ind&0xf0)==0xf0)||((ind&0xf0)==0x50)) { 
                 *ptrAux=ind;
                 if (!currentKey){
                     addr_prov = getPKAddr(p1,ind&0x0f);
                     addr_prov = ((aux1&0xf0)==0xC0)?addr_prov+(16*8):addr_prov;
                     //if ((aux1&0xf0)==0xC0){addr_prov=addr_prov+8;}
                   // If no key in use then populate the key details too
                   ee_readString(&buffer[aux2+4],addr_prov,8);
                 }
                   
                 /* For the moment don`t want to support the PPV returns :)
                 // Registry of suppliers - Credit PPV
                 } else if ((aux1&0xf0)==0xd0) { 
                     // We initialized answer with 0x00
                     fillBuffer(aux2+3,aux2+13,0x00); 
              // PPV Credit handler not available in GoM!
              
              //buffer[aux2+7]=fichasppv;
              //buffer[aux2+8]=FechaRec[0];
              //buffer[aux2+9]=FechaRec[1]-1;
            
            // Registry of Suppliers - a Registry of Event PPV anyone
                 } else if ((aux1&0xf0)==0xb0) { 
              ee_readString(ptrAux, EE_SECA_PPVSTARTUP, 11);
              // So that the events are not always equal
              // PPV Credit handler not available in GoM!
              
              //buffer[aux2+4]=FechaRec[0]; 
                 */
               }    
              buffer[aux2+14]=aux1; // Descriptive byte
               aux2+=17;           // We increased leader of construction of message in 1 registry 
          RegActual++;       // We increased I number of registry by which we go
        }
            
          } else {
            // A invalid record request always returns 0x03....
            buffer[0]=0x03;
          }            
    
    
        } else
    
    
        // - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        // INSTRUCTION 0x0E: Serial number of the card
        if (inst==0x0E){
          fillBuffer(0,2,0x00);
          // I number of series this in SECA.UA
          ee_readString(buffer + 2, EE_NUM_TARJETA, 6);
    
    
          // Turn off the pheonix interface when the serial is requested
          support_phoenix=0x00;
        } else
    
    
        // - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        // INSTRUCTION 0x16: Enumeration of Suppliers
        if (inst==0x16){
          fillBuffer(0,6,0x00);
    
    
          if (currentKey){
            // This is for the euro boys :p
            aux1=ProviderCount;
            // This one will not get caught by main increment
        IncrementECMCount(inst);        
          } else {
            aux1=numProviders + 1; //number of suppliers + seca  
          }
          
          buffer[2]=rightShift(0xff,16-aux1);
          buffer[3]=rightShift(0xff,(aux1<8?(8-aux1):0));
        } else
    
    
        // - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        // INSTRUCTION 0x12: ProviderID (Ident)
        if (inst==0x12){
          // Dont want to include this in the history!
          setupInfo(p1,p3);
        
        } else
    
    
        // - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        // INSTRUCTION 0x3C: ECM ControlWords encrypted
        if (inst==0x3C){
          // p1 = provider number & pk-sk
          // p2 = key index & superencription
          
          // AntiECM - need to clear CW incase 3c fails
          //_memcpy(CW,version+(16),16);
          needPin = TRUE;
          pinChecked = FALSE;
          currentKey=p2&0x0F;
          
          // Grib, moved sigcheck prep to sub
          if (PrepareSigCheck(p1,p2,p3,FALSE)){
           goto TX_Data;
          }
          
          // Do the LED display if necessary
          LED_Display();
          
          if (signatureCheck(p1,p3)){
            RED_INFO_LED_OFF;
            processNanos(p1,kECM,FALSE);
    
    
            // Store the current provider... if the key
            // in use is a normal operational one
            if (currentKey==0x0c || currentKey==0x0d){
              currentProvider=p1&0x0F;
              /*
              if (currentProvider!=lLastProvider){
                lLastProvider=currentProvider;
                // Re-capture PPV events for this new provider
                CommandCountDown=60;
              }
              */
            }
    
    
          } else {
            // 90 02: Signature fails
            sw2=02; 
            RED_INFO_LED_ON;
          }
          
        } else
    
    
        // - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        // INSTRUCTION 0x3A: ECM ControlWords decrypted
        if (inst==0x3A){
          // Invalid command sequence
          if (lastInst!=0x3C){
            sw2=0x14;
            goto TX_Data;
          }
    
    
          // enviar CW desencriptadas
          _memcpy(buffer,CW,16);
          
          // Clear the Provider info flag
          ECM_LastProviderChecked=0x00;
        } else
        
        // INSTRUCTION 0x30: Transactions protected by PIN
        if (inst==0x30){
          /*
          ; C1 30 00 00 10 (old pin)(new pin) : insert/modify pin
          ; C1 30 00 01 09 (pin)(protection status 0/1) : modify pin protection status
          ; C1 30 00 02 09 (pin)(flags) : modify flags (6 bit)
          ;    bit 0 - addressable bit 01 (20.1 not used)
          ;    bit 1 - addressable bit 06 (20.6 override parental control protection)
          ;    bit 2 - addressable bit 07 (20.7 ppv management)
          ;    bit 3 - addressable bit 03 (20.3 ppv special management)
          ;    bit 6 - addressable bit 00 (20.0 ppv management)
          ;    bit 7 - addressable bit 08 (21.0 instruction protected flag)
          ;-------------------------------------------------------------------------------
          */
          if (p1!=0x00 || p2>0x02){
            sw2=0x10; // Invalid pin number.....
        goto TX_Data;
    
    
          } else if ((p2==0x00 && p3!=0x10) || ((p2==0x01 || p2==0x02) && p3!=0x09)){
            // There is an incorrect len check on PIN change
            sw1=0x67;
            goto TX_Data;      
          }
          
          /*
          //  Introduccion/modificacion de PIN
          //   - El PIN se almacena en eeprom externa.
          //   - Utilizo los dos ultimos bytes de la UA
          //    del proveedor con indice 1 (sigue a SECA).
          if (buffer[14]==0x27){
            // Apagar Keyleds?
            if (buffer[15]==0x0f){
              ee_write(EE_KEYLEDS + Extra_Funcard_Space,0);
            }
    
    
            // Keyleds muestran indice de la clave en uso
            if (buffer[15]==0x0e){
              ee_write(EE_KEYLEDS + Extra_Funcard_Space,1);
            }
    
    
            // Keyleds muestran indice del proveedor actual
            if (buffer[15]==0x0d){
              ee_write(EE_KEYLEDS + Extra_Funcard_Space,2);
            }
          } else
          //if ((buffer[14]==PIN_INFO_H) && (buffer[15]==PIN_INFO_L))
            //infoMode=!(infoMode);
          */
          
          #ifdef MODO_LOG  
          // No need to supply provider anymore, reuses first call
          // tratar_PINS_log( buffer[14], buffer[15], numProviders );
          tratar_PINS_log(buffer[14], buffer[15]);
          #endif
          
          
          /*-----------------------------------------------------------------------------
          | Bloqueo de taquillas oficial:
          |   Una vez que se bloquea una taquiila, el deco pedirá PIN a la hora de la
          |   compra aún cuando esa taquilla no esté bloqueada. En una taquilla bloqueada,
          |   lo pide 2 veces: a la hora de entrar en la taquilla y a la hora de la compra.
          |
          | Lo que intentamos es simular el bloqueo de taquillas evitando la petición del
          | PIN, a la hora de la compra, si esa taquilla no está bloqueada. En una bloqueada
          | lo seguirá pidiendo 2 veces.
          |
          | A la hora de realizar la compra o volver a una taquilla ya comprada, el deco no 
          | nos da datos suficientes para poder saber en que situación estamos. El sistema
          | que hemos adoptado garantiza, al menos, una petición de PIN cuando se entre en
          | una taquilla bloqueada, ya sea para el proceso de compra o si cambiamos a una
          | taquilla bloqueada con un evento de compra ya activado. En contra partida, en alguna
          | situación, puede darse el caso de que se pida PIN en el proceso de compra de una 
          | taquilla sin bloquear :-)
          |
          | Variables que controlan la situación:
          |   needPin : Se activa al inicio, en cada INS 3C, si se introduce in PIN correcto
          |             o si en la comprobación del PIN se encontraba sin activar needPIN o 
          |             pinChecked.
          |             Se desactiva con la INS 32, comando 4 (compra PPV)
          |
          |   pinChecked : Se activa si se introduce un PIN correcto o si en la comprobación
          |                del PIN se encontraba sin activar needPIN o pinChecked.
          |                Se desactiva al inicio y en cada INS 3C.
          |
          | Se comprueba el PIN si cualquiera de las dos variables se encuentran 
          | activas en el momento de la petición del mismo.
          +------------------------------------------------------------------------------------*/
    
    
          if ((pinChecked) || (needPin)){
            if (mem2eeprom_cmp(EE_PIN + Extra_Funcard_Space,&buffer[14],2)==0){
              // ultimo PIN validado = PIN almacenado   ?
              if (mem2eeprom_cmp(EE_PIN + Extra_Funcard_Space,&buffer[6],2)==1){
                // modificación del PIN
                ee_writeString(EE_PIN + Extra_Funcard_Space,&buffer[14],2);
              } 
              else {
                sw2=0x10; // no validar PIN: 9010
              }
            } else {
            needPin = pinChecked = TRUE;
            }
          } else {                            // Aunque parezca mentira
            needPin = pinChecked = TRUE;    // esta línea ocupa -2 bytes !!??
          } // fin comprobación pin
          
        } else
        
        // - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        // INSTRUCTION 0x02: give 8 bytes of data as result from IN THE 0x04 
        if (inst==0x02){
          if (lastInst!=inst && lastInst!=0x04){
            // Last instruction had to be a 0x04 ... return 9014
            sw2=0x14;
        goto TX_Data;
          }
          // Return the encoded 8 bytes
          _memcpy(buffer,hash,8);
        } else
        
        // INSTRUCTION 0x04: Supply 8 bytes for encryption using 0x0f key
        if (inst==0x04){
          // Return result of 04 request to encrypt using 0f (in p2) key
          if (p3!=8){
            // Length of incorrect entrance: 67 00
            sw1=0x67;
              goto TX_Data;
          }
          if (p2!=0x0f){
        // Requesting using key other than 0x0f ... return 9021
        sw2=0x21;
        goto TX_Data;
          }
          getKey(p1,p2);
          // To prepare 16*0xff
          encript(Key,buffer);
    
    
          // Encode the contents of the buffer from 0 -> 7
          _memcpy(hash,buffer,8);
        } else
    
    
        // - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        // INSTRUCTION 0x48: set flags 20.2 and 20.5 ?
        // INSTRUCTION 0x4A: associated 4c can be used but 4a retrieve still valid
        //                   but returns just FF * p3
        if (inst==0x48 || inst==0x4A){
          // No action, just need to support the call
          IncrementECMCount(inst);
          
        } else
    
    
        // - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        // INSTRUCTION 0x4C: Puts down bitmap of the allowed IN THE 0x44-Nanos and Protection Flags 
        // INSTRUCTION 0x50: Add new provider...
        // INSTRUCTION 0x54: LP Mode something...
        // INSTRUCTION 0x56: LP Mode something...
        if (inst==0x4c || inst==0x50 || inst==0x54 || inst==0x56){
          // High or Low programming mode required.... therefore not available here!
          // 90 11    Test-bit put not down, therefore instruction doesn't support 
          // but maybe 90 22 Card in the wrong mode ???
          // maybe 9017 from the Rom dump????
          sw2=0x11; 
          
        } else
        
        // - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        // INSTRUCTION 0x7c --------------------------------------------------------------
        // result just taken from Secom (301)
        if (inst==0x7c){ 
          // Have no information on what this indicates.... not a return
          // code in the SecaFAQ!
          sw1=0x98; sw2=0x01; 
          
        } else
                
        // - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        // INSTRUCTION 0x42: Edition of the data from IN THE 0x44 
        // result just taken from Secom (301)
        if (inst==0x42){
            // 90 14: Gone ahead instruction wrong 
            sw2=0x14; 
            
        } else
        
        // INSTRUCTION 0x38: Some bollocks to do with PPV
        if (inst==0x38){
          /*
          ; Ins 38 : data request and PPV event recording request
          ; C1 38 xx yy 1A  16 (d1) 2A (d2 d3) 2B (d4 d5) 86 (8 bytes) 82 (signature)
          ; Superencryption may be active
          ; on exit : 29h=d1 2Dh=d2 2Eh=d3 2Fh=d4 30h=d5 87-8Eh=(8 bytes for security)
          ;           d1 d2 d3 as in ins 34   d4-d5 : PPV event spot
          */
          // Grib, moved sigcheck prep to sub
          if (PrepareSigCheck(p1,p2,p3,TRUE)){
           goto TX_Data;
          }
          // Should check p1 for super encryption....
          if (signatureCheck(p1,p3)==0){
            // 90 02: Signature fails
            sw2=0x02; 
            goto TX_Data;
          }      
          // Store the copy security word in the 86 if supplied
          if (buffer[p3-18]==0x86){
            _memcpy(hash,&buffer[p3-17],8);
          }
          _memcpy(Comando34+1,buffer+1,1);
          _memcpy(Comando34+2,buffer+3,2);
          // Store d4 and d5 PPV Event ID too
          _memcpy(Comando34+4,buffer+6,2);
          
        } else
    
    
        // - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        // INSTRUCTION 0x40: EMM - pass to nano processing....
        if (inst==0x40){
          // Grib, moved sigcheck prep to sub
          if (PrepareSigCheck(p1,p2,p3,TRUE)){
           goto TX_Data;
          }
    
    
          // we ignored SECA ( C1 40 00 81 17 )
          if (p1&0x0f){
            if (signatureCheck(p1,p3)){
              if (processNanos(p1,kEMM,TRUE)){
                processNanos(p1,kEMM,FALSE);
              } // PPUA does not exist          
            } else {sw2=0x02;}
          }
        } else
        
        // - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        // INSTRUCTION 0x1A: Reading of the Indices of keys
        if (inst==0x1A){
          // FF FF 0B 40 00
          ee_readString(buffer, EE_AVAIL_KEYS, 5);
    
    
          for (p2=0, aux1=5; p2<16; p2++){
            ind=keyExist(p1,p2)|p2;
            if (ind&0xf0){
              // Nota: it considers space in SECA  
              //if(p1 | (p2 < 8)){ 
                buffer[aux1++]=ind;
              //}
            }
          }
        } else
        
        // - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        // INSTRUCTION 0x5C: Lay down word to be encrypted
        if (inst==0x5C){
          if (p3!=0x08){
              sw1=0x67;
          }
    
    
        } else
            
        // - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        // INSTRUCTION 0x5A: Lectura de claves encriptadas
        if (inst==0x5A){
          //lastInst=inst;
    
    
          // Reading of encrypted keys
          // Nota: it considers space in SECA
          // aux1 = (p1 | (p2 < 8))? keyExist(p1,p2&0x0f) : 0x00;
          aux1 = keyExist(p1,p2&0x0f);
          if (aux1==0x00){
            // It does not exist key primary 90 1D
            sw2=0x1d;
            goto TX_Data;
    
    
          } else if (aux1==0x50 && (p1&0x10)){
            // It does not exist key secondary 90 1F
            sw2=0x1F;
            goto TX_Data;
          }
          getKey(p1,p2);
    
    
          // To prepare 8*0x00
          fillBuffer(0,16,0x00);
          encript(Key,buffer);
          
        } else
        
        // - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        // INSTRUCTION 0x0A: System of Operation of the Card
        if (inst==0x0A){
          _memcpy(buffer,version,TOTAL_VERSION);
          // Need to decrypt buffer + 39
          // Decrypt the firmware result
          antipurple(39,3);
    
    
        } else
        // - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        // INSTRUCTION 0x22: Reading of eeprom
        // C1 22 P1 P2 P3
        // P1 Low Addr
        // P2 High Addr
        // P3 Bytes to read
        if ( (inst==0x22) && support_phoenix){
          ee_readString(buffer,(((u16)p1)<<8)+p2,p3);
        
        } else
        // - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        // INSTRUCTION 0x20: writing of eeprom
        // C1 20 P1 P2 P3
        // P1 Low Addr
        // P2 High Addr
        // P3 Bytes to write
        
        if ( (inst==0x20) && support_phoenix){
          //RED_INFO_LED_ON;
          ee_writeString((((u16)p1)<<8)+p2,buffer,p3);
          //RED_INFO_LED_OFF;
        
        } else {
          // UNKNOWN INSTRUCTION
          sw1=0x6D;
        }
    
    
      TX_Data:
        // Check if the result was valid :)
        lastInst=inst;
        // Need for the associate 32/36 instruction, must be the same
        // for some record requests
        lastprovider = p1;
        
        if (sw1!=0x90 || sw2){
          IncrementECMCount(inst);
          // Check if it exceeded visible provider count
          if ((p1&0x0F)>=ProviderCount && inst!=0x40){
            sw1=0x90; sw2=0x04;
            if (inst&2){
              // CARD->CAM
              fillBuffer(0,MAX_COMMAND_LENGHT,0xFF);
            }
          }
          if (inst!=0x3c || (sw1==0x90 && sw2==0x02)){
            lastInst=0;
          }
        }
      
      // Transmit without the hidden provider checks
      TX_Date_MPSkip:
        // Store the last command used global for the SetupInfo function...
        if (inst!=0x12){LastNonProviderInst = inst;}
      
        #ifdef MODO_LOG
        if (modo_log && !support_phoenix){ 
          // Log the current instruction to the eeprom
          capturar_inst(0xc1,inst,p1,p2,p3);
        }
        #endif
        
        // Grib - Bug fix :)
        if(p3 && inst&2){
          // CARD->CAM
          sendString(buffer,p3);
        }
        (*ptrSend)(sw1);
        (*ptrSend)(sw2);
    
    
    /*
        #ifdef MODO_LOG
        if (ins_capturadas){
          ORANGE_INFO_LED_ON;
        }
        #endif
    */
    
    
     } // end of while(1){}
      return 0;
    } // end of main()

  4. Internet, Programming and Graphics   -   #14
    Notepad++ and Sublime text are the best code editing softwares...

  5. Internet, Programming and Graphics   -   #15
    BANNED
    Join Date
    Aug 2018
    Location
    Noida
    Posts
    30
    An editor is any program that allows you to write computer code. They range from simple, like a basic text editor, to advanced software, such as Adobe Dreamweaver, Eclipse, JDeveloper, or Microsoft Visual Studio. Fortunately, any program can be written in a text editor, which means you can get started for free.

  6. Internet, Programming and Graphics   -   #16
    Try Visual Studio Community Edition, full featured and free

  7. Internet, Programming and Graphics   -   #17
    Well, you can use Visual Studio Code as a free IDE (editor for your code). With that you can write programs in most languages.

    To get started you could look into Python or Javascript.

    To get serious and code games, you'll need to be looking at C or C#

Page 2 of 2 FirstFirst 12

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •