📄 nagra2-0101.c
字号:
} default: if(!cMapCore::DoMap(f,data,l)) PRINTF(L_SYS_MAP,"0101: unsupported call %02x",f); break; }}// -- cN2Prov0101 --------------------------------------------------------------class cN2Prov0101 : public cN2Prov, public cN2Emu, private cMap0101 {private: int desSize; DES_key_schedule desks1, desks2; unsigned char desblock[8]; IdeaKS ks; cMapMemHW *hwMapper; // void AddRomCallbacks(void); bool RomCallbacks(void); bool ProcessMap(int f); bool ProcessDESMap(int f);protected: int mecmAddr[2]; int mecmKeyId; // virtual bool Algo(int algo, const unsigned char *hd, unsigned char *hw); virtual void DynamicHD(unsigned char *hd, const unsigned char *ed); virtual bool RomInit(void); virtual void Stepper(void); virtual void TimerHandler(unsigned int num);public: cN2Prov0101(int Id, int Flags); virtual bool PostProcAU(int id, unsigned char *data); virtual int ProcessBx(unsigned char *data, int len, int pos); virtual int ProcessEx(unsigned char *data, int len, int pos); int RunEmu(unsigned char *data, int len, unsigned short load, unsigned short run, unsigned short stop, unsigned short fetch, int fetch_len); };static cN2ProvLinkReg<cN2Prov0101,0x0101,(N2FLAG_MECM|N2FLAG_POSTAU|N2FLAG_Bx|N2FLAG_Ex)> staticPL0101;cN2Prov0101::cN2Prov0101(int Id, int Flags):cN2Prov(Id,Flags){ mecmAddr[0]=0x91d7; mecmAddr[1]=0x92d7; mecmKeyId=0x106; seedSize=10; desSize=16; hwMapper=0;}void cN2Prov0101::DynamicHD(unsigned char *hd, const unsigned char *ed){ hd[5]=ed[5]; hd[6]=(ed[7]&0xEF) | ((ed[6]&0x40)>>2); hd[7]=ed[8]; hd[8]=(ed[9]&0x7F) | ((ed[6]&0x20)<<2); hd[9]=ed[6]&0x80;}bool cN2Prov0101::Algo(int algo, const unsigned char *hd, unsigned char *hw){ if(algo!=0x40 && algo!=0x60) { PRINTF(L_SYS_ECM,"%04X: unknown MECM algo %02x",id,algo); return false; } if(!Init(id,102)) { PRINTF(L_SYS_ECM,"%04X: failed to initialize ROM",id); return false; } unsigned char keyNr=(algo>>5)&0x01; unsigned char mecmCode[256]; GetMem(mecmAddr[keyNr],mecmCode,256,0x80); cPlainKey *pk; unsigned char ideaKey[16]; if(!(pk=keys.FindKey('N',mecmKeyId,keyNr,sizeof(ideaKey)))) { PRINTF(L_SYS_KEY,"missing %04x %02x MECM key",mecmKeyId,keyNr); return false; } pk->Get(ideaKey); idea.SetEncKey(ideaKey,&ks); for(int i=0x100-8; i>=8; i-=8) { idea.Encrypt(mecmCode+i,8,mecmCode+i,&ks,0); xxor(mecmCode+i,8,mecmCode+i,mecmCode+i-8); } idea.Encrypt(mecmCode,8,mecmCode,&ks,0); HEXDUMP(L_SYS_RAWECM,mecmCode,sizeof(mecmCode),"decrypted MECM code"); // check signature unsigned char data[256]; 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(0x0ba2,hw,0x80); AddBreakpoint(0x0000); AddRomCallbacks(); SetPc(0x0100); while(!Run(10000)) { 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(5000)) { 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; int size=wordsize<<3; unsigned char tmp[256]; switch(f) { case SETSIZE: // set map size DoMap(f,0,Get(0x48)); if((wordsize<<3)>256) { PRINTF(L_SYS_EMU,"%04x: MAP word size too large: %d",id,wordsize); return false; } break; case IMPORT_J: //Import Ram at [44:45] to Map Registers A-E, E is 0x03 the rest in sequence case IMPORT_A: case IMPORT_B: case IMPORT_C: case IMPORT_D: case IMPORT_LAST: addr=HILO(0x44); GetMem(addr,tmp,size,0); DoMap(f,tmp); break; case EXPORT_J: //Export Registers A-E with 44:45: 0x09 is E case EXPORT_A: case EXPORT_B: case EXPORT_C: case EXPORT_D: case EXPORT_LAST: addr=HILO(0x44); DoMap(f,tmp); SetMem(addr,tmp,size,0); break; case SWAP_A: //Swap Registers A-D with 44:45 case SWAP_B: case SWAP_C: case SWAP_D: addr=HILO(0x44); GetMem(addr,tmp,size,0); DoMap(f,tmp); SetMem(addr,tmp,size,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(0x49)<<8)|Get(0x4a))); AddCycles(MapCycles()); break; case 0x3b: size=Get(0x48); if(!size) size=wordsize; GetMem(HILO(0x44),tmp,size<<3,0); DoMap(f,tmp,size); break; case 0x3e: GetMem(HILO(0x44),tmp,size,0); DoMap(f,tmp,Get(0x48)); AddCycles(MapCycles()); 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); AddCycles(MapCycles()); break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -