nagra2-0101.c
来自「VDR softcam plugin 0.9.1」· C语言 代码 · 共 969 行 · 第 1/2 页
C
969 行
memcpy(data,mecmCode,sizeof(data)); RotateBytes(data,sizeof(data)); SHA1(data,sizeof(data)-8,data); RotateBytes(data,20); if(memcmp(data,mecmCode,8)) { PRINTF(L_SYS_ECM,"%04X: MECM %02x decrypt signature failed",id,keyNr); return false; } memcpy(hw,hd,seedSize); ExpandInput(hw); SetSp(0x0FFF,0x0EF8); ClearBreakpoints(); SetMem(0x0100,mecmCode+8,0x100-8); SetMem(0xa00,hd,seedSize); SetMem(0x0ba2,hw,0x80); AddBreakpoint(0x0000); AddRomCallbacks(); SetPc(0x0100); while(!Run(100000)) { if(GetPc()==0x0000) { GetMem(0x0ba2,hw,0x80); return true; } else if(!RomCallbacks()) return false; }/* if(algo==0x40) { const int hwCount=2; memcpy(hw,hd,hwCount+1); ExpandInput(hw); hw[0x18]|=1; hw[0x40]|=1; DoMap(SETSIZE,0,2); DoMap(IMPORT_A,hw,3); DoMap(IMPORT_D,hw+24); DoMap(0x3b); DoMap(EXPORT_C,hw); DoMap(IMPORT_A,hw+40,3); DoMap(IMPORT_D,hw+64); DoMap(0x3b); DoMap(EXPORT_C,hw+40); DoMap(0x43); DoMap(0x44,hw); DoMap(0x44,hw+64); memcpy(&hw[0],&hw[64+4],hwCount); memset(&hw[hwCount],0,128-hwCount); return true; } else if(algo==0x60) { // map 4D/4E/57 hw[127]|=0x80; hw[0]|=0x01; DoMap(SETSIZE,0,16); DoMap(IMPORT_A,hw); DoMap(0x4d); DoMap(0x4e); DoMap(EXPORT_A,hw); RotateBytes(hw,16); DoMap(IMPORT_A,hw); DoMap(0x4e); DoMap(EXPORT_A,hw); DoMap(0x57,hw); return true; } PRINTF(L_SYS_ECM,"%04X: unknown MECM algo %02x",id,algo);*/ return false;}bool cN2Prov0101::PostProcAU(int id, unsigned char *data){ if(data[1]&0x5f) return false; return true;}bool cN2Prov0101::RomInit(void){ if(!AddMapper(hwMapper=new cMapMemHW(),HW_OFFSET,HW_REGS,0x00)) return false; SetPc(0x4000); SetSp(0x0FFF,0x0FE0); ClearBreakpoints(); AddBreakpoint(0x537d); AddBreakpoint(0x8992); AddBreakpoint(0xA822); while(!Run(7000)) { switch(GetPc()) { case 0x537d: PRINTF(L_SYS_EMU,"%04x: ROM init successfull",id); return true; default: PRINTF(L_SYS_EMU,"%04x: ROM init failed: unexpected breakpoint",id); break; } } return false;}bool cN2Prov0101::ProcessMap(int f){ unsigned short addr; unsigned char tmp[512]; int l=GetOpSize(Get(0x48)); int dl=l<<3; switch(f) { case SETSIZE: DoMap(f,0,Get(0x48)); break; case IMPORT_J: l=8; dl=8<<3; // fall throught case IMPORT_A: case IMPORT_B: case IMPORT_C: case IMPORT_D: case IMPORT_LAST: addr=HILO(0x44); GetMem(addr,tmp,dl,0); DoMap(f,tmp,l); break; case EXPORT_J: l=8; dl=8<<3; // fall throught case EXPORT_A: case EXPORT_B: case EXPORT_C: case EXPORT_D: case EXPORT_LAST: addr=HILO(0x44); DoMap(f,tmp,l); SetMem(addr,tmp,dl,0); break; case SWAP_A: case SWAP_B: case SWAP_C: case SWAP_D: addr=HILO(0x44); GetMem(addr,tmp,dl,0); DoMap(f,tmp,l); SetMem(addr,tmp,dl,0); break; case CLEAR_A: case CLEAR_B: case CLEAR_C: case CLEAR_D: case COPY_A_B: case COPY_B_A: case COPY_A_C: case COPY_C_A: case COPY_C_D: case COPY_D_C: DoMap(f); break; case 0x22: DoMap(f,tmp,(Get(0x48)<<16)|(Get(0x4a)<<8)|Get(0x49)); break; case 0x29: case 0x2a: DoMap(f,tmp); Set(0x4b,tmp[0]); break; case 0x3c: case 0x3e: GetMem(HILO(0x44),tmp,dl,0); DoMap(f,tmp,Get(0x48)); break; case 0x32: case 0x39: case 0x3b: GetMem(HILO(0x44),tmp,dl,0); DoMap(f,tmp,l); break; case 0x21: case 0x23: case 0x25: case 0x30: case 0x31: case 0x36: case 0x38: case 0x3a: case 0x43: DoMap(f); break; case 0x44: case 0x45: GetMem(0x400,tmp,64,0); DoMap(f,tmp,l); SetMem(0x440,tmp,20,0); break; case 0x4d: DoMap(f,tmp,-((Get(0x48)<<16)|(Get(0x49)<<8)|Get(0x4a))); SetMem(0x400,tmp,53,0); break; case 0x4e: GetMem(0x400,tmp,53,0); DoMap(f,tmp); SetMem(0x400,tmp,53,0); break; case 0x57: addr=HILO(0x46); l=wordsize; if(l<2 || l>4) l=4; dl=l<<3; for(int i=0; i<6; i++) GetMem(HILO(addr+i*2),tmp+i*dl,dl,0); DoMap(f,tmp); SetMem(0x400,tmp,0x40,0); memset(tmp,0,11*32); SetMem(0x440,tmp,11*32,0); break; default: PRINTF(L_SYS_EMU,"%04x: map call %02x not emulated",id,f); return false; } c6805::a=0; c6805::x=0; c6805::y=0; return true;}bool cN2Prov0101::ProcessDESMap(int f){ unsigned char data[16]; switch(f) { case 0x05: // 3DES encrypt DES_ecb2_encrypt(DES_CAST(desblock),DES_CAST(desblock),&desks1,&desks2,DES_ENCRYPT); break; case 0x06: // 3DES decrypt DES_ecb2_encrypt(DES_CAST(desblock),DES_CAST(desblock),&desks1,&desks2,DES_DECRYPT); break; case 0x07: Set(0x2d,0x02); //XXX quick-hack or the real thing?? break; case 0x0b: // load DES data block from memory GetMem(HILO(0x25),desblock,8,Get(0x24)); break; case 0x0c: // store DES data block to memory SetMem(HILO(0x2b),desblock,8,Get(0x2a)); break; case 0x0e: // get DES key1 and key2 GetMem(HILO(0x25),data,8,Get(0x24)); DES_key_sched((DES_cblock *)data,&desks1); GetMem(HILO(0x28),data,8,Get(0x27)); DES_key_sched((DES_cblock *)data,&desks2); break; case 0x0f: // set DES size desSize=Get(0x2d); if(desSize!=0x10 && desSize!=0x18) { PRINTF(L_SYS_EMU,"%04x: invalid DES key size %02x",id,desSize); return false; } break; default: PRINTF(L_SYS_EMU,"%04x: DES map call %02x not emulated",id,f); return false; } return true;}bool cN2Prov0101::RomCallbacks(void){ bool dopop=true; unsigned int ea=GetPc(); if(ea&0x8000) ea|=(cr<<16); switch(ea) { case 0x3840: //MAP Handler case 0x00A822: if(!ProcessMap(a)) return false; if(Interrupted()) dopop=false; break; case 0x3844: //DES Handler case 0x008992: if(!ProcessDESMap(a)) return false; break; case 0x5F23: //Erase_RAM_and_Hang case 0x5F27: //Erase_RAM_and_Hang_Lp case 0x5F5E: //BrainDead PRINTF(L_SYS_EMU,"%04x: emu hung at %04x",id,ea); return false; case 0x70A6: //Write_Row_EEP_RC2_Len_A_To_RC1 { unsigned short rc1=HILO(0x47); unsigned short rc2=HILO(0x4a); for(int i=0; i<a; i++) Set(0x80,rc1++,Get(dr,rc2++)); Set(0x4a,rc2>>8); Set(0x4b,rc2&0xff); break; } case 0x7BFE: //Write_Row_EEPROM_A_from_X_to_RC1 { unsigned short rc1=HILO(0x47); unsigned short rc2=c6805::x; for(int i=0; i<a; i++) Set(0x80,rc1++,Get(rc2++)); break; } case 0x7CFF: //UPDATE_USW_03DD_03DE Set(0x30E8,Get(0x03DD)); Set(0x30E9,Get(0x03DE)); break; case 0x00A23C: //IDEA_Generate_Expanded_Key { unsigned char key[16]; GetMem(0x0a20,key,16); idea.SetEncKey(key,&ks); break; } case 0x00A2E9: //IDEA_Cypher { unsigned char data[8]; GetMem(0x070,data,8); idea.Encrypt(data,8,data,&ks,0); SetMem(0x070,data,8); break; } default: PRINTF(L_SYS_EMU,"%04X: unknown ROM breakpoint %04x",id,ea); return false; } if(dopop) { if(ea>=0x8000) PopCr(); PopPc(); } return true;}void cN2Prov0101::AddRomCallbacks(void){ AddBreakpoint(0xA822); // map handler AddBreakpoint(0x3840); AddBreakpoint(0x3844); AddBreakpoint(0xA23C); //IDEA AddBreakpoint(0xA2E9); AddBreakpoint(0x70A6); AddBreakpoint(0x7BFE); AddBreakpoint(0x7CFF); AddBreakpoint(0x5F23); AddBreakpoint(0x5F27); AddBreakpoint(0x5F5E);}int cN2Prov0101::ProcessBx(unsigned char *data, int len, int pos){ if(Init(id,102)) { SetMem(0x92,data+pos-1,len-pos+1); SetPc(0x93); SetSp(0x0FFF,0x0EF8); ClearBreakpoints(); AddBreakpoint(0x9569); AddBreakpoint(0x0000); AddRomCallbacks(); while(!Run(1000)) { if(GetPc()==0x9569) { GetMem(0x80,data,len); return a; } else if(GetPc()==0x0000) break; else if(!RomCallbacks()) break; } } return -1;}int cN2Prov0101::ProcessEx(unsigned char *data, int len, int pos){ if(Init(id,102)) { SetMem(0x80,data,len); SetPc(0x9591); SetSp(0x0FFF,0x0EF8); Push(0x99); //push the bug-table return onto the stack Push(0x95); Push(0x00); Set(0x00,0x62,0x26); Set(0x00,0x63,0x02); Set(0x00,0x03d3,len-0x12); ClearBreakpoints(); AddBreakpoint(0x9569); AddBreakpoint(0x9599); AddRomCallbacks(); while(!Run(10000)) { if(GetPc()==0x9569) { GetMem(0x80,data,len); return max((int)a,6); } else if(GetPc()==0x9599) break; else if(!RomCallbacks()) break; } } return -1;}int cN2Prov0101::RunEmu(unsigned char *data, int len, unsigned short load, unsigned short run, unsigned short stop, unsigned short fetch, int fetch_len){ if(Init(id,102)) { SetSp(0x0FFF,0x0EF8); SetMem(load,data,len); SetPc(run); ClearBreakpoints(); AddBreakpoint(stop); if(stop!=0x0000) AddBreakpoint(0x0000); AddRomCallbacks(); while(!Run(100000)) { if(GetPc()==0x0000 || GetPc()==stop) { GetMem(fetch,data,fetch_len); return 1; } else if(!RomCallbacks()) break; } } return -1;}void cN2Prov0101::ReadHandler(unsigned char seg, unsigned short ea, unsigned char &op){ if(ea==0x2f70) op=random()&0xFF; else if(ea==0x2f71) { unsigned int n=random()&0xFF; unsigned int cy=Cycles(); if(cy>rndtime && cy<=rndtime+4) { unsigned int o=sn8(rnd); n=(n&0xE3) | (o&4) | ((o>>1)&16) | ((o^(o>>1))&8); } op=rnd=n; rndtime=cy; }}void cN2Prov0101::TimerHandler(unsigned int num){ if(hwMapper) { int mask=hwMapper->AddCycles(num); for(int t=0; mask; mask>>=1,t++) if(mask&1) { DisableTimers(11); if(t==2) { PRINTF(L_SYS_EMU,"0101: Timer interrupt %u @ %04x",t,GetPc()); RaiseException(9); if(Interruptible()) throw(t); } } }}void cN2Prov0101::Stepper(void){ unsigned short pc=GetPc(); if(pc>=0x93 && pc<=0xE0) { // pc in EMM data unsigned char op=Get(pc); if((op&0xF0)==0x00) { // current opcode BRCLR/BRSET int fake=0; // 1=branch -1=non-branch if(Get(pc+3)==0x81) // next opcode == RTS fake=1; // fake branch else { unsigned char off=Get(pc+2); unsigned short target=pc+3+off; if(off&0x80) target-=0x100; if(Get(target)==0x81) // branch target == RTS fake=-1; // fake non-branch } if(fake) { unsigned short ea=Get(pc+1); unsigned char val=Get(dr,ea); int bit=1<<((op&0xF)>>1); // set/clr bit according to fake-mode and opcode if((fake>0 && (op&0x01)) || (fake<0 && !(op&0x01))) { if(val&bit) loglb->Printf("*"); val&=~bit; } else { if(!(val&bit)) loglb->Printf("*"); val|=bit; } Set(dr,ea,val); } } }}// -- cN2Prov0901 --------------------------------------------------------------class cN2Prov0901 : public cN2Prov0101 {public: cN2Prov0901(int Id, int Flags); };static cN2ProvLinkReg<cN2Prov0901,0x0901,(N2FLAG_MECM|N2FLAG_POSTAU|N2FLAG_Bx|N2FLAG_Ex)> staticPL0901;cN2Prov0901::cN2Prov0901(int Id, int Flags):cN2Prov0101(Id,Flags){ mecmAddr[0]=0x91f5; mecmAddr[1]=0x92f5; mecmKeyId=0x907;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?