ctrl&=~(tmRUNNING|tmLATCHED);
}
-// -- cMapMemHW ----------------------------------------------------------------
+// -- cN2CRC -------------------------------------------------------------------
#define CRC_POLY 0x8408 // ccitt poly
-cMapMemHW::cMapMemHW(void)
-:cMapMem(HW_OFFSET,HW_REGS)
+cN2CRC::cN2CRC(void)
{
- cycles=0;
- CRCvalue=0xffff; CRCpos=0; CRCstarttime=0; CRCinput=0; CRCupdate=false;
- GenCRC16Table();
- for(int i=0; i<MAX_TIMERS; i++) timer[i].SetNumber(HW_NUM(i));
- PRINTF(L_SYS_EMU,"mapmemhw: new HW map off=%04x size=%04x",offset,size);
+ cycles=0; CRCpos=0; CRCtime=0; CRCin=0;
+ CRCvalue=0xffff; CRCit=CRCCALC_DELAY+1; ctrl=CRC_DISABLED;
+ GenTable();
}
-void cMapMemHW::GenCRC16Table(void)
+void cN2CRC::AddCycles(unsigned int num)
+{
+ cycles+=num;
+}
+
+void cN2CRC::GenTable(void)
{
for(int i=0; i<256; i++) {
unsigned short c=i;
for(int j=0; j<8; j++) c=(c>>1)^((c&1)?CRC_POLY:0);
- crc16table[i]=c;
+ table[i]=c;
}
}
-unsigned short cMapMemHW::CRC(unsigned short crc, unsigned char val, int bits)
+void cN2CRC::Update(void)
{
- if(bits>=8) return (crc>>8)^crc16table[(crc^val)&0xff];
- if(bits>0) crc^=(val&(0xff>>(8-bits)));
- for(int i=0; i<bits; i++) crc=(crc>>1)^((crc&1)?CRC_POLY:0);
- return crc;
+ if(!(ctrl&CRC_DISABLED) && CRCit<=CRCCALC_DELAY) {
+ unsigned int it=CRCit;
+ CRCit+=cycles-CRCtime;
+ if(CRCit>CRCCALC_DELAY) // > instead of >= because of CRC_BUSY lockout
+ CRCit=CRCCALC_DELAY+1;
+ if(it==0 && CRCit>=CRCCALC_DELAY)
+ CRCvalue=(CRCvalue>>8)^table[(CRCvalue^CRCin)&0xff];
+ else
+ for(; it<CRCit && it<CRCCALC_DELAY; it++)
+ CRCvalue=(CRCvalue>>1) ^ (((CRCvalue^(CRCin>>it))&1) ? CRC_POLY : 0);
+ CRCtime=cycles;
+ }
+}
+
+unsigned char cN2CRC::Ctrl(void)
+{
+ Update();
+ unsigned char r=ctrl;
+ if(CRCit<CRCCALC_DELAY) r|=CRC_BUSY; else r&=~CRC_BUSY;
+ return r|0x80;
+}
+
+void cN2CRC::Ctrl(unsigned char c)
+{
+ if(ctrl&CRC_DISABLED) {
+ if(!(c&CRC_DISABLED)) {
+ CRCvalue=0xffff; CRCpos=0; CRCtime=cycles;
+ if(CRCit<=CRCCALC_DELAY) { CRCtime++; CRCit++; }
+ }
+ }
+ else if(c&CRC_DISABLED) Update();
+ ctrl=c;
+}
+
+unsigned char cN2CRC::Data(void)
+{
+ Update();
+ return (CRCvalue^0xffff)>>((CRCpos++&1)<<3);
+}
+
+void cN2CRC::Data(unsigned char d)
+{
+ Update();
+ if(CRCit>CRCCALC_DELAY && !(ctrl&CRC_DISABLED)) {
+ CRCin=d;
+ CRCit=0; CRCtime=cycles;
+ }
+}
+
+// -- cMapMemHW ----------------------------------------------------------------
+
+cMapMemHW::cMapMemHW(void)
+:cMapMem(HW_OFFSET,HW_REGS)
+{
+ for(int i=0; i<MAX_TIMERS; i++) timer[i].SetNumber(HW_NUM(i));
+ PRINTF(L_SYS_EMU,"mapmemhw: new HW map off=%04x size=%04x",offset,size);
}
int cMapMemHW::AddCycles(unsigned int num)
{
+ crc.AddCycles(num);
int mask=0;
- cycles+=num;
for(int i=0; i<MAX_TIMERS; i++)
if(timer[i].AddCycles(num)) mask|=1<<timer[i].Number();
return mask;
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<CRCCALC_DELAY) r|=CRC_BUSY; // busy
- else r&=~CRC_BUSY; // not busy
- return r;
- }
+ return crc.Ctrl();
case HW_CRC_DATA:
- {
- unsigned short crc;
- if(CRCupdate) {
- crc=CRC(CRCvalue,CRCinput,cycles-CRCstarttime-1);
- if(cycles-CRCstarttime>=CRCCALC_DELAY) {
- CRCvalue=crc; CRCupdate=false;
- }
- }
- else crc=CRCvalue;
- unsigned char r=(crc^0xffff)>>((CRCpos&1)<<3);
- CRCpos^=1;
- return r;
- }
+ return crc.Data();
default:
return mem[ea];
}
timer[TIMER_NUM(ea)].Latch(val);
break;
case HW_CRC_CONTROL:
- if((mem[ea]&CRC_DISABLED) && !(val&CRC_DISABLED)) {
- CRCvalue=0xffff; CRCinput=0; CRCpos=0; CRCupdate=false;
- CRCstarttime=cycles-CRCCALC_DELAY;
- }
- mem[ea]=val;
+ crc.Ctrl(val);
break;
case HW_CRC_DATA:
- if(cycles-CRCstarttime>=CRCCALC_DELAY) {
- if(CRCupdate) {
- CRCvalue=CRC(CRCvalue,CRCinput,8);
- CRCupdate=false;
- }
- if(!(mem[HW_CRC_CONTROL]&CRC_DISABLED)) {
- CRCinput=val;
- CRCupdate=true;
- CRCstarttime=cycles;
- }
- }
+ crc.Data(val);
break;
default:
mem[ea]=val;
// ----------------------------------------------------------------
+class cN2CRC {
+private:
+ enum { CRCCALC_DELAY=8, CRC_BUSY=1, CRC_DISABLED=2 };
+ unsigned short CRCvalue;
+ unsigned char ctrl, CRCpos, CRCin;
+ unsigned int cycles, CRCtime, CRCit;
+ unsigned short table[256];
+ //
+ void GenTable(void);
+ void Update(void);
+public:
+ cN2CRC(void);
+ void AddCycles(unsigned int num);
+ unsigned char Ctrl(void);
+ void Ctrl(unsigned char c);
+ unsigned char Data(void);
+ void Data(unsigned char d);
+ };
+
+// ----------------------------------------------------------------
+
#define HW_REGS 0x20
#define HW_OFFSET 0x0000
// timer hardware
cN2Timer timer[MAX_TIMERS];
// CRC hardware
- enum { CRCCALC_DELAY=9, CRC_BUSY=1, CRC_DISABLED=2 };
- unsigned short CRCvalue, CRCinput;
- unsigned char CRCpos;
- unsigned int CRCstarttime;
- unsigned short crc16table[256];
- bool CRCupdate;
- // counter
- unsigned int cycles;
- //
- void GenCRC16Table(void);
- unsigned short CRC(unsigned short crc, unsigned char val, int bits);
+ cN2CRC crc;
public:
cMapMemHW(void);
virtual unsigned char Get(unsigned short ea);