📄 nagra1.cpp
字号:
/*
* 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 <unistd.h>
#include <ctype.h>
#include "stdafx.h"
//#include <vdr/tools.h>
#include "asprintf.h"
#include "common.h"
#include "sc.h"
#include "system.h"
#include "misc.h"
#include "opts.h"
#include "debug.h"
#include "nagra.h"
#include "cpu.h"
#include "xnprintf.h"
#include "debug.h"
#include "nagra.h"
#include "cpu.h"
#define SYSTEM_NAME "Nagra"
#define SYSTEM_PRI -10
// -- cEmu ---------------------------------------------------------------------
#define MAX_COUNT 200000
class cEmu : public c6805 {
protected:
int romNr, id;
char *romName, *romExtName, *eepromName;
//
int InitStart, InitEnd;
int EmmStart, EmmEnd, EmmKey0, EmmKey1;
int FindKeyStart, FindKeyEnd;
int MapAddr;
int Rc1H, Rc1L;
int EnsIrdChk, Cmd83Chk;
int SoftInt, StackHigh;
//
bool AddRom(unsigned short addr, unsigned short size, const char *name);
bool AddEeprom(unsigned short addr, unsigned short size, unsigned short otpSize, const char *name);
//
virtual bool InitSetup(void) { return true; }
virtual bool UpdateSetup(const unsigned char *emm) { return true; }
virtual bool MathMapHandler(void);
public:
cEmu(void);
virtual ~cEmu();
bool Init(int RomNr, int Id);
bool GetOpKeys(const unsigned char *Emm, unsigned char *id, unsigned char *key0, unsigned char *key1);
bool GetPkKeys(const unsigned char *select, unsigned char *pkset);
bool Matches(int RomNr, int Id);
};
cEmu::cEmu(void)
{
romName=romExtName=eepromName=0;
}
cEmu::~cEmu()
{
free(romName);
free(romExtName);
free(eepromName);
}
bool cEmu::AddRom(unsigned short addr, unsigned short size, const char *name)
{
cMap *map=new cMapRom(addr,name);
return AddMapper(map,addr,size);
}
bool cEmu::AddEeprom(unsigned short addr, unsigned short size, unsigned short otpSize, const char *name)
{
cMap *map=new cMapEeprom(addr,name,otpSize);
return AddMapper(map,addr,size);
}
bool cEmu::Matches(int RomNr, int Id)
{
return (romNr==RomNr && id==Id);
}
bool cEmu::Init(int RomNr, int Id)
{
romNr=RomNr; id=Id;
asprintf(&romName,"ROM%d.bin",romNr);
asprintf(&romExtName,"ROM%dext.bin",romNr);
asprintf(&eepromName,"eep%i_%02x.bin",romNr,(id&0xff00)>>8);
if(InitSetup()) {
ForceSet(EnsIrdChk, 0x81,true);
ForceSet(Cmd83Chk+0,0x98,true);
ForceSet(Cmd83Chk+1,0x9d,true);
if(SoftInt) {
Set(0x1ffc,SoftInt>>8);
Set(0x1ffd,SoftInt&0xff);
}
SetSp(StackHigh,0);
SetPc(InitStart);
ClearBreakpoints();
AddBreakpoint(InitEnd);
if(!Run(MAX_COUNT)) return true;
}
return false;
}
bool cEmu::GetOpKeys(const unsigned char *Emm, unsigned char *id, unsigned char *key0, unsigned char *key1)
{
int keys=0;
if(UpdateSetup(Emm)) {
SetMem(0x0080,&Emm[0],64);
SetMem(0x00F8,&Emm[1],2);
SetPc(EmmStart);
ClearBreakpoints();
AddBreakpoint(EmmEnd);
AddBreakpoint(MapAddr);
AddBreakpoint(EmmKey0);
AddBreakpoint(EmmKey1);
while(!Run(MAX_COUNT)) {
unsigned short pc=GetPc();
if(pc==EmmKey0) {
GetMem(0x82,key0,8);
keys++;
}
if(pc==EmmKey1) {
GetMem(0x82,key1,8);
keys++;
}
if(pc==MapAddr) {
if(!MathMapHandler()) break;
PopPc(); // remove return address from stack
}
if(pc==EmmEnd) {
GetMem(0x00F8,id,2);
break;
}
}
}
return (keys==2);
}
bool cEmu::GetPkKeys(const unsigned char *select, unsigned char *pkset)
{
Set(0x0081,select[2]<<7);
SetMem(0x00F8,select,3);
SetPc(FindKeyStart);
ClearBreakpoints();
AddBreakpoint(FindKeyEnd);
while(!Run(MAX_COUNT)) {
unsigned short pc=GetPc();
if(pc==FindKeyEnd) {
if(!cc.c) {
dee(printf("Updating PK keys\n"))
unsigned short loc=(Get(Rc1H)<<8)+Get(Rc1L);
for(int i=0; i<45; i+=15) GetMem(loc+4+i,pkset+i,15);
return true;
}
else {
dee(printf("Updating PK keys failed. Used a correct EEPROM image for provider %04x ?\n",((select[0]<<8)|select[1])))
break;
}
}
}
return false;
}
bool cEmu::MathMapHandler(void)
{
dee(printf("Unsupported math call $%02x in ROM %d, please report\n",a,romNr))
return false;
}
// -- cEmuRom3Core -------------------------------------------------------------
class cEmuRom3Core : public cEmu {
protected:
virtual void Stepper(void);
bool CoreInitSetup(void);
bool DoMaps(bool hasExt);
};
void cEmuRom3Core::Stepper(void)
{
int rnd=rand();
unsigned char mem4=Get(0x04);
if(!bitset(mem4,2)) {
Set(0x06,(rnd&0xff00)>>8);
Set(0x07,rnd&0xff);
}
}
bool cEmuRom3Core::CoreInitSetup(void)
{
ForceSet(0x0001,1<<3,true);
Set(0x0002,0x03);
Set(0x004e,0x4B);
return true;
}
bool cEmuRom3Core::DoMaps(bool hasExt)
{
// Eeprom & ROMext are non-fatal also they are required for some providers
if(hasExt) AddRom(0x2000,0x2000,romExtName);
AddEeprom(0xE000,0x1000,0x20,eepromName);
return AddRom(0x4000,0x4000,romName);
}
// -- cEmuRom3 -----------------------------------------------------------------
class cEmuRom3 : public cEmuRom3Core {
protected:
virtual bool InitSetup(void);
virtual bool UpdateSetup(const unsigned char *emm);
public:
cEmuRom3(void);
};
cEmuRom3::cEmuRom3(void)
{
InitStart=0x4000;
InitEnd =0x734b;
EmmStart =0x5a82;
EmmEnd =0x67db;
EmmKey0 =0x617c;
EmmKey1 =0x6184;
FindKeyStart=0x6133;
FindKeyEnd =0x6147;
MapAddr =0x2800;
Rc1H =0x0024;
Rc1L =0x0025;
EnsIrdChk=0x6437;
Cmd83Chk =0x6431;
SoftInt =0x0000;
StackHigh=0x7f;
}
bool cEmuRom3::InitSetup(void)
{
return DoMaps(true) && CoreInitSetup();
}
bool cEmuRom3::UpdateSetup(const unsigned char *emm)
{
return CoreInitSetup();
}
// -- cEmuRom7 -----------------------------------------------------------------
class cEmuRom7 : public cEmuRom3Core {
protected:
virtual bool InitSetup(void);
virtual bool UpdateSetup(const unsigned char *emm);
public:
cEmuRom7(void);
};
cEmuRom7::cEmuRom7(void)
{
InitStart=0x4000;
InitEnd =0x7b68;
EmmStart =0x482b;
EmmEnd =0x6146;
EmmKey0 =0x4f2a;
EmmKey1 =0x4f32;
FindKeyStart=0x4ee4;
FindKeyEnd =0x4ef5;
MapAddr =0x200f;
Rc1H =0x0028;
Rc1L =0x0029;
EnsIrdChk=0x51df;
Cmd83Chk =0x51d9;
SoftInt =0x4008;
StackHigh=0x7f;
}
bool cEmuRom7::InitSetup(void)
{
return DoMaps(false) && CoreInitSetup();
}
bool cEmuRom7::UpdateSetup(const unsigned char *emm)
{
SetMem(0x01A2,&emm[1],2);
return true;
}
// -- cEmuRom10Core ------------------------------------------------------------
class cEmuRom10Core : public cEmu {
protected:
struct Map { unsigned char A[64], B[64], C[64], D[4], opSize; } map;
//
virtual void Stepper(void);
bool DoMaps(bool hasExt, int romSize);
bool CoreInitSetup(void);
bool CoreUpdateSetup(const unsigned char *emm);
};
void cEmuRom10Core::Stepper(void)
{
int rnd=rand();
unsigned char mem7=Get(0x07);
if(cc.i) mem7&=0xFD; else mem7|=0x02;
Set(0x07,mem7);
if(bitset(mem7,1) && bitset(mem7,7)) {
Set(0x05,(rnd&0xFF00)>>8);
Set(0x06,rnd&0xFF);
}
}
bool cEmuRom10Core::DoMaps(bool hasExt, int romSize)
{
// Eeprom & ROMext are non-fatal also they are required for some providers
if(hasExt) AddRom(0x2000,0x2000,romExtName);
AddEeprom(0xC000,0x2000,0x40,eepromName);
return AddRom(0x4000,romSize,romName);
}
bool cEmuRom10Core::CoreInitSetup(void)
{
ForceSet(0x01,0x13,true);
Set(0x02,0x3);
Set(0x07,0xFF);
return true;
}
bool cEmuRom10Core::CoreUpdateSetup(const unsigned char *emm)
{
SetMem(0x01A2,&emm[1],2);
SetMem(0x0307,&emm[1],2);
Set(0x0300,emm[5]);
Set(0x0301,emm[2]);
return true;
}
// -- cEmuRom10 ----------------------------------------------------------------
class cEmuRom10 : public cEmuRom10Core {
protected:
virtual bool InitSetup(void);
virtual bool UpdateSetup(const unsigned char *emm);
virtual bool MathMapHandler(void);
public:
cEmuRom10(void);
};
cEmuRom10::cEmuRom10(void)
{
InitStart=0x4000;
InitEnd =0x81ca;
EmmStart =0x6a71;
EmmEnd =0x81f7;
EmmKey0 =0x7172;
EmmKey1 =0x717a;
FindKeyStart=0x712c;
FindKeyEnd =0x713d;
MapAddr =0x2020;
Rc1H =0x004a;
Rc1L =0x004b;
EnsIrdChk=0x7427;
Cmd83Chk =0x7421;
SoftInt =0x4004;
StackHigh=0x3ff;
}
bool cEmuRom10::InitSetup(void)
{
return DoMaps(false,0x5A00) && CoreInitSetup();
}
bool cEmuRom10::UpdateSetup(const unsigned char *emm)
{
Set(0x006e,0x4B);
return CoreUpdateSetup(emm);
}
bool cEmuRom10::MathMapHandler(void)
{
dee(printf("math call: $%02x\n",a))
switch(a) {
case 0x02:
switch(Get(0x41)) {
case 0: map.opSize=0x04; break;
case 1: map.opSize=0x20; break;
case 2: map.opSize=0x24; break;
case 3: map.opSize=0x30; break;
case 4: map.opSize=0x34; break;
case 5:
default: map.opSize=0x40; break;
}
return true;
case 0x0e: case 0x0f: case 0x10:
{
const unsigned short addr=(Get(0x4d)<<8)|Get(0x4e);
unsigned char tmp[64];
GetMem(addr,tmp,map.opSize);
unsigned char *reg;
switch(a) {
case 0x0e: reg=map.A; break;
case 0x0f: reg=map.B; break;
case 0x10: reg=map.C; break;
default: return false;
}
SetMem(addr,reg,map.opSize);
memcpy(reg,tmp,map.opSize);
Set(0x41,map.opSize);
return true;
}
case 0x29:
Set(0x120,1);
return true;
}
return cEmu::MathMapHandler();
}
// -- cEmuRom11 ----------------------------------------------------------------
class cEmuRom11 : public cEmuRom10Core {
protected:
virtual bool InitSetup(void);
virtual bool UpdateSetup(const unsigned char *emm);
public:
cEmuRom11(void);
};
cEmuRom11::cEmuRom11(void)
{
InitStart=0x4000;
InitEnd =0x405b;
EmmStart =0x5865;
EmmEnd =0x9990;
EmmKey0 =0x5f66;
EmmKey1 =0x5f6e;
FindKeyStart=0x5f20;
FindKeyEnd =0x5f31;
MapAddr =0x2020;
Rc1H =0x004a;
Rc1L =0x004b;
EnsIrdChk=0x621b;
Cmd83Chk =0x6215;
SoftInt =0x4004;
StackHigh=0x3ff;
}
bool cEmuRom11::InitSetup(void)
{
return DoMaps(false,0x8000) && CoreInitSetup();
}
bool cEmuRom11::UpdateSetup(const unsigned char *emm)
{
Set(0x0068,0x4B);
return CoreUpdateSetup(emm);
}
#ifndef TESTER
// -- cNagraDES ----------------------------------------------------------------
class cNagraDES {
private:
cDes des;
protected:
void Decrypt(const unsigned char *data, const unsigned char *key, unsigned char *out, bool desmod=false);
void Crypt(const unsigned char *data, const unsigned char *key, unsigned char *out);
bool SigCheck(const unsigned char *block, const unsigned char *sig, const unsigned char *vkey, const int rounds);
};
void cNagraDES::Decrypt(const unsigned char *data, const unsigned char *key, unsigned char *out, bool desmod)
{
unsigned char cardkey[8];
memcpy(cardkey,key,8);
RotateBytes(cardkey,8);
memcpy(out,data,8);
if(!desmod) RotateBytes(out,8);
des.Des(out,cardkey,NAGRA_DES_DECR);
if(!desmod) RotateBytes(out,8);
}
void cNagraDES::Crypt(const unsigned char *data, const unsigned char *key, unsigned char *out)
{
unsigned char cardkey[8];
memcpy(cardkey,key,8);
RotateBytes(cardkey,8);
memcpy(out,data,8);
RotateBytes(out,8);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -