// -- 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
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[] = {
{
PRINTF(L_SYS_MAP,"0101: calling function %02X",f);
l=GetOpSize(l);
- cycles=0;
+ cycles=0; interrupted=false;
switch(f) {
case 0x22:
{
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;
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;
}
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)
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)
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)
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);
#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:
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);
};
// ----------------------------------------------------------------