int main(void) { unsigned char key; Sys_Clock_Init(); SysTick_Configuration();//Sys定时器 USART_Configuration(); //配置串口 NVIC_Configuration(); //中断配置 // sys_power_on();//开启系统电源 LED_Init(); //指示灯 // KEY_Init(); //按键 USART1_Puts("this is a uart test!\n"); CheckRTC(); //2.RTC LED2_OFF(); while (1) { LED1_OFF();delay_nms(3000); LED1_ON(); delay_nms(100); key=KEY_Scan(); if(key==1) {LED2_ON(); } // // if(mode==0) //显示时间 // { if(RTC_1S==TRUE) { RTC_1S=FALSE; UpdateRTC(); } // } } }
// returns true if the ROM was loaded OK bool LoadCart(LPGBCART Cart, LPCTSTR RomFileName, LPCTSTR RamFileName, LPCTSTR TdfFileName) { HANDLE hTemp; DWORD dwFilesize; DWORD NumQuarterBlocks = 0; UnloadCart(Cart); // first, make sure any previous carts have been unloaded Cart->iCurrentRamBankNo = 0; Cart->iCurrentRomBankNo = 1; Cart->bRamEnableState = 0; Cart->bMBC1RAMbanking = 0; // Attempt to load the ROM file. hTemp = CreateFile(RomFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (hTemp != INVALID_HANDLE_VALUE && (Cart->hRomFile = CreateFileMapping(hTemp, NULL, PAGE_READONLY, 0, 0, NULL) ) ) { // if the first case fails, the file doesn't exist. The second case can fail if the file size is zero. dwFilesize = GetFileSize(hTemp, NULL); CloseHandle(hTemp); Cart->RomData = (LPCBYTE)MapViewOfFile( Cart->hRomFile, FILE_MAP_READ, 0, 0, 0 ); } else { DebugWriteA("Couldn't load the ROM file, GetLastError returned %08x\n", GetLastError()); if (hTemp != INVALID_HANDLE_VALUE) CloseHandle(hTemp); // if file size was zero, make sure we don't leak the handle ErrorMessage(IDS_ERR_GBROM, 0, false); return false; } if (dwFilesize < 0x8000) // a Rom file has to be at least 32kb { DebugWriteA("ROM file wasn't big enough to be a GB ROM!\n"); ErrorMessage(IDS_ERR_GBROM, 0, false); UnloadCart(Cart); return false; } DebugWriteA(" Cartridge Type #:"); DebugWriteByteA(Cart->RomData[0x147]); DebugWriteA("\n"); switch (Cart->RomData[0x147]) { // if we hadn't checked the file size before, this might have caused an access violation case 0x00: Cart->iCartType = GB_NORM; Cart->bHasRam = false; Cart->bHasBattery = false; Cart->bHasTimer = false; Cart->bHasRumble = false; break; case 0x01: Cart->iCartType = GB_MBC1; Cart->bHasRam = false; Cart->bHasBattery = false; Cart->bHasTimer = false; Cart->bHasRumble = false; break; case 0x02: Cart->iCartType = GB_MBC1; Cart->bHasRam = true; Cart->bHasBattery = false; Cart->bHasTimer = false; Cart->bHasRumble = false; break; case 0x03: Cart->iCartType = GB_MBC1; Cart->bHasRam = true; Cart->bHasBattery = true; Cart->bHasTimer = false; Cart->bHasRumble = false; break; case 0x05: Cart->iCartType = GB_MBC2; Cart->bHasRam = false; Cart->bHasBattery = false; Cart->bHasTimer = false; Cart->bHasRumble = false; break; case 0x06: Cart->iCartType = GB_MBC2; Cart->bHasRam = false; Cart->bHasBattery = true; Cart->bHasTimer = false; Cart->bHasRumble = false; break; case 0x08: Cart->iCartType = GB_NORM; Cart->bHasRam = true; Cart->bHasBattery = false; Cart->bHasTimer = false; Cart->bHasRumble = false; break; case 0x09: Cart->iCartType = GB_NORM; Cart->bHasRam = true; Cart->bHasBattery = true; Cart->bHasTimer = false; Cart->bHasRumble = false; break; case 0x0B: Cart->iCartType = GB_MMMO1; Cart->bHasRam = false; Cart->bHasBattery = false; Cart->bHasTimer = false; Cart->bHasRumble = false; break; case 0x0C: Cart->iCartType = GB_MMMO1; Cart->bHasRam = true; Cart->bHasBattery = false; Cart->bHasTimer = false; Cart->bHasRumble = false; break; case 0x0D: Cart->iCartType = GB_MMMO1; Cart->bHasRam = true; Cart->bHasBattery = true; Cart->bHasTimer = false; Cart->bHasRumble = false; break; case 0x0F: Cart->iCartType = GB_MBC3; Cart->bHasRam = false; Cart->bHasBattery = true; Cart->bHasTimer = true; Cart->bHasRumble = false; break; case 0x10: Cart->iCartType = GB_MBC3; Cart->bHasRam = true; Cart->bHasBattery = true; Cart->bHasTimer = true; Cart->bHasRumble = false; break; case 0x11: Cart->iCartType = GB_MBC3; Cart->bHasRam = false; Cart->bHasBattery = false; Cart->bHasTimer = false; Cart->bHasRumble = false; break; case 0x12: Cart->iCartType = GB_MBC3; Cart->bHasRam = true; Cart->bHasBattery = true; Cart->bHasTimer = false; Cart->bHasRumble = false; break; case 0x13: Cart->iCartType = GB_MBC3; Cart->bHasRam = true; Cart->bHasBattery = true; Cart->bHasTimer = false; Cart->bHasRumble = false; break; case 0x19: Cart->iCartType = GB_MBC5; Cart->bHasRam = false; Cart->bHasBattery = false; Cart->bHasTimer = false; Cart->bHasRumble = false; break; case 0x1A: Cart->iCartType = GB_MBC5; Cart->bHasRam = true; Cart->bHasBattery = false; Cart->bHasTimer = false; Cart->bHasRumble = false; break; case 0x1B: Cart->iCartType = GB_MBC5; Cart->bHasRam = true; Cart->bHasBattery = true; Cart->bHasTimer = false; Cart->bHasRumble = false; break; case 0x1C: Cart->iCartType = GB_MBC5; Cart->bHasRam = false; Cart->bHasBattery = false; Cart->bHasTimer = false; Cart->bHasRumble = true; break; case 0x1D: Cart->iCartType = GB_MBC5; Cart->bHasRam = true; Cart->bHasBattery = false; Cart->bHasTimer = false; Cart->bHasRumble = true; break; case 0x1E: Cart->iCartType = GB_MBC5; Cart->bHasRam = true; Cart->bHasBattery = true; Cart->bHasTimer = false; Cart->bHasRumble = true; break; default: WarningMessage( IDS_ERR_GBROM, MB_OK | MB_ICONWARNING); DebugWriteA("TPak: unsupported paktype\n"); UnloadCart(Cart); return false; } // assign read/write handlers switch (Cart->iCartType) { case GB_NORM: // Raw cartridge Cart->ptrfnReadCart = &ReadCartNorm; Cart->ptrfnWriteCart = &WriteCartNorm; break; case GB_MBC1: Cart->ptrfnReadCart = &ReadCartMBC1; Cart->ptrfnWriteCart = &WriteCartMBC1; break; case GB_MBC2: Cart->ptrfnReadCart = &ReadCartMBC2; Cart->ptrfnWriteCart = &WriteCartMBC2; break; case GB_MBC3: Cart->ptrfnReadCart = &ReadCartMBC3; Cart->ptrfnWriteCart = &WriteCartMBC3; break; case GB_MBC5: Cart->ptrfnReadCart = &ReadCartMBC5; Cart->ptrfnWriteCart = &WriteCartMBC5; break; default: // Don't pretend we know how to handle carts we don't support Cart->ptrfnReadCart = NULL; Cart->ptrfnWriteCart = NULL; DebugWriteA("Unsupported paktype: can't read/write cart type %02X\n", Cart->iCartType); UnloadCart(Cart); return false; } // Determine ROM size for paging checks Cart->iNumRomBanks = 2; switch (Cart->RomData[0x148]) { case 0x01: Cart->iNumRomBanks = 4; break; case 0x02: Cart->iNumRomBanks = 8; break; case 0x03: Cart->iNumRomBanks = 16; break; case 0x04: Cart->iNumRomBanks = 32; break; case 0x05: Cart->iNumRomBanks = 64; break; case 0x06: Cart->iNumRomBanks = 128; break; case 0x52: Cart->iNumRomBanks = 72; break; case 0x53: Cart->iNumRomBanks = 80; break; case 0x54: Cart->iNumRomBanks = 96; break; } if (dwFilesize != 0x4000 * Cart->iNumRomBanks) // Now that we know how big the ROM is supposed to be, check it again { ErrorMessage(IDS_ERR_GBROM, 0, false); UnloadCart(Cart); return false; } // Determine RAM size for paging checks Cart->iNumRamBanks = 0; switch (Cart->RomData[0x149]) { case 0x01: Cart->iNumRamBanks = 1; NumQuarterBlocks = 1; break; case 0x02: Cart->iNumRamBanks = 1; NumQuarterBlocks = 4; break; case 0x03: Cart->iNumRamBanks = 4; NumQuarterBlocks = 16; break; case 0x04: Cart->iNumRamBanks = 16; NumQuarterBlocks = 64; break; case 0x05: Cart->iNumRamBanks = 8; NumQuarterBlocks = 32; break; } DebugWriteA("GB cart has %d ROM banks, %d RAM quarter banks\n", Cart->iNumRomBanks, NumQuarterBlocks); if (Cart->bHasTimer) { DebugWriteA("GB cart timer present\n"); } // Attempt to load the SRAM file, but only if RAM is supposed to be present. // For saving back to a file, if we map too much it will expand the file. if (Cart->bHasRam) { if (Cart->bHasBattery) { hTemp = CreateFile( RamFileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, NULL ); if( hTemp == INVALID_HANDLE_VALUE ) {// test if Read-only access is possible hTemp = CreateFile( RamFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, NULL ); if (Cart->bHasTimer && Cart->bHasBattery) { Cart->RamData = (LPBYTE)P_malloc(NumQuarterBlocks * 0x0800 + sizeof(gbCartRTC)); ClearData(Cart->RamData, NumQuarterBlocks * 0x0800 + sizeof(gbCartRTC)); } else { Cart->RamData = (LPBYTE)P_malloc(NumQuarterBlocks * 0x0800); ClearData(Cart->RamData, NumQuarterBlocks * 0x0800); } if( hTemp != INVALID_HANDLE_VALUE ) { DWORD dwBytesRead; if (Cart->bHasTimer && Cart->bHasBattery) ReadFile(hTemp, Cart->RamData, NumQuarterBlocks * 0x0800 + sizeof(gbCartRTC), &dwBytesRead, NULL); else ReadFile(hTemp, Cart->RamData, NumQuarterBlocks * 0x0800, &dwBytesRead, NULL); WarningMessage( IDS_DLG_TPAK_READONLY, MB_OK | MB_ICONWARNING); } else { WarningMessage( IDS_ERR_GBSRAMERR, MB_OK | MB_ICONWARNING); return true; } } else { // file is OK, use a mapping if (Cart->bHasTimer && Cart->bHasBattery) Cart->hRamFile = CreateFileMapping( hTemp, NULL, PAGE_READWRITE, 0, NumQuarterBlocks * 0x0800 + sizeof(gbCartRTC), NULL); else Cart->hRamFile = CreateFileMapping( hTemp, NULL, PAGE_READWRITE, 0, NumQuarterBlocks * 0x0800, NULL); if (Cart->hRamFile != NULL) { Cart->RamData = (LPBYTE)MapViewOfFile( Cart->hRamFile, FILE_MAP_ALL_ACCESS, 0, 0, 0 ); } else { // could happen, if the file isn't big enough AND can't be grown to fit DWORD dwBytesRead; if (Cart->bHasTimer && Cart->bHasBattery) { Cart->RamData = (LPBYTE)P_malloc(NumQuarterBlocks * 0x0800 + sizeof(gbCartRTC)); ReadFile(hTemp, Cart->RamData, NumQuarterBlocks * 0x0800 + sizeof(gbCartRTC), &dwBytesRead, NULL); } else { Cart->RamData = (LPBYTE)P_malloc(NumQuarterBlocks * 0x0800); ReadFile(hTemp, Cart->RamData, NumQuarterBlocks * 0x0800, &dwBytesRead, NULL); } if (dwBytesRead < NumQuarterBlocks * 0x0800 + ((Cart->bHasTimer && Cart->bHasBattery) ? sizeof(gbCartRTC) : 0)) { ClearData(Cart->RamData, NumQuarterBlocks * 0x0800 + ((Cart->bHasTimer && Cart->bHasBattery) ? sizeof(gbCartRTC) : 0)); WarningMessage( IDS_ERR_GBSRAMERR, MB_OK | MB_ICONWARNING); } else { WarningMessage( IDS_DLG_TPAK_READONLY, MB_OK | MB_ICONWARNING); } } } if (Cart->bHasTimer && Cart->bHasBattery) { dwFilesize = GetFileSize(hTemp, 0); if (dwFilesize >= (NumQuarterBlocks * 0x0800 + sizeof(gbCartRTC) ) ) { // Looks like there is extra data in the SAV file than just RAM data... assume it is RTC data. gbCartRTC RTCTimer; CopyMemory( &RTCTimer, &Cart->RamData[NumQuarterBlocks * 0x0800], sizeof(RTCTimer) ); Cart->TimerData[0] = (BYTE)RTCTimer.mapperSeconds; Cart->TimerData[1] = (BYTE)RTCTimer.mapperMinutes; Cart->TimerData[2] = (BYTE)RTCTimer.mapperHours; Cart->TimerData[3] = (BYTE)RTCTimer.mapperDays; Cart->TimerData[4] = (BYTE)RTCTimer.mapperControl; Cart->LatchedTimerData[0] = (BYTE)RTCTimer.mapperLSeconds; Cart->LatchedTimerData[1] = (BYTE)RTCTimer.mapperLMinutes; Cart->LatchedTimerData[2] = (BYTE)RTCTimer.mapperLHours; Cart->LatchedTimerData[3] = (BYTE)RTCTimer.mapperLDays; Cart->LatchedTimerData[4] = (BYTE)RTCTimer.mapperLControl; Cart->timerLastUpdate = RTCTimer.mapperLastTime; UpdateRTC(Cart); } else { ReadTDF(Cart); // try to open TDF format, clear/init Cart->TimerData if that fails } } CloseHandle(hTemp); } else { // no battery; just allocate some RAM Cart->RamData = (LPBYTE)P_malloc(Cart->iNumRamBanks * 0x2000); } } Cart->TimerDataLatched = false; return true; }
void MBC3MemoryRule::PerformWrite(u16 address, u8 value) { switch (address & 0xE000) { case 0x0000: { if (m_pCartridge->GetRAMSize() > 0) m_bRamEnabled = (value & 0x0F) == 0x0A; m_bRTCEnabled = (value & 0x0F) == 0x0A; break; } case 0x2000: { m_iCurrentROMBank = value & 0x7F; if (m_iCurrentROMBank == 0) m_iCurrentROMBank = 1; m_iCurrentROMBank &= (m_pCartridge->GetROMBankCount() - 1); m_CurrentROMAddress = m_iCurrentROMBank * 0x4000; break; } case 0x4000: { if ((value >= 0x08) && (value <= 0x0C)) { // RTC if (m_pCartridge->IsRTCPresent() && m_bRTCEnabled) { m_RTCRegister = value; m_iCurrentRAMBank = -1; } else { Log("--> ** Attempting to select RTC register when RTC is disabled or not present %X %X", address, value); } } else if (value <= 0x03) { m_iCurrentRAMBank = value; m_iCurrentRAMBank &= (m_pCartridge->GetRAMBankCount() - 1); m_CurrentRAMAddress = m_iCurrentRAMBank * 0x2000; } else { Log("--> ** Attempting to select unkwon register %X %X", address, value); } break; } case 0x6000: { if (m_pCartridge->IsRTCPresent()) { // RTC Latch if ((m_iRTCLatch == 0x00) && (value == 0x01)) { UpdateRTC(); m_iRTCLatchedSeconds = m_iRTCSeconds; m_iRTCLatchedMinutes = m_iRTCMinutes; m_iRTCLatchedHours = m_iRTCHours; m_iRTCLatchedDays = m_iRTCDays; m_iRTCLatchedControl = m_iRTCControl; } if ((value == 0x00) || (value == 0x01)) { m_iRTCLatch = value; } } break; } case 0xA000: { if (m_iCurrentRAMBank >= 0) { if (m_bRamEnabled) { m_pRAMBanks[(address - 0xA000) + m_CurrentRAMAddress] = value; } else { Log("--> ** Attempting to write on RAM when ram is disabled %X %X", address, value); } } else if (m_pCartridge->IsRTCPresent() && m_bRTCEnabled) { m_RTCLastTime = m_pCartridge->GetCurrentRTC(); switch (m_RTCRegister) { case 0x08: m_iRTCSeconds = value; break; case 0x09: m_iRTCMinutes = value; break; case 0x0A: m_iRTCHours = value; break; case 0x0B: m_iRTCDays = value; break; case 0x0C: if (m_iRTCControl & 0x80) m_iRTCControl = 0x80 | value; else m_iRTCControl = value; break; } } else { Log("--> ** Attempting to write on RTC when RTC is disabled or not present %X %X", address, value); } break; } default: { m_pMemory->Load(address, value); break; } } }
__interrupt void RTCinterrupt(void) { UpdateRTC(); // if (IsCommandEmpty() != 0) LPM1_EXIT; //sorry, this code has to write here... }