⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nagra2.c

📁 VDR softcam plugin 0.9.1
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * 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 */#include <stdlib.h>#include <string.h>#include "system.h"#include "opts.h"#include "log-core.h"#include "nagra.h"#include "nagra2.h"#define SYSTEM_NAME          "Nagra2"#define SYSTEM_PRI           -10// -- cN2Timer -----------------------------------------------------------------cN2Timer::cN2Timer(void){  cycles=0; ctrl=0; divisor=1; remainder=-1; latch=0xFF;}bool cN2Timer::AddCycles(unsigned int count){  bool irq=false;  if(Running()) {    bool stop=false;    remainder+=count;    if(remainder>=divisor) {      cycles-=remainder/divisor;      remainder%=divisor;      }    if(cycles<0 || (cycles==0 && remainder>=2))      stop=true;    if(ctrl&tmCONTINUOUS) {      while(cycles<0) cycles+=latch+1;      }    else if(stop) {      PRINTF(L_SYS_EMU,"n2timer %d: timer stop (cycles=%d remainder=%d)",nr,cycles,remainder);      cycles=0;      Stop();      }    if((ctrl&tmINTERRUPT) && stop) {      PRINTF(L_SYS_EMU,"n2timer %d: IRQ triggered",nr);      irq=true;      }    }  return irq;}void cN2Timer::Latch(unsigned char val){  if(!Running()) {    latch=val; if(latch==0) latch=0x100;    cycles=latch; remainder=0;    ctrl|=tmLATCHED;    }}void cN2Timer::Ctrl(unsigned char val){  if(Running()) {    ctrl=(ctrl&~tmRUNNING) | (val&tmRUNNING);    if(!Running()) {      Stop();      PRINTF(L_SYS_EMU,"n2timer %d: stopped cycles=%x ctrl=%x",nr,cycles,ctrl);      }    }  else {    ctrl=(ctrl&~tmMASK) | (val&tmMASK);    if(Running()) {      if((ctrl&0xc0)==0x40) divisor=1 << (2 *(1 + ((ctrl & 0x38) >> 3)));      else divisor=4; // This is wrong, but we haven't figured the right value out yet      if(divisor<=0) divisor=1; // sanity      if(!(ctrl&tmLATCHED)) cycles=(unsigned int)(cycles-1)&0xFF;      PRINTF(L_SYS_EMU,"n2timer %d: started latch=%x div=%d cycles=%x ctrl=%x",nr,latch,divisor,cycles,ctrl);      remainder=-1;      if(!(ctrl&tmCONTINUOUS) && cycles==0) ctrl&=~tmRUNNING;      }    }}void cN2Timer::Stop(void){  ctrl&=~(tmRUNNING|tmLATCHED);}// -- cN2CRC -------------------------------------------------------------------#define CRC_POLY 0x8408 // ccitt polycN2CRC::cN2CRC(void){  cycles=0; CRCpos=0; CRCtime=0; CRCin=0;  CRCvalue=0xffff; CRCit=CRCCALC_DELAY+1; ctrl=CRC_DISABLED;  GenTable();}void cN2CRC::AddCycles(unsigned int num){  cycles+=num;}void cN2CRC::GenTable(void){  for(int i=0; i<256; i++) {    unsigned short c=i;    for(int j=0; j<8; j++) c=(c>>1)^((c&1)?CRC_POLY:0);    table[i]=c;    }}void cN2CRC::Update(void){  if(!(ctrl&CRC_DISABLED) && CRCit<=CRCCALC_DELAY) {    unsigned int it=CRCit;    CRCit+=cycles-CRCtime;    if(CRCit>CRCCALC_DELAY)  // > instead of >= because of CRC_BUSY lockout      CRCit=CRCCALC_DELAY+1;    if(it==0 && CRCit>=CRCCALC_DELAY)      CRCvalue=(CRCvalue>>8)^table[(CRCvalue^CRCin)&0xff];    else      for(; it<CRCit && it<CRCCALC_DELAY; it++)        CRCvalue=(CRCvalue>>1) ^ (((CRCvalue^(CRCin>>it))&1) ? CRC_POLY : 0);    CRCtime=cycles;    }}unsigned char cN2CRC::Ctrl(void){  Update();  unsigned char r=ctrl;  if(CRCit<CRCCALC_DELAY) r|=CRC_BUSY; else r&=~CRC_BUSY;  return r|0x80;}void cN2CRC::Ctrl(unsigned char c){  if(ctrl&CRC_DISABLED) {    if(!(c&CRC_DISABLED)) {      CRCvalue=0xffff; CRCpos=0; CRCtime=cycles;      if(CRCit<=CRCCALC_DELAY) { CRCtime++; CRCit++; }      }    }  else if(c&CRC_DISABLED) Update();  ctrl=c;}unsigned char cN2CRC::Data(void){  Update();  return (CRCvalue^0xffff)>>((CRCpos++&1)<<3);}void cN2CRC::Data(unsigned char d){  Update();  if(CRCit>CRCCALC_DELAY && !(ctrl&CRC_DISABLED)) {    CRCin=d;    CRCit=0; CRCtime=cycles;    }}// -- cMapMemHW ----------------------------------------------------------------cMapMemHW::cMapMemHW(void):cMapMem(HW_OFFSET,HW_REGS){  for(int i=0; i<MAX_TIMERS; i++) timer[i].SetNumber(HW_NUM(i));  PRINTF(L_SYS_EMU,"mapmemhw: new HW map off=%04x size=%04x",offset,size);}int cMapMemHW::AddCycles(unsigned int num){  crc.AddCycles(num);  int mask=0;  for(int i=0; i<MAX_TIMERS; i++)    if(timer[i].AddCycles(num)) mask|=1<<timer[i].Number();  return mask;}unsigned char cMapMemHW::Get(unsigned short ea){  if(ea<offset || ea>=offset+size) return 0;  ea-=offset;  switch(ea) {    case HW_SECURITY:      return (mem[ea]&0x70)|0x0F;    case HW_TIMER0_CONTROL:    case HW_TIMER1_CONTROL:    case HW_TIMER2_CONTROL:      return timer[TIMER_NUM(ea)].Ctrl();    case HW_TIMER0_DATA:    case HW_TIMER1_DATA:    case HW_TIMER2_DATA:      return timer[TIMER_NUM(ea)].Cycles();    case HW_TIMER0_LATCH:    case HW_TIMER1_LATCH:    case HW_TIMER2_LATCH:      return timer[TIMER_NUM(ea)].Latch();    case HW_CRC_CONTROL:      return crc.Ctrl();    case HW_CRC_DATA:      return crc.Data();    default:      return mem[ea];    }}void cMapMemHW::Set(unsigned short ea, unsigned char val){  if(ea<offset || ea>=offset+size) return;  ea-=offset;  switch(ea) {    case HW_TIMER0_CONTROL:    case HW_TIMER1_CONTROL:    case HW_TIMER2_CONTROL:      timer[TIMER_NUM(ea)].Ctrl(val);      break;    case HW_TIMER0_LATCH:    case HW_TIMER1_LATCH:    case HW_TIMER2_LATCH:      timer[TIMER_NUM(ea)].Latch(val);      break;    case HW_CRC_CONTROL:      crc.Ctrl(val);      break;    case HW_CRC_DATA:      crc.Data(val);      break;    default:      mem[ea]=val;      break;    }}// -- cN2Emu -------------------------------------------------------------------cN2Emu::cN2Emu(void){  initDone=false;}bool cN2Emu::Init(int id, int romv){  if(!initDone) {    ResetMapper();    char buff[256];    snprintf(buff,sizeof(buff),"ROM%d.bin",romv);    // UROM  0x00:0x4000-0x7fff    if(!AddMapper(new cMapRom(0x4000,buff,0x00000),0x4000,0x4000,0x00)) return false;    // ROM00 0x00:0x8000-0xffff    if(!AddMapper(new cMapRom(0x8000,buff,0x04000),0x8000,0x8000,0x00)) return false;    // ROM01 0x01:0x8000-0xffff    if(!AddMapper(new cMapRom(0x8000,buff,0x0C000),0x8000,0x8000,0x01)) return false;    // ROM02 0x02:0x8000-0xbfff    if(!AddMapper(new cMapRom(0x8000,buff,0x14000),0x8000,romv>=110?0x8000:0x4000,0x02)) return false;    snprintf(buff,sizeof(buff),"EEP%02X_%d.bin",(id>>8)&0xFF|0x01,romv);    // Eeprom00 0x00:0x3000-0x37ff OTP 0x80    //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    //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 initDone;}// -- cMapReg ------------------------------------------------------------------cMapReg::cMapReg(int *_defwordsize, int _maxwordsize){  SetDefWordSize(_defwordsize);  SetMaxWordSize(_maxwordsize);  wordsize=DEF_WORDSIZE;}BIGNUM *cMapReg::Value(int wsize, bool mask){  wsize=OpWordSize(wsize);  if(wordsize!=wsize) {    Commit();    Reload();    }  else if(mask)    BN_mask_bits(reg,wsize*64);  return reg;}void cMapReg::ClearReg(int wsize){  BN_rshift(reg,reg,wsize*64);  BN_lshift(reg,reg,wsize*64);}void cMapReg::ClearFullReg(int wsize){  BN_rshift(fullreg,fullreg,wsize*64);  BN_lshift(fullreg,fullreg,wsize*64);}void cMapReg::PrepTmp(BIGNUM *val, int wsize){  if(val->neg) {    BN_clear(tmp);    BN_set_bit(tmp,wsize*64);    BN_add(tmp,tmp,val);    }  else    BN_copy(tmp,val);  BN_mask_bits(tmp,wsize*64);}void cMapReg::Commit(int wsize, int resync){  if(resync<0 && wsize<0) resync=1;  wsize=OpWordSize(wsize>=0?wsize:wordsize);  ClearFullReg(wsize);  PrepTmp(reg,wsize);  BN_add(fullreg,fullreg,tmp);  if(resync) {    if(wordsize==wsize) BN_mask_bits(reg,wsize*64);    else wordsize=wsize;    }}void cMapReg::Reload(int wsize){  wsize=OpWordSize(wsize>=0?wsize:wordsize);  wordsize=wsize;  BN_copy(reg,fullreg);  BN_mask_bits(reg,64*wsize);}void cMapReg::GetLE(const unsigned char *in, int n){  int wsize=OpWordSize(n<=0?n:(n+7)/8);  if(wordsize>wsize) Commit();  reg.GetLE(in,wsize*8);  Commit(wsize);}void cMapReg::PutLE(unsigned char *out, int n){  int wsize=OpWordSize(n<=0?n:(n+7)/8);  Commit();  fullreg.PutLE(out,wsize*8);}void cMapReg::Set(BIGNUM *val, int wsize){  wsize=OpWordSize(wsize);  if(wordsize!=wsize) Commit();  ClearReg(wsize);  PrepTmp(val,wsize);  if(wordsize!=wsize) {    ClearFullReg(wsize);    BN_add(fullreg,fullreg,tmp);    }  BN_add(reg,reg,tmp);}void cMapReg::Clear(int wsize){  wsize=OpWordSize(wsize);  if(wordsize!=wsize) {    Commit();    ClearFullReg(wsize);    }  ClearReg(wsize);}// -- cMapMath -----------------------------------------------------------------cMapMath::cMapMath(void):A(&wordsize),B(&wordsize),C(&wordsize),D(&wordsize),J(0,1),I(&wordsize){  wordsize=DEF_WORDSIZE; words=-1;}bool cMapMath::ModAdd(BIGNUM *r, BIGNUM *a, BIGNUM *b, BIGNUM *d){  BN_add(r,a,b);  bool ret=false;  if(BN_cmp(r,d)>=0) {    BN_sub(r,r,d);    ret=true;    }  BN_mask_bits(r,wordsize<<6);  return ret;}bool cMapMath::ModSub(BIGNUM *r, BIGNUM *d, BIGNUM *b){  cBN p;  bool ret=BN_cmp(d,b)<0;  BN_set_bit(p,wordsize<<6);  BN_mod_sub(r,d,b,p,ctx);  BN_mask_bits(r,wordsize<<6);  return ret;}void cMapMath::MakeJ0(BIGNUM *j, BIGNUM *d, BIGNUM *c, int bits){#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); j->neg=1;  BN_set_bit(j,0);  BN_set_bit(x,bits);  BN_mod_inverse(j,j,x,ctx);  if(c) {    BN_copy(c,d);    BN_mask_bits(c,bits);    BN_mul(c,j,c,ctx);    BN_rshift(c,c,bits);    BN_mask_bits(c,bits);    }}void cMapMath::MonMul(BIGNUM *o, BIGNUM *a, BIGNUM *b){  MonMul(o,a,b,C,D,J,0);}void cMapMath::MonMul(BIGNUM *o, BIGNUM *a, BIGNUM *b, int w){  MonMul(o,a,b,C,D,J,w);}void cMapMath::MonMul(BIGNUM *o, BIGNUM *a, BIGNUM *b, BIGNUM *c, BIGNUM *d, BIGNUM *j, int w){  MonMul0(o,a,b,c,d,j,w);  MonFin(o,d);}void cMapMath::MonMul0(BIGNUM *o, BIGNUM *a, BIGNUM *b, BIGNUM *c, BIGNUM *d, BIGNUM *j, int w){  if(!w) w=wordsize;  MonStart(w);  int i=0;  while(words>0) {    BN_rshift(x,a,(i++)<<6);    MonLoop(o,x,b,c,d,j);    }}void cMapMath::MonStart(int w){  if(words<=0) {    words=w;    BN_zero(s);    }}// modifies a, but pointing a to x is allowed !!void cMapMath::MonLoop(BIGNUM *o, BIGNUM *a, BIGNUM *b, BIGNUM *c, BIGNUM *d, BIGNUM *j){  words--;  BN_mask_bits(a,64);  BN_mul(a,a,b,ctx);  BN_add(s,s,a);  BN_copy(x,s);  BN_mask_bits(x,64);  BN_mul(x,x,j,ctx);  if(!words) {    BN_lshift(y,x,64);    BN_add(y,y,x);    // Low    BN_rshift(c,y,2);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -