示例#1
0
bool CConfigDB::WriteFile(EConfigNamespace ns, const VfsPath& path)
{
	if (ns < 0 || ns >= CFG_LAST)
	{
		debug_warn(L"CConfigDB: Invalid ns value");
		return false;
	}

	shared_ptr<u8> buf;
	AllocateAligned(buf, 1*MiB, maxSectorSize);
	char* pos = (char*)buf.get();
	TConfigMap &map=m_Map[ns];
	for(TConfigMap::const_iterator it = map.begin(); it != map.end(); ++it)
	{
		pos += sprintf(pos, "%s = \"%s\"\n", it->first.c_str(), it->second[0].m_String.c_str());
	}
	const size_t len = pos - (char*)buf.get();

	Status ret = g_VFS->CreateFile(path, buf, len);
	if(ret < 0)
	{
		LOGERROR(L"CConfigDB::WriteFile(): CreateFile \"%ls\" failed (error: %d)", path.string().c_str(), (int)ret);
		return false;
	}

	return true;
}
示例#2
0
文件: Util.cpp 项目: krichter722/0ad
// <extension> identifies the file format that is to be written
// (case-insensitive). examples: "bmp", "png", "jpg".
// BMP is good for quick output at the expense of large files.
void WriteScreenshot(const VfsPath& extension)
{
    // get next available numbered filename
    // note: %04d -> always 4 digits, so sorting by filename works correctly.
    const VfsPath basenameFormat(L"screenshots/screenshot%04d");
    const VfsPath filenameFormat = basenameFormat.ChangeExtension(extension);
    VfsPath filename;
    vfs::NextNumberedFilename(g_VFS, filenameFormat, s_nextScreenshotNumber, filename);

    const size_t w = (size_t)g_xres, h = (size_t)g_yres;
    const size_t bpp = 24;
    GLenum fmt = GL_RGB;
    int flags = TEX_BOTTOM_UP;
    // we want writing BMP to be as fast as possible,
    // so read data from OpenGL in BMP format to obviate conversion.
    if(extension == L".bmp")
    {
#if !CONFIG2_GLES // GLES doesn't support BGR
        fmt = GL_BGR;
        flags |= TEX_BGR;
#endif
    }

    // Hide log messages and re-render
    RenderLogger(false);
    Render();
    RenderLogger(true);

    const size_t img_size = w * h * bpp/8;
    const size_t hdr_size = tex_hdr_size(filename);
    shared_ptr<u8> buf;
    AllocateAligned(buf, hdr_size+img_size, maxSectorSize);
    GLvoid* img = buf.get() + hdr_size;
    Tex t;
    if(t.wrap(w, h, bpp, flags, buf, hdr_size) < 0)
        return;
    glReadPixels(0, 0, (GLsizei)w, (GLsizei)h, fmt, GL_UNSIGNED_BYTE, img);

    if (tex_write(&t, filename) == INFO::OK)
    {
        OsPath realPath;
        g_VFS->GetRealPath(filename, realPath);

        LOGMESSAGERENDER(g_L10n.Translate("Screenshot written to '%s'"), realPath.string8());

        debug_printf(
            CStr(g_L10n.Translate("Screenshot written to '%s'") + "\n").c_str(),
            realPath.string8().c_str());
    }
    else
        LOGERROR("Error writing screenshot to '%s'", filename.string8());
}
示例#3
0
void WriteBuffer::Append(const void* data, size_t size)
{
	if(m_size + size > m_capacity)
	{
		m_capacity = round_up_to_pow2(m_size + size);
		shared_ptr<u8> newData;
		AllocateAligned(newData, m_capacity, maxSectorSize);
		memcpy(newData.get(), m_data.get(), m_size);
		m_data = newData;
	}

	memcpy(m_data.get() + m_size, data, size);
	m_size += size;
}
示例#4
0
bool XMLWriter_File::StoreVFS(const PIVFS& vfs, const VfsPath& pathname)
{
	if (m_LastElement) debug_warn(L"ERROR: Saving XML while an element is still open");

	const size_t size = m_Data.length();
	shared_ptr<u8> data;
	AllocateAligned(data, size, maxSectorSize);
	memcpy(data.get(), m_Data.data(), size);
	Status ret = vfs->CreateFile(pathname, data, size);
	if (ret < 0)
	{
		LOGERROR(L"Error saving XML data through VFS: %lld '%ls'", (long long)ret, pathname.string().c_str());
		return false;
	}
	return true;
}
示例#5
0
// split out of png_decode to simplify resource cleanup and avoid
// "dtor / setjmp interaction" warning.
static Status png_decode_impl(DynArray* da, png_structp png_ptr, png_infop info_ptr, Tex* t)
{
	png_set_read_fn(png_ptr, da, io_read);

	// read header and determine format
	png_read_info(png_ptr, info_ptr);
	png_uint_32 w, h;
	int bit_depth, colour_type;
	png_get_IHDR(png_ptr, info_ptr, &w, &h, &bit_depth, &colour_type, 0, 0, 0);
	const size_t pitch = png_get_rowbytes(png_ptr, info_ptr);
	const u32 bpp = (u32)(pitch/w * 8);

	size_t flags = 0;
	if(bpp == 32)
		flags |= TEX_ALPHA;
	if(colour_type == PNG_COLOR_TYPE_GRAY)
		flags |= TEX_GREY;

	// make sure format is acceptable
	if(bit_depth != 8)
		WARN_RETURN(ERR::TEX_NOT_8BIT_PRECISION);
	if(colour_type & PNG_COLOR_MASK_PALETTE)
		WARN_RETURN(ERR::TEX_INVALID_COLOR_TYPE);

	const size_t img_size = pitch * h;
	shared_ptr<u8> data;
	AllocateAligned(data, img_size, pageSize);

	std::vector<RowPtr> rows = tex_codec_alloc_rows(data.get(), h, pitch, TEX_TOP_DOWN, 0);
	png_read_image(png_ptr, (png_bytepp)&rows[0]);
	png_read_end(png_ptr, info_ptr);

	// success; make sure all data was consumed.
	ENSURE(da->pos == da->cur_size);

	// store image info
	t->data  = data;
	t->dataSize = img_size;
	t->ofs   = 0;
	t->w     = w;
	t->h     = h;
	t->bpp   = bpp;
	t->flags = flags;

	return INFO::OK;
}
示例#6
0
	virtual Status LoadFile(const VfsPath& pathname, shared_ptr<u8>& fileContents, size_t& size)
	{
		ScopedLock s;
		const bool isCacheHit = m_fileCache.Retrieve(pathname, fileContents, size);
		if(!isCacheHit)
		{
			VfsDirectory* directory; VfsFile* file;
			// per 2010-05-01 meeting, this shouldn't raise 'scary error
			// dialogs', which might fail to display the culprit pathname
			// instead, callers should log the error, including pathname.
			RETURN_STATUS_IF_ERR(vfs_Lookup(pathname, &m_rootDirectory, directory, &file));

			fileContents = DummySharedPtr((u8*)0);
			size = file->Size();
			if(size != 0)	// (the file cache can't handle zero-length allocations)
			{
				if(size < m_cacheSize/2)	// (avoid evicting lots of previous data)
					fileContents = m_fileCache.Reserve(size);
				if(fileContents)
				{
					RETURN_STATUS_IF_ERR(file->Loader()->Load(file->Name(), fileContents, file->Size()));
					m_fileCache.Add(pathname, fileContents, size);
				}
				else
				{
					RETURN_STATUS_IF_ERR(AllocateAligned(fileContents, size, maxSectorSize));
					RETURN_STATUS_IF_ERR(file->Loader()->Load(file->Name(), fileContents, file->Size()));
				}
			}
		}

		stats_io_user_request(size);
		stats_cache(isCacheHit? CR_HIT : CR_MISS, size);
		m_trace->NotifyLoad(pathname, size);

		return INFO::OK;
	}
示例#7
0
		/**
		 * Debug function for AI scripts to dump 2D array data (e.g. terrain tile weights).
		 */
		static void DumpImage(void* UNUSED(cbdata), std::wstring name, std::vector<u32> data, u32 w, u32 h, u32 max)
		{
			// TODO: this is totally not threadsafe.

			VfsPath filename = L"screenshots/aidump/" + name;

			if (data.size() != w*h)
			{
				debug_warn(L"DumpImage: data size doesn't match w*h");
				return;
			}

			if (max == 0)
			{
				debug_warn(L"DumpImage: max must not be 0");
				return;
			}

			const size_t bpp = 8;
			int flags = TEX_BOTTOM_UP|TEX_GREY;

			const size_t img_size = w * h * bpp/8;
			const size_t hdr_size = tex_hdr_size(filename);
			shared_ptr<u8> buf;
			AllocateAligned(buf, hdr_size+img_size, maxSectorSize);
			Tex t;
			if (tex_wrap(w, h, bpp, flags, buf, hdr_size, &t) < 0)
				return;

			u8* img = buf.get() + hdr_size;
			for (size_t i = 0; i < data.size(); ++i)
				img[i] = (u8)((data[i] * 255) / max);

			tex_write(&t, filename);
			tex_free(&t);
		}
示例#8
0
文件: Util.cpp 项目: krichter722/0ad
// Similar to WriteScreenshot, but generates an image of size 640*tiles x 480*tiles.
void WriteBigScreenshot(const VfsPath& extension, int tiles)
{
    // If the game hasn't started yet then use WriteScreenshot to generate the image.
    if(g_Game == NULL) {
        WriteScreenshot(L".bmp");
        return;
    }

    // get next available numbered filename
    // note: %04d -> always 4 digits, so sorting by filename works correctly.
    const VfsPath basenameFormat(L"screenshots/screenshot%04d");
    const VfsPath filenameFormat = basenameFormat.ChangeExtension(extension);
    VfsPath filename;
    vfs::NextNumberedFilename(g_VFS, filenameFormat, s_nextScreenshotNumber, filename);

    // Slightly ugly and inflexible: Always draw 640*480 tiles onto the screen, and
    // hope the screen is actually large enough for that.
    const int tile_w = 640, tile_h = 480;
    ENSURE(g_xres >= tile_w && g_yres >= tile_h);

    const int img_w = tile_w*tiles, img_h = tile_h*tiles;
    const int bpp = 24;
    GLenum fmt = GL_RGB;
    int flags = TEX_BOTTOM_UP;
    // we want writing BMP to be as fast as possible,
    // so read data from OpenGL in BMP format to obviate conversion.
    if(extension == L".bmp")
    {
#if !CONFIG2_GLES // GLES doesn't support BGR
        fmt = GL_BGR;
        flags |= TEX_BGR;
#endif
    }

    const size_t img_size = img_w * img_h * bpp/8;
    const size_t tile_size = tile_w * tile_h * bpp/8;
    const size_t hdr_size = tex_hdr_size(filename);
    void* tile_data = malloc(tile_size);
    if(!tile_data)
    {
        WARN_IF_ERR(ERR::NO_MEM);
        return;
    }
    shared_ptr<u8> img_buf;
    AllocateAligned(img_buf, hdr_size+img_size, maxSectorSize);

    Tex t;
    GLvoid* img = img_buf.get() + hdr_size;
    if(t.wrap(img_w, img_h, bpp, flags, img_buf, hdr_size) < 0)
    {
        free(tile_data);
        return;
    }

    ogl_WarnIfError();

    // Resize various things so that the sizes and aspect ratios are correct
    {
        g_Renderer.Resize(tile_w, tile_h);
        SViewPort vp = { 0, 0, tile_w, tile_h };
        g_Game->GetView()->GetCamera()->SetViewPort(vp);
        g_Game->GetView()->SetCameraProjection();
    }

#if !CONFIG2_GLES
    // Temporarily move everything onto the front buffer, so the user can
    // see the exciting progress as it renders (and can tell when it's finished).
    // (It doesn't just use SwapBuffers, because it doesn't know whether to
    // call the SDL version or the Atlas version.)
    GLint oldReadBuffer, oldDrawBuffer;
    glGetIntegerv(GL_READ_BUFFER, &oldReadBuffer);
    glGetIntegerv(GL_DRAW_BUFFER, &oldDrawBuffer);
    glDrawBuffer(GL_FRONT);
    glReadBuffer(GL_FRONT);
#endif

    // Hide the cursor
    CStrW oldCursor = g_CursorName;
    g_CursorName = L"";

    // Render each tile
    for (int tile_y = 0; tile_y < tiles; ++tile_y)
    {
        for (int tile_x = 0; tile_x < tiles; ++tile_x)
        {
            // Adjust the camera to render the appropriate region
            g_Game->GetView()->GetCamera()->SetProjectionTile(tiles, tile_x, tile_y);

            RenderLogger(false);
            RenderGui(false);
            Render();
            RenderGui(true);
            RenderLogger(true);

            // Copy the tile pixels into the main image
            glReadPixels(0, 0, tile_w, tile_h, fmt, GL_UNSIGNED_BYTE, tile_data);
            for (int y = 0; y < tile_h; ++y)
            {
                void* dest = (char*)img + ((tile_y*tile_h + y) * img_w + (tile_x*tile_w)) * bpp/8;
                void* src = (char*)tile_data + y * tile_w * bpp/8;
                memcpy(dest, src, tile_w * bpp/8);
            }
        }
    }

    // Restore the old cursor
    g_CursorName = oldCursor;

#if !CONFIG2_GLES
    // Restore the buffer settings
    glDrawBuffer(oldDrawBuffer);
    glReadBuffer(oldReadBuffer);
#endif

    // Restore the viewport settings
    {
        g_Renderer.Resize(g_xres, g_yres);
        SViewPort vp = { 0, 0, g_xres, g_yres };
        g_Game->GetView()->GetCamera()->SetViewPort(vp);
        g_Game->GetView()->SetCameraProjection();
        g_Game->GetView()->GetCamera()->SetProjectionTile(1, 0, 0);
    }

    if (tex_write(&t, filename) == INFO::OK)
    {
        OsPath realPath;
        g_VFS->GetRealPath(filename, realPath);

        LOGMESSAGERENDER(g_L10n.Translate("Screenshot written to '%s'"), realPath.string8());

        debug_printf(
            CStr(g_L10n.Translate("Screenshot written to '%s'") + "\n").c_str(),
            realPath.string8().c_str());
    }
    else
        LOGERROR("Error writing screenshot to '%s'", filename.string8());

    free(tile_data);
}
示例#9
0
static Status jpg_decode_impl(rpU8 data, size_t size, jpeg_decompress_struct* cinfo, Tex* t)
{
	src_prepare(cinfo, data, size);

	// ignore return value since:
	// - suspension is not possible with the mem data source
	// - we passed TRUE to raise an error if table-only JPEG file
	(void)jpeg_read_header(cinfo, TRUE);

	// set libjpg output format. we cannot go with the default because
	// Photoshop writes non-standard CMYK files that must be converted to RGB.
	size_t flags = 0;
	cinfo->out_color_space = JCS_RGB;
	if(cinfo->num_components == 1)
	{
		flags |= TEX_GREY;
		cinfo->out_color_space = JCS_GRAYSCALE;
	}

	// lower quality, but faster
	cinfo->dct_method = JDCT_IFAST;
	cinfo->do_fancy_upsampling = FALSE;

	// ignore return value since suspension is not possible with the
	// mem data source.
	// note: since we've set out_color_space, JPEG will always
	// return an acceptable image format; no need to check.
	(void)jpeg_start_decompress(cinfo);

	// scaled output image dimensions and final bpp are now available.
	int w = cinfo->output_width;
	int h = cinfo->output_height;
	int bpp = cinfo->output_components * 8;

	// alloc destination buffer
	const size_t pitch = w * bpp / 8;
	const size_t imgSize = pitch * h;	// for allow_rows
	shared_ptr<u8> img;
	AllocateAligned(img, imgSize, pageSize);

	// read rows
	std::vector<RowPtr> rows = tex_codec_alloc_rows(img.get(), h, pitch, TEX_TOP_DOWN, 0);
	// could use cinfo->output_scanline to keep track of progress,
	// but we need to count lines_left anyway (paranoia).
	JSAMPARRAY row = (JSAMPARRAY)&rows[0];
	JDIMENSION lines_left = h;
	while(lines_left != 0)
	{
		JDIMENSION lines_read = jpeg_read_scanlines(cinfo, row, lines_left);
		row += lines_read;
		lines_left -= lines_read;

		// we've decoded in-place; no need to further process
	}

	// ignore return value since suspension is not possible with the
	// mem data source.
	(void)jpeg_finish_decompress(cinfo);

	Status ret = INFO::OK;
	if(cinfo->err->num_warnings != 0)
		ret = WARN::TEX_INVALID_DATA;

	// store image info and validate
	return ret | t->wrap(w,h,bpp,flags,img,0);
}