📄 nagra2.c
字号:
/* * 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 <stdio.h>#include <stdlib.h>#include <string.h>#include "system.h"#include "opts.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;}void cN2Timer::AddCycles(unsigned int count){ if(Running()) { 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::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: stopped cycles=%x ctrl=%x",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: started latch=%x div=%d cycles=%x ctrl=%x",latch,divisor,cycles,ctrl); remainder=-1; if(!(ctrl&tmCONTINUOUS) && cycles==0) ctrl&=~tmRUNNING; } }}void cN2Timer::Stop(void){ ctrl&=~(tmRUNNING|tmLATCHED);}// -- cMapMemHW ----------------------------------------------------------------cMapMemHW::cMapMemHW(void):cMapMem(HW_OFFSET,HW_REGS){ cycles=0; CRCvalue=0; CRCpos=0; CRCstarttime=0; GenCRC16Table(); PRINTF(L_SYS_EMU,"mapmemhw: new HW map off=%04x size=%04x",offset,size);}void cMapMemHW::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 cMapMemHW::AddCycles(unsigned int num){ cycles+=num; for(int i=0; i<MAX_TIMERS; i++) timer[i].AddCycles(num);}unsigned char cMapMemHW::Get(unsigned short ea){ if(ea<offset || ea>=offset+size) return 0; ea-=offset; switch(ea) { case HW_SECURITY: return 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: { unsigned char r=mem[ea]; if(!(r&CRC_DISABLED) && cycles-CRCstarttime<CRCCALC_DELAY) r|=CRC_BUSY; // busy else r&=~CRC_BUSY; // not busy return r; } case HW_CRC_DATA: { unsigned char r=CRCvalue>>((CRCpos&1)<<3); CRCpos=!CRCpos; return r; } 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_SECURITY: break; 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: mem[ea]=val; if(!(val&CRC_DISABLED)) { CRCvalue=0; CRCpos=0; CRCstarttime=cycles-CRCCALC_DELAY; } break; case HW_CRC_DATA: if(!(mem[HW_CRC_CONTROL]&CRC_DISABLED) && cycles-CRCstarttime>=CRCCALC_DELAY) { CRCvalue=(CRCvalue>>8)^crc16table[(CRCvalue^val)&0xFF]; CRCpos=0; CRCstarttime=cycles; } 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;}// -- cMapCore -----------------------------------------------------------------cMapCore::cMapCore(void){ wordsize=4; last=1; regs[0]=&J; regs[1]=&A; regs[2]=&B; regs[3]=&C; regs[4]=&D;}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_set_bit(x,64); BN_mod_inverse(j,j,x,ctx);}void cMapCore::MonMul(BIGNUM *o, BIGNUM *a, BIGNUM *b, BIGNUM *c, BIGNUM *d, BIGNUM *j, int words){ if(!words) words=wordsize; BN_zero(s); for(int i=0; i<words;) { BN_rshift(x,a,(i++)<<6); BN_mask_bits(x,64); 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) { 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_mask_bits(x,64); BN_mul(x,x,d,ctx); BN_add(s,s,x); if(i==words) { // High BN_lshift(y,s,12); BN_add(c,c,y); BN_mask_bits(c,wordsize<<6); } BN_rshift(s,s,64); if(BN_cmp(s,d)==1) { BN_copy(x,s); 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -