void Service_Send(unsigned char* rssi_table) { char buffer[68]; static uint8_t rssi_index = 0; uint16_t crc; uint8_t len; static unsigned long last_pack_time = 0; //paczka z danymi RSSI (kazda paczka wysylana jest co 50ms) if ((millis()-last_pack_time>50)&&(UART0_wyslano)) { memset(UART0_SendBuffer,0,sizeof(UART0_SendBuffer)); UART0_SendBuffer[0]=UART_CMD_RSSI; buffer[0]=rssi_index; memcpy(buffer+1,rssi_table+(rssi_index*64),64); crc = GetCRC(buffer, 65); memcpy(buffer+65,&crc,2); base64_encode((unsigned char*)buffer, 67, (unsigned char*)UART0_SendBuffer+1); len = strlen((char *)UART0_SendBuffer); UART0_SendBuffer[len] = UART_EOT; UART0_wyslano = 0; UDR0 = UART0_SendBuffer[0]; last_pack_time = millis(); } }
//--------------------------------------------------------------------------- USHORT __fastcall GetCRC(WIN32_FIND_DATA *fp) { USHORT d = GetCRC(fp->cFileName); d = AddCRC(d, (const BYTE *)&fp->ftLastWriteTime, sizeof(FILETIME)); d = AddCRC(d, (const BYTE *)&fp->nFileSizeLow, sizeof(DWORD)); if( !d ) d++; return d; }
void Service_ReadEEPROMData(uint8_t command_type, uint8_t command_size, char *command) { char buffer[101]; char buffer_coded[101]; int16_t crc; int16_t crc_data; uint16_t offset = (command[1]<<8) + command[0]; //odczyt offsetu uint8_t len = command[2]; //odczyt dlugosci if (len>100) len = 100; crc = GetCRC(command,command_size-2); //wygenerowanie CRC crc_data = (command[command_size-1]<<8) + command[command_size-2]; //odczyt CRC if (crc!=crc_data) { Service_send_ERROR("CRC Error"); return; } //odczyt paczki z eepromu GetBlockEE((char *)(buffer+2), offset,len); buffer[0] = command[0]; //offset (ten sam, ktory przyszedl w zadaniu) buffer[1] = command[1]; //obliczanie crc crc = GetCRC(buffer,len+2); memcpy(buffer+len+2,&crc,2); //zakodowanie informacji base64_encode((unsigned char*)buffer, len+4, (unsigned char*)buffer_coded); len = strlen((char *)buffer_coded); //odeslanie paczki przez uart USART_Transmit(UART_CMD_EEPROM_DATA); //przesylamy dane for (int i=0;i<len;i++) USART_Transmit(buffer_coded[i]); USART_Transmit(UART_EOT); }
//====================================================================== // 函 数 名: COMFrmVrify // 功能描述: 接受帧校验 // 输入参数: 待校验的数组首地址,长度 // 输出参数: 1为校验正确,0校验失败 // 创建日期: 2007.6.18 // 修改日期: 2008.3.5 // 作 者: john // 修 改 者: hfl // 附加说明: //====================================================================== u8 COMFrmVrify(u8 *Array, u8 DataCount) { u16 verify,temp; //校验码 CRC校验 verify = GetCRC(Array,DataCount - 2 ) ; temp = Array[DataCount - 1] | (Array[DataCount - 2] << 8); if ( verify == temp ) return 1; else return 0 ; }
//====================================================================== // 函 数 名: UartSlaveDataHandle // 功能描述: 串口主机接受帧函数 // 输入参数: void // 输出参数: void // 创建日期: 2007.6.18 // 修改日期: 2008.3.5 // 作 者: john // 修 改 者: hfl // 附加说明: 通过全局指针交换数据 //====================================================================== void UartRecvDataHandle() //标准MOD-BUD { u16 usTemp ; u16 tmp ; tmp = pComInBuf[3] + (pComInBuf[2]<< 8) ; //内存地址 //根据接收帧构造发送帧并启动发送 pComOutBuf[0]=pComInBuf[0] ; //sensor_id pComOutBuf[1]=pComInBuf[1] ; if ( pComInBuf[1] == 0x03 ) // 上位机发的读数据命令 { usTemp = pComInBuf[5]<<1; //字节个数 pComOutBuf[2] = usTemp; memcpy(pComOutBuf+3, tmp+ CassMem ,usTemp ) ; ComOutDataLen =usTemp + 5 ; } else if (pComInBuf[1] == 0x06) //写命令 { //usTemp = pComInBuf[5]<<1; //字节个数 memcpy(tmp+ CassMem, pComInBuf+ 4, 2) ; //数据拷贝到内存区 memcpy(pComOutBuf,pComInBuf,8) ; ComOutDataLen = 8 ; } else if ( pComInBuf[1] == 0x10 ) { usTemp = pComInBuf[6];//字节个数 memcpy(tmp+ CassMem, pComInBuf+ 7, usTemp ) ; //数据拷贝到内存区 memcpy(pComOutBuf,pComInBuf,6) ; ComOutDataLen = 8 ; } else if ( pComInBuf[1] == 0x20 ) { if(tmp > BMP_IMAGE_SIZE/UART_SND_BLK_DATA_SIZE) return; if(tmp == 0) update_outbuf_flag = 0; memcpy((u8 *)&usTemp, (u8 *)(out_data+tmp*UART_SND_BLK_SIZE+4),2); usTemp+=8; memcpy(pComOutBuf, (u8 *)(out_data+tmp*UART_SND_BLK_SIZE), usTemp); if(usTemp != UART_SND_BLK_SIZE) update_outbuf_flag = 1; ComOutDataLen = usTemp; return; } usTemp = GetCRC(pComOutBuf,ComOutDataLen - 2 ) ; pComOutBuf[ComOutDataLen - 1] = usTemp ; //返回帧尾 pComOutBuf[ComOutDataLen - 2] = usTemp >> 8 ; }
//====================================================================== // 函 数 名: UartSlaveDataHandle // 功能描述: 串口主机接受帧函数 // 输入参数: void // 输出参数: void // 创建日期: 2007.6.18 // 修改日期: 2008.3.5 // 作 者: john // 修 改 者: hfl // 附加说明: 通过全局指针交换数据 //====================================================================== void UartRecvDataHandle() //标准MOD-BUD { u16 usTemp ; u16 tmp ; tmp = pComInBuf[3] + (pComInBuf[2]<< 8) ; //内存地址 pComOutBuf[0] = pComInBuf[0] ; pComOutBuf[1] = pComInBuf[1] ; //根据接收帧构造发送帧并启动发送 if ( pComInBuf[1] == 0x03 ) // 上位机发的读数据命令 { usTemp = pComInBuf[5]<<1; //字节个数 pComOutBuf[2] = usTemp ; memcpy( pComOutBuf+3, tmp+ CassMem ,usTemp ) ; ComOutDataLen =usTemp + 5 ; } else if (pComInBuf[1] == 0x06) //写命令 { //usTemp = pComInBuf[5]<<1; //字节个数 memcpy(tmp+ CassMem, pComInBuf+ 4, 2) ; //数据拷贝到内存区 memcpy(pComOutBuf,pComInBuf,8) ; ComOutDataLen = 8 ; } else if ( pComInBuf[1] == 0x10 ) { usTemp = pComInBuf[6];//字节个数 memcpy(tmp+ CassMem, pComInBuf+ 7, usTemp ) ; //数据拷贝到内存区 memcpy(pComOutBuf,pComInBuf,6) ; ComOutDataLen = 8 ; } else if ( pComInBuf[1] == 0x20 ) { pComOutBuf[2] = cass_mv_boarder_width%255; //weight pComOutBuf[3] = cass_mv_boarder_width/255; //weight pComOutBuf[4] = cass_mv_boarder_height%255; //height pComOutBuf[5] = cass_mv_boarder_height/255; //height memcpy(pComOutBuf+6, out_data , cass_mv_boarder_width * cass_mv_boarder_height) ; ComOutDataLen =cass_mv_boarder_width*cass_mv_boarder_height+6; return; } usTemp = GetCRC(pComOutBuf,ComOutDataLen - 2 ) ; pComOutBuf[ComOutDataLen - 1] = usTemp ; //返回帧尾 pComOutBuf[ComOutDataLen - 2] = usTemp >> 8 ; }
void Service_SaveEEPROMData(uint8_t command_type, uint8_t command_size, char *command) { int16_t crc = GetCRC(command,command_size-2); int16_t offset = (command[1]<<8) + command[0]; //odczyt offsetu int16_t crc_data = (command[command_size-1]<<8) + command[command_size-2]; // CRC danych przychodzacych if (crc_data!=crc) { Service_send_ERROR("CRC Error"); return; } //przepisanie danych z paczki do EEPROM'u SetBlockEE((char *)(command+2), offset,command_size-4); Service_send_OK(); }
void CArchiveScanner::ScanArchive(const std::string& fullName, bool doChecksum) { struct stat info; stat(fullName.c_str(), &info); const std::string fn = filesystem.GetFilename(fullName); const std::string fpath = filesystem.GetDirectory(fullName); const std::string lcfn = StringToLower(fn); //! Determine whether this archive has earlier be found to be broken std::map<std::string, BrokenArchive>::iterator bai = brokenArchives.find(lcfn); if (bai != brokenArchives.end()) { if ((unsigned)info.st_mtime == bai->second.modified && fpath == bai->second.path) { bai->second.updated = true; return; } } //! Determine whether to rely on the cached info or not bool cached = false; std::map<std::string, ArchiveInfo>::iterator aii = archiveInfo.find(lcfn); if (aii != archiveInfo.end()) { //! This archive may have been obsoleted, do not process it if so if (aii->second.replaced.length() > 0) { return; } if ((unsigned)info.st_mtime == aii->second.modified && fpath == aii->second.path) { cached = true; aii->second.updated = true; } //! If we are here, we could have invalid info in the cache //! Force a reread if it's a directory archive, as st_mtime only //! reflects changes to the directory itself, not the contents. if (!cached) { archiveInfo.erase(aii); } } //! Time to parse the info we are interested in if (cached) { //! If cached is true, aii will point to the archive if (doChecksum && (aii->second.checksum == 0)) aii->second.checksum = GetCRC(fullName); } else { CArchiveBase* ar = CArchiveFactory::OpenArchive(fullName); if (!ar || !ar->IsOpen()) { logOutput.Print("Unable to open archive: %s", fullName.c_str()); return; } ArchiveInfo ai; std::string error = ""; std::string mapfile; bool hasModinfo = ar->FileExists("modinfo.lua"); bool hasMapinfo = ar->FileExists("mapinfo.lua"); //! check for smf/sm3 and if the uncompression of important files is too costy for (unsigned fid = 0; fid != ar->NumFiles(); ++fid) { std::string name; int size; ar->FileInfo(fid, name, size); const std::string lowerName = StringToLower(name); const std::string ext = filesystem.GetExtension(lowerName); if ((ext == "smf") || (ext == "sm3")) { mapfile = name; } const unsigned char metaFileClass = GetMetaFileClass(lowerName); if ((metaFileClass != 0) && !(ar->HasLowReadingCost(fid))) { //! is a meta-file and not cheap to read if (metaFileClass == 1) { //! 1st class error = "Unpacking/reading cost for meta file " + name + " is too high, please repack the archive (make sure to use a non-solid algorithm, if applicable)"; break; } else if (metaFileClass == 2) { //! 2nd class logOutput.Print(LOG_ARCHIVESCANNER, "Warning: Archive %s: The cost for reading a 2nd class meta-file is too high: %s", fullName.c_str(), name.c_str()); } } } if (!error.empty()) { //! we already have an error, no further evaluation required } if (hasMapinfo || !mapfile.empty()) { //! it is a map if (hasMapinfo) { ScanArchiveLua(ar, "mapinfo.lua", ai, error); } else if (hasModinfo) { //! backwards-compat for modinfo.lua in maps ScanArchiveLua(ar, "modinfo.lua", ai, error); } if (ai.archiveData.GetName().empty()) { //! FIXME The name will never be empty, if version is set (see HACK in ArchiveData) ai.archiveData.SetInfoItemValueString("name", filesystem.GetBasename(mapfile)); } if (ai.archiveData.GetMapFile().empty()) { ai.archiveData.SetInfoItemValueString("mapfile", mapfile); } AddDependency(ai.archiveData.GetDependencies(), "Map Helper v1"); ai.archiveData.SetInfoItemValueInteger("modType", modtype::map); logOutput.Print(LOG_ARCHIVESCANNER, "Found new map: %s", ai.archiveData.GetName().c_str()); } else if (hasModinfo) { //! it is a mod ScanArchiveLua(ar, "modinfo.lua", ai, error); if (ai.archiveData.GetModType() == modtype::primary) { AddDependency(ai.archiveData.GetDependencies(), "Spring content v1"); } logOutput.Print(LOG_ARCHIVESCANNER, "Found new game: %s", ai.archiveData.GetName().c_str()); } else { //! neither a map nor a mod: error error = "missing modinfo.lua/mapinfo.lua"; } delete ar; if (!error.empty()) { //! for some reason, the archive is marked as broken logOutput.Print("Failed to scan %s (%s)", fullName.c_str(), error.c_str()); //! record it as broken, so we don't need to look inside everytime BrokenArchive ba; ba.path = fpath; ba.modified = info.st_mtime; ba.updated = true; ba.problem = error; brokenArchives[lcfn] = ba; return; } ai.path = fpath; ai.modified = info.st_mtime; ai.origName = fn; ai.updated = true; //! Optionally calculate a checksum for the file //! To prevent reading all files in all directory (.sdd) archives //! every time this function is called, directory archive checksums //! are calculated on the fly. if (doChecksum) { ai.checksum = GetCRC(fullName); } else { ai.checksum = 0; } archiveInfo[lcfn] = ai; } }
void CArchiveScanner::ScanArchive(const std::string& fullName, bool doChecksum) { struct stat info; stat(fullName.c_str(), &info); const std::string fn = filesystem.GetFilename(fullName); const std::string fpath = filesystem.GetDirectory(fullName); const std::string lcfn = StringToLower(fn); // Determine whether this archive has earlier be found to be broken std::map<std::string, BrokenArchive>::iterator bai = brokenArchives.find(lcfn); if (bai != brokenArchives.end()) { if ((unsigned)info.st_mtime == bai->second.modified && fpath == bai->second.path) { bai->second.updated = true; return; } } // Determine whether to rely on the cached info or not bool cached = false; std::map<std::string, ArchiveInfo>::iterator aii = archiveInfo.find(lcfn); if (aii != archiveInfo.end()) { // This archive may have been obsoleted, do not process it if so if (aii->second.replaced.length() > 0) { return; } if ((unsigned)info.st_mtime == aii->second.modified && fpath == aii->second.path) { cached = true; aii->second.updated = true; } // If we are here, we could have invalid info in the cache // Force a reread if it's a directory archive, as st_mtime only // reflects changes to the directory itself, not the contents. if (!cached) { archiveInfo.erase(aii); } } // Time to parse the info we are interested in if (cached) { // If cached is true, aii will point to the archive if (doChecksum && (aii->second.checksum == 0)) aii->second.checksum = GetCRC(fullName); } else { CArchiveBase* ar = CArchiveFactory::OpenArchive(fullName); if (ar && ar->IsOpen()) { ArchiveInfo ai; std::string mapfile; bool hasModinfo = false; bool hasMapinfo = false; for (unsigned fid = 0; fid != ar->NumFiles(); ++fid) { std::string name; int size; ar->FileInfo(fid, name, size); const std::string lowerName = StringToLower(name); const std::string ext = filesystem.GetExtension(lowerName); if ((ext == "smf") || (ext == "sm3")) { mapfile = name; } else if (lowerName == "modinfo.lua") { hasModinfo = true; } else if (lowerName == "mapinfo.lua") { hasMapinfo = true; } } if (hasMapinfo || !mapfile.empty()) { // it is a map if (hasMapinfo) { ScanArchiveLua(ar, "mapinfo.lua", ai); } else if (hasModinfo) { // backwards-compat for modinfo.lua in maps ScanArchiveLua(ar, "modinfo.lua", ai); } if (ai.archiveData.name.empty()) { ai.archiveData.name = filesystem.GetBasename(mapfile); } if (ai.archiveData.mapfile.empty()) { ai.archiveData.mapfile = mapfile; } AddDependency(ai.archiveData.dependencies, "Map Helper v1"); ai.archiveData.modType = modtype::map; } else if (hasModinfo) { // it is a mod ScanArchiveLua(ar, "modinfo.lua", ai); if (ai.archiveData.modType == modtype::primary) AddDependency(ai.archiveData.dependencies, "Spring content v1"); } else { // neither a map nor a mod: error logOutput.Print(LOG_ARCHIVESCANNER, "Failed to scan %s (missing modinfo.lua/mapinfo.lua)", fullName.c_str()); delete ar; // record it as broken, so we don't need to look inside everytime BrokenArchive ba; ba.path = fpath; ba.modified = info.st_mtime; ba.updated = true; brokenArchives[lcfn] = ba; return; } ai.path = fpath; ai.modified = info.st_mtime; ai.origName = fn; ai.updated = true; delete ar; // Optionally calculate a checksum for the file // To prevent reading all files in all directory (.sdd) archives // every time this function is called, directory archive checksums // are calculated on the fly. if (doChecksum) { ai.checksum = GetCRC(fullName); } else { ai.checksum = 0; } archiveInfo[lcfn] = ai; } else { logOutput.Print(LOG_ARCHIVESCANNER, "Unable to open archive: %s", fullName.c_str()); } } }
void main(void) { uint8_t inputProgramType; char *inputProgram; uint16_t inputProgramSize; ti_var_t programSlot; uint8_t selectedProgram, amountOfPrograms, res = VALID, type; unsigned int programDataSize, offset, totalSize; uint8_t beginList, amountOfProgramsToDisplay; uint8_t relativeSelectedProgram; const char ICEheader[] = {tii, 0}; ti_var_t tempProg; char buf[30], *temp_name = "", var_name[9]; sk_key_t key = 0; void *search_pos; bool didCompile; // Install hooks ti_CloseAll(); if ((tempProg = ti_Open("ICEHOOKS", "r"))) { ti_SetArchiveStatus(true, tempProg); SetHooks(ti_GetDataPtr(tempProg)); } // Enable lowercase asm("ld iy, 0D00080h"); asm("set 3, (iy+024h)"); // check if a program was used as input ti_CloseAll(); ice.usingInputProgram = false; inputProgram = os_RclAns(&inputProgramType); if (inputProgram && inputProgramType == TI_STRING_TYPE && inputProgram[2] == tProg && (inputProgramSize = *(uint16_t*)inputProgram) < 10) { memset(var_name, 0, sizeof var_name); memcpy(var_name, inputProgram + 3, inputProgramSize - 1); programSlot = ti_OpenVar(var_name, "r", TI_PRGM_TYPE); if (programSlot) { ice.usingInputProgram = true; } } // Yay, GUI! :) displayMainScreen: gfx_Begin(); gfx_SetColor(189); gfx_FillRectangle_NoClip(0, 0, 320, 10); gfx_SetColor(0); gfx_SetTextFGColor(0); gfx_HorizLine_NoClip(0, 10, 320); gfx_PrintStringXY(infoStr, 12, 1); // Get all the programs that start with the [i] token selectedProgram = 0; didCompile = false; ti_CloseAll(); if (ice.usingInputProgram) { goto compile_program; } search_pos = NULL; while ((temp_name = ti_DetectAny(&search_pos, ICEheader, &type)) != NULL) { if (type == TI_PRGM_TYPE || type == TI_PPRGM_TYPE) { // Hidden programs if ((uint8_t)(*temp_name) < 64) { *temp_name += 64; } // Save the program name inputPrograms[selectedProgram] = malloc(9); strcpy(inputPrograms[selectedProgram++], temp_name); } if (selectedProgram >= NUMBEROFPROGRAM) { break; } } amountOfPrograms = selectedProgram; beginList = 0; amountOfProgramsToDisplay = (amountOfPrograms > PROGRAMPERSCREEN ? PROGRAMPERSCREEN : amountOfPrograms); // Check if there are ICE programs if (!amountOfPrograms) { gfx_PrintStringXY("No programs found!", 10, 13); goto stop; } // Display all the sorted programs qsort(inputPrograms, amountOfPrograms, sizeof(char *), myCompare); displayProgramList(beginList, amountOfProgramsToDisplay); // Display buttons gfx_PrintStringXY("Build", 4, 232); printButton(1); gfx_PrintStringXY("Debug", 66, 232); printButton(65); gfx_PrintStringXY("Quit", 285, 232); printButton(279); gfx_SetColor(0); // Select a program selectedProgram = 1; relativeSelectedProgram = 1; while ((key = os_GetCSC()) != sk_Enter && key != sk_2nd && key != sk_Yequ && key != sk_Window) { uint8_t selectionOffset = relativeSelectedProgram * 10 + 3; gfx_PrintStringXY(">", 1, selectionOffset); if (key) { gfx_SetColor(255); gfx_FillRectangle_NoClip(1, selectionOffset, 8, 8); // Stop and quit if (key == sk_Clear || key == sk_Graph) { goto err; } // Select the next program if (key == sk_Down) { if (selectedProgram != amountOfPrograms) { selectedProgram++; relativeSelectedProgram++; if (relativeSelectedProgram > PROGRAMPERSCREEN) { clearProgramList(); relativeSelectedProgram--; beginList++; displayProgramList(beginList, amountOfProgramsToDisplay); } } else { clearProgramList(); selectedProgram = 1; relativeSelectedProgram = 1; beginList = 0; displayProgramList(beginList, amountOfProgramsToDisplay); } } // Select the previous program if (key == sk_Up) { if (selectedProgram != 1) { selectedProgram--; relativeSelectedProgram--; if(relativeSelectedProgram == 0) { clearProgramList(); relativeSelectedProgram++; beginList--; displayProgramList(beginList, amountOfProgramsToDisplay); } } else { clearProgramList(); selectedProgram = amountOfPrograms; relativeSelectedProgram = (amountOfPrograms > PROGRAMPERSCREEN ? PROGRAMPERSCREEN : amountOfPrograms); beginList = (selectedProgram >= PROGRAMPERSCREEN ? selectedProgram - PROGRAMPERSCREEN : 0); displayProgramList(beginList, amountOfProgramsToDisplay); } } } } // Set some vars strcpy(var_name, inputPrograms[selectedProgram - 1]); for (selectedProgram = 0; selectedProgram < amountOfPrograms; selectedProgram++) { free(inputPrograms[selectedProgram]); } compile_program: // Erase screen gfx_SetColor(255); gfx_FillRectangle_NoClip(0, 11, 320, 210); gfx_FillRectangle_NoClip(0, 220, 270, 20); didCompile = true; memset(&ice, 0, sizeof ice); memset(&expr, 0, sizeof expr); memset(®, 0, sizeof reg); memset(&prescan, 0, sizeof prescan); memset(&debug, 0, sizeof debug); // Output debug appvar if (key == sk_Window) { ice.debug = true; } gfx_SetTextXY(1, 12); displayMessageLineScroll("Prescanning..."); displayLoadingBarFrame(); ice.inPrgm = _open(var_name); _seek(0, SEEK_END, ice.inPrgm); ice.programLength = _tell(ice.inPrgm); ice.programData = (uint8_t*)0xD52C00; ice.programPtr = ice.programData; ice.programDataData = ice.programData + 0xFFFF; ice.programDataPtr = ice.programDataData; // Get the name/icon/description _rewind(ice.inPrgm); if ((res = getNameIconDescription()) != VALID) { displayError(res); goto stop; } // Open debug appvar to store things to sprintf(buf, "%.5sDBG", ice.outName); debug.dbgPrgm = ti_Open(buf, "w"); if (ice.debug) { if (!debug.dbgPrgm) { displayError(E_NO_DBG_FILE); goto stop; } // Write version bytes to debug appvar ti_PutC(DEBUG_VERSION_MAJOR, debug.dbgPrgm); ti_PutC(DEBUG_VERSION_MINOR, debug.dbgPrgm); // Write amount of programs to debug appvar ti_PutC(0, debug.dbgPrgm); } else if (debug.dbgPrgm) { ti_Delete(buf); } // Prescan the program and output the header preScanProgram(); if ((res = parsePrescan()) != VALID) { displayError(res); goto stop; } if (prescan.amountOfVariablesUsed > 84) { gfx_SetTextFGColor(224); sprintf(buf, "Too much variables used: %d", prescan.amountOfVariablesUsed); displayMessageLineScroll(buf); didCompile = false; goto stop; } // Allow hidden programs from Cesium if (*var_name < 64) { *var_name += 64; } sprintf(buf, "Compiling program %s...", var_name); displayMessageLineScroll(buf); // Create or empty the output program if parsing succeeded if ((res = parseProgram()) == VALID) { unsigned int previousSize = 0; // Get the sizes of both stacks ice.programSize = (uintptr_t)ice.programPtr - (uintptr_t)ice.programData; programDataSize = (uintptr_t)ice.programDataData - (uintptr_t)ice.programDataPtr; // Change the pointers to the data as well, but first calculate the offset offset = PRGM_START + ice.programSize - (uintptr_t)ice.programDataPtr; while (ice.dataOffsetElements--) { unsigned int *tempDataOffsetStackPtr = ice.dataOffsetStack[ice.dataOffsetElements]; *tempDataOffsetStackPtr += offset; } totalSize = ice.programSize + programDataSize + 3; // Export the program ice.outPrgm = _open(ice.outName); if (ice.outPrgm) { // This program already exists if ((uint8_t)ti_GetC(ice.outPrgm) != 0xEF || (uint8_t)ti_GetC(ice.outPrgm) != 0x7B) { gfx_SetTextFGColor(224); displayMessageLineScroll("Output program already exists!"); displayMessageLineScroll("Delete program to continue."); didCompile = false; goto stop; } previousSize = ti_GetSize(ice.outPrgm); ti_Close(ice.outPrgm); } ice.outPrgm = _new(ice.outName); if (!ice.outPrgm) { displayMessageLineScroll("Failed to open output file"); goto stop; } // Write ASM header ti_PutC(tExtTok, ice.outPrgm); ti_PutC(tAsm84CeCmp, ice.outPrgm); // Write ICE header to be recognized by Cesium ti_PutC(0x7F, ice.outPrgm); // Write the header, main program, and data to output :D ti_Write(ice.programData, ice.programSize, 1, ice.outPrgm); if (programDataSize) ti_Write(ice.programDataPtr, programDataSize, 1, ice.outPrgm); _rewind(ice.outPrgm); // Write final CRC to debug program, as well as the ending line of the first program and the amount of total programs if (ice.debug) { uint16_t CRC; CRC = GetCRC(ti_GetDataPtr(ice.outPrgm), ti_GetSize(ice.outPrgm)); WriteWordToDebugProg(CRC); ti_Seek(3 + offsetof(debug_prog_t, endingLine), SEEK_SET, debug.dbgPrgm); WriteWordToDebugProg(debug.currentLine); ti_Seek(2, SEEK_SET, debug.dbgPrgm); ti_PutC(debug.amountOfPrograms + 1, debug.dbgPrgm); // +1 because the main program starts at 0 } // Yep, we are really done! gfx_SetTextFGColor(4); displayMessageLineScroll("Successfully compiled!"); if (ice.debug) { displayMessageLineScroll("Successfully exported debug appvar"); } // Skip line displayMessageLineScroll(" "); // Display the size gfx_SetTextFGColor(0); sprintf(buf, "Output size: %u bytes", totalSize); displayMessageLineScroll(buf); if (previousSize) { sprintf(buf, "Previous size: %u bytes", previousSize); displayMessageLineScroll(buf); } sprintf(buf, "Output program: %s", ice.outName); displayMessageLineScroll(buf); } else if (res != W_VALID) { displayError(res); } stop: gfx_SetTextFGColor(0); if (didCompile) { if (res == VALID) { gfx_PrintStringXY("Run", 9, 232); printButton(1); } else if (!ti_IsArchived(ice.inPrgm)) { gfx_PrintStringXY("Goto", 222, 232); printButton(217); } gfx_PrintStringXY("Back", 70, 232); printButton(65); gfx_PrintStringXY("Quit", 285, 232); printButton(279); } while (!(key = os_GetCSC())); err: gfx_End(); if (key != sk_Graph && didCompile) { if (key == sk_Yequ && res == VALID) { RunPrgm(ice.outName); } if (key == sk_Window) { // Erase screen gfx_SetColor(255); gfx_FillRectangle_NoClip(0, 11, 320, 229); goto displayMainScreen; } if (key == sk_Trace && res != VALID && !ti_IsArchived(ice.inPrgm)) { char buf[9]; ti_GetName(buf, ice.inPrgm); GotoEditor(buf, ti_Tell(ice.inPrgm) - 1); } } ti_CloseAll(); }
bool CArchiveScanner::CheckCachedData(const std::string& fullName, unsigned* modified, bool doChecksum) { // If stat fails, assume the archive is not broken nor cached if ((*modified = FileSystemAbstraction::GetFileModificationTime(fullName)) == 0) return false; const std::string& fn = FileSystem::GetFilename(fullName); const std::string& fpath = FileSystem::GetDirectory(fullName); const std::string& lcfn = StringToLower(fn); // Determine whether this archive has earlier be found to be broken auto bai = brokenArchives.find(lcfn); if (bai != brokenArchives.end()) { BrokenArchive& ba = bai->second; if (*modified == ba.modified && fpath == ba.path) { return (ba.updated = true); } } // Determine whether to rely on the cached info or not auto aii = archiveInfos.find(lcfn); if (aii != archiveInfos.end()) { ArchiveInfo& ai = aii->second; // This archive may have been obsoleted, do not process it if so if (!ai.replaced.empty()) return true; if (*modified == ai.modified && fpath == ai.path) { // cache found update checksum if wanted ai.updated = true; if (doChecksum && (ai.checksum == 0)) ai.checksum = GetCRC(fullName); return true; } if (ai.updated) { LOG_L(L_ERROR, "[AS::%s] found a \"%s\" already in \"%s\", ignoring.", __func__, fullName.c_str(), (ai.path + ai.origName).c_str()); if (baseContentArchives.find(aii->first) == baseContentArchives.end()) return true; // ignore throw user_error( std::string("duplicate base content detected:\n\t") + ai.path + std::string("\n\t") + fpath + std::string("\nPlease fix your configuration/installation as this can cause desyncs!")); } // If we are here, we could have invalid info in the cache // Force a reread if it is a directory archive (.sdd), as // st_mtime only reflects changes to the directory itself, // not the contents. archiveInfos.erase(aii); } return false; }
BOOL CMD_DUMPCART (void) { int dtype = 2; int rbyte = 0, rcount = 0; PPlugin plugin; char *path, *ext; char filename[MAX_PATH]; char fnamebuf[MAX_PATH]; int cmode, battery, bytes, numk; int mapper,submapper=0; int nes2=0, wram=0, vram=0; BYTE ctype; WORD nblks; char Status[256]; FILE *CRC, *DATA; // select board name plugin = PromptPlugin(PLUG_STD); if (plugin == NULL) return FALSE; mapper = plugin->num; PromptTitle = "Choose a ROM filename (omit extension)"; if (!Prompt(topHWnd)) return FALSE; strcpy(filename,PromptResult); OpenStatus(topHWnd); StatusText("Resetting USB CopyNES..."); ResetNES(RESET_COPYMODE); StatusText("Unloading any existing plugin..."); if (!LoadPlugin("clear.bin")) { CloseStatus(); return FALSE; } RunCode(); Sleep(SLEEP_SHORT); StatusText("Resetting USB CopyNES..."); ResetNES(RESET_COPYMODE); StatusText("Loading plugin..."); if (!LoadPlugin(plugin->file)) { CloseStatus(); return FALSE; } StatusText("Running plugin..."); RunCode(); Sleep(SLEEP_LONG); if (SaveCRC) CRC = fopen(strjoin3(fnamebuf,Path_CRC,filename,".txt"),"wb"); cmode = 0; if (!ReadByte((BYTE *)&cmode)) // mirroring { CloseStatus(); return FALSE; } battery = 0; while (1) { // for the first 'header' byte, wait longer than usual // since the plugin might be busy doing size detection, which can take a while int s; if (!ReadByteEx((BYTE *)&nblks,10,TRUE) || !ReadByte((BYTE *)&nblks+1)) { CloseStatus(); return FALSE; } bytes = nblks << 8; numk = bytes / 1024; if (!ReadByte(&ctype)) { CloseStatus(); return FALSE; } if (ctype == 0) break; switch (ctype) { case 1: ext = ".prg"; if(numk >= 4096) nes2 = 1; path = Path_PRG; sprintf(Status,"Dumping %iK PRG ROM...",numk); break; case 2: ext = ".chr"; if(numk >= 2048) nes2 = 1; path = Path_CHR; sprintf(Status,"Dumping %iK CHR ROM...",numk); break; case 3: ext = ".sav"; path = Path_WRAM; sprintf(Status,"Dumping %iK WRAM/VRAM...",numk); battery = 1; break; case 4: rbyte = nblks / 4; continue; case 5: nes2 = 1; wram = nblks & 0xFF; vram = nblks >> 8; if(wram & 0xF0) battery = 1; if(vram & 0xF0) battery = 1; sprintf(Status,"Non battery WRAM size: %i Bytes...", ((wram & 0x0f)?64 << (wram & 0x0F):0)); StatusText(Status); sprintf(Status,"battery WRAM size: %i Bytes...", ((wram >> 4)?64 << (wram & 0x0F):0)); StatusText(Status); sprintf(Status,"Non battery VRAM size: %i Bytes...", ((vram & 0x0f)?64 << (vram & 0x0F):0)); StatusText(Status); sprintf(Status,"battery VRAM size: %i Bytes...", ((vram >> 4)?64 << (vram & 0x0F):0)); StatusText(Status); continue; case 6: //Mapper number override by plugin. mapper = nblks & 0xFFF; submapper = (nblks & 0xF000) >> 12; sprintf(Status,"Mapper number: %i, submapper: %i...",mapper,submapper); StatusText(Status); if((mapper > 255) || (submapper > 0)) nes2 = 1; continue; case 255: sprintf(Status,"."); continue; //Prevent timeout. default:StatusText("Unknown block type %i! Aborting...",ctype); StatusOK(); return FALSE; break; } StatusText(Status); DATA = fopen(strjoin3(fnamebuf,path,filename,ext),"w+b"); if (DATA == NULL) { StatusText("Unable to open output file!"); StatusOK(); return FALSE; } for (s = 0; s < numk; s++) { int a; BYTE n; for (a = 0; a < 1024; a++) { if (!ReadByte(&n)) { CloseStatus(); return FALSE; } fwrite(&n,1,1,DATA); } if (rbyte) { rcount++; if (rbyte <= rcount) { rcount = 0; StatusText("Resetting USB CopyNES as requested by plugin..."); ResetNES(RESET_COPYMODE); StatusText("Reloading plugin..."); LoadPlugin(plugin->file); StatusText("Rerunning plugin..."); RunCode(); rbyte = 0; if (!ReadByte((BYTE *)&rbyte) || !ReadByte((BYTE *)&rbyte+1)) { CloseStatus(); return FALSE; } rbyte /= 4; } } StatusPercent((s*100)/numk); DoEvents(); } StatusPercent(100); StatusText("...done!"); if (SaveCRC) fprintf(CRC,"%s%s %08X\n",filename,ext,GetCRC(DATA)); fclose(DATA); } if (SaveCRC) fclose(CRC); StatusText("Dump complete!"); StatusOK(); ResetNES(RESET_COPYMODE); { int scrn4 = (cmode & 0x2) >> 1; int mirror = (~cmode & 0x1); int mcon = (cmode & 0x4) >> 2; if (plugin->num == 9999) return TRUE; WriteNES(filename,mapper,battery,mirror,scrn4,nes2,wram,vram,submapper,0); if (MakeUnif == 1) WriteUNIF(filename,plugin->name,battery,mirror,scrn4,mcon); if (SaveFiles == 0) { unlink(strjoin3(fnamebuf,Path_CHR,filename,".chr")); unlink(strjoin3(fnamebuf,Path_PRG,filename,".prg")); } } return TRUE; }
void CArchiveScanner::ScanArchive(const std::string& fullName, bool doChecksum) { const std::string fn = FileSystem::GetFilename(fullName); const std::string fpath = FileSystem::GetDirectory(fullName); const std::string lcfn = StringToLower(fn); // Stat file struct stat info = {0}; int statfailed = stat(fullName.c_str(), &info); // If stat fails, assume the archive is not broken nor cached if (!statfailed) { // Determine whether this archive has earlier be found to be broken std::map<std::string, BrokenArchive>::iterator bai = brokenArchives.find(lcfn); if (bai != brokenArchives.end()) { if ((unsigned)info.st_mtime == bai->second.modified && fpath == bai->second.path) { bai->second.updated = true; return; } } // Determine whether to rely on the cached info or not std::map<std::string, ArchiveInfo>::iterator aii = archiveInfos.find(lcfn); if (aii != archiveInfos.end()) { // This archive may have been obsoleted, do not process it if so if (!aii->second.replaced.empty()) { return; } if ((unsigned)info.st_mtime == aii->second.modified && fpath == aii->second.path) { // cache found update checksum if wanted aii->second.updated = true; if (doChecksum && (aii->second.checksum == 0)) { aii->second.checksum = GetCRC(fullName); } return; } else { if (aii->second.updated) { const std::string filename = aii->first; LOG_L(L_ERROR, "Found a \"%s\" already in \"%s\", ignoring.", fullName.c_str(), (aii->second.path + aii->second.origName).c_str()); if (IsBaseContent(filename)) { throw user_error(std::string("duplicate base content detected:\n\t") + aii->second.path + std::string("\n\t") + fpath + std::string("\nPlease fix your configuration/installation as this can cause desyncs!")); } return; } // If we are here, we could have invalid info in the cache // Force a reread if it is a directory archive (.sdd), as // st_mtime only reflects changes to the directory itself, // not the contents. archiveInfos.erase(aii); } } } boost::scoped_ptr<IArchive> ar(archiveLoader.OpenArchive(fullName)); if (!ar || !ar->IsOpen()) { LOG_L(L_WARNING, "Unable to open archive: %s", fullName.c_str()); // record it as broken, so we don't need to look inside everytime BrokenArchive& ba = brokenArchives[lcfn]; ba.path = fpath; ba.modified = info.st_mtime; ba.updated = true; ba.problem = "Unable to open archive"; return; } std::string error; std::string mapfile; const bool hasModinfo = ar->FileExists("modinfo.lua"); const bool hasMapinfo = ar->FileExists("mapinfo.lua"); ArchiveInfo ai; auto& ad = ai.archiveData; if (hasMapinfo) { ScanArchiveLua(ar.get(), "mapinfo.lua", ai, error); if (ad.GetMapFile().empty()) { LOG_L(L_WARNING, "%s: mapfile isn't set in mapinfo.lua, please set it for faster loading!", fullName.c_str()); mapfile = SearchMapFile(ar.get(), error); } } else if (hasModinfo) { ScanArchiveLua(ar.get(), "modinfo.lua", ai, error); } else { mapfile = SearchMapFile(ar.get(), error); } CheckCompression(ar.get(), fullName, error); if (!error.empty()) { // for some reason, the archive is marked as broken LOG_L(L_WARNING, "Failed to scan %s (%s)", fullName.c_str(), error.c_str()); // record it as broken, so we don't need to look inside everytime BrokenArchive& ba = brokenArchives[lcfn]; ba.path = fpath; ba.modified = info.st_mtime; ba.updated = true; ba.problem = error; return; } if (hasMapinfo || !mapfile.empty()) { // it is a map if (ad.GetName().empty()) { // FIXME The name will never be empty, if version is set (see HACK in ArchiveData) ad.SetInfoItemValueString("name_pure", FileSystem::GetBasename(mapfile)); ad.SetInfoItemValueString("name", FileSystem::GetBasename(mapfile)); } if (ad.GetMapFile().empty()) { ad.SetInfoItemValueString("mapfile", mapfile); } AddDependency(ad.GetDependencies(), "Map Helper v1"); ad.SetInfoItemValueInteger("modType", modtype::map); LOG_S(LOG_SECTION_ARCHIVESCANNER, "Found new map: %s", ad.GetNameVersioned().c_str()); } else if (hasModinfo) { // it is a game if (ad.GetModType() == modtype::primary) { AddDependency(ad.GetDependencies(), "Spring content v1"); } LOG_S(LOG_SECTION_ARCHIVESCANNER, "Found new game: %s", ad.GetNameVersioned().c_str()); } else { // neither a map nor a mod: error error = "missing modinfo.lua/mapinfo.lua"; } ai.path = fpath; ai.modified = info.st_mtime; ai.origName = fn; ai.updated = true; ai.checksum = (doChecksum) ? GetCRC(fullName) : 0; archiveInfos[lcfn] = ai; }
void CArchiveScanner::Scan(const string& curPath, bool checksum) { InitCrcTable(); isDirty = true; const int flags = (FileSystem::INCLUDE_DIRS | FileSystem::RECURSE); std::vector<std::string> found = filesystem.FindFiles(curPath, "*", flags); for (std::vector<std::string>::iterator it = found.begin(); it != found.end(); ++it) { string fullName = *it; // Strip const char lastFullChar = fullName[fullName.size() - 1]; if ((lastFullChar == '/') || (lastFullChar == '\\')) { fullName = fullName.substr(0, fullName.size() - 1); } const string fn = filesystem.GetFilename(fullName); const string fpath = filesystem.GetDirectory(fullName); const string lcfn = StringToLower(fn); const string lcfpath = StringToLower(fpath); // Exclude archivefiles found inside directory archives (.sdd) if (lcfpath.find(".sdd") != string::npos) { continue; } // Exclude archivefiles found inside hidden directories if ((lcfpath.find("/hidden/") != string::npos) || (lcfpath.find("\\hidden\\") != string::npos)) { continue; } // Is this an archive we should look into? if (CArchiveFactory::IsArchive(fullName)) { struct stat info; stat(fullName.c_str(), &info); // Determine whether to rely on the cached info or not bool cached = false; map<string, ArchiveInfo>::iterator aii = archiveInfo.find(lcfn); if (aii != archiveInfo.end()) { // This archive may have been obsoleted, do not process it if so if (aii->second.replaced.length() > 0) continue; /* For truely correct updating of .sdd archives, this code should be enabled. Unfortunately it has as side effect that all files in all .sdd's always need to be stat()'ed, which really slows down program startup. An update can be forced anyway by removing ArchiveCacheV*.txt or renaming the archive. */ /*if (S_ISDIR(info.st_mode)) { struct stat info2; std::vector<std::string> sddfiles = filesystem.FindFiles(fpath, "*", FileSystem::RECURSE | FileSystem::INCLUDE_DIRS); for (std::vector<std::string>::iterator sddit = found.begin(); sddit != found.end(); ++sddit) { stat(sddit->c_str(), &info2); if (info.st_mtime < info2.st_mtime) { info.st_mtime = info2.st_mtime; } } }*/ if ((unsigned)info.st_mtime == aii->second.modified && fpath == aii->second.path) { cached = true; aii->second.updated = true; } // If we are here, we could have invalid info in the cache // Force a reread if it's a directory archive, as st_mtime only // reflects changes to the directory itself, not the contents. if (!cached) { archiveInfo.erase(aii); } } // Time to parse the info we are interested in if (!cached) { //printf("scanning archive: %s\n", fullName.c_str()); CArchiveBase* ar = CArchiveFactory::OpenArchive(fullName); if (ar) { int cur; string name; int size; ArchiveInfo ai; cur = ar->FindFiles(0, &name, &size); while (cur != 0) { //printf("found %s %d\n", name.c_str(), size); string ext = StringToLower(name.substr(name.find_last_of('.') + 1)); // only accept new format maps if (ext == "smf" || ext == "sm3") { MapData md; if (name.find_last_of('\\') == string::npos && name.find_last_of('/') == string::npos) { md.name = name; md.virtualPath = "/"; } else { if (name.find_last_of('\\') == string::npos) { md.name = name.substr(name.find_last_of('/') + 1); md.virtualPath = name.substr(0, name.find_last_of('/') + 1); // include the backslash } else { md.name = name.substr(name.find_last_of('\\') + 1); md.virtualPath = name.substr(0, name.find_last_of('\\') + 1); // include the backslash } //md.name = md.name.substr(0, md.name.find_last_of('.')); } ai.mapData.push_back(md); } if (name == "modinfo.tdf") { int fh = ar->OpenFile(name); if (fh) { int fsize = ar->FileSize(fh); char* buf = SAFE_NEW char[fsize]; ar->ReadFile(fh, buf, fsize); ar->CloseFile(fh); try { TdfParser p( buf, fsize ); ai.modData = GetModData(&p, "mod"); } catch (const TdfParser::parse_error&) { // Silently ignore mods with parse errors } delete [] buf; } } cur = ar->FindFiles(cur, &name, &size); } ai.path = fpath; ai.modified = info.st_mtime; ai.origName = fn; ai.updated = true; delete ar; // Optionally calculate a checksum for the file // To prevent reading all files in all directory (.sdd) archives every time this function // is called, directory archive checksums are calculated on the fly. if (checksum) { ai.checksum = GetCRC(fullName); } else { ai.checksum = 0; } archiveInfo[lcfn] = ai; } } else { // If cached is true, aii will point to the archive if ((checksum) && (aii->second.checksum == 0)) {
// To prevent reading all files in all directory (.sdd) archives every time this function // is called, directory archive checksums are calculated on the fly. if (checksum) { ai.checksum = GetCRC(fullName); } else { ai.checksum = 0; } archiveInfo[lcfn] = ai; } } else { // If cached is true, aii will point to the archive if ((checksum) && (aii->second.checksum == 0)) { aii->second.checksum = GetCRC(fullName); } } } } // Now we'll have to parse the replaces-stuff found in the mods for (map<string, ArchiveInfo>::iterator aii = archiveInfo.begin(); aii != archiveInfo.end(); ++aii) { for (vector<string>::iterator i = aii->second.modData.replaces.begin(); i != aii->second.modData.replaces.end(); ++i) { string lcname = StringToLower(*i); map<string, ArchiveInfo>::iterator ar = archiveInfo.find(lcname); // If it's not there, we will create a new entry if (ar == archiveInfo.end()) {
void CArchiveScanner::Scan(const string& curPath, bool checksum) { isDirty = true; std::vector<std::string> found = filesystem.FindFiles(curPath, "*", FileSystem::RECURSE | FileSystem::INCLUDE_DIRS); struct stat info; for (std::vector<std::string>::iterator it = found.begin(); it != found.end(); ++it) { stat(it->c_str(),&info); string fullName = *it; string fn = filesystem.GetFilename(fullName); string fpath = filesystem.GetDirectory(fullName); string lcfn = StringToLower(fn); string lcfpath = StringToLower(fpath); // Exclude archivefiles found inside directory (.sdd) archives. string::size_type sdd = lcfpath.find(".sdd"); if (sdd != string::npos) continue; // Is this an archive we should look into? if (CArchiveFactory::IsArchive(fullName)) { // Determine whether to rely on the cached info or not bool cached = false; map<string, ArchiveInfo>::iterator aii = archiveInfo.find(lcfn); if (aii != archiveInfo.end()) { // This archive may have been obsoleted, do not process it if so if (aii->second.replaced.length() > 0) continue; if (S_ISDIR(info.st_mode)) { struct stat info2; std::vector<std::string> sddfiles = filesystem.FindFiles(fpath, "*", FileSystem::RECURSE | FileSystem::INCLUDE_DIRS); for (std::vector<std::string>::iterator sddit = found.begin(); sddit != found.end(); ++sddit) { stat(sddit->c_str(), &info2); if (info.st_mtime < info2.st_mtime) { info.st_mtime = info2.st_mtime; } } } if (info.st_mtime == aii->second.modified && fpath == aii->second.path) { cached = true; aii->second.updated = true; } // If we are here, we could have invalid info in the cache // Force a reread if it's a directory archive, as st_mtime only // reflects changes to the directory itself, not the contents. if (!cached) { archiveInfo.erase(aii); } } // Time to parse the info we are interested in if (!cached) { CArchiveBase* ar = CArchiveFactory::OpenArchive(fullName); if (ar) { int cur; string name; int size; ArchiveInfo ai; cur = ar->FindFiles(0, &name, &size); while (cur != 0) { //printf("found %s %d\n", name.c_str(), size); string ext = StringToLower(name.substr(name.find_last_of('.') + 1)); // only accept new format maps if (ext == "smf" || ext == "sm3") { MapData md; if (name.find_last_of('\\') == string::npos && name.find_last_of('/') == string::npos) { md.name = name; md.virtualPath = "/"; } else { if (name.find_last_of('\\') == string::npos) { md.name = name.substr(name.find_last_of('/') + 1); md.virtualPath = name.substr(0, name.find_last_of('/') + 1); // include the backslash } else { md.name = name.substr(name.find_last_of('\\') + 1); md.virtualPath = name.substr(0, name.find_last_of('\\') + 1); // include the backslash } //md.name = md.name.substr(0, md.name.find_last_of('.')); } ai.mapData.push_back(md); } if (name == "modinfo.tdf") { int fh = ar->OpenFile(name); if (fh) { int fsize = ar->FileSize(fh); void* buf = malloc(fsize); ar->ReadFile(fh, buf, fsize); ar->CloseFile(fh); try { TdfParser p( reinterpret_cast<char*>(buf), fsize ); ai.modData = GetModData(&p, "mod"); } catch (const TdfParser::parse_error& e) { // Silently ignore mods with parse errors } free(buf); } } cur = ar->FindFiles(cur, &name, &size); } ai.path = fpath; ai.modified = info.st_mtime; ai.origName = fn; ai.updated = true; delete ar; // Optionally calculate a checksum for the file // To prevent reading all files in all directory (.sdd) archives every time this function // is called, directory archive checksums are calculated on the fly. if (checksum) { ai.checksum = GetCRC(fullName); } else { ai.checksum = 0; } archiveInfo[lcfn] = ai; } } else { // If cached is true, aii will point to the archive if ((checksum) && (aii->second.checksum == 0)) { aii->second.checksum = GetCRC(fullName); } } } } // Now we'll have to parse the replaces-stuff found in the mods for (map<string, ArchiveInfo>::iterator aii = archiveInfo.begin(); aii != archiveInfo.end(); ++aii) { for (vector<string>::iterator i = aii->second.modData.replaces.begin(); i != aii->second.modData.replaces.end(); ++i) { string lcname = StringToLower(*i); map<string, ArchiveInfo>::iterator ar = archiveInfo.find(lcname); // If it's not there, we will create a new entry if (ar == archiveInfo.end()) { ArchiveInfo tmp; archiveInfo[lcname] = tmp; ar = archiveInfo.find(lcname); } // Overwrite the info for this archive with a replaced pointer ar->second.path = ""; ar->second.origName = lcname; ar->second.modified = 1; ar->second.mapData.clear(); ar->second.modData.name = ""; ar->second.modData.replaces.clear(); ar->second.updated = true; ar->second.replaced = aii->first; } } }
//--------------------------------------------------------------------------- void __fastcall TFileViewDlg::LoadFileList(void) { if( pCurPage->pList == NULL ){ pCurPage->pList = new CFILEL; } pCurPage->pList->Delete(); WIN32_FIND_DATA FileData; HANDLE hSearch; MultProc(); if( pCurPage->m_Folder.IsEmpty() || (::SetCurrentDirectory(pCurPage->m_Folder.c_str()) != TRUE) ){ if( NewFolder() == TRUE ){ if( ::SetCurrentDirectory(pCurPage->m_Folder.c_str()) != TRUE ){ pCurPage->m_Folder = "\\"; ::SetCurrentDirectory(pCurPage->m_Folder.c_str()); } } else { pCurPage->m_Folder = "\\"; ::SetCurrentDirectory(pCurPage->m_Folder.c_str()); } } MultProc(); hSearch = FindFirstFile("*.*", &FileData); if(hSearch == INVALID_HANDLE_VALUE){ UpdateStat(); return; } MultProc(); while(1){ LPCSTR pExt = GetEXT(FileData.cFileName); int f = 0; switch(pCurPage->m_Type){ case 0: if( IsPic(pExt) ) f = 1; break; case 1: if( !strcmpi(pExt, "MTM") ) f = 1; break; case 2: if( !strcmpi(pExt, "MTI") ) f = 1; break; case 3: if( !strcmpi(pExt, "DLL") ) f = 1; break; case 4: if( !(FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ){ if( *pExt && strcmpi(pExt, "DLL") && strcmpi(pExt, "EXE") ) f = 1; } break; } if( f ){ pCurPage->pList->Add(FileData.cFileName, GetCRC(&FileData)); } if(!FindNextFile(hSearch, &FileData)) break; MultProcA(); } FindClose(hSearch); pCurPage->pList->Sort(); if( pCurPage->m_UseIndex && pCurPage->pList->Count ){ pCurPage->m_Thumb.OpenFolder(m_MyIndex, m_CurPage, pCurPage->pList->Count, GetCRC(pCurPage->m_Folder.c_str())); pCurPage->m_Thumb.SetSize(m_RectS.Right, m_RectS.Bottom); } UpdateStat(); MultProc(); }
void CArchiveScanner::ScanArchive(const std::string& fullName, bool doChecksum) { unsigned modifiedTime = 0; if (CheckCachedData(fullName, &modifiedTime, doChecksum)) return; isDirty = true; const std::string& fn = FileSystem::GetFilename(fullName); const std::string& fpath = FileSystem::GetDirectory(fullName); const std::string& lcfn = StringToLower(fn); std::unique_ptr<IArchive> ar(archiveLoader.OpenArchive(fullName)); if (ar == nullptr || !ar->IsOpen()) { LOG_L(L_WARNING, "[AS::%s] unable to open archive \"%s\"", __func__, fullName.c_str()); // record it as broken, so we don't need to look inside everytime BrokenArchive& ba = brokenArchives[lcfn]; ba.path = fpath; ba.modified = modifiedTime; ba.updated = true; ba.problem = "Unable to open archive"; // does not count as a scan // numScannedArchives += 1; return; } std::string error; std::string arMapFile; // file in archive with "smf" or "sm3" extension std::string miMapFile; // value for the 'mapfile' key parsed from mapinfo const bool hasModinfo = ar->FileExists("modinfo.lua"); const bool hasMapinfo = ar->FileExists("mapinfo.lua"); ArchiveInfo ai; ArchiveData& ad = ai.archiveData; // execute the respective .lua, otherwise assume this archive is a map if (hasMapinfo) { ScanArchiveLua(ar.get(), "mapinfo.lua", ai, error); if ((miMapFile = ad.GetMapFile()).empty()) { LOG_L(L_WARNING, "[AS::%s] set the 'mapfile' key in mapinfo.lua of archive \"%s\" for faster loading!", __func__, fullName.c_str()); arMapFile = SearchMapFile(ar.get(), error); } } else if (hasModinfo) { ScanArchiveLua(ar.get(), "modinfo.lua", ai, error); } else { arMapFile = SearchMapFile(ar.get(), error); } if (!CheckCompression(ar.get(), fullName, error)) { // for some reason, the archive is marked as broken LOG_L(L_WARNING, "[AS::%s] failed to scan \"%s\" (%s)", __func__, fullName.c_str(), error.c_str()); // record it as broken, so we don't need to look inside everytime BrokenArchive& ba = brokenArchives[lcfn]; ba.path = fpath; ba.modified = modifiedTime; ba.updated = true; ba.problem = error; // does count as a scan numScannedArchives += 1; return; } if (hasMapinfo || !arMapFile.empty()) { // map archive if ((ad.GetName()).empty()) { // FIXME The name will never be empty, if version is set (see HACK in ArchiveData) ad.SetInfoItemValueString("name_pure", FileSystem::GetBasename(arMapFile)); ad.SetInfoItemValueString("name", FileSystem::GetBasename(arMapFile)); } if (miMapFile.empty()) ad.SetInfoItemValueString("mapfile", arMapFile); AddDependency(ad.GetDependencies(), GetMapHelperContentName()); ad.SetInfoItemValueInteger("modType", modtype::map); LOG_S(LOG_SECTION_ARCHIVESCANNER, "Found new map: %s", ad.GetNameVersioned().c_str()); } else if (hasModinfo) { // game or base-type (cursors, bitmaps, ...) archive // babysitting like this is really no longer required if (ad.IsGame() || ad.IsMenu()) AddDependency(ad.GetDependencies(), GetSpringBaseContentName()); LOG_S(LOG_SECTION_ARCHIVESCANNER, "Found new game: %s", ad.GetNameVersioned().c_str()); } else { // neither a map nor a mod: error error = "missing modinfo.lua/mapinfo.lua"; } ai.path = fpath; ai.modified = modifiedTime; ai.origName = fn; ai.updated = true; ai.checksum = (doChecksum) ? GetCRC(fullName) : 0; archiveInfos[lcfn] = ai; numScannedArchives += 1; }