virtual physx::PxU32 write(const void* src, physx::PxU32 count) { if (size + (int)count > capacity) { int new_capacity = Math::maximum(size + (int)count, capacity + 4096); uint8* new_data = (uint8*)allocator.allocate(sizeof(uint8) * new_capacity); copyMemory(new_data, data, size); allocator.deallocate(data); data = new_data; capacity = new_capacity; } copyMemory(data + size, src, count); size += count; return count; }
void JsonSerializer::deserializeRawString(char* buffer, int max_length) { int size = Math::minimum(max_length - 1, m_token_size); copyMemory(buffer, m_token, size); buffer[size] = '\0'; deserializeToken(); }
virtual physx::PxU32 read(void* dest, physx::PxU32 count) { if (pos + (int)count <= size) { copyMemory(dest, data + pos, count); pos += count; return count; } else { copyMemory(dest, data + pos, size - pos); int real_count = size - pos; pos = size; return real_count; } }
float JsonSerializer::tokenToFloat() { char tmp[64]; int size = Math::minimum((int)sizeof(tmp) - 1, m_token_size); copyMemory(tmp, m_token, size); tmp[size] = '\0'; return (float)atof(tmp); }
// This function must not call malloc(), free(), or any other function that might // acquire a lock. Since 'thread' is suspended, trying to acquire a lock // will deadlock if 'thread' holds that lock. // This function, specifically the memory copying, was causing problems with Address Sanitizer in // apps. Since we cannot blacklist the system memcpy we must use our own naive implementation, // copyMemory, for ASan to work on either instrumented or non-instrumented builds. This is not a // significant performance loss as tryCopyOtherThreadStack is only called as part of an O(heapsize) // operation. As the heap is generally much larger than the stack the performance hit is minimal. // See: https://bugs.webkit.org/show_bug.cgi?id=146297 void MachineThreads::tryCopyOtherThreadStack(Thread* thread, void* buffer, size_t capacity, size_t* size) { Thread::Registers registers; size_t registersSize = thread->getRegisters(registers); std::pair<void*, size_t> stack = thread->captureStack(registers.stackPointer()); bool canCopy = *size + registersSize + stack.second <= capacity; if (canCopy) copyMemory(static_cast<char*>(buffer) + *size, ®isters, registersSize); *size += registersSize; if (canCopy) copyMemory(static_cast<char*>(buffer) + *size, stack.first, stack.second); *size += stack.second; thread->freeRegisters(registers); }
Ref<String> String::catenate (Iterator<String&> &str_iter) { unsigned long total_len = 0; while (!str_iter.done ()) { String &str = str_iter.next (); if (total_len + str.getLength () < total_len) { /* TODO This is questionable. I don't want to force * checking the return value, but abortIfReached() * is no good either. */ abortIfReached (); /* oopsMessage (); return NULL; */ } total_len += str.getLength (); } if (total_len == 0) return String::nullString (); Ref<String> ret_str = grab (new String ()); ret_str->allocate (total_len); str_iter.reset (); unsigned long pos = 0; while (!str_iter.done ()) { String &str = str_iter.next (); if (pos + str.getLength () < pos) { abortIfReached (); /* oopsMessage (); return NULL; */ } if (pos + str.getLength () > total_len) { abortIfReached (); /* oopsMessage (); return NULL; */ } copyMemory (ret_str->getMemoryDesc ().getRegionOffset (pos), str.getMemoryDesc ()); pos += str.getLength (); } ret_str->getData () [pos] = 0; return ret_str; }
void OutputBlob::write(const void* data, int size) { if (size) { int pos = m_data.size(); m_data.resize(m_data.size() + size); copyMemory(&m_data[0] + pos, data, size); } }
void OutputBlob::reserve(int size) { if (size <= m_size) return; ASSERT(m_allocator); uint8* tmp = (uint8*)m_allocator->allocate(size); copyMemory(tmp, m_data, m_size); m_allocator->deallocate(m_data); m_data = tmp; m_size = size; }
void OutputBlob::write(const void* data, int size) { if (!size) return; if (m_pos + size > m_size) { reserve((m_pos + size) << 1); } copyMemory((uint8*)m_data + m_pos, data, size); m_pos += size; }
static LLVMValueRef translateStringLit(ASTNode *Node) { int Length = strlen(Node->Value); LLVMValueRef GlobVar = LLVMAddGlobal(Module, LLVMArrayType(LLVMInt8Type(), Length+1), "global.var"); LLVMSetInitializer(GlobVar, LLVMConstString(Node->Value, Length, 0)); LLVMValueRef LocalVar = LLVMBuildAlloca(Builder, LLVMArrayType(LLVMInt8Type(), Length+1), "local.string."); LLVMValueRef LocalI8 = LLVMBuildBitCast(Builder, LocalVar, LLVMPointerType(LLVMInt8Type(), 0), ""); copyMemory(LocalI8, GlobVar, getSConstInt(Length+1)); return wrapValue(LocalI8); }
bool Clip::load(FS::IFile& file) { short* output = nullptr; auto res = stb_vorbis_decode_memory( (unsigned char*)file.getBuffer(), (int)file.size(), &m_channels, &m_sample_rate, &output); if (res <= 0) return false; m_data.resize(res * m_channels); copyMemory(&m_data[0], output, res * m_channels * sizeof(m_data[0])); free(output); return true; }
void JsonSerializer::deserialize(char* value, int max_length, const char* default_value) { if (!m_is_string_token) { copyString(value, max_length, default_value); } else { int size = Math::minimum(max_length - 1, m_token_size); copyMemory(value, m_token, size); value[size] = '\0'; deserializeToken(); } }
static LLVMValueRef translateArrayExpr(SymbolTable *TyTable, SymbolTable *ValTable, ASTNode *Node) { PtrVector *V = &(Node->Child); ASTNode *SizeNode = (ASTNode*) ptrVectorGet(V, 0), *InitNode = (ASTNode*) ptrVectorGet(V, 1); Type *ThisType = createType(IdTy, Node->Value); LLVMTypeRef ArrayType = getLLVMTypeFromType(TyTable, ThisType); LLVMValueRef SizeVal = translateExpr(TyTable, ValTable, SizeNode), InitVal = translateExpr(TyTable, ValTable, InitNode); LLVMValueRef ArrayVal = LLVMBuildArrayMalloc(Builder, ArrayType, SizeVal, ""); // This BasicBlock and ThisFunction LLVMBasicBlockRef ThisBB = LLVMGetInsertBlock(Builder); LLVMValueRef ThisFn = LLVMGetBasicBlockParent(ThisBB); LLVMValueRef Counter = LLVMBuildAlloca(Builder, LLVMInt32Type(), ""); LLVMBuildStore(Builder, LLVMConstInt(LLVMInt32Type(), 0, 1), Counter); LLVMTargetDataRef DataRef = LLVMCreateTargetData(LLVMGetDataLayout(Module)); unsigned long long Size = LLVMStoreSizeOfType(DataRef, ArrayType); LLVMBasicBlockRef InitBB, MidBB, EndBB; InitBB = LLVMAppendBasicBlock(ThisFn, "for.init"); EndBB = LLVMAppendBasicBlock(ThisFn, "for.end"); MidBB = LLVMAppendBasicBlock(ThisFn, "for.mid"); LLVMBuildBr(Builder, InitBB); LLVMPositionBuilderAtEnd(Builder, InitBB); LLVMValueRef CurrentCounter = LLVMBuildLoad(Builder, Counter, ""); LLVMValueRef Comparation = LLVMBuildICmp(Builder, LLVMIntSLT, CurrentCounter, SizeVal, ""); LLVMBuildCondBr(Builder, Comparation, MidBB, EndBB); LLVMPositionBuilderAtEnd(Builder, MidBB); CurrentCounter = LLVMBuildLoad(Builder, Counter, ""); LLVMValueRef TheValue = LLVMBuildLoad(Builder, InitVal, ""); LLVMValueRef ElemIdx[] = { LLVMConstInt(LLVMInt32Type(), 0, 1), CurrentCounter }; LLVMValueRef Elem = LLVMBuildInBoundsGEP(Builder, ArrayVal, ElemIdx, 2, ""); copyMemory(Elem, TheValue, getSConstInt(Size)); LLVMBuildBr(Builder, InitBB); LLVMPositionBuilderAtEnd(Builder, EndBB); return ArrayVal; }
bool InputBlob::read(void* data, int size) { if (m_pos + (int)size > m_size) { for (int32 i = 0; i < size; ++i) ((unsigned char*)data)[i] = 0; return false; } if (size) { copyMemory(data, ((char*)m_data) + m_pos, size); } m_pos += size; return true; }
OutputBlob::OutputBlob(const OutputBlob& blob, IAllocator& allocator) : m_allocator(&allocator) , m_pos(blob.m_pos) { if (blob.m_size > 0) { m_data = allocator.allocate(blob.m_size); copyMemory(m_data, blob.m_data, blob.m_size); m_size = blob.m_size; } else { m_data = nullptr; m_size = 0; } }
OutputBlob::OutputBlob(const InputBlob& blob, IAllocator& allocator) : m_allocator(&allocator) , m_pos(blob.getSize()) { if (blob.getSize() > 0) { m_data = allocator.allocate(blob.getSize()); copyMemory(m_data, blob.getData(), blob.getSize()); m_size = blob.getSize(); } else { m_data = nullptr; m_size = 0; } }
OutputBlob::OutputBlob(const OutputBlob& rhs) { m_allocator = rhs.m_allocator; m_pos = rhs.m_pos; if (rhs.m_size > 0) { m_data = m_allocator->allocate(rhs.m_size); copyMemory(m_data, rhs.m_data, rhs.m_size); m_size = rhs.m_size; } else { m_data = nullptr; m_size = 0; } }
void JsonSerializer::deserialize(Path& value, const Path& default_value) { if (!m_is_string_token) { value = default_value; } else { char tmp[MAX_PATH_LENGTH]; int size = Math::minimum(lengthOf(tmp) - 1, m_token_size); copyMemory(tmp, m_token, size); tmp[size] = '\0'; value = tmp; deserializeToken(); } }
void* Allocator::reallocate(void* user_ptr, size_t size) { #ifndef _DEBUG return m_source.reallocate(user_ptr, size); #else if (user_ptr == nullptr) return allocate(size); if (size == 0) return nullptr; void* new_data = allocate(size); if (!new_data) return nullptr; AllocationInfo* info = getAllocationInfoFromUser(user_ptr); copyMemory(new_data, user_ptr, info->m_size < size ? info->m_size : size); deallocate(user_ptr); return new_data; #endif }
void JsonSerializer::deserializeArrayItem(char* value, int max_length, const char* default_value) { deserializeArrayComma(); if (m_is_string_token) { int size = Math::minimum(max_length - 1, m_token_size); copyMemory(value, m_token, size); value[size] = '\0'; deserializeToken(); } else { ErrorProxy(*this).log() << "Unexpected token \"" << string(m_token, m_token_size, m_allocator) << "\", expected string."; deserializeToken(); copyString(value, max_length, default_value); } }
void OutputBlob::operator =(const OutputBlob& rhs) { ASSERT(rhs.m_allocator); if (m_allocator) m_allocator->deallocate(m_data); m_allocator = rhs.m_allocator; m_pos = rhs.m_pos; if (rhs.m_size > 0) { m_data = m_allocator->allocate(rhs.m_size); copyMemory(m_data, rhs.m_data, rhs.m_size); m_size = rhs.m_size; } else { m_data = nullptr; m_size = 0; } }
void Model::create(const bgfx::VertexDecl& def, Material* material, const int* indices_data, int indices_size, const void* attributes_data, int attributes_size) { ASSERT(!bgfx::isValid(m_vertices_handle)); m_vertices_handle = bgfx::createVertexBuffer(bgfx::copy(attributes_data, attributes_size), def); m_vertices_size = attributes_size; ASSERT(!bgfx::isValid(m_indices_handle)); auto* mem = bgfx::copy(indices_data, indices_size); m_indices_handle = bgfx::createIndexBuffer(mem, BGFX_BUFFER_INDEX32); m_indices_size = indices_size; m_meshes.emplace(def, material, 0, attributes_size, 0, indices_size / int(sizeof(int)), "default", m_allocator); Model::LOD lod; lod.m_distance = FLT_MAX; lod.m_from_mesh = 0; lod.m_to_mesh = 0; m_lods.push(lod); m_indices.resize(indices_size / sizeof(m_indices[0])); copyMemory(&m_indices[0], indices_data, indices_size); m_vertices.resize(attributes_size / def.getStride()); computeRuntimeData((const uint8*)attributes_data); onCreated(State::READY); }
void Texture::onDataUpdated(int x, int y, int w, int h) { const bgfx::Memory* mem = nullptr; if (m_BPP == 2) { const uint16* src_mem = (const uint16*)&m_data[0]; mem = bgfx::alloc(w * h * sizeof(float)); float* dst_mem = (float*)mem->data; for (int j = 0; j < h; ++j) { for (int i = 0; i < w; ++i) { dst_mem[i + j * w] = src_mem[x + i + (y + j) * m_width] / 65535.0f; } } } else { const uint8* src_mem = (const uint8*)&m_data[0]; mem = bgfx::alloc(w * h * m_BPP); uint8* dst_mem = mem->data; for (int j = 0; j < h; ++j) { for (int i = 0; i < w; ++i) { copyMemory(&dst_mem[(i + j * w) * m_BPP], &src_mem[(x + i + (y + j) * m_width) * m_BPP], m_BPP); } } } bgfx::updateTexture2D( m_texture_handle, 0, (uint16_t)x, (uint16_t)y, (uint16_t)w, (uint16_t)h, mem); }
bool Model::parseMeshes(const bgfx::VertexDecl& global_vertex_decl, FS::IFile& file, FileVersion version, u32 global_flags) { if (version <= FileVersion::MULTIPLE_VERTEX_DECLS) return parseMeshesOld(global_vertex_decl, file, version, global_flags); int object_count = 0; file.read(&object_count, sizeof(object_count)); if (object_count <= 0) return false; char model_dir[MAX_PATH_LENGTH]; PathUtils::getDir(model_dir, MAX_PATH_LENGTH, getPath().c_str()); m_meshes.reserve(object_count); for (int i = 0; i < object_count; ++i) { bgfx::VertexDecl vertex_decl; if (!parseVertexDeclEx(file, &vertex_decl)) return false; i32 str_size; file.read(&str_size, sizeof(str_size)); char material_name[MAX_PATH_LENGTH]; file.read(material_name, str_size); if (str_size >= MAX_PATH_LENGTH) return false; material_name[str_size] = 0; char material_path[MAX_PATH_LENGTH]; copyString(material_path, model_dir); catString(material_path, material_name); catString(material_path, ".mat"); auto* material_manager = m_resource_manager.getOwner().get(Material::TYPE); Material* material = static_cast<Material*>(material_manager->load(Path(material_path))); file.read(&str_size, sizeof(str_size)); char mesh_name[MAX_PATH_LENGTH]; mesh_name[str_size] = 0; file.read(mesh_name, str_size); m_meshes.emplace(material, vertex_decl, mesh_name, m_allocator); addDependency(*material); } for (int i = 0; i < object_count; ++i) { Mesh& mesh = m_meshes[i]; int index_size; int indices_count; file.read(&index_size, sizeof(index_size)); if (index_size != 2 && index_size != 4) return false; file.read(&indices_count, sizeof(indices_count)); if (indices_count <= 0) return false; mesh.indices.resize(index_size * indices_count); file.read(&mesh.indices[0], mesh.indices.size()); if (index_size == 2) mesh.flags.set(Mesh::Flags::INDICES_16_BIT); mesh.indices_count = indices_count; const bgfx::Memory* indices_mem = bgfx::copy(&mesh.indices[0], mesh.indices.size()); mesh.index_buffer_handle = bgfx::createIndexBuffer(indices_mem); } for (int i = 0; i < object_count; ++i) { Mesh& mesh = m_meshes[i]; int data_size; file.read(&data_size, sizeof(data_size)); const bgfx::Memory* vertices_mem = bgfx::alloc(data_size); file.read(vertices_mem->data, vertices_mem->size); const bgfx::VertexDecl& vertex_decl = mesh.vertex_decl; int position_attribute_offset = vertex_decl.getOffset(bgfx::Attrib::Position); int uv_attribute_offset = vertex_decl.getOffset(bgfx::Attrib::TexCoord0); int weights_attribute_offset = vertex_decl.getOffset(bgfx::Attrib::Weight); int bone_indices_attribute_offset = vertex_decl.getOffset(bgfx::Attrib::Indices); bool keep_skin = vertex_decl.has(bgfx::Attrib::Weight) && vertex_decl.has(bgfx::Attrib::Indices); int vertex_size = mesh.vertex_decl.getStride(); int mesh_vertex_count = vertices_mem->size / mesh.vertex_decl.getStride(); mesh.vertices.resize(mesh_vertex_count); mesh.uvs.resize(mesh_vertex_count); if (keep_skin) mesh.skin.resize(mesh_vertex_count); const u8* vertices = vertices_mem->data; for (int j = 0; j < mesh_vertex_count; ++j) { int offset = j * vertex_size; if (keep_skin) { mesh.skin[j].weights = *(const Vec4*)&vertices[offset + weights_attribute_offset]; copyMemory(mesh.skin[j].indices, &vertices[offset + bone_indices_attribute_offset], sizeof(mesh.skin[j].indices)); } mesh.vertices[j] = *(const Vec3*)&vertices[offset + position_attribute_offset]; mesh.uvs[j] = *(const Vec2*)&vertices[offset + uv_attribute_offset]; } mesh.vertex_buffer_handle = bgfx::createVertexBuffer(vertices_mem, mesh.vertex_decl); } file.read(&m_bounding_radius, sizeof(m_bounding_radius)); file.read(&m_aabb, sizeof(m_aabb)); return true; }
bool Model::parseMeshesOld(bgfx::VertexDecl global_vertex_decl, FS::IFile& file, FileVersion version, u32 global_flags) { int object_count = 0; file.read(&object_count, sizeof(object_count)); if (object_count <= 0) return false; m_meshes.reserve(object_count); char model_dir[MAX_PATH_LENGTH]; PathUtils::getDir(model_dir, MAX_PATH_LENGTH, getPath().c_str()); struct Offsets { i32 attribute_array_offset; i32 attribute_array_size; i32 indices_offset; i32 mesh_tri_count; }; Array<Offsets> mesh_offsets(m_allocator); for (int i = 0; i < object_count; ++i) { i32 str_size; file.read(&str_size, sizeof(str_size)); char material_name[MAX_PATH_LENGTH]; file.read(material_name, str_size); if (str_size >= MAX_PATH_LENGTH) return false; material_name[str_size] = 0; char material_path[MAX_PATH_LENGTH]; copyString(material_path, model_dir); catString(material_path, material_name); catString(material_path, ".mat"); auto* material_manager = m_resource_manager.getOwner().get(Material::TYPE); Material* material = static_cast<Material*>(material_manager->load(Path(material_path))); Offsets& offsets = mesh_offsets.emplace(); file.read(&offsets.attribute_array_offset, sizeof(offsets.attribute_array_offset)); file.read(&offsets.attribute_array_size, sizeof(offsets.attribute_array_size)); file.read(&offsets.indices_offset, sizeof(offsets.indices_offset)); file.read(&offsets.mesh_tri_count, sizeof(offsets.mesh_tri_count)); file.read(&str_size, sizeof(str_size)); if (str_size >= MAX_PATH_LENGTH) { material_manager->unload(*material); return false; } char mesh_name[MAX_PATH_LENGTH]; mesh_name[str_size] = 0; file.read(mesh_name, str_size); bgfx::VertexDecl vertex_decl = global_vertex_decl; if (version <= FileVersion::SINGLE_VERTEX_DECL) { parseVertexDecl(file, &vertex_decl); if (i != 0 && global_vertex_decl.m_hash != vertex_decl.m_hash) { g_log_error.log("Renderer") << "Model " << getPath().c_str() << " contains meshes with different vertex declarations."; } if(i == 0) global_vertex_decl = vertex_decl; } m_meshes.emplace(material, vertex_decl, mesh_name, m_allocator); addDependency(*material); } i32 indices_count = 0; file.read(&indices_count, sizeof(indices_count)); if (indices_count <= 0) return false; u32 INDICES_16BIT_FLAG = 1; int index_size = global_flags & INDICES_16BIT_FLAG ? 2 : 4; Array<u8> indices(m_allocator); indices.resize(indices_count * index_size); file.read(&indices[0], indices.size()); i32 vertices_size = 0; file.read(&vertices_size, sizeof(vertices_size)); if (vertices_size <= 0) return false; Array<u8> vertices(m_allocator); vertices.resize(vertices_size); file.read(&vertices[0], vertices.size()); int vertex_count = 0; for (const Offsets& offsets : mesh_offsets) { vertex_count += offsets.attribute_array_size / global_vertex_decl.getStride(); } if (version > FileVersion::BOUNDING_SHAPES_PRECOMPUTED) { file.read(&m_bounding_radius, sizeof(m_bounding_radius)); file.read(&m_aabb, sizeof(m_aabb)); } float bounding_radius_squared = 0; Vec3 min_vertex(0, 0, 0); Vec3 max_vertex(0, 0, 0); int vertex_size = global_vertex_decl.getStride(); int position_attribute_offset = global_vertex_decl.getOffset(bgfx::Attrib::Position); int uv_attribute_offset = global_vertex_decl.getOffset(bgfx::Attrib::TexCoord0); int weights_attribute_offset = global_vertex_decl.getOffset(bgfx::Attrib::Weight); int bone_indices_attribute_offset = global_vertex_decl.getOffset(bgfx::Attrib::Indices); bool keep_skin = global_vertex_decl.has(bgfx::Attrib::Weight) && global_vertex_decl.has(bgfx::Attrib::Indices); for (int i = 0; i < m_meshes.size(); ++i) { Offsets& offsets = mesh_offsets[i]; Mesh& mesh = m_meshes[i]; mesh.indices_count = offsets.mesh_tri_count * 3; mesh.indices.resize(mesh.indices_count * index_size); copyMemory(&mesh.indices[0], &indices[offsets.indices_offset * index_size], mesh.indices_count * index_size); int mesh_vertex_count = offsets.attribute_array_size / global_vertex_decl.getStride(); int mesh_attributes_array_offset = offsets.attribute_array_offset; mesh.vertices.resize(mesh_vertex_count); mesh.uvs.resize(mesh_vertex_count); if (keep_skin) mesh.skin.resize(mesh_vertex_count); for (int j = 0; j < mesh_vertex_count; ++j) { int offset = mesh_attributes_array_offset + j * vertex_size; if (keep_skin) { mesh.skin[j].weights = *(const Vec4*)&vertices[offset + weights_attribute_offset]; copyMemory(mesh.skin[j].indices, &vertices[offset + bone_indices_attribute_offset], sizeof(mesh.skin[j].indices)); } mesh.vertices[j] = *(const Vec3*)&vertices[offset + position_attribute_offset]; mesh.uvs[j] = *(const Vec2*)&vertices[offset + uv_attribute_offset]; float sq_len = mesh.vertices[j].squaredLength(); bounding_radius_squared = Math::maximum(bounding_radius_squared, sq_len > 0 ? sq_len : 0); min_vertex.x = Math::minimum(min_vertex.x, mesh.vertices[j].x); min_vertex.y = Math::minimum(min_vertex.y, mesh.vertices[j].y); min_vertex.z = Math::minimum(min_vertex.z, mesh.vertices[j].z); max_vertex.x = Math::maximum(max_vertex.x, mesh.vertices[j].x); max_vertex.y = Math::maximum(max_vertex.y, mesh.vertices[j].y); max_vertex.z = Math::maximum(max_vertex.z, mesh.vertices[j].z); } } if (version <= FileVersion::BOUNDING_SHAPES_PRECOMPUTED) { m_bounding_radius = sqrt(bounding_radius_squared); m_aabb = AABB(min_vertex, max_vertex); } for (int i = 0; i < m_meshes.size(); ++i) { Mesh& mesh = m_meshes[i]; Offsets offsets = mesh_offsets[i]; ASSERT(!bgfx::isValid(mesh.index_buffer_handle)); if (global_flags & INDICES_16BIT_FLAG) { mesh.flags.set(Mesh::Flags::INDICES_16_BIT); } int indices_size = index_size * mesh.indices_count; const bgfx::Memory* mem = bgfx::copy(&indices[offsets.indices_offset * index_size], indices_size); mesh.index_buffer_handle = bgfx::createIndexBuffer(mem, index_size == 4 ? BGFX_BUFFER_INDEX32 : 0); if (!bgfx::isValid(mesh.index_buffer_handle)) return false; ASSERT(!bgfx::isValid(mesh.vertex_buffer_handle)); const bgfx::Memory* vertices_mem = bgfx::copy(&vertices[offsets.attribute_array_offset], offsets.attribute_array_size); mesh.vertex_buffer_handle = bgfx::createVertexBuffer(vertices_mem, mesh.vertex_decl); if (!bgfx::isValid(mesh.vertex_buffer_handle)) return false; } return true; }
static RestoreSaveResult restoreSaveStateFromFile(CPU *cpu, MMU *mmu, const char *romName, int saveSlot) { CO_ASSERT(saveSlot >= 0 && saveSlot <= 9); char *tmpROMNamePtr = mmu->romName; CartRAMPlatformState tmpCartRAMPlatformState = mmu->cartRAMPlatformState; u8 *tmpROM = mmu->romData; char tmpROMName[MAX_ROM_NAME_LEN + 1] = {}; CPU backupCPU = *cpu; MMU backupMMU = *mmu; char *saveStateFileName = nullptr; buf_gen_memory_printf(saveStateFileName, "%s_%d.gbes", romName, saveSlot); FILE *f = fopen(saveStateFileName, "rb"); if (!f) { return RestoreSaveResult::NothingInSlot; } buf_gen_memory_free(saveStateFileName); SerializingState ss; ss.f = f; ss.isWriting = false; auto res = serialize(&ss.version, &ss); if (res != FileSystemResultCode::OK) { CO_ERR("Could not read version number of save state"); return RestoreSaveResult::Error; } res = serialize(tmpROMName, mmu->romNameLen, &ss); if (res != FileSystemResultCode::OK) { CO_ERR("Could not restore game state save. Could not read rom name."); fclose(f); return RestoreSaveResult::Error; } if (!areStringsEqual(romName, tmpROMName, mmu->romNameLen)) { CO_ERR("Save state is not for this rom! Actual %s, Expected %s", tmpROMName, romName); fclose(f); return RestoreSaveResult::Error; } res = serialize(cpu, &ss); if (res != FileSystemResultCode::OK) { CO_ERR("Could not load game state. Could not load CPU."); goto error; } res = serialize(mmu, &ss); if (res != FileSystemResultCode::OK) { CO_ERR("Could not load game state. Could not load MMU."); goto error; } if (mmu->hasRAM && mmu->hasBattery) { mmu->cartRAMPlatformState = tmpCartRAMPlatformState; usize expectedRAMLen = (usize)mmu->cartRAMSize; if (mmu->hasRTC) expectedRAMLen += sizeof(RTCFileState); if (expectedRAMLen != mmu->cartRAMPlatformState.ramLen) { goto error; } copyMemory(mmu->cartRAM, mmu->cartRAMPlatformState.cartRAMFileMap, mmu->cartRAMSize); } mmu->romName = tmpROMNamePtr; mmu->romData = tmpROM; fclose(f); return RestoreSaveResult::Success; error: *cpu = backupCPU; *mmu = backupMMU; fclose(f); return RestoreSaveResult::Error; }
void PEFormat::save(SharedPtr<DataSource> target) { //1. Preparation List<IMAGE_SECTION_HEADER> sectionHeaders; Map<uint32_t, uint32_t> rawDataMap; const uint32_t sectionAlignment = 0x1000; const uint32_t fileAlignment = 0x200; uint32_t imageSize = 0; uint32_t dataOffset = 0x400; for(auto &i : sections_) { IMAGE_SECTION_HEADER sectionHeader; zeroMemory(§ionHeader, sizeof(sectionHeader)); copyMemory(sectionHeader.Name, &i.name[0], i.name.length() + 1); sectionHeader.VirtualAddress = static_cast<uint32_t>(i.baseAddress); sectionHeader.VirtualSize = static_cast<uint32_t>(i.size); sectionHeader.SizeOfRawData = multipleOf(i.data->size(), fileAlignment); if(sectionHeader.SizeOfRawData) sectionHeader.PointerToRawData = dataOffset; else sectionHeader.PointerToRawData = 0; sectionHeader.Characteristics = 0; if(i.flag & SectionFlagData) sectionHeader.Characteristics |= IMAGE_SCN_CNT_INITIALIZED_DATA; if(i.flag & SectionFlagUninitializedData) sectionHeader.Characteristics |= IMAGE_SCN_CNT_UNINITIALIZED_DATA; if(i.flag & SectionFlagCode) sectionHeader.Characteristics |= IMAGE_SCN_CNT_CODE; if(i.flag & SectionFlagRead) sectionHeader.Characteristics |= IMAGE_SCN_MEM_READ; if(i.flag & SectionFlagWrite) sectionHeader.Characteristics |= IMAGE_SCN_MEM_WRITE; if(i.flag & SectionFlagExecute) sectionHeader.Characteristics |= IMAGE_SCN_MEM_EXECUTE; sectionHeaders.push_back(sectionHeader); rawDataMap.insert(sectionHeader.VirtualAddress, dataOffset); dataOffset += sectionHeader.SizeOfRawData; imageSize = multipleOf(sectionHeader.VirtualAddress + sectionHeader.VirtualSize, sectionAlignment); } //2. Write headers uint8_t *originalHeader = header_->get(); uint8_t *targetMap = target->map(0); IMAGE_DOS_HEADER *dosHeader = getStructureAtOffset<IMAGE_DOS_HEADER>(originalHeader, 0); IMAGE_FILE_HEADER fileHeader; IMAGE_OPTIONAL_HEADER_BASE optionalHeaderBase; const uint32_t ntSignature = IMAGE_NT_SIGNATURE; copyMemory(&fileHeader, getStructureAtOffset<IMAGE_FILE_HEADER>(originalHeader, dosHeader->e_lfanew + sizeof(uint32_t)), sizeof(IMAGE_FILE_HEADER)); copyMemory(&optionalHeaderBase, getStructureAtOffset<IMAGE_OPTIONAL_HEADER_BASE>(originalHeader, dosHeader->e_lfanew + sizeof(uint32_t) + sizeof(IMAGE_FILE_HEADER)), sizeof(IMAGE_OPTIONAL_HEADER_BASE)); fileHeader.NumberOfSections = sections_.size(); size_t offset = 0; copyMemory(targetMap, originalHeader, dosHeader->e_lfanew); offset += dosHeader->e_lfanew; copyMemory(targetMap + offset, &ntSignature, sizeof(ntSignature)); offset += sizeof(ntSignature); copyMemory(targetMap + offset, &fileHeader, sizeof(IMAGE_FILE_HEADER)); offset += sizeof(IMAGE_FILE_HEADER); if(info_.architecture == ArchitectureWin32) { IMAGE_OPTIONAL_HEADER32 optionalHeader; copyMemory(&optionalHeader, getStructureAtOffset<IMAGE_OPTIONAL_HEADER32>(originalHeader, offset), sizeof(IMAGE_OPTIONAL_HEADER32)); optionalHeader.SizeOfImage = imageSize; optionalHeader.FileAlignment = fileAlignment; optionalHeader.SectionAlignment = sectionAlignment; copyMemory(targetMap + offset, &optionalHeader, sizeof(IMAGE_OPTIONAL_HEADER32)); offset += sizeof(IMAGE_OPTIONAL_HEADER32); } else if(info_.architecture == ArchitectureWin32AMD64) { IMAGE_OPTIONAL_HEADER64 optionalHeader; copyMemory(&optionalHeader, getStructureAtOffset<IMAGE_OPTIONAL_HEADER64>(originalHeader, offset), sizeof(IMAGE_OPTIONAL_HEADER64)); optionalHeader.SizeOfImage = sectionAlignment; optionalHeader.FileAlignment = fileAlignment; optionalHeader.SectionAlignment = sectionAlignment; copyMemory(targetMap + offset, &optionalHeader, sizeof(IMAGE_OPTIONAL_HEADER64)); offset += sizeof(IMAGE_OPTIONAL_HEADER64); } for(auto &i : sectionHeaders) { copyMemory(targetMap + offset, &i, sizeof(IMAGE_SECTION_HEADER)); offset += sizeof(IMAGE_SECTION_HEADER); } for(auto &i : sections_) { dataOffset = rawDataMap[static_cast<uint32_t>(i.baseAddress)]; copyMemory(targetMap + dataOffset, i.data->get(), i.data->size()); } target->unmap(); }