📄 spc7110.cpp
字号:
{ short adj; adj=((short)(s7r.reg4815<<8))|s7r.reg4814; i+=adj; } else { uint16 adj; adj=(s7r.reg4815<<8)|s7r.reg4814; i+=adj; } i%=s7r.DataRomSize; s7r.reg4811=i&0x00FF; s7r.reg4812=(i&0x00FF00)>>8; s7r.reg4813=((i&0xFF0000)>>16); } } } } s7r.written|=0x10; break; //data port increment low case 0x4816: s7r.reg4816=data; break; //data port increment high case 0x4817: s7r.reg4817=data; break; //data port mode switches //note that it starts inactive. case 0x4818: if((s7r.written&0x18)!=0x18) break; s7r.offset_add=0; s7r.reg4818=data; break; //multiplicand low or dividend lowest case 0x4820: s7r.reg4820=data; break; //multiplicand high or dividend lower case 0x4821: s7r.reg4821=data; break; //dividend higher case 0x4822: s7r.reg4822=data; break; //dividend highest case 0x4823: s7r.reg4823=data; break; //multiplier low case 0x4824: s7r.reg4824=data; break; //multiplier high (triggers operation) case 0x4825: s7r.reg4825=data; if(s7r.reg482E&0x01) { int mul; short m1=(short)((s7r.reg4824)|(s7r.reg4825<<8)); short m2=(short)((s7r.reg4820)|(s7r.reg4821<<8)); mul=m1*m2; s7r.reg4828=(uint8)(mul&0x000000FF); s7r.reg4829=(uint8)((mul&0x0000FF00)>>8); s7r.reg482A=(uint8)((mul&0x00FF0000)>>16); s7r.reg482B=(uint8)((mul&0xFF000000)>>24); } else { uint32 mul; uint16 m1=(uint16)((s7r.reg4824)|(s7r.reg4825<<8)); uint16 m2=(uint16)((s7r.reg4820)|(s7r.reg4821<<8)); mul=m1*m2; s7r.reg4828=(uint8)(mul&0x000000FF); s7r.reg4829=(uint8)((mul&0x0000FF00)>>8); s7r.reg482A=(uint8)((mul&0x00FF0000)>>16); s7r.reg482B=(uint8)((mul&0xFF000000)>>24); } s7r.reg482F=0x80; break; //divisor low case 0x4826: s7r.reg4826=data; break; //divisor high (triggers operation) case 0x4827: s7r.reg4827=data; if(s7r.reg482E&0x01) { int quotient; short remainder; int dividend=(int)(s7r.reg4820|(s7r.reg4821<<8)|(s7r.reg4822<<16)|(s7r.reg4823<<24)); short divisor=(short)(s7r.reg4826|(s7r.reg4827<<8)); if(divisor != 0) { quotient=(int)(dividend/divisor); remainder=(short)(dividend%divisor); } else { quotient=0; remainder=dividend&0x0000FFFF; } s7r.reg4828=(uint8)(quotient&0x000000FF); s7r.reg4829=(uint8)((quotient&0x0000FF00)>>8); s7r.reg482A=(uint8)((quotient&0x00FF0000)>>16); s7r.reg482B=(uint8)((quotient&0xFF000000)>>24); s7r.reg482C=(uint8)remainder&0x00FF; s7r.reg482D=(uint8)((remainder&0xFF00)>>8); } else { uint32 quotient; uint16 remainder; uint32 dividend=(uint32)(s7r.reg4820|(s7r.reg4821<<8)|(s7r.reg4822<<16)|(s7r.reg4823<<24)); uint16 divisor=(uint16)(s7r.reg4826|(s7r.reg4827<<8)); if(divisor != 0) { quotient=(uint32)(dividend/divisor); remainder=(uint16)(dividend%divisor); } else { quotient=0; remainder=dividend&0x0000FFFF; } s7r.reg4828=(uint8)(quotient&0x000000FF); s7r.reg4829=(uint8)((quotient&0x0000FF00)>>8); s7r.reg482A=(uint8)((quotient&0x00FF0000)>>16); s7r.reg482B=(uint8)((quotient&0xFF000000)>>24); s7r.reg482C=(uint8)remainder&0x00FF; s7r.reg482D=(uint8)((remainder&0xFF00)>>8); } s7r.reg482F=0x80; break; //result registers are possibly read-only //reset: writes here nuke the whole math unit //Zero indicates unsigned math, resets with non-zero values turn on signed math case 0x482E: s7r.reg4820=s7r.reg4821=s7r.reg4822=s7r.reg4823=s7r.reg4824=s7r.reg4825=s7r.reg4826=s7r.reg4827=s7r.reg4828=s7r.reg4829=s7r.reg482A=s7r.reg482B=s7r.reg482C=s7r.reg482D=0; s7r.reg482E=data; break; //math status register possibly read only //SRAM toggle case 0x4830: Memory.SPC7110Sram(data); s7r.reg4830=data; break; //Bank DX mapping case 0x4831: s7r.reg4831=data; break; //Bank EX mapping case 0x4832: s7r.reg4832=data; break; //Bank FX mapping case 0x4833: s7r.reg4833=data; break; //S-RAM mapping? who knows? case 0x4834: s7r.reg4834=data; break; //RTC Toggle case 0x4840: if(0==data) { S9xUpdateRTC(); // rtc_f9.init=false; // rtc_f9.index=-1; } if(data&0x01) { s7r.reg4842=0x80; //rtc_f9.last_used=time(NULL);//???? rtc_f9.init=false; rtc_f9.index=-1; } s7r.reg4840=data; break; //RTC init/command/index register case 0x4841: if(rtc_f9.init) { if(-1==rtc_f9.index) { rtc_f9.index=data&0x0F; break; } if(rtc_f9.control==0x0C) { rtc_f9.index=data&0x0F; s7r.reg4842=0x80; rtc_f9.last_used=time(NULL); } else { if(0x0D==rtc_f9.index) { if(data&0x08) { if(rtc_f9.reg[1]<3) { S9xUpdateRTC(); rtc_f9.reg[0]=0; rtc_f9.reg[1]=0; rtc_f9.last_used=time(NULL); } else { S9xUpdateRTC(); rtc_f9.reg[0]=0; rtc_f9.reg[1]=0; rtc_f9.last_used=time(NULL)-60; S9xUpdateRTC(); rtc_f9.last_used=time(NULL); } data&=0x07; } if(rtc_f9.reg[0x0D]&0x01) { if(!(data%2)) { rtc_f9.reg[rtc_f9.index&0x0F]=data; rtc_f9.last_used=time(NULL)-1; S9xUpdateRTC(); rtc_f9.last_used=time(NULL); } } } if(0x0F==rtc_f9.index) { if(data&0x01&&!(rtc_f9.reg[0x0F]&0x01)) { S9xUpdateRTC(); rtc_f9.reg[0]=0; rtc_f9.reg[1]=0; rtc_f9.last_used=time(NULL); } if(data&0x02&&!(rtc_f9.reg[0x0F]&0x02)) { S9xUpdateRTC(); rtc_f9.last_used=time(NULL); } } rtc_f9.reg[rtc_f9.index&0x0F]=data; s7r.reg4842=0x80; rtc_f9.index=(rtc_f9.index+1)%0x10; } } else { if(data==0x03||data==0x0C) { rtc_f9.init=true; rtc_f9.control=data; rtc_f9.index=-1; } } break; //writes to RTC status register aren't expected to be meaningful default: Address-=0x4800; break; //16 BIT MULTIPLIER: ($FF00) high byte, defval:00 }}extern "C"{//emulate the SPC7110's ability to remap banks Dx, Ex, and Fx.uint8 S9xGetSPC7110Byte(uint32 Address){ uint32 i; switch((Address&0x00F00000)>>16) { case 0xD0: i=s7r.reg4831*0x00100000; break; case 0xE0: i=s7r.reg4832*0x00100000; break; case 0xF0: i=s7r.reg4833*0x00100000; break; default:i=0; } i+=Address&0x000FFFFF; i+=s7r.DataRomOffset; return ROM[i];}}/**********************************************************************************************//* S9xSRTCDaysInMonth() *//* Return the number of days in a specific month for a certain year *//* copied directly for RTC functionality, separated in case of incompatibilities *//**********************************************************************************************/int S9xRTCDaysInMonth( int month, int year ){ int mdays; switch ( month ) { case 2: if ( ( year % 4 == 0 ) ) // DKJM2 only uses 199x - 22xx mdays = 29; else mdays = 28; break; case 4: case 6: case 9: case 11: mdays = 30; break; default: // months 1,3,5,7,8,10,12 mdays = 31; break; } return mdays;}#define DAYTICKS (60*60*24)#define HOURTICKS (60*60)#define MINUTETICKS 60/**********************************************************************************************//* S9xUpdateRTC() *//* Advance the RTC time *//**********************************************************************************************/void S9xUpdateRTC (){ time_t cur_systime; long time_diff; // Keep track of game time by computing the number of seconds that pass on the system // clock and adding the same number of seconds to the RTC clock structure. if (rtc_f9.init && 0==(rtc_f9.reg[0x0D]&0x01) && 0==(rtc_f9.reg[0x0F]&0x03)) { cur_systime = time (NULL); // This method assumes one time_t clock tick is one second // which should work on PCs and GNU systems. // If your tick interval is different adjust the // DAYTICK, HOURTICK, and MINUTETICK defines time_diff = (long) (cur_systime - rtc_f9.last_used); rtc_f9.last_used = cur_systime; if ( time_diff > 0 ) { int seconds; int minutes; int hours; int days; int month; int year; int temp_days; int year_hundreds; int year_tens; int year_ones; if ( time_diff > DAYTICKS ) { days = time_diff / DAYTICKS; time_diff = time_diff - days * DAYTICKS; } else { days = 0; } if ( time_diff > HOURTICKS ) { hours = time_diff / HOURTICKS; time_diff = time_diff - hours * HOURTICKS; } else { hours = 0; } if ( time_diff > MINUTETICKS ) { minutes = time_diff / MINUTETICKS; time_diff = time_diff - minutes * MINUTETICKS; } else { minutes = 0; } if ( time_diff > 0 ) { seconds = time_diff; } else { seconds = 0; } seconds += (rtc_f9.reg[1]*10 + rtc_f9.reg[0]); if ( seconds >= 60 ) { seconds -= 60; minutes += 1; } minutes += (rtc_f9.reg[3]*10 + rtc_f9.reg[2]); if ( minutes >= 60 ) { minutes -= 60; hours += 1; } hours += (rtc_f9.reg[5]*10 + rtc_f9.reg[4]); if ( hours >= 24 ) { hours -= 24; days += 1; } year = rtc_f9.reg[11]*10 + rtc_f9.reg[10]; year += ( 1900 ); month = rtc_f9.reg[8]+10*rtc_f9.reg[9]; rtc_f9.reg[12]+=days; days += (rtc_f9.reg[7]*10 + rtc_f9.reg[6]); if ( days > 0 ) { while ( days > (temp_days = S9xRTCDaysInMonth( month, year )) ) { days -= temp_days; month += 1; if ( month > 12 ) { year += 1; month = 1; } } } year_tens = year % 100; year_ones = year_tens % 10; year_tens /= 10; year_hundreds = (year - 1000) / 100; rtc_f9.reg[0] = seconds % 10; rtc_f9.reg[1] = seconds / 10; rtc_f9.reg[2] = minutes % 10; rtc_f9.reg[3] = minutes / 10; rtc_f9.reg[4] = hours % 10; rtc_f9.reg[5] = hours / 10; rtc_f9.reg[6] = days % 10; rtc_f9.reg[7] = days / 10; rtc_f9.reg[8] = month%10; rtc_f9.reg[9] = month /10; rtc_f9.reg[10] = year_ones; rtc_f9.reg[11] = year_tens; rtc_f9.reg[12] %= 7; return; } }}extern "C"{//allows DMA from the ROM (is this even possible on the SPC7110?uint8* Get7110BasePtr(uint32 Address){ uint32 i; switch((Address&0x00F00000)>>16) { case 0xD0: i=s7r.reg4831*0x100000; break; case 0xE0: i=s7r.reg4832*0x100000; break; case 0xF0: i=s7r.reg4833*0x100000; break; default:i=0; } i+=Address&0x000F0000; return &ROM[i];}//end extern}//loads the index into memory.//index.bin is little-endian//format index (1)-table(3)-file offset(4)-length(4)bool Load7110Index(char* filename){ FILE* fp; uint8 buffer[12]; int table=0; uint8 index=0; uint32 offset=0; uint32 size=0; int i=0; fp=fopen(filename, "rb"); if(NULL==fp) return false; do { i=0; fread(buffer, 1, 12,fp); table=(buffer[3]<<16)|(buffer[2]<<8)|buffer[1]; index=buffer[0]; offset=(buffer[7]<<24)|(buffer[6]<<16)|(buffer[5]<<8)|buffer[4]; size=(buffer[11]<<24)|(buffer[10]<<16)|(buffer[9]<<8)|buffer[8]; while(i<MAX_TABLES&&decompack->tableEnts[i].table!=table&&decompack->tableEnts[i].table!=0) i++; if(i==MAX_TABLES) return false; //added decompack->tableEnts[i].table=table; //----- decompack->tableEnts[i].location[index].offset=offset; decompack->tableEnts[i].location[index].size=size; decompack->tableEnts[i].location[index].used_len=0; decompack->tableEnts[i].location[index].used_offset=0; } while(!feof(fp)); fclose(fp); return true;}//Cache 1 load functionvoid SPC7110Load(char* dirname){ char temp_path[PATH_MAX]; int i=0; decompack=new Pack7110;#ifndef _XBOX getcwd(temp_path,PATH_MAX);#endif ZeroMemory(decompack, sizeof(Pack7110)); #ifndef _XBOX if(-1==chdir(dirname)) { S9xMessage(0,0,"Graphics Pack not found!"); }#endif#ifndef _XBOX Load7110Index("index.bin");#else // D:\\ is always app.path in Xbox Load7110Index("d:\\index.bin");#endif for(i=0;i<MAX_TABLES;i++) { if(decompack->tableEnts[i].table!=0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -