]> www.vanbest.org Git - sasc-ng.git/commitdiff
nagra: add timer irq handling
authoranon <unknown>
Mon, 26 May 2008 13:20:41 +0000 (21:20 +0800)
committeranon <unknown>
Mon, 26 May 2008 13:20:41 +0000 (21:20 +0800)
systems/nagra/nagra2-0101.c
systems/nagra/nagra2.c
systems/nagra/nagra2.h

index e59d37964dc25d7c48578f989ecd3e733a8c85c7..88d4006987f341ab8ae4438fbe623c5f4e745efb 100644 (file)
@@ -116,10 +116,14 @@ int cAuxSrv::Map(int map, unsigned char *data, int len, int outlen)
 
 // -- cMap0101 ----------------------------------------------------------------
 
+#define MAP_IRQ_BEGIN interruptable=true; try {
+#define MAP_IRQ_END   } catch(int) { interrupted=true; } interruptable=false;
+
 class cMap0101 : public cMapCore {
 private:
   static const unsigned char primes[];
   static const unsigned short coef22[][32];
+  bool interruptable, interrupted;
 #ifdef HAS_AUXSRV
   cAuxSrv aux;
 #endif
@@ -127,6 +131,10 @@ private:
   void MakePrime(BIGNUM *n, unsigned char *residues);
 protected:
   void DoMap(int f, unsigned char *data=0, int l=0);
+  bool Interruptable(void) { return interruptable; }
+  bool Interrupted(void) { return interrupted; }
+public:
+  cMap0101(void) { interruptable=false; }
   };
 
 const unsigned char cMap0101::primes[] = {
@@ -421,7 +429,7 @@ void cMap0101::DoMap(int f, unsigned char *data, int l)
 {
   PRINTF(L_SYS_MAP,"0101: calling function %02X",f);
   l=GetOpSize(l);
-  cycles=0;
+  cycles=0; interrupted=false;
   switch(f) {
     case 0x22:
       {
@@ -919,12 +927,14 @@ bool cN2Prov0101::ProcessDESMap(int f)
 
 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
       if(!ProcessDESMap(a)) return false;
@@ -973,8 +983,10 @@ bool cN2Prov0101::RomCallbacks(void)
       PRINTF(L_SYS_EMU,"%04X: unknown ROM breakpoint %04x",id,ea);
       return false;
     }
-  if(ea>=0x8000) PopCr();
-  PopPc();
+  if(dopop) {
+    if(ea>=0x8000) PopCr();
+    PopPc();
+    }
   return true;
 }
 
@@ -1066,7 +1078,17 @@ int cN2Prov0101::RunEmu(unsigned char *data, int len, unsigned short load, unsig
 
 void cN2Prov0101::TimerHandler(unsigned int num)
 {
-  if(hwMapper) hwMapper->AddCycles(num);
+  if(hwMapper) {
+    int mask=hwMapper->AddCycles(num);
+    for(int t=1; mask; mask>>=1,t++) {
+      DisableTimers(11);
+      if(t==2) {
+        PRINTF(L_SYS_EMU,"Timer interrupt %u @ %04x",t,GetPc());
+        RaiseException(9);
+        if(Interruptable()) throw(t);
+        }
+      }
+    }
 }
 
 void cN2Prov0101::Stepper(void)
index 38f0bcecc2669bc471fcad2bd7f9c42c7d350bfe..df986ab2b0d64684cda6e04c8077757f5e9c82c9 100644 (file)
@@ -37,22 +37,29 @@ cN2Timer::cN2Timer(void)
   cycles=0; ctrl=0; divisor=1; remainder=-1; latch=0xFF;
 }
 
-void cN2Timer::AddCycles(unsigned int count)
+bool cN2Timer::AddCycles(unsigned int count)
 {
+  bool irq=false;
   if(Running()) {
+    bool stop=false;
     remainder+=count;
     if(remainder>=divisor) {
       cycles-=remainder/divisor;
       remainder%=divisor;
       }
+    if(cycles<0 || (cycles==0 && remainder>=2))
+      stop=true;
     if(ctrl&tmCONTINUOUS) {
       while(cycles<0) cycles+=latch+1;
       }
-    else if(cycles<0 || (cycles==0 && remainder>=4)) {
+    else if(stop) {
       cycles=0;
       Stop();
       }
+    if((ctrl&tmINTERRUPT) && stop)
+      irq=true;
     }
+  return irq;
 }
 
 void cN2Timer::Latch(unsigned char val)
@@ -122,10 +129,13 @@ unsigned short cMapMemHW::CRC(unsigned short crc, unsigned char val, int bits)
   return crc;
 }
 
-void cMapMemHW::AddCycles(unsigned int num)
+int cMapMemHW::AddCycles(unsigned int num)
 {
+  int mask=0;
   cycles+=num;
-  for(int i=0; i<MAX_TIMERS; i++) timer[i].AddCycles(num);
+  for(int i=0; i<MAX_TIMERS; i++)
+    if(timer[i].AddCycles(num)) mask|=(1<<HW_NUM(i));
+  return mask;
 }
 
 unsigned char cMapMemHW::Get(unsigned short ea)
index f1003eac19198fa78f92f4b9597490ad017597c4..ba363a169b54000a6d88f5827fe2081a7cc4b77c 100644 (file)
@@ -139,13 +139,13 @@ public:
 class cN2Timer {
 private:
   int ctrl, divisor, cycles, remainder, latch;
-  enum { tmCONTINUOUS=0x01, tmRUNNING=0x02, tmMASK=0xFF, tmLATCHED=0x100 };
+  enum { tmCONTINUOUS=0x01, tmRUNNING=0x02, tmINTERRUPT=0x04, tmMASK=0xFF, tmLATCHED=0x100 };
   //
   bool Running(void) { return ctrl&tmRUNNING; }
   void Stop(void);
 public:
   cN2Timer(void);
-  void AddCycles(unsigned int count);
+  bool AddCycles(unsigned int count);
   unsigned int Cycles(void) { return cycles; }
   unsigned char Ctrl(void) { return ctrl&tmMASK; }
   void Ctrl(unsigned char c);
@@ -160,6 +160,7 @@ public:
 
 #define MAX_TIMERS 3
 #define TIMER_NUM(x) (((x)>>2)&3) // timer order doesn't match HW order
+#define HW_NUM(x)    ((x+2)%3)
 
 class cMapMemHW : public cMapMem {
 private:
@@ -189,7 +190,7 @@ public:
   cMapMemHW(void);
   virtual unsigned char Get(unsigned short ea);
   virtual void Set(unsigned short ea, unsigned char val);
-  void AddCycles(unsigned int num);
+  int AddCycles(unsigned int num);
   };
 
 // ----------------------------------------------------------------