ERR ParsePFD( PKImageDecode* pID, size_t offPos, U16 cEntry) { ERR err = WMP_errSuccess; struct WMPStream* pWS = pID->pStream; U16 i = 0; for (i = 0; i < cEntry; ++i) { U16 uTag = 0; U16 uType = 0; U32 uCount = 0; U32 uValue = 0; Call(GetUShort(pWS, offPos, &uTag)); offPos += 2; Call(GetUShort(pWS, offPos, &uType)); offPos += 2; Call(GetULong(pWS, offPos, &uCount)); offPos += 4; Call(GetULong(pWS, offPos, &uValue)); offPos += 4; Call(ParsePFDEntry(pID, uTag, uType, uCount, uValue)); } pID->WMP.bHasAlpha = ((pID->WMP.bHasAlpha) && (pID->WMP.wmiDEMisc.uAlphaOffset != 0) && (pID->WMP.wmiDEMisc.uAlphaByteCount != 0));//has planar alpha Cleanup: return err; }
// Reads a map from GRF's GAT and RSW files int read_map(char *name, struct map_data *m) { char filename[256]; unsigned char *gat, *rsw; int water_height; size_t xy, off, num_cells; float height; uint32 type; // Open map GAT sprintf(filename,"data\\%s.gat", name); gat = (unsigned char *)grfio_read(filename); if (gat == NULL) return 0; // Open map RSW sprintf(filename,"data\\%s.rsw", name); rsw = (unsigned char *)grfio_read(filename); // Read water height if (rsw) { water_height = (int)GetFloat(rsw+166); aFree(rsw); } else water_height = NO_WATER; // Read map size and allocate needed memory m->xs = (int16)GetULong(gat+6); m->ys = (int16)GetULong(gat+10); if (m->xs <= 0 || m->ys <= 0) { aFree(gat); return 0; } num_cells = (size_t)m->xs*(size_t)m->ys; m->cells = (unsigned char *)aMalloc(num_cells); // Set cell properties off = 14; for (xy = 0; xy < num_cells; xy++) { // Height of the bottom-left corner height = GetFloat( gat + off ); // Type of cell type = GetULong( gat + off + 16 ); off += 20; if (type == 0 && water_height != NO_WATER && height > water_height) type = 3; // Cell is 0 (walkable) but under water level, set to 3 (walkable water) m->cells[xy] = (unsigned char)type; } aFree(gat); return 1; }
const wxBrush& CMuleColour::GetBrush(int style) const { #if USE_MULE_BRUSH_CACHE wxBrush* result = NULL; if (m_cachedbrush && (m_cachedbrush->GetStyle() == style)) { result = m_cachedbrush; } else { const uint32_t hash = ((style & 0xF) << 24) | (GetULong() & 0xFFFFFF); std::map<uint32_t, wxBrush*>::iterator it = wxBrushCache.find(hash); if (it != wxBrushCache.end()) { result = it->second; m_cachedbrush = result; } else { result = wxTheBrushList->FindOrCreateBrush(wxColour(m_red, m_green, m_blue), style); m_cachedbrush = result; wxBrushCache.insert(std::pair<uint32_t, wxBrush*>(hash, result)); } } return *result; #else return *wxTheBrushList->FindOrCreateBrush(wxColour(m_red, m_green, m_blue), style); #endif }
const wxPen& CMuleColour::GetPen(int width, int style) const { #if USE_MULE_PEN_CACHE wxPen* result = NULL; if (m_cachedpen && (m_cachedpen->GetWidth() == width) && (m_cachedpen->GetStyle() == style)) { result = m_cachedpen; } else { const uint32_t hash = ((width & 0xF) << 28) | ((style & 0xF) << 24) | (GetULong() & 0xFFFFFF); std::map<uint32_t, wxPen*>::iterator it = wxPenCache.find(hash); if (it != wxPenCache.end()) { result = it->second; m_cachedpen = result; } else { result = wxThePenList->FindOrCreatePen(wxColour(m_red, m_green, m_blue), width, style); m_cachedpen = result; wxPenCache.insert(std::pair<uint32_t, wxPen*>(hash, result)); } } return *result; #else return *wxThePenList->FindOrCreatePen(wxColour(m_red, m_green, m_blue), width, style); #endif }
dis_handler_return JVMLookupSwitch( dis_handle *h, void *d, dis_dec_ins *ins ) { unsigned off; //NYI: this instruction can get bigger than 255 bytes (max that can // fit in ins->size). off = DisCliGetAlign( d, 1, 4 ); ins->num_ops = 2; ins->op[0].type = DO_RELATIVE; ins->op[0].value = GetULong( d, off ); off += 4; ins->op[1].type = DO_IMMED; ins->op[1].value = GetULong( d, off ); off += 4; ins->size += off + ins->op[1].value * 8; return( DHR_DONE ); }
dis_handler_return JVMBrInt( dis_handle *h, void *d, dis_dec_ins *ins ) { ins->size += 5; ins->num_ops = 1; ins->op[0].type = DO_RELATIVE; ins->op[0].value = GetULong( d, 1 ); return( DHR_DONE ); }
ERR ReadContainer( PKImageDecode* pID) { ERR err = WMP_errSuccess; struct WMPStream* pWS = pID->pStream; size_t offPos = 0; char szSig[2] = {0}; U16 uWmpID = 0; U32 offPFD = 0; U16 cPFDEntry = 0; U8 bVersion; //================================ Call(pWS->GetPos(pWS, &offPos)); FailIf(0 != offPos, WMP_errUnsupportedFormat); //================================ // Header Call(pWS->Read(pWS, szSig, sizeof(szSig))); offPos += 2; FailIf(szSig != strstr(szSig, "II"), WMP_errUnsupportedFormat); Call(GetUShort(pWS, offPos, &uWmpID)); offPos += 2; FailIf(WMP_valWMPhotoID != (0x00FF & uWmpID), WMP_errUnsupportedFormat); // We accept version 00 and version 01 bitstreams - all others rejected bVersion = (0xFF00 & uWmpID) >> 8; FailIf(bVersion != 0 && bVersion != 1, WMP_errUnsupportedFormat); Call(GetULong(pWS, offPos, &offPFD)); offPos += 4; //================================ // PFD offPos = (size_t)offPFD; Call(GetUShort(pWS, offPos, &cPFDEntry)); offPos += 2; FailIf(0 == cPFDEntry || USHRT_MAX == cPFDEntry, WMP_errUnsupportedFormat); Call(ParsePFD(pID, offPos, cPFDEntry)); //================================ Call(pWS->SetPos(pWS, pID->WMP.wmiDEMisc.uImageOffset)); Cleanup: return err; }
int read_registers(const struct ca_segment* segment, struct reg_value* regs, int bufsz) { int ptr_sz = g_ptr_bit >> 3; if (regs) { if (bufsz >= TOTAL_REGS) { thread_context* lpThreadContext = (thread_context*) segment->m_thread.context; for (int i=0; i<TOTAL_REGS; i++) { unsigned long r_val = ptr_sz == 8 ? GetULong(&lpThreadContext->pr_reg[i]) : GetUInt(&lpThreadContext->pr_reg[i]); regs[i].reg_num = i; regs[i].reg_width = ptr_sz; regs[i].value = (address_t) r_val; } return TOTAL_REGS; } } else return TOTAL_REGS; return 0; }
CA_BOOL search_registers(const struct ca_segment*segment, struct CA_LIST* targets, struct CA_LIST* refs) { int ptr_sz = g_ptr_bit >> 3; if (segment->m_type != ENUM_STACK) return false; bool lbFound = false; thread_context* lpThreadContext = (thread_context*) segment->m_thread.context; for (int i=0; i<TOTAL_REGS; i++) { unsigned long r_val = ptr_sz == 8 ? GetULong(&lpThreadContext->pr_reg[i]) : GetUInt(&lpThreadContext->pr_reg[i]); struct object_range* target; ca_list_traverse_start(targets); while ( (target = (struct object_range*) ca_list_traverse_next(targets)) ) { if (r_val >= target->low && r_val < target->high) { struct object_reference* ref = (struct object_reference*) malloc(sizeof(struct object_reference)); ref->storage_type = ENUM_REGISTER; ref->where.reg.tid = segment->m_thread.tid; ref->where.reg.reg_num = i; ref->where.reg.name = reg_names[i]; ref->vaddr = 0; ref->value = r_val; ca_list_push_back(refs, ref); lbFound = CA_TRUE; break; } } } return lbFound; }
int get_frame_number(const struct ca_segment* segment, address_t vaddr, int* offset) { int frame_num; thread_context* lpThreadContext = (thread_context*) segment->m_thread.context; unsigned long rsp = GET_RSP(lpThreadContext); *offset = (int) (vaddr - rsp); if (vaddr < rsp) { frame_num = -1; } else { frame_num = 0; #ifdef sun // we can get frame# on sparcv9 // This doesn't account for leaf function, hence may under-count frame# const char* start = segment->m_faddr; for (frame_num=1; ;frame_num++) { struct frame* pframe = (struct frame*) (start + (rsp - segment->m_vaddr)); unsigned long next_rsp = GetULong(&pframe->fr_savfp) + 2047; if (next_rsp > rsp) { if (vaddr>=rsp && vaddr<next_rsp) { break; } rsp = next_rsp; } else break; } #endif } return frame_num; }
int do_init(int argc, char** argv) { FILE *list; char line[1024]; struct map_data map; char name[MAP_NAME_LENGTH_EXT]; grf_list_file = aStrdup("conf/grf-files.txt"); map_list_file = aStrdup("db/map_index.txt"); /* setup pre-defined, #define-dependant */ map_cache_file = aStrdup("db/map_cache.dat"); cmdline->exec(argc, argv, CMDLINE_OPT_PREINIT); cmdline->exec(argc, argv, CMDLINE_OPT_NORMAL); ShowStatus("Initializing grfio with %s\n", grf_list_file); grfio_init(grf_list_file); // Attempt to open the map cache file and force rebuild if not found ShowStatus("Opening map cache: %s\n", map_cache_file); if(!rebuild) { map_cache_fp = fopen(map_cache_file, "rb"); if(map_cache_fp == NULL) { ShowNotice("Existing map cache not found, forcing rebuild mode\n"); rebuild = 1; } else fclose(map_cache_fp); } if(rebuild) map_cache_fp = fopen(map_cache_file, "w+b"); else map_cache_fp = fopen(map_cache_file, "r+b"); if(map_cache_fp == NULL) { ShowError("Failure when opening map cache file %s\n", map_cache_file); exit(EXIT_FAILURE); } // Open the map list ShowStatus("Opening map list: %s\n", map_list_file); list = fopen(map_list_file, "r"); if(list == NULL) { ShowError("Failure when opening maps list file %s\n", map_list_file); exit(EXIT_FAILURE); } // Initialize the main header if(rebuild) { header.file_size = sizeof(struct main_header); header.map_count = 0; } else { if(fread(&header, sizeof(struct main_header), 1, map_cache_fp) != 1){ printf("An error as occured while reading map_cache_fp \n"); } header.file_size = GetULong((unsigned char *)&(header.file_size)); header.map_count = GetUShort((unsigned char *)&(header.map_count)); } // Read and process the map list while(fgets(line, sizeof(line), list)) { if(line[0] == '/' && line[1] == '/') continue; if(sscanf(line, "%15s", name) < 1) continue; if(strcmp("map:", name) == 0 && sscanf(line, "%*s %15s", name) < 1) continue; name[MAP_NAME_LENGTH_EXT-1] = '\0'; remove_extension(name); if (find_map(name)) { ShowInfo("Map '"CL_WHITE"%s"CL_RESET"' already in cache.\n", name); } else if(!read_map(name, &map)) { ShowError("Map '"CL_WHITE"%s"CL_RESET"' not found!\n", name); } else if (!cache_map(name, &map)) { ShowError("Map '"CL_WHITE"%s"CL_RESET"' failed to cache (write error).\n", name); } else { ShowInfo("Map '"CL_WHITE"%s"CL_RESET"' successfully cached.\n", name); } } ShowStatus("Closing map list: %s\n", map_list_file); fclose(list); // Write the main header and close the map cache ShowStatus("Closing map cache: %s\n", map_cache_file); fseek(map_cache_fp, 0, SEEK_SET); fwrite(&header, sizeof(struct main_header), 1, map_cache_fp); fclose(map_cache_fp); ShowStatus("Finalizing grfio\n"); grfio_final(); ShowInfo("%d maps now in cache\n", header.map_count); aFree(grf_list_file); aFree(map_list_file); aFree(map_cache_file); return 0; }
////////////////// // // XPK fileformat: // chunk-based, crunched data in chunks // // File header: // starts as common IFF-style header: // - 4-byte ID, 'XPKF' // - 4-byte int for filesize minus header (8) // - 4-byte sub-type (cruncher-ID) e.g. 'SQSH' // - 4-byte int for total uncompressed length ? // - first 16-bytes of original file // - 1 byte for flags // - 1 byte for header checksum ? // - 1 byte for minor version of cruncher/library ? // - actually version required of sub-library.. // - 1 byte for major version of cruncher/library ? // bool XpkTags::ReadStreamHeader(CIOBuffer &Buffer) { // should have enough data to actually parse file header if (Buffer.GetSize() < sizeof(XpkStreamHeader)) { return false; } if (isXpkFile(Buffer.GetBegin()) == false) { return false; } Buffer.SetCurrentPos(0); // start at beginning if not already.. // set default m_formatType = XPKMODE_UPSTD; // "XPKF", 0x58504b46 (XPK_COOKIE, magic number) // note: support also XFD-packed files? ("XFDD") m_streamHeader.xsh_PackID = GetULong(Buffer.GetNext(4)); if (m_streamHeader.xsh_PackID != MakeTag("XPKF")) // this too ? && m_streamHeader.xsh_PackID != MakeTag("XFDD")) { return false; } // file length without IFF header (type+length = 8) ? m_streamHeader.xsh_CompressedLen = GetULong(Buffer.GetNext(4)); // keep packer type as type name/ID, // just access as-is m_typeName.assign((char*)Buffer.GetAtCurrent(), 4); // packer type, e.g. "SQSH", "NUKE", "RLEN".. m_streamHeader.xsh_PackerType = GetULong(Buffer.GetNext(4)); // TODO: check supported types..? if != MakeTag().. // -> caller/parent should do (knows libraries..) // uncompressed length? m_streamHeader.xsh_UnpackedLen = GetULong(Buffer.GetNext(4)); // first 16 bytes of original file ::memcpy(m_streamHeader.xsh_Initial, Buffer.GetNext(16), 16); // flags m_streamHeader.xsh_Flags = Buffer.GetNextByte(); /* // also check "XFDD", 0x58464444 in file ID? if (m_streamHeader.xsh_Flags & XMF_XFD && m_streamHeader.xsh_PackID == MakeTag("XFDD")) { m_formatType = XPKMODE_UPXFD; } if (m_streamHeader.xsh_Flags & XMF_PASSTHRU) { // unpacked? m_formatType = XPKMODE_UPUP; } if (m_streamHeader.xsh_Flags & XPKSTREAMF_PASSWORD) { // password-protected file? } */ // ..no idea.. header checksum? m_streamHeader.xsh_HeaderChk = Buffer.GetNextByte(); // minor&major version of XPK master/cruncher? m_streamHeader.xsh_SubVrs = Buffer.GetNextByte(); // sub-library version required? m_streamHeader.xsh_MasVrs = Buffer.GetNextByte(); // TODO: remove later, debug-test.. if (Buffer.GetCurrentPos() != sizeof(XpkStreamHeader)) { throw IOException("Read size does not match stream-header size"); } // non-zero header checksum? (note where doing checksumming..) if (hchecksum(Buffer.GetBegin(), sizeof(XpkStreamHeader)) != 0) { throw ArcException("Header checksum error", m_streamHeader.xsh_HeaderChk); } // has extended header? if (m_streamHeader.xsh_Flags & XPKSTREAMF_EXTHEADER) { // size of extended header if present? m_extHeaderLen = GetUWord(Buffer.GetNext(2)); /* // this done above.. if(!hookread(xbuf, XIO_READ, &exthlen, sizeof(UWORD))) goto Abort; -> exception // no read, just skip it?? if(!hookread(xbuf, XIO_READ, NULL, exthlen)) goto Abort; -> exception // later it is read anyway, why not just directly when detected? */ // increment by length-field size anyway.. m_extHeaderLen += sizeof(uint16_t); /* for unwinding while XpkExamine */ // note: increase buffer position by size of extended header? } // header parsed, should be valid file? return true; }
//================================================================ // PKImageDecode_WMP //================================================================ ERR ParsePFDEntry( PKImageDecode* pID, U16 uTag, U16 uType, U32 uCount, U32 uValue) { ERR err = WMP_errSuccess; PKPixelInfo PI; struct WMPStream* pWS = pID->pStream; size_t offPos = 0; union uf{ U32 uVal; Float fVal; }ufValue = {0}; //================================ switch (uTag) { case WMP_tagPixelFormat: { unsigned char *pGuid = (unsigned char *) &pID->guidPixFormat; /** following code is endian-agnostic **/ Call(GetULong(pWS, uValue, (unsigned long *)pGuid)); Call(GetUShort(pWS, uValue + 4, (unsigned short *)(pGuid + 4))); Call(GetUShort(pWS, uValue + 6, (unsigned short *)(pGuid + 6))); Call(pWS->Read(pWS, pGuid + 8, 8)); PI.pGUIDPixFmt = &pID->guidPixFormat; PixelFormatLookup(&PI, LOOKUP_FORWARD); pID->WMP.bHasAlpha = !!(PI.grBit & PK_pixfmtHasAlpha); pID->WMP.wmiI.cBitsPerUnit = PI.cbitUnit; pID->WMP.wmiI.bRGB = !(PI.grBit & PK_pixfmtBGR); break; } case WMP_tagImageWidth: FailIf(0 == uValue, WMP_errUnsupportedFormat); break; case WMP_tagImageHeight: FailIf(0 == uValue, WMP_errUnsupportedFormat); break; case WMP_tagImageOffset: FailIf(1 != uCount, WMP_errUnsupportedFormat); pID->WMP.wmiDEMisc.uImageOffset = uValue; break; case WMP_tagImageByteCount: FailIf(1 != uCount, WMP_errUnsupportedFormat); pID->WMP.wmiDEMisc.uImageByteCount = uValue; break; case WMP_tagAlphaOffset: FailIf(1 != uCount, WMP_errUnsupportedFormat); pID->WMP.wmiDEMisc.uAlphaOffset = uValue; break; case WMP_tagAlphaByteCount: FailIf(1 != uCount, WMP_errUnsupportedFormat); pID->WMP.wmiDEMisc.uAlphaByteCount = uValue; break; case WMP_tagWidthResolution: FailIf(1 != uCount, WMP_errUnsupportedFormat); ufValue.uVal = uValue; pID->fResX = ufValue.fVal; break; case WMP_tagHeightResolution: FailIf(1 != uCount, WMP_errUnsupportedFormat); ufValue.uVal = uValue; pID->fResY = ufValue.fVal; break; case WMP_tagXMPMetadata: case WMP_tagIccProfile: case WMP_tagEXIFMetadata: case WMP_tagTransformation: case WMP_tagCompression: case WMP_tagImageType: case WMP_tagImageDataDiscard: case WMP_tagAlphaDataDiscard: break; default: fprintf(stderr, "Unrecognized WMPTag: %d(%#x), %d, %d, %#x" CRLF, (int)uTag, (int)uTag, (int)uType, (int)uCount, (int)uValue); break; } Cleanup: return err; }
static bool InitLinkMap_32(MmapFile& irExec, MmapFile& irCore) { char* lpExecStart = irExec.GetStartAddr(); char* lpCoreStart = irCore.GetStartAddr(); char* lpCoreEnd = irCore.GetEndAddr(); Elf32_Ehdr* elfhdr = (Elf32_Ehdr*)lpExecStart; // search for .dynamic section Elf32_Dyn* dyn = NULL; #if defined(linux) Elf32_Xword dyn_size = 0; #elif defined(sun) Elf32_Word dyn_size = 0; #endif Elf32_Shdr* shdr = (Elf32_Shdr*)(lpExecStart + elfhdr->e_shoff); Elf32_Shdr* shstrtbl = shdr + elfhdr->e_shstrndx; char* shstr = lpExecStart + shstrtbl->sh_offset; for (int i=0; i < elfhdr->e_shnum; i++) { if (0 == strcmp(shstr+shdr->sh_name, ".dynamic") && shdr->sh_type == SHT_DYNAMIC) { dyn = (Elf32_Dyn*) shdr->sh_addr; dyn_size = shdr->sh_size; //printf("Exec's .dynamic section vaddr = 0x%lx\n", dyn); break; } shdr++; } if (!dyn) { printf("Failed to find Exec's .dynamic\n"); return false; } // The content of .dynamic section is in core Elf32_Dyn* core_dyn = (Elf32_Dyn*) core_to_mmap_addr((address_t)dyn); if (!core_dyn) { printf("Failed to find Exec's .dynamic section in core\n"); return false; } // Find the DT_DEBUG entry in the the .dynamic section. Elf32_Dyn* debug_dyn = NULL; for (dyn = core_dyn; (char*)dyn - (char*)core_dyn < dyn_size; dyn++) { if (GetUInt(&dyn->d_tag) == DT_DEBUG) { debug_dyn = dyn; break; } } if (!debug_dyn) { printf("Failed to find debug_dyn\n"); return false; } // If the executable's dynamic section has a DT_DEBUG element, // the run-time linker sets that element's value to the address // where this struct r_debug (link.h) can be found. struct r_debug_32* pdebug = (struct r_debug_32*)GetUInt(&debug_dyn->d_un.d_ptr); pdebug = (struct r_debug_32*) core_to_mmap_addr((address_t)pdebug); if (!pdebug) { printf("Failed to find link map in core\n"); return false; } gLinkMap_32 = (struct link_map_32 *) core_to_mmap_addr((address_t)GetUInt(&pdebug->r_map)); if (!gLinkMap_32) { printf("Failed to find link map in core\n"); return false; } // set executable and library segments. struct link_map_32 * linkmap = gLinkMap_32; while (linkmap && (char*)linkmap > lpCoreStart && (char*)linkmap < lpCoreEnd) { ca_segment* segment = NULL; #ifdef sun address_t load_addr = GetUInt(&linkmap->l_addr); if (! (segment = get_segment(load_addr, 1) ) ) break; #endif Elf32_Dyn* dyn = (Elf32_Dyn*) core_to_mmap_addr((address_t)GetUInt(&linkmap->l_ld)); for (; (char*)dyn >lpCoreStart && (char*)dyn < lpCoreEnd; dyn++) { #if defined(linux) Elf32_Xword tag = GetUInt(&dyn->d_tag); #elif defined(sun) Elf32_Sword tag = GetUInt(&dyn->d_tag); #endif if (tag == DT_NULL) break; #ifdef linux address_t vaddr = GetUInt(&dyn->d_un.d_ptr); #elif defined(sun) address_t vaddr = load_addr + GetUInt(&dyn->d_un.d_ptr); #endif if (vaddr) { // The segment is likely the same as previous dynamic section if (!segment || vaddr < segment->m_vaddr || vaddr >= segment->m_vaddr + segment->m_vsize) segment = get_segment(vaddr, 1); if (segment && segment->m_type == ENUM_UNKNOWN) { if (segment->m_write) segment->m_type = ENUM_MODULE_DATA; else segment->m_type = ENUM_MODULE_TEXT; segment->m_module_name = (char*) core_to_mmap_addr((address_t)GetUInt(&linkmap->l_name)); #ifdef linux if (segment->m_module_name == NULL) { if (linkmap == gLinkMap_32) segment->m_module_name = gpInputExecName; else segment->m_module_name = "/lib/ld-linux-x86-64.so.2"; } #endif } } } if ((address_t)GetUInt(&linkmap->l_next) == 0) break; linkmap = (struct link_map_32*) core_to_mmap_addr((address_t)GetULong(&linkmap->l_next)); if (linkmap == gLinkMap_32) break; } #ifdef CA_DEBUG linkmap = gLinkMap_32; for (int i=0; linkmap; i++) { char* name = (char*) core_to_mmap_addr((address_t)GetUInt(&linkmap->l_name)); // find the strtab void* strtab = NULL; dyn = (Elf32_Dyn*) core_to_mmap_addr((address_t)GetUInt(&linkmap->l_ld)); while (dyn && GetUInt(&dyn->d_tag)) { if (GetUInt(&dyn->d_tag) == DT_STRTAB) strtab = (void*)GetUInt(&dyn->d_un.d_ptr); dyn++; }; printf("[%d] base=[0x%lx] name=%s .dyn=0x%lx\n", i, GetUInt(&linkmap->l_addr), name, GetUInt(&linkmap->l_ld)); if (linkmap->l_next == 0) break; linkmap = (struct link_map_32*) core_to_mmap_addr((address_t)GetUInt(&linkmap->l_next)); if (linkmap == gLinkMap_32) break; } #endif return true; }
int do_init(int argc, char** argv) { /* setup pre-defined, #define-dependant */ map_cache_file = std::string(db_path) + "/" + std::string(DBPATH) + "map_cache.dat"; // Process the command-line arguments process_args(argc, argv); ShowStatus("Initializing grfio with %s\n", grf_list_file.c_str()); grfio_init(grf_list_file.c_str()); // Attempt to open the map cache file and force rebuild if not found ShowStatus("Opening map cache: %s\n", map_cache_file.c_str()); if(!rebuild) { map_cache_fp = fopen(map_cache_file.c_str(), "rb"); if(map_cache_fp == NULL) { ShowNotice("Existing map cache not found, forcing rebuild mode\n"); rebuild = 1; } else fclose(map_cache_fp); } if(rebuild) map_cache_fp = fopen(map_cache_file.c_str(), "w+b"); else map_cache_fp = fopen(map_cache_file.c_str(), "r+b"); if(map_cache_fp == NULL) { ShowError("Failure when opening map cache file %s\n", map_cache_file.c_str()); exit(EXIT_FAILURE); } // Open the map list FILE *list; std::vector<std::string> directories = { std::string(db_path) + "/", std::string(db_path) + "/" + std::string(DBIMPORT) + "/" }; for (const auto &directory : directories) { std::string filename = directory + map_list_file; ShowStatus("Opening map list: %s\n", filename.c_str()); list = fopen(filename.c_str(), "r"); if (list == NULL) { ShowError("Failure when opening maps list file %s\n", filename.c_str()); exit(EXIT_FAILURE); } // Initialize the main header if (rebuild) { header.file_size = sizeof(struct main_header); header.map_count = 0; } else { if (fread(&header, sizeof(struct main_header), 1, map_cache_fp) != 1) { printf("An error as occured while reading map_cache_fp \n"); } header.file_size = GetULong((unsigned char *)&(header.file_size)); header.map_count = GetUShort((unsigned char *)&(header.map_count)); } // Read and process the map list char line[1024]; while (fgets(line, sizeof(line), list)) { if (line[0] == '/' && line[1] == '/') continue; char name[MAP_NAME_LENGTH_EXT]; if (sscanf(line, "%15s", name) < 1) continue; if (strcmp("map:", name) == 0 && sscanf(line, "%*s %15s", name) < 1) continue; struct map_data map; name[MAP_NAME_LENGTH_EXT - 1] = '\0'; remove_extension(name); if (find_map(name)) ShowInfo("Map '" CL_WHITE "%s" CL_RESET "' already in cache.\n", name); else if (read_map(name, &map)) { cache_map(name, &map); ShowInfo("Map '" CL_WHITE "%s" CL_RESET "' successfully cached.\n", name); } else ShowError("Map '" CL_WHITE "%s" CL_RESET "' not found!\n", name); } ShowStatus("Closing map list: %s\n", filename.c_str()); fclose(list); } // Write the main header and close the map cache ShowStatus("Closing map cache: %s\n", map_cache_file.c_str()); fseek(map_cache_fp, 0, SEEK_SET); fwrite(&header, sizeof(struct main_header), 1, map_cache_fp); fclose(map_cache_fp); ShowStatus("Finalizing grfio\n"); grfio_final(); ShowInfo("%d maps now in cache\n", header.map_count); return 0; }