From 0773f608d3fbe84e19d5bb171a778ca27b16b773 Mon Sep 17 00:00:00 2001 From: leslie Date: Thu, 27 Dec 2007 22:23:59 +0100 Subject: [PATCH] nagra 0501: AU with timed map call --- systems/nagra/nagra2-0101.c | 217 ------------------------------------ systems/nagra/nagra2-0501.c | 115 ++++++++++++++++++- systems/nagra/nagra2.c | 165 +++++++++++++++++++++++++++ systems/nagra/nagra2.h | 58 ++++++++++ 4 files changed, 333 insertions(+), 222 deletions(-) diff --git a/systems/nagra/nagra2-0101.c b/systems/nagra/nagra2-0101.c index 985b852..db99763 100644 --- a/systems/nagra/nagra2-0101.c +++ b/systems/nagra/nagra2-0101.c @@ -122,7 +122,6 @@ class cMap0101 : public cMapCore { private: static const unsigned char primes[]; static const unsigned short coef22[][32]; - unsigned int cycles; #ifdef HAS_AUXSRV cAuxSrv aux; #endif @@ -130,7 +129,6 @@ private: void MakePrime(BIGNUM *n, unsigned char *residues); protected: void DoMap(int f, unsigned char *data=0, int l=0); - unsigned int MapCycles() { return cycles; } }; const unsigned char cMap0101::primes[] = { @@ -520,221 +518,6 @@ void cMap0101::DoMap(int f, unsigned char *data, int l) } } -// -- cN2Timer ----------------------------------------------------------------- - -class cN2Timer { -private: - int ctrl, divisor, cycles, remainder, latch; - enum { tmCONTINUOUS=0x01, tmRUNNING=0x02, tmMASK=0xFF, tmLATCHED=0x100 }; - // - bool Running(void) { return ctrl&tmRUNNING; } - void Stop(void); -public: - cN2Timer(void); - void AddCycles(int count); - unsigned int Cycles(void) { return (unsigned int)cycles; } - unsigned char Ctrl(void) { return ctrl&tmMASK; } - void Ctrl(unsigned char c); - unsigned char Latch(void) { return latch&0xFF; } - void Latch(unsigned char val); - }; - -cN2Timer::cN2Timer(void) -{ - cycles=0; ctrl=0; divisor=1; remainder=-1; latch=0xFF; -} - -void cN2Timer::AddCycles(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(); - } - 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; - remainder=-1; - if(!(ctrl&tmCONTINUOUS) && cycles==0) ctrl&=~tmRUNNING; - } - } -} - -void cN2Timer::Stop(void) -{ - ctrl&=~(tmRUNNING|tmLATCHED); -} - -// -- cMapMemHW ---------------------------------------------------------------- - -#define HW_REGS 0x20 -#define HW_OFFSET 0x0000 - -#define MAX_TIMERS 3 -#define TIMER_NUM(x) (((x)>>2)&3) // timer order doesn't match HW order - -class cMapMemHW : public cMapMem { -private: - // memory mapped HW - enum { - HW_IO=0x00, HW_SECURITY, - HW_TIMER0_DATA=0x08, HW_TIMER0_LATCH, HW_TIMER0_CONTROL, - HW_CRC_CONTROL=0x0e, HW_CRC_DATA, - HW_TIMER1_DATA=0x10, HW_TIMER1_LATCH, HW_TIMER1_CONTROL, - HW_TIMER2_DATA=0x14, HW_TIMER2_LATCH, HW_TIMER2_CONTROL - }; - // timer hardware - cN2Timer timer[MAX_TIMERS]; - // CRC hardware - enum { CRCCALC_DELAY=9, CRC_BUSY=1, CRC_DISABLED=2 }; - unsigned short CRCvalue; - unsigned char CRCpos; - unsigned int CRCstarttime; - unsigned short crc16table[256]; - // counter - unsigned int cycles; - // - void GenCRC16Table(void); -public: - cMapMemHW(void); - virtual unsigned char Get(unsigned short ea); - virtual void Set(unsigned short ea, unsigned char val); - void AddCycles(unsigned int num); - }; - -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=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>((CRCpos&1)<<3); - CRCpos=!CRCpos; - return r; - } - default: - return mem[ea]; - } -} - -void cMapMemHW::Set(unsigned short ea, unsigned char val) -{ - if(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; - } -} - // -- cN2Prov0101 -------------------------------------------------------------- class cN2Prov0101 : public cN2Prov, public cN2Emu, private cMap0101 { diff --git a/systems/nagra/nagra2-0501.c b/systems/nagra/nagra2-0501.c index 03dfce8..ae6e8a7 100644 --- a/systems/nagra/nagra2-0501.c +++ b/systems/nagra/nagra2-0501.c @@ -42,6 +42,7 @@ cMap0501::cMap0501(int Id) void cMap0501::DoMap(int f, unsigned char *data, int l) { PRINTF(L_SYS_MAP,"%04x: calling function %02X",mId,f); + cycles=0; switch(f) { case 0x37: l=(l?l:wordsize)<<3; @@ -63,9 +64,17 @@ void cMap0501::DoMap(int f, unsigned char *data, int l) // -- cN2Prov0501 -------------------------------------------------------------- class cN2Prov0501 : public cN2Prov, private cMap0501, public cN2Emu { +private: + cMapMemHW *hwMapper; + // + bool ProcessMap(int f); + bool RomCallbacks(void); + void AddRomCallbacks(void); protected: virtual bool Algo(int algo, unsigned char *hd, const unsigned char *ed, unsigned char *hw); virtual bool NeedsCwSwap(void) { return true; } + virtual bool RomInit(void); + virtual void TimerHandler(unsigned int num); public: cN2Prov0501(int Id, int Flags); virtual int ProcessBx(unsigned char *data, int len, int pos); @@ -76,7 +85,9 @@ static cN2ProvLinkReg sta cN2Prov0501::cN2Prov0501(int Id, int Flags) :cN2Prov(Id,Flags) ,cMap0501(Id) -{} +{ + hwMapper=0; +} bool cN2Prov0501::Algo(int algo, unsigned char *hd, const unsigned char *ed, unsigned char *hw) { @@ -107,6 +118,92 @@ bool cN2Prov0501::Algo(int algo, unsigned char *hd, const unsigned char *ed, uns return false; } +bool cN2Prov0501::RomInit(void) +{ + if(!AddMapper(hwMapper=new cMapMemHW(),HW_OFFSET,HW_REGS,0x00)) return false; + return true; +} + +bool cN2Prov0501::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); + AddCycles(MapCycles()); + 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; + default: + PRINTF(L_SYS_EMU,"%04x: map call %02x not emulated",id,f); + return false; + } + return true; +} + +bool cN2Prov0501::RomCallbacks(void) +{ + unsigned int ea=GetPc(); + if(ea&0x8000) ea|=(cr<<16); + switch(ea) { + case 0x3840: //MAP Handler + if(!ProcessMap(a)) return false; + break; + default: + PRINTF(L_SYS_EMU,"%04X: unknown ROM breakpoint %04x",id,ea); + return false; + } + if(ea>=0x8000) PopCr(); + PopPc(); + return true; +} + +void cN2Prov0501::AddRomCallbacks(void) +{ + AddBreakpoint(0x3840); // map handler +} + int cN2Prov0501::ProcessBx(unsigned char *data, int len, int pos) { if(Init(id,120)) { @@ -118,17 +215,25 @@ int cN2Prov0501::ProcessBx(unsigned char *data, int len, int pos) Set(0x0000,0x04); ClearBreakpoints(); AddBreakpoint(0x821f); + AddBreakpoint(0x0000); + AddRomCallbacks(); while(!Run(5000)) { - switch(GetPc()) { - case 0x821f: - GetMem(0x80,data,len); - return a; + if(GetPc()==0x821f) { + GetMem(0x80,data,len); + return a; } + else if(GetPc()==0x0000) break; + else if(!RomCallbacks()) break; } } return -1; } +void cN2Prov0501::TimerHandler(unsigned int num) +{ + if(hwMapper) hwMapper->AddCycles(num); +} + // -- cN2Prov0511 ---------------------------------------------------------------- static cN2ProvLinkReg staticPL0511; diff --git a/systems/nagra/nagra2.c b/systems/nagra/nagra2.c index b4700cd..746b966 100644 --- a/systems/nagra/nagra2.c +++ b/systems/nagra/nagra2.c @@ -30,6 +30,170 @@ #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(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(); + } + 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=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>((CRCpos&1)<<3); + CRCpos=!CRCpos; + return r; + } + default: + return mem[ea]; + } +} + +void cMapMemHW::Set(unsigned short ea, unsigned char val) +{ + if(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) @@ -297,6 +461,7 @@ bool cMapCore::DoMap(int f, unsigned char *data, int l) // fall through case IMPORT_LAST: regs[last]->GetLE(data,last>0?dl:8); + cycles=944; // certainly dependant on the wordsize, but for now enough for PW break; case EXPORT_J: diff --git a/systems/nagra/nagra2.h b/systems/nagra/nagra2.h index 96e00a1..97c5bf5 100644 --- a/systems/nagra/nagra2.h +++ b/systems/nagra/nagra2.h @@ -39,6 +39,62 @@ // ---------------------------------------------------------------- +class cN2Timer { +private: + int ctrl, divisor, cycles, remainder, latch; + enum { tmCONTINUOUS=0x01, tmRUNNING=0x02, tmMASK=0xFF, tmLATCHED=0x100 }; + // + bool Running(void) { return ctrl&tmRUNNING; } + void Stop(void); +public: + cN2Timer(void); + void AddCycles(int count); + unsigned int Cycles(void) { return (unsigned int)cycles; } + unsigned char Ctrl(void) { return ctrl&tmMASK; } + void Ctrl(unsigned char c); + unsigned char Latch(void) { return latch&0xFF; } + void Latch(unsigned char val); + }; + +// ---------------------------------------------------------------- + +#define HW_REGS 0x20 +#define HW_OFFSET 0x0000 + +#define MAX_TIMERS 3 +#define TIMER_NUM(x) (((x)>>2)&3) // timer order doesn't match HW order + +class cMapMemHW : public cMapMem { +private: + // memory mapped HW + enum { + HW_IO=0x00, HW_SECURITY, + HW_TIMER0_DATA=0x08, HW_TIMER0_LATCH, HW_TIMER0_CONTROL, + HW_CRC_CONTROL=0x0e, HW_CRC_DATA, + HW_TIMER1_DATA=0x10, HW_TIMER1_LATCH, HW_TIMER1_CONTROL, + HW_TIMER2_DATA=0x14, HW_TIMER2_LATCH, HW_TIMER2_CONTROL + }; + // timer hardware + cN2Timer timer[MAX_TIMERS]; + // CRC hardware + enum { CRCCALC_DELAY=9, CRC_BUSY=1, CRC_DISABLED=2 }; + unsigned short CRCvalue; + unsigned char CRCpos; + unsigned int CRCstarttime; + unsigned short crc16table[256]; + // counter + unsigned int cycles; + // + void GenCRC16Table(void); +public: + cMapMemHW(void); + virtual unsigned char Get(unsigned short ea); + virtual void Set(unsigned short ea, unsigned char val); + void AddCycles(unsigned int num); + }; + +// ---------------------------------------------------------------- + class cN2Emu : protected c6805 { private: bool initDone; @@ -87,6 +143,7 @@ private: cBN *regs[5]; cBN x, y, s; protected: + unsigned int cycles; int wordsize; cBN A, B, C, D, J, I; cBN Px, Py, Pz,Qx, Qy, Qz; // 0x00,0x20,0x40,0x60,0x80,0x180 @@ -110,6 +167,7 @@ protected: void CurveInit(BIGNUM *a); // bool DoMap(int f, unsigned char *data=0, int l=0); + unsigned int MapCycles() { return cycles; } public: cMapCore(void); }; -- 2.39.5