#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <os_common_api.h>
#include <ui_mem.h>
#include <memory/mem_cache.h>
#include "res_manager_api.h"
#include "res_mempool.h"
#ifdef CONFIG_JPEG_HAL
#include <jpeg_hal.h>
#endif
#ifndef CONFIG_SIMULATOR
#include "lz4.h"
#include <sdfs.h>
#else
#include <fs/fs.h>

#define FS_O_READ		0x01
#define FS_SEEK_SET     SEEK_SET
#define FS_SEEK_END     SEEK_END
#endif

#ifdef CONFIG_SIMULATOR
#define MAX_PARTITION_ID	0
#else
#define MAX_PARTITION_ID	1
#endif

#define RES_MEM_DEBUG			0

#define SCENE_ITEM_SIZE 3

#define MAX_REGULAR_NUM			512

#define STY_PATH_MAX_LEN		24
#ifndef CONFIG_RES_COMPACT_BUFFER_BLOCK_SIZE
#define COMPACT_BUFFER_BLOCK_SIZE		360*360*2+64
#else
#define COMPACT_BUFFER_BLOCK_SIZE		CONFIG_RES_COMPACT_BUFFER_BLOCK_SIZE
#endif
#define COMPACT_BUFFER_MAX_PAD_SIZE		4*1024
#define COMPACT_BUFFER_MARGIN_SIZE		64

#define PACK __attribute__ ((packed))

//以下宏定义资源图片的类型
typedef enum{
    RES_TYPE_INVALID                 = 0,
    RES_TYPE_PIC                     = 1,  // 16 bit picture (RGB_565, R[15:11], G[10:5], B[4:0])
    RES_TYPE_STRING                  = 2,  // string
    RES_TYPE_MSTRING,                      // multi-Language string
    RES_TYPE_LOGO                    = 4,  // BIN format picture
    RES_TYPE_PNG,                          // 24 bit picture with alpha (ARGB_8565, A[23:16], R[15:11], G[10:5], B[4:0])
    RES_TYPE_PIC_4,
    RES_TYPE_PIC_COMPRESSED          = 7,  // compressed 16 bit picture (compressed RGB_565)
    RES_TYPE_PNG_COMPRESSED,               // compressed 24 bit compressed picture with alpha (compressed ARGB_8565)
    RES_TYPE_LOGO_COMPRESSED,              // compressed BIN format picture

    RES_TYPE_PIC_RGB888              = 10, // 24 bit picture without alpha (RGB_888, R[23:16], G[16:8], B[7:0])
    RES_TYPE_PIC_ARGB8888,                 // 32 bit picture with alpha (ARGB_8888, , A[31:24], R[23:16], G[16:8], B[7:0])
    RES_TYPE_PIC_RGB888_COMPRESSED,        // compressed 24 bit picture without alpha (RGB_888)
    RES_TYPE_PIC_ARGB8888_COMPRESSED = 13, // compressed 32 bit picture with alpha (ARGB_8888)

    RES_TYPE_PIC_LZ4 = 14,		// 16 bit picture (RGB_565, R[15:11], G[10:5], B[4:0]) with LZ4 compressed
    RES_TYPE_PIC_ARGB8888_LZ4,	// 32 bit picture with alpha (ARGB_8888, , A[31:24], R[23:16], G[16:8], B[7:0]) with LZ4 compressed

    RES_TYPE_A8 = 30,                 			// Raw format of A8
    RES_TYPE_A8_LZ4,             			// LZ4 compressed format of A8

    RES_TYPE_ARGB6666,           			// Raw format of ARGB6666
    RES_TYPE_ARGB6666_LZ4,       			// LZ4 compressed of ARGB6666

	RES_TYPE_PIC_ARGB1555,			 // Raw format of ARGB1555

    RES_TYPE_JPEG,              			// jpeg format

    RES_TYPE_TILE_COMPRESSED,  				// tile compressed format

    RES_TYPE_ETC2_LZ4 = 42,  				// LZ4 compressed format of ETC2
}res_type_e;

//style header
typedef struct
{
    uint32_t    scene_sum;
    uint32_t	reserve;
}style_head_t;



//资源文件数据结构
typedef struct
{
    uint8_t  magic[4];        //'R', 'E', 'S', 0x19
    uint16_t counts;
    uint16_t w_format;
    uint8_t brgb;
    uint8_t version;
	uint16_t id_start;
    uint8_t reserved[3];
    uint8_t ch_extend;
}res_head_t;

typedef struct
{
    uint32_t   offset;
    uint16_t   length;
    uint8_t    type;
    uint8_t    name[8];
    uint8_t    len_ext;
}res_entry_t;

typedef struct _buf_block_s
{
	uint32_t source;
	uint32_t id;
	uint32_t size;
	uint32_t ref;
	uint32_t width;
	uint32_t height;
	uint32_t bytes_per_pixel;
	uint32_t format;
	uint8_t* addr;
	uint32_t regular_info;
	uint8_t align_reserved[20];
	struct _buf_block_s* next;
}buf_block_t;

typedef struct
{
	compact_buffer_t* compact_buffer_list;
	buf_block_t* head;
}resource_buffer_t;

typedef struct _regular_info_s
{
	uint32_t scene_id;
	uint32_t magic;
	uint32_t num;
	uint32_t* id;
	struct _regular_info_s* next;	
}regular_info_t;



static resource_buffer_t bitmap_buffer;
static resource_buffer_t text_buffer;
static resource_buffer_t scene_buffer;
static regular_info_t* regular_info_list;
static int screen_bitmap_size;
static int ui_mem_total = 0;

static size_t res_mem_align = 4;

os_mutex bitmap_cache_mutex;
os_mutex bitmap_read_mutex;

//#define MAX_RES_VERSIONS 1
//static const char* part_path[6] = {"/NAND:A/","/NAND:B","/NAND:C/","/NAND:D", "/NAND:E/","/NAND:F"};
//static char latest_partition;
static const char storage_part_name[10] = {'A','B','C','D','E','F','G','H','I','J'};

#ifdef CONFIG_RES_MANAGER_IMG_DECODER
static const uint8_t** current_string_res;
static uint32_t current_string_res_cnt;
extern res_string_item_t RES_STRING_ID_DIC[];
#endif

extern int sd_fmap(const char *filename, void** addr, int *len);
static int _search_res_id_in_files(resource_info_t* info, resource_bitmap_t* bitmap, uint32_t* bmp_pos, uint32_t* compress_size);
	
void _resource_buffer_deinit(uint32_t force_clear)
{
	buf_block_t* item;
	buf_block_t* listp;

	if(force_clear)
	{
		listp = text_buffer.head;
		while(listp != NULL)
		{
			item = listp;
			listp = listp->next;
			res_mem_free(RES_MEM_POOL_TXT, item);
		}
		memset(&text_buffer, 0, sizeof(text_buffer));

		listp = scene_buffer.head;
		while(listp != NULL)
		{
			item = listp;
			listp = listp->next;
			res_mem_free(RES_MEM_POOL_SCENE, item);
		}
		memset(&scene_buffer, 0, sizeof(scene_buffer));

		listp = bitmap_buffer.head;
		while(listp != NULL)
		{		
			item = listp;
			listp = listp->next;
			if(item->size > sizeof(buf_block_t))
			{
				res_mem_free(RES_MEM_POOL_BMP, item);
			}
			else
			{
				SYS_LOG_DBG("%d ui mem free %d\n", __LINE__, item->id);
				res_mem_free_block(item->addr);
				ui_mem_total--;
				res_mem_free(RES_MEM_POOL_BMP, item);
			}
		}
		memset(&bitmap_buffer, 0, sizeof(bitmap_buffer));		
	}

}

void _resource_buffer_init(void)
{
	memset(&bitmap_buffer, 0, sizeof(bitmap_buffer));
	memset(&text_buffer, 0, sizeof(text_buffer));
	memset(&scene_buffer, 0, sizeof(scene_buffer));
	regular_info_list = NULL;
}

compact_buffer_t* _init_compact_buffer(uint32_t scene_id, uint32_t request_size)
{
	compact_buffer_t* buffer;
	compact_buffer_t* tail;
	buf_block_t* item;

	buffer = (compact_buffer_t*)res_array_alloc(RES_MEM_SIMPLE_COMPACT, sizeof(compact_buffer_t));
	if(buffer == NULL)
	{
		SYS_LOG_INF("malloc compact buffer struct failed\n");
		return NULL;
	}

#ifdef CONFIG_RES_MANAGER_ALIGN
	buffer->addr = (uint8_t*)res_mem_aligned_alloc(RES_MEM_POOL_BMP, res_mem_align, request_size);
#else
	buffer->addr = (uint8_t*)res_mem_alloc(RES_MEM_POOL_BMP, request_size);
#endif
	if(buffer->addr == NULL)
	{
/*		
		SYS_LOG_INF("no enough sapce for scene 0x%x compact buffer, size %d\n", scene_id, request_size);
		res_array_free(buffer);
		res_manager_dump_info();
		return NULL;
*/
		buffer->addr = res_mem_alloc_block(screen_bitmap_size, __func__);
		if(buffer->addr == NULL)
		{
			SYS_LOG_INF("no extra sapce for scene 0x%x\n", scene_id);
			res_array_free(buffer);
			res_manager_dump_info();
			return NULL;
		}
		ui_mem_total++;
		buffer->free_size = screen_bitmap_size;

	}
	else
	{
		buffer->free_size = request_size;
	}

	//init first item block to prevent false check
	item = (buf_block_t*)buffer->addr;
	item->regular_info = 0;
	
	buffer->scene_id = scene_id;
	
	buffer->offset = 0;

#if RES_MEM_DEBUG
	{
		compact_buffer_t* check = bitmap_buffer.compact_buffer_list;
		uint32_t check_count = 0;
		while(check != NULL)
		{
			if(check == buffer)
			{
				SYS_LOG_INF("invalid compact buffer list for buffer 0x%x:\n", buffer);
				break;
			}
			check = check->next;
			check_count++;
			if(check_count > 500)
			{
				SYS_LOG_INF("loophole compact buffer list for buffer 0x%x:\n", buffer);
				break;
			}
		}
		
		if(check != NULL)
		{
			check = bitmap_buffer.compact_buffer_list;
			check_count = 0;
			while(check != NULL)
			{
				SYS_LOG_INF("compact_buffer: 0x%x, addr 0x%x\n", check, check->addr);
				check = check->next;
				check_count++;
				if(check_count > 500)
				{
					break;
				}				
			}

			res_mem_free(RES_MEM_POOL_BMP, buffer->addr);
			res_array_free(buffer);
			return NULL;
			
		}
	}
#endif

//	buffer->next = bitmap_buffer.compact_buffer_list;
//	bitmap_buffer.compact_buffer_list = buffer;
	buffer->next = NULL;
	tail = bitmap_buffer.compact_buffer_list;
	if(tail == NULL)
	{
		bitmap_buffer.compact_buffer_list = buffer;
	}
	else
	{
		while(tail->next != NULL)
		{
			tail = tail->next;
		}

		tail->next = buffer;
	}

//	SYS_LOG_INF("\n testalloc compact buffer inited for 0x%x, size %d, buffer %p, addr %p\n", scene_id, request_size, buffer, buffer->addr);
#if RES_MEM_DEBUG
	if(res_mem_check()<0)
	{
		SYS_LOG_INF("%s %d\n", __FILE__, __LINE__);	
		res_mem_dump();
	}
#endif

	return buffer;
}



uint8_t* _get_resource_scene_buffer(uint32_t source, uint32_t id, uint32_t size)
{
	buf_block_t* item = NULL;

	item = scene_buffer.head;
	while(item != NULL)
	{
		if((item->source == source)&&(item->id == id))
		{
			break;
		}
		item = item->next;
	}

	if(item != NULL)
	{
		//found loaded scene, which is not supposed to happen but fine
		item->ref ++;
		return item->addr;
	}
	else
	{
		item = (buf_block_t*)res_mem_alloc(RES_MEM_POOL_SCENE, sizeof(buf_block_t) + size);
		if(item == NULL)
		{
			SYS_LOG_INF("error: scene buffer not enough for size %d \n", size);
			res_manager_dump_info();
			return NULL;
		}
		SYS_LOG_INF("item %p", item);
		item->source = source;
		item->id = id;
		item->size = sizeof(buf_block_t) + size;
		item->ref = 1;
		item->addr = (uint8_t*)item+sizeof(buf_block_t);
		item->next = scene_buffer.head;
		scene_buffer.head = item;

#if RES_MEM_DEBUG
		if(res_mem_check()<0)
		{
			SYS_LOG_INF("%s %d\n", __FILE__, __LINE__);
			res_mem_dump();
		}
#endif		
		return item->addr;
	}
}

uint8_t* _try_resource_scene_buffer(uint32_t source, uint32_t id)
{
	buf_block_t* item;

	item = scene_buffer.head;
	while(item != NULL)
	{
		if((item->source == source)&&(item->id == id))
		{
			break;
		}
		item = item->next;
	}

	if(item != NULL)
	{
		//found loaded text
		item->ref ++;
		return item->addr;
	}
	else
	{
		//not found, need to load from file
		return NULL;
	}
}

void _free_resource_scene_buffer(void* p)
{
	buf_block_t* item = scene_buffer.head;
	buf_block_t* prev = NULL;

	if(p == NULL)
	{
		return;
	}

	while(item != NULL)
	{
		if(item->addr == p)
		{
			break;
		}
		prev = item;
		item = item->next;
	}

	if(item == NULL)
	{
		SYS_LOG_INF("scene not found \n");
		return;
	}
	else if((item != NULL)&&(item->ref > 1))
	{
		item->ref --;
		//FIXME
	}
	else
	{
		if(prev == NULL)
		{
			scene_buffer.head = item->next;
		}
		else
		{
			prev->next = item->next;
		}
		res_mem_free(RES_MEM_POOL_SCENE, (void*)item);

#if RES_MEM_DEBUG
		if(res_mem_check()<0)
		{
			SYS_LOG_INF("%s %d\n", __FILE__, __LINE__);
			res_mem_dump();
		}
#endif		
	}
}

uint8_t* _get_resource_text_buffer(uint32_t source, uint32_t id, uint32_t size)
{
	buf_block_t* item;

	item = text_buffer.head;
	while(item != NULL)
	{
		if((item->source == source)&&(item->id == id))
		{
			break;
		}
		item = item->next;
	}

	if(item != NULL)
	{
		//found loaded text, which is not supposed to happen but fine
		item->ref ++;
		return item->addr;
	}
	else
	{
		item = (buf_block_t*)res_mem_alloc(RES_MEM_POOL_TXT, sizeof(buf_block_t) + size);
		if(item == NULL)
		{
			SYS_LOG_INF("error: resource buffer not enough for size 0x%x \n", size);
			res_manager_dump_info();
			return NULL;
		}
		item->source = source;
		item->id = id;
		item->size = sizeof(buf_block_t) + size;
		item->ref = 1;
		item->addr = (uint8_t*)item+sizeof(buf_block_t);
		item->next = text_buffer.head;
		text_buffer.head = item;
		return item->addr;
	}

}


uint8_t* _try_resource_text_buffer(uint32_t source, uint32_t id)
{
	buf_block_t* item;

	item = text_buffer.head;
	while(item != NULL)
	{
		if((item->source == source)&&(item->id == id))
		{
			break;
		}
		item = item->next;
	}

	if(item != NULL)
	{
		//found loaded text
		item->ref ++;
		return item->addr;
	}
	else
	{
		//not found, need to load from file
		return NULL;
	}
}

void _free_resource_text_buffer(void* p)
{
	buf_block_t* item = text_buffer.head;
	buf_block_t* prev = NULL;

	while(item != NULL)
	{
		if(item->addr == p)
		{
			break;
		}
		prev = item;
		item = item->next;
	}

	if(item == NULL)
	{
		SYS_LOG_INF("resource text %p not found \n", p);
		return;
	}
	else if((item != NULL)&&(item->ref > 1))
	{
		item->ref --;
		//FIXME
		return;
	}
	else
	{
		if(prev == NULL)
		{
			text_buffer.head = item->next;
		}
		else
		{
			prev->next = item->next;
		}
		res_mem_free(RES_MEM_POOL_TXT, (void*)item);
	}
}


uint8_t* _get_resource_bitmap_buffer_compact(uint32_t source, resource_bitmap_t* bitmap, uint32_t size, uint32_t scene_id)
{
	compact_buffer_t* buffer;
	buf_block_t* item = NULL;
	uint8_t* ui_mem_buf = NULL;

	buffer = bitmap_buffer.compact_buffer_list;

	if(size == screen_bitmap_size)
	{
		ui_mem_buf = res_mem_alloc_block(size, __func__);
		if(ui_mem_buf == NULL)
		{
			SYS_LOG_INF("cant malloc screen size bitmap buffer from ui mem \n");
			res_manager_dump_info();
			return NULL;
		}
		SYS_LOG_DBG("1 ui mem alloc %d, addr %p, scene 0x%x\n", bitmap->sty_data->id, ui_mem_buf, scene_id);		
		ui_mem_total++;
	}

	if(bitmap->regular_info != 0)
	{
		if(size == screen_bitmap_size)
		{
			buffer = _init_compact_buffer(scene_id, sizeof(buf_block_t)+COMPACT_BUFFER_MARGIN_SIZE);
			if(buffer == NULL)
			{
				SYS_LOG_DBG("%d ui mem free %d\n", __LINE__, bitmap->sty_data->id);
				res_mem_free_block(ui_mem_buf);
				ui_mem_total--;
				return NULL;
			}
		}
		else
		{
			buffer = _init_compact_buffer(scene_id, size+sizeof(buf_block_t)+COMPACT_BUFFER_MARGIN_SIZE);
			if(buffer == NULL)
			{
				return NULL;
			}
		}
		item = (buf_block_t*)(buffer->addr + buffer->offset);
	}
	else
	{
		while(buffer != NULL)
		{
	//		SYS_LOG_INF("buffer->scene_id 0x%x\n", buffer->scene_id);
			if(buffer->scene_id == scene_id)
			{
				//check current buffer free size
				if(size != screen_bitmap_size && buffer->free_size >= size+sizeof(buf_block_t))
				{
					break;
				}

				if(size == screen_bitmap_size && buffer->free_size >= sizeof(buf_block_t))
				{
					break;
				}
			}
			buffer = buffer->next;
		}

		if(buffer == NULL)
		{
			//malloc a new compact buffer for scene id
			buffer = _init_compact_buffer(scene_id, size+sizeof(buf_block_t)+COMPACT_BUFFER_MARGIN_SIZE);
			if(buffer == NULL)
			{
				return NULL;
			}
		}

		item = (buf_block_t*)(buffer->addr+buffer->offset);		
	}
	item->source = source;
	item->id = bitmap->sty_data->id;
	item->ref = 0;
	item->width = (uint32_t)bitmap->sty_data->width;
	item->height = (uint32_t)bitmap->sty_data->height;
	item->bytes_per_pixel = (uint32_t)bitmap->sty_data->bytes_per_pixel;
	item->format = (uint32_t)bitmap->sty_data->format;
	if(size == screen_bitmap_size)
	{
		item->size = sizeof(buf_block_t);
		item->addr = ui_mem_buf;
	}
	else
	{		
		item->size = sizeof(buf_block_t) + size;
		item->addr = (uint8_t *)item + sizeof(buf_block_t);
	}
	item->next = bitmap_buffer.head;
	item->regular_info = bitmap->regular_info;
	bitmap_buffer.head = item;

//	SYS_LOG_INF("\n\n cache bitmap %d return 0x%x\n", id, item->addr);
	buffer->offset += item->size;
	buffer->free_size -= item->size;

#if RES_MEM_DEBUG
	if(res_mem_check()<0)
	{
		SYS_LOG_INF("%s %d\n", __FILE__, __LINE__);
		res_mem_dump();
	}
#endif	
	return item->addr;

}

static buf_block_t* _malloc_buf_block(uint32_t size)
{
	buf_block_t* item;
	uint8_t* ui_mem_buf;
	
	if(size == screen_bitmap_size)
	{
		ui_mem_buf = res_mem_alloc_block(size, __func__);
		if(ui_mem_buf == NULL)
		{
			SYS_LOG_INF("cant malloc screen size bitmap buffer from ui mem \n");
			return NULL;
		}
		ui_mem_total++;
		//SYS_LOG_DBG("2 ui mem alloc %d, addr %p, styid 0x%x\n", bitmap->sty_data->id, ui_mem_buf, bitmap->sty_data->sty_id);

#ifdef CONFIG_RES_MANAGER_ALIGN
		item = (buf_block_t*)res_mem_aligned_alloc(RES_MEM_POOL_BMP, res_mem_align, sizeof(buf_block_t));
#else
		item = (buf_block_t*)res_mem_alloc(RES_MEM_POOL_BMP, sizeof(buf_block_t));	
#endif
		if(item == NULL)
		{
			//SYS_LOG_DBG("%d ui mem free %d\n", __LINE__, bitmap->sty_data->id);
			res_mem_free_block(ui_mem_buf);
			ui_mem_total--;
			SYS_LOG_INF("%s %d: error: resource buffer not enough for size %d\n", __func__, __LINE__, size);
			return NULL;
		}
		item->size = sizeof(buf_block_t);
		item->addr = ui_mem_buf;
	}
	else
	{
#ifdef CONFIG_RES_MANAGER_ALIGN
		item = (buf_block_t*)res_mem_aligned_alloc(RES_MEM_POOL_BMP, res_mem_align, sizeof(buf_block_t) + size);
#else
		item = (buf_block_t*)res_mem_alloc(RES_MEM_POOL_BMP, sizeof(buf_block_t) + size);
#endif
		if(item == NULL)
		{
			SYS_LOG_INF("error: resource buffer not enough for size %d\n", size);
			return NULL;
		}
		
		item->size = sizeof(buf_block_t) + size;
		item->addr = (uint8_t *)item + sizeof(buf_block_t);
	}
	
	return item;
}

static uint8_t* _get_resource_bitmap_buffer(uint32_t source, resource_bitmap_t* bitmap, uint32_t size, uint32_t force_ref)
{
	buf_block_t* item;

	size = ((size+res_mem_align-1)/res_mem_align)*res_mem_align;  //aligned next offset to 4 bytes

	if(force_ref > 1 )
	{
		return _get_resource_bitmap_buffer_compact(source, bitmap, size, force_ref);
	}

	item = bitmap_buffer.head;
	while(item != NULL)
	{
		if((item->source == source)&&(item->id == bitmap->sty_data->id))
		{
			break;
		}
		item = item->next;
	}

	if(item != NULL)
	{
		//found loaded bitmap, which is not supposed to happen but fine
		SYS_LOG_INF("should not happen\n");
		if(force_ref >= 1)
		{
			item->ref ++;
		}
	
		return item->addr;
	}
	else
	{
		item = _malloc_buf_block(size);
		if (item == NULL)
		{
			res_manager_dump_info();
			return NULL;
		}
		item->source = source;
		item->id = bitmap->sty_data->id;

		if(force_ref >= 1)
		{
			item->ref = 1;
		}
		else
		{
			item->ref = 0;
		}
		item->width = (uint32_t)bitmap->sty_data->width;
		item->height = (uint32_t)bitmap->sty_data->height;
		item->bytes_per_pixel = (uint32_t)bitmap->sty_data->bytes_per_pixel;
		item->format = (uint32_t)bitmap->sty_data->format;
		item->next = bitmap_buffer.head;
		bitmap_buffer.head = item;
		item->regular_info = bitmap->regular_info;
#if RES_MEM_DEBUG
		if(res_mem_check()<0)
		{
			SYS_LOG_INF("%s %d\n", __FILE__, __LINE__);
			res_mem_dump();
		}
#endif

		return item->addr;
	}

}

//uint8_t* _try_resource_bitmap_buffer(uint32_t source, uint32_t id, uint32_t* width, uint32_t* height,
//										uint32_t* bytes_per_pixel, uint32_t* format, uint32_t force_ref)
static uint8_t* _try_resource_bitmap_buffer(uint32_t source, resource_bitmap_t* bitmap, uint32_t force_ref)
{
	buf_block_t* item;

	item = bitmap_buffer.head;
	while(item != NULL)
	{
		if((item->source == source)&&(item->id == bitmap->sty_data->id))
		{
			break;
		}
		item = item->next;
	}

	if(item != NULL)
	{
		//found loaded bitmap
		bitmap->regular_info = item->regular_info;
		if(force_ref == 1)
		{
			item->ref ++;
		}

//		SYS_LOG_INF("\n ### got cached bitmap id %d\n", id);
		return item->addr;
	}
	else
	{
		//not found, need to load from file
		return NULL;
	}
}


static int32_t _get_resource_bitmap_map(resource_info_t* info, resource_bitmap_t* bitmap)
{
#ifdef CONFIG_RES_MANAGER_USE_STYLE_MMAP
	int32_t ret;
	int32_t compress_size = 0;
	uint32_t bmp_pos = 0;

	if(bitmap->sty_data->format != RESOURCE_BITMAP_FORMAT_RAW
	&& bitmap->sty_data->format != RESOURCE_BITMAP_FORMAT_INDEX8
	&& bitmap->sty_data->format != RESOURCE_BITMAP_FORMAT_INDEX4
#ifdef CONFIG_LVGL_USE_IMG_DECODER_ACTS
	 && bitmap->sty_data->format != RESOURCE_BITMAP_FORMAT_JPEG
#endif
	 )
	{
		return -1;	
	}

	
#ifndef CONFIG_SIMULATOR
	if(info->pic_res_mmap_addr == NULL)
	{
		SYS_LOG_INF("info->pic_res_mmap_addr %p\n", info->pic_res_mmap_addr);
		return -1;
	}

	ret = _search_res_id_in_files(info, bitmap, &bmp_pos, &compress_size);
	if(ret < 0)
	{
		//search faild, how to fix?
		SYS_LOG_INF("search res id in files faild in map\n");
		return -1;
	}

	bitmap->buffer = info->pic_res_mmap_addr + bmp_pos;

	return 0;
#else
	ret = _search_res_id_in_files(info, bitmap, &bmp_pos, &compress_size);
	if(ret < 0)
	{
		//search faild, how to fix?
		SYS_LOG_INF("search res id in files faild in map\n");
		return -1;
	}

	bitmap->buffer = malloc(compress_size);
	fs_seek(&info->pic_fp, bmp_pos, FS_SEEK_SET);
	ret = fs_read(&info->pic_fp, bitmap->buffer, compress_size);
	if(ret < compress_size)
	{
		SYS_LOG_INF("bitmap read error %d\n", ret);
	}

	return 0;
#endif
#else

	//config not defined
	return -1;
#endif //CONFIG_RES_MANAGER_USE_STYLE_MMAP

}


uint32_t _check_bitmap_in_compact_buffer(void* p)
{
	compact_buffer_t* buffer;
	uint32_t ret = 0;
	buf_block_t* item = (buf_block_t*)p;

	buffer = bitmap_buffer.compact_buffer_list;
	while(buffer != NULL)
	{
		if(p >= (void*)buffer->addr && p < (void*)(buffer->addr + buffer->offset))
		{
			ret = 1;
			if(p==buffer->addr && item->size == buffer->offset && buffer->free_size <= COMPACT_BUFFER_MARGIN_SIZE)
			{
				SYS_LOG_DBG("compact to be released %p\n", p);
				ret = (uint32_t)buffer;
			}
			break;
		}
		buffer = buffer->next;
	}

	return ret;
}

void _free_resource_bitmap_buffer(void *p)
{
	buf_block_t* item = bitmap_buffer.head;
	buf_block_t* prev = NULL;
	uint32_t is_compact = 0;

#if RES_MEM_DEBUG
	if(res_mem_check()<0)
	{
		SYS_LOG_INF("%s %d item 0x%x \n", __FILE__, __LINE__, item);
		res_mem_dump();
	}
#endif	

#ifdef CONFIG_SIMULATOR
#if CONFIG_UI_RES_MEM_POOL_SIZE > 0
	if (!ui_mem_is_res(p) && !ui_mem_is_fb(p))
	{
		free(p);
		return;
	}
#endif
#endif

	while(item != NULL)
	{
		if(item->addr == p)
		{
			break;
		}
		prev = item;
		item = item->next;
	}

	if(item == NULL)
	{
//		SYS_LOG_INF("resource bitmap not found %p", p);
/*		
		item = bitmap_buffer.head;
		while(item!=NULL)
		{
			SYS_LOG_INF("item in list 0x%x \n", item->addr);
			item = item->next;
		}
*/

		return;
	}

	//check if p belongs to scene buffer, use item in check in case p is in ui mem
	if(bitmap_buffer.compact_buffer_list != NULL)
	{
		is_compact = _check_bitmap_in_compact_buffer((void*)item);
	}
	
	if(item->ref > 1)
	{
		item->ref --;
		//FIXME
		return;
	}
	else if(item->regular_info != 0)
	{
		return;
	}
	else
	{
		if(prev == NULL)
		{
			bitmap_buffer.head = item->next;
		}
		else
		{
			prev->next = item->next;
		}

		if(is_compact == 0)
		{
			//if item size equals buf_block_t meaning it's a screen size
			if(item->size > sizeof(buf_block_t))
			{
				res_mem_free(RES_MEM_POOL_BMP, (void*)item);
			}			
			else
			{
				SYS_LOG_DBG("%d ui mem free %d\n", __LINE__, item->id);
				res_mem_free_block(item->addr);
				ui_mem_total--;
				res_mem_free(RES_MEM_POOL_BMP, (void*)item);
			}
		}
		else
		{
			//in case item was deleted in bitmap list first, 
			//then when scene unloads, no check upon it, so ui mem leaked.
			if(item->size == sizeof(buf_block_t))
			{
				SYS_LOG_DBG("%d ui mem free %d\n", __LINE__, item->id);
				res_mem_free_block(item->addr);
				ui_mem_total--;
				item->addr = NULL; 
			}
			else if(is_compact > 1)
			{
				//only 1 pic in compact buffer, compact buffer can be released here
				//theoretically, when a pic is unloaded in a scene, it wont be used before next preload
				compact_buffer_t* waste = (compact_buffer_t*)is_compact;
				compact_buffer_t* prbuf = NULL;
				compact_buffer_t* buffer = bitmap_buffer.compact_buffer_list;
				while(waste != buffer)
				{
					prbuf = buffer;
					buffer = buffer->next;
				}

				if(prbuf == NULL)
				{
					bitmap_buffer.compact_buffer_list = buffer->next;
				}
				else
				{
					prbuf->next = buffer->next;
				}

				SYS_LOG_DBG("compact early release %p\n", buffer->addr);
				if(buffer->free_size + buffer->offset == screen_bitmap_size)
				{
					res_mem_free_block(buffer->addr);
					ui_mem_total--;
				}
				else
				{
					res_mem_free(RES_MEM_POOL_BMP, buffer->addr);
				}

				res_array_free(buffer);
			}
		}

#if RES_MEM_DEBUG
		if(res_mem_check()<0)
		{
			SYS_LOG_INF("%s %d\n", __FILE__, __LINE__);
			res_mem_dump();
		}
#endif		
	}
}

static void _init_pic_mmap_addr(resource_info_t* info, const char* picres_path)
{
#ifdef CONFIG_RES_MANAGER_USE_STYLE_MMAP
#ifndef CONFIG_SIMULATOR
	uint32_t res_size;
	
	sd_fmap(picres_path, (void**)&info->pic_res_mmap_addr, &res_size); 
#endif //CONFIG_SIMULATOR
#endif //CONFIG_RES_MANAGER_USE_STYLE_MMAP
}


static int _init_pic_search_param(resource_info_t* info, const char* picres_path)
{
	int i,k;
	int ret;
	res_head_t res_head;
	res_entry_t* entry;
	char* partition;
	char* res_path = NULL;
	int part_count = 0;
	
	info->pic_search_param = (pic_search_param_t*)res_mem_alloc(RES_MEM_POOL_BMP, (MAX_PARTITION_ID+1)*sizeof(pic_search_param_t));
	if(info->pic_search_param == NULL)
	{
		SYS_LOG_INF("no enough memory to store pic res param\n");
		res_manager_dump_info();
		return -1;
	}
	memset(info->pic_search_param, 0, (MAX_PARTITION_ID+1)*sizeof(pic_search_param_t));

	res_path = (char*)mem_malloc(strlen(picres_path)+1);
	if(res_path == NULL)
	{
		SYS_LOG_INF("no enough memory to store pic res path\n");
		return -1;
	}
	memset(res_path, 0, strlen(picres_path)+1);
	strcpy(res_path, picres_path);
#ifdef CONFIG_SIMULATOR
	partition = NULL;
	part_count = 0;
#else
	if(res_is_auto_search_files())
	{
		partition = strrchr(res_path, ':') + 1;
		part_count = MAX_PARTITION_ID;

		//path out of normal path boundry, use it directly
		if(*partition > storage_part_name[part_count])
		{
			partition = NULL;
			part_count = 0;
		}
		
	}
	else
	{
		partition = NULL;
		part_count = 0;
	}
#endif
	for(i=0;i<=part_count;i++)
	{
		if (partition)
		{
			*partition = storage_part_name[i];
			SYS_LOG_DBG("partition %c\n", *partition);
		}

		SYS_LOG_DBG("res_path %s\n", res_path);

		if(i == 0)
		{
			ret = fs_open(&info->pic_fp, res_path, FS_O_READ);
			if ( ret < 0 )
			{
				SYS_LOG_INF(" open picture resource file %s failed!\n", res_path);
				mem_free(res_path);
				return -1;
			}
			
			fs_seek(&info->pic_fp, 0, FS_SEEK_SET);
			ret = fs_read(&info->pic_fp, &res_head, sizeof(res_head_t));
			if(ret < sizeof(res_head_t))
			{
				SYS_LOG_INF("read picture resource header failed\n");
				fs_close(&info->pic_fp);
				mem_free(res_path);
				return -1;
			}


			if(res_head.magic[0]!='R' || res_head.magic[1]!='E' || res_head.magic[2]!='S')
			{
				SYS_LOG_INF("read picture resource header invalid\n");
				fs_close(&info->pic_fp);
				mem_free(res_path);
				return -1;
			}
			
			entry = res_mem_alloc(RES_MEM_POOL_BMP, res_head.counts*sizeof(res_entry_t));
			if(entry == NULL)
			{
				SYS_LOG_INF("malloc res entries failed\n");
				fs_close(&info->pic_fp);
				mem_free(res_path);
				res_manager_dump_info();
				return -1;
			}
			ret = fs_read(&info->pic_fp, entry, res_head.counts*sizeof(res_entry_t));
			if(ret < res_head.counts*sizeof(res_entry_t))
			{
				SYS_LOG_INF("read picture resource entries failed\n");
				res_mem_free(RES_MEM_POOL_BMP, entry);
				fs_close(&info->pic_fp);
				mem_free(res_path);
				return -1;
			}
			info->pic_search_param[i].id_start = 1;
			info->pic_search_param[i].id_end = info->pic_search_param[i].id_start + res_head.counts - 1;
			info->pic_search_param[i].pic_offsets = res_mem_alloc(RES_MEM_POOL_BMP, res_head.counts*sizeof(uint32_t));
			if(info->pic_search_param[i].pic_offsets == NULL)
			{
				SYS_LOG_INF("malloc pic search offsets failed");
				res_mem_free(RES_MEM_POOL_BMP, entry);
				fs_close(&info->pic_fp);
				mem_free(res_path);
				res_manager_dump_info();
				return -1;
			}

			info->pic_search_param[i].compress_size = res_mem_alloc(RES_MEM_POOL_BMP, res_head.counts*sizeof(uint32_t));
			if(info->pic_search_param[i].compress_size == NULL)
			{
				SYS_LOG_INF("malloc pic search offsets failed");
				res_mem_free(RES_MEM_POOL_BMP, entry);
				res_mem_free(RES_MEM_POOL_BMP, info->pic_search_param[i].pic_offsets);
				info->pic_search_param[i].pic_offsets = NULL;
				fs_close(&info->pic_search_param[i].res_fp);
				mem_free(res_path);
				res_manager_dump_info();
				return -1;
			}			

			SYS_LOG_INF("id start %d, id_end %d\n", info->pic_search_param[i].id_start, info->pic_search_param[i].id_end);
			for(k=0;k<res_head.counts;k++)
			{
				//skip 4 bytes before bitmap data, which are metric params
				info->pic_search_param[i].pic_offsets[k]= entry[k].offset+4;
				info->pic_search_param[i].compress_size[k] = ((entry[k].len_ext << 16) | entry[k].length) - 4;
			}
			res_mem_free(RES_MEM_POOL_BMP, entry);
		}
		else
		{

			ret = fs_open(&info->pic_search_param[i].res_fp, res_path, FS_O_READ);
			if ( ret < 0 )
			{
				continue;
			}
			fs_seek(&info->pic_search_param[i].res_fp, 0, FS_SEEK_SET);
			ret = fs_read(&info->pic_search_param[i].res_fp, &res_head, sizeof(res_head_t));
			if(ret < sizeof(res_head_t))
			{
				SYS_LOG_INF("read picture resource header failed\n");
				mem_free(res_path);
				return -1;
			}			
			entry = res_mem_alloc(RES_MEM_POOL_BMP, res_head.counts*sizeof(res_entry_t));
			if(entry == NULL)
			{
				SYS_LOG_INF("malloc res entries failed\n");
				fs_close(&info->pic_search_param[i].res_fp);
				mem_free(res_path);
				res_manager_dump_info();
				return -1;
			}			
			ret = fs_read(&info->pic_search_param[i].res_fp, entry, res_head.counts*sizeof(res_entry_t));
			if(ret < res_head.counts*sizeof(res_entry_t))
			{
				SYS_LOG_INF("read picture resource entries failed\n");
				res_mem_free(RES_MEM_POOL_BMP, entry);
				fs_close(&info->pic_search_param[i].res_fp);
				mem_free(res_path);
				return -1;
			}			
			info->pic_search_param[i].id_start = res_head.id_start;
			info->pic_search_param[i].id_end = res_head.id_start + res_head.counts - 1;
			info->pic_search_param[i].pic_offsets = res_mem_alloc(RES_MEM_POOL_BMP, res_head.counts*sizeof(uint32_t));
			if(info->pic_search_param[i].pic_offsets == NULL)
			{
				SYS_LOG_INF("malloc pic search offsets failed");
				res_mem_free(RES_MEM_POOL_BMP, entry);
				fs_close(&info->pic_search_param[i].res_fp);
				mem_free(res_path);
				res_manager_dump_info();
				return -1;
			}			

			info->pic_search_param[i].compress_size = res_mem_alloc(RES_MEM_POOL_BMP, res_head.counts*sizeof(uint32_t));
			if(info->pic_search_param[i].compress_size == NULL)
			{
				SYS_LOG_INF("malloc pic search compress size failed");
				res_mem_free(RES_MEM_POOL_BMP, entry);
				res_mem_free(RES_MEM_POOL_BMP, info->pic_search_param[i].pic_offsets);
				info->pic_search_param[i].pic_offsets = NULL;
				fs_close(&info->pic_search_param[i].res_fp);
				mem_free(res_path);
				res_manager_dump_info();
				return -1;
			}			

			SYS_LOG_INF("id start %d, id_end %d\n", info->pic_search_param[i].id_start, info->pic_search_param[i].id_end);

			for(k=0;k<res_head.counts;k++)
			{
				//skip 4 bytes before bitmap data, which are metric params			
				info->pic_search_param[i].pic_offsets[k]= entry[k].offset+4;
				info->pic_search_param[i].compress_size[k] = ((entry[k].len_ext << 16) | entry[k].length) - 4;
			}
			res_mem_free(RES_MEM_POOL_BMP, entry);
		}
		info->pic_search_max_volume++;
	}
	mem_free(res_path);

	_init_pic_mmap_addr(info, picres_path);
	
	return 0;
}

//读取style 文件的头部信息, 返回值是该配置文件中scene 的总数
//缓存图片资源文件索引信息
static int _read_head( resource_info_t* info )
{
    style_head_t* head;
    int ret;
	uint32_t sty_size;

	os_strace_u32(SYS_TRACE_ID_RES_SCENE_PRELOAD_0, (uint32_t)0);	

	fs_seek(&info->style_fp, 0, FS_SEEK_END);
	sty_size = fs_tell(&info->style_fp);

	fs_seek(&info->style_fp, 0, FS_SEEK_SET);

#if defined(CONFIG_RES_MANAGER_USE_STYLE_MMAP) && !defined(CONFIG_SIMULATOR)
	ret = sd_fmap(info->sty_path, (void**)&info->sty_mem, &sty_size);
	if(ret < 0)
	{
		SYS_LOG_INF("mmap style file failed\n");
		return -1;
	}

	head = (style_head_t*)info->sty_mem;
	if(head->scene_sum == 0xffffffff)
	{
		SYS_LOG_INF("read style file invalid 0x%x\n", head->scene_sum);
		info->sty_mem = NULL;
		return -1;
	}
#else
	
	info->sty_mem = (uint8_t*)res_mem_alloc(RES_MEM_POOL_SCENE, sty_size);
	if(info->sty_mem == NULL)
	{
		SYS_LOG_INF("no enough mem for style data\n");
		res_manager_dump_info();
		return -1;
	}

	os_strace_end_call_u32(SYS_TRACE_ID_RES_SCENE_PRELOAD_0, (uint32_t)0);
	ret = fs_read(&info->style_fp, info->sty_mem, sty_size);
	if(ret < sty_size)
	{
		SYS_LOG_INF("read style file error:%d\n", ret);
		res_mem_free(RES_MEM_POOL_SCENE, info->sty_mem);
		info->sty_mem = NULL;
		return -1;
	}


	head = (style_head_t*)info->sty_mem;
	if(head->scene_sum == 0xffffffff)
	{
		SYS_LOG_INF("read style file invalid 0x%x\n", head->scene_sum);
		free(info->sty_mem);
		info->sty_mem = NULL;
		return -1;
	}
#endif


	info->sum = head->scene_sum;
	info->scenes = (resource_scene_t*)(info->sty_mem + sizeof(style_head_t));
	info->sty_data = info->sty_mem + sizeof(style_head_t) + sizeof(resource_scene_t)*info->sum;


#if RES_MEM_DEBUG
	if(res_mem_check()<0)
	{
		SYS_LOG_INF("%s %d\n", __FILE__, __LINE__);
		res_mem_dump();
	}
#endif		

    return 0;
}

static int res_manager_inited = 0;
void res_manager_init(void)
{
	if(res_manager_inited == 0)
	{
		res_mem_init();
		_resource_buffer_init();
		res_mem_align = res_mem_get_align();	

		os_mutex_init(&bitmap_cache_mutex);
		os_mutex_init(&bitmap_read_mutex);
		res_manager_inited = 1;
	}
}

void res_manager_set_screen_size(uint32_t screen_w, uint32_t screen_h)
{
	uint32_t align = res_mem_get_align();
	uint32_t size;

	size = screen_w*screen_h*2;
	size = ((size+align-1)/align)*align;

	screen_bitmap_size = size;
}

void res_manager_clear_cache(uint32_t force_clear)
{
	_resource_buffer_deinit(force_clear);
}

int32_t res_manager_set_str_file(resource_info_t* info, const char* text_path)
{
	char* file_path = NULL;
	char* partition;	
	int i = 0;
	int ret;
	buf_block_t* listp;
	buf_block_t* item;
	buf_block_t* prev;

	if( text_path != NULL)
	{
		//close old file
		fs_close(&info->text_fp);
		if(info->str_path)
		{
			mem_free(info->str_path);
			info->str_path = NULL;
		}
		
#ifdef CONFIG_SIMULATOR
		ret = fs_open(&info->text_fp, text_path, FS_O_READ);
		if ( ret < 0 )
		{
			SYS_LOG_INF(" open text resource file %s failed! \n", text_path);
			goto ERR_EXIT;
		}

#else
		if(res_is_auto_search_files())
		{
			file_path = (char*)mem_malloc(strlen(text_path)+1);
			if(file_path == NULL)
			{
				SYS_LOG_INF("malloc file path failed\n");
				goto ERR_EXIT;
			}

			memset(file_path, 0, strlen(text_path)+1);				
			strcpy(file_path, text_path);
			partition = strrchr(file_path, ':') + 1;
			if(partition == NULL)
			{
				SYS_LOG_INF("invalid str file path\n");
				goto ERR_EXIT;
			}

			for(i=MAX_PARTITION_ID;i>=0;i--)
			{
				*partition = storage_part_name[i];
				ret = fs_open(&info->text_fp, file_path, FS_O_READ);
				if ( ret < 0 )
				{
					SYS_LOG_INF("open str file path %s failed\n", file_path);
					continue;
				}
				else
				{
					SYS_LOG_INF("open str file path %s ok\n", file_path);
					break;
				}
			}

			if(i<0)
			{
				SYS_LOG_INF(" open str file %s failed! \n", text_path);
				goto ERR_EXIT;
			}
		}
		else
		{
			ret = fs_open(&info->text_fp, text_path, FS_O_READ);
			if ( ret < 0 )
			{
				SYS_LOG_INF(" open text resource file %s failed! \n", text_path);
				goto ERR_EXIT;
			}
		}
#endif

		info->str_path = (uint8_t*)mem_malloc(strlen(text_path)+1);
		if(info->str_path == NULL)
		{
			SYS_LOG_INF("malloc info str path failed\n");
			goto ERR_EXIT;
		}
		memset(info->str_path, 0, strlen(text_path)+1);
		strcpy(info->str_path, text_path);	

		//clear cache
		listp = text_buffer.head;
		prev = NULL;
		while(listp != NULL)
		{			
			if(listp->source == (uint32_t)info)
			{
				item = listp;
				listp = listp->next;
				if(prev)
				{
					prev->next = listp;
				}
				if(text_buffer.head == item)
				{
					text_buffer.head = listp;
				}
				res_mem_free(RES_MEM_POOL_TXT, item);
			}
			else
			{
				prev = listp;
				listp = listp->next;
			}
		}
//		memset(&text_buffer, 0, sizeof(text_buffer));	
	}
	else
	{
		SYS_LOG_INF("text resource file path null");
	}

	
	if(file_path)
	{
		mem_free(file_path);
	}
	return 0;
ERR_EXIT:
	if(file_path)
		mem_free(file_path);
	fs_close(&info->text_fp);
	if(info->str_path)
	{
		mem_free(info->str_path);
		info->str_path = NULL;
	}
	return -1;	
}

resource_info_t* res_manager_open_resources( const char* style_path, const char* picture_path, const char* text_path )
{
    int ret;
    resource_info_t* info;
	char* partition;
	char* file_path = NULL;

	os_strace_u32(SYS_TRACE_ID_RES_SCENE_PRELOAD_2, (uint32_t)0);	
    info = (resource_info_t*)mem_malloc( sizeof( resource_info_t ) );
    if ( info == NULL )
    {
        SYS_LOG_INF( "error: malloc resource info failed ! \n" );
        return NULL;
    }
    memset(info, 0, sizeof(resource_info_t));
	
    if ( style_path != NULL )
    {
    	int i;
		
		SYS_LOG_INF("open sty file %s\n", style_path);
		
#ifdef CONFIG_SIMULATOR
		ret = fs_open(&info->style_fp, style_path, FS_O_READ);
		if ( ret < 0 )
	    {
	        SYS_LOG_INF(" open style file %s failed! \n", style_path);
	        goto ERR_EXIT;
	    }
#else
		if(res_is_auto_search_files())
		{
			file_path = (char*)mem_malloc(strlen(style_path)+1);
			if(file_path == NULL)
			{
		        SYS_LOG_INF("malloc style file path failed! \n");
		        goto ERR_EXIT;
			}
			memset(file_path, 0, strlen(style_path)+1);
	    	strcpy(file_path, style_path);
			partition = strrchr(file_path, ':') + 1;
			if(partition == NULL)
				goto ERR_EXIT;
		
			SYS_LOG_INF("MAX_PARTITION_ID %d\n", MAX_PARTITION_ID);
			for(i=MAX_PARTITION_ID;i>=0;i--)
			{
				SYS_LOG_INF("partition %d: %c\n", i, *partition);
				*partition = storage_part_name[i];
				ret = fs_open(&info->style_fp, file_path, FS_O_READ);
				if ( ret < 0 )
				{
					continue;
				}
				else
				{
					SYS_LOG_INF("style file_path %d: %s\n", i, file_path);			
					break;
				}
			}

			if(i<0)
			{
				ret = fs_open(&info->style_fp, style_path, FS_O_READ);
				if ( ret < 0 )
				{
					SYS_LOG_INF(" open style file %s failed! \n", style_path);
					goto ERR_EXIT;
				}
			}
		}
		else
		{
			ret = fs_open(&info->style_fp, style_path, FS_O_READ);
			if ( ret < 0 )
			{
				SYS_LOG_INF(" open style file %s failed! \n", style_path);
				goto ERR_EXIT;
			}
		}
#endif
		info->sty_path = (uint8_t*)mem_malloc(strlen(style_path)+1);
		memset(info->sty_path, 0, strlen(style_path)+1);
		strcpy(info->sty_path, style_path);
    }
    else
    {
        SYS_LOG_INF("style file path null");
    }

    if( picture_path != NULL)
    {
		SYS_LOG_INF("open pic file %s\n", picture_path);
		_init_pic_search_param(info, picture_path);		
    }
    else
    {
    	SYS_LOG_INF("picture resource file path null");
    }

    if( text_path != NULL)
    {
		SYS_LOG_INF("open text file %s\n", text_path);
#ifdef CONFIG_SIMULATOR
		ret = fs_open(&info->text_fp, text_path, FS_O_READ);
	    if ( ret < 0 )
	    {
	        SYS_LOG_INF(" open text resource file %s failed! \n", text_path);
	        goto ERR_EXIT;
	    }

#else
		if(res_is_auto_search_files())
		{
	    	int i = 0;
			if(file_path)
				mem_free(file_path);
			
			file_path = (char*)mem_malloc(strlen(text_path)+1);
			memset(file_path, 0, strlen(text_path)+1);		    	
	    	strcpy(file_path, text_path);
			partition = strrchr(file_path, ':') + 1;
			if(partition == NULL)
				goto ERR_EXIT;

			for(i=MAX_PARTITION_ID;i>=0;i--)
			{
				*partition = storage_part_name[i];
				ret = fs_open(&info->text_fp, file_path, FS_O_READ);
				if ( ret < 0 )
				{
					continue;
				}
				else
				{
					break;
				}
			}

			if(i<0)
			{
				ret = fs_open(&info->text_fp, text_path, FS_O_READ);
				if ( ret < 0 )
				{
					SYS_LOG_INF(" open text resource file %s failed!\n", text_path);
					goto ERR_EXIT;
				}
			}
		}
		else
		{
			ret = fs_open(&info->text_fp, text_path, FS_O_READ);
			if ( ret < 0 )
			{
				SYS_LOG_INF(" open text resource file %s failed!\n", text_path);
				goto ERR_EXIT;
			}
		}
#endif

		info->str_path = (uint8_t*)mem_malloc(strlen(text_path)+1);
		memset(info->str_path, 0, strlen(text_path)+1);
		strcpy(info->str_path, text_path);		
    }
    else
    {
    	SYS_LOG_INF("text resource file path null \n");
    }

	os_strace_end_call_u32(SYS_TRACE_ID_RES_SCENE_PRELOAD_2, (uint32_t)0);
    _read_head( info );    //读取style头部信息,不做返回值判断,可能不存在样式文件。

	if(file_path)
		mem_free(file_path);
    return info;

ERR_EXIT:
	if(file_path)
		mem_free(file_path);
	fs_close(&info->style_fp);
	fs_close(&info->pic_fp);
	fs_close(&info->text_fp);
	if(info->sty_path)
	{
		mem_free(info->sty_path);
		info->sty_path = NULL;
	}
	if(info->str_path)
	{
		mem_free(info->str_path);
		info->str_path = NULL;
	}
	mem_free(info);
	return NULL;
}

void res_manager_close_resources( resource_info_t* info )
{
	if(info == NULL)
	{
		SYS_LOG_INF("null resource info pointer \n");
		return;
	}

	if(info->sty_path != NULL)
	{
		SYS_LOG_INF("close sty file %s\n", info->sty_path);
		fs_close(&info->style_fp);
#ifndef CONFIG_SIMULATOR
		memset(&info->style_fp, 0, sizeof(struct fs_file_t));
#endif
	}

	if(info->pic_search_param != NULL)
	{
		fs_close(&info->pic_fp);
#ifndef CONFIG_SIMULATOR		
		memset(&info->pic_fp, 0, sizeof(struct fs_file_t));
#endif
	}

	if(info->str_path != NULL)
	{
		fs_close(&info->text_fp);
#ifndef CONFIG_SIMULATOR		
		memset(&info->text_fp, 0, sizeof(struct fs_file_t));
#endif
	}

	if(info->sty_mem != NULL)
	{
		res_mem_free(RES_MEM_POOL_SCENE, info->sty_mem);
		info->sty_mem = NULL;
		info->scenes = NULL;
	}


	if(info->sty_path != NULL)
	{
		mem_free(info->sty_path);
		info->sty_path = NULL;
	}

	if(info->str_path != NULL)
	{
		mem_free(info->str_path);
		info->str_path = NULL;
	}

	if(info->pic_search_param != NULL)
	{
		int i;
		for(i=0;i<(MAX_PARTITION_ID+1);i++)
		{
			if(info->pic_search_param[i].pic_offsets != NULL)
			{
				res_mem_free(RES_MEM_POOL_BMP, info->pic_search_param[i].pic_offsets);
			}

			if(info->pic_search_param[i].compress_size != NULL)
			{
				res_mem_free(RES_MEM_POOL_BMP, info->pic_search_param[i].compress_size);
			}			
		}
		res_mem_free(RES_MEM_POOL_BMP, info->pic_search_param);
		info->pic_search_param = NULL;
	}
	mem_free(info);
}

resource_scene_t* _get_scene( resource_info_t* info, unsigned int* scene_item, uint32_t id )
{
	resource_scene_t* scene;
    unsigned int offset;
    unsigned int size;

	//FIXME: scene buffer should differ from bitmap buffer as in space range, 
	//so the mutex wont affect each other.
	os_strace_u32(SYS_TRACE_ID_RES_SCENE_PRELOAD_1, (uint32_t)id);
#if RES_MEM_DEBUG
	if(res_mem_check()<0)
	{
		SYS_LOG_INF("%s %d\n", __FILE__, __LINE__);
		res_mem_dump();
	}
#endif		

	
    offset = *( scene_item + 1 );
    size = *( scene_item + 2 );
	SYS_LOG_INF("sty data %p, scene size %d, offset 0x%x \n", info->sty_data, size, offset);	
    scene = ( resource_scene_t* )_try_resource_scene_buffer((uint32_t)info, id);
	if(scene != NULL)
	{
//		SYS_LOG_INF("scene cached buffer 0x%x, size 0x%x", scene, size);
//		SYS_LOG_INF("scene %d, %d, %d %d", scene->x, scene->y, scene->width, scene->height);
		os_strace_end_call_u32(SYS_TRACE_ID_RES_SCENE_PRELOAD_1, (uint32_t)id);
		return scene;
	}
	else
	{
		scene = ( resource_scene_t* )_get_resource_scene_buffer((uint32_t)info, id, size);
		if(scene == NULL)
		{
			SYS_LOG_INF("error: cant get scene buffer \n");
			return NULL;
		}
	}	
	os_strace_end_call_u32(SYS_TRACE_ID_RES_SCENE_PRELOAD_1, (uint32_t)id);
	os_strace_u32(SYS_TRACE_ID_RES_SCENE_PRELOAD_2, (uint32_t)id);

	memcpy(scene, info->sty_data+offset, size);
	scene->scene_id = id;
	os_strace_end_call_u32(SYS_TRACE_ID_RES_SCENE_PRELOAD_2, (uint32_t)id);
//	SYS_LOG_INF("scene id 0x%x, scene_id 0x%x\n", id, scene->scene_id);
//	SYS_LOG_INF("scene %d, %d, %d %d", scene->x, scene->y, scene->width, scene->height);
	
#if RES_MEM_DEBUG
	if(res_mem_check()<0)
	{
		SYS_LOG_INF("%s %d\n", __FILE__, __LINE__);
		res_mem_dump();
	}
#endif		
	
    return scene;
}

resource_scene_t* res_manager_load_scene(resource_info_t* info, uint32_t scene_id)
{
    unsigned int i;
    resource_scene_t* scenes;
	
    if ( info == NULL )
    {
        SYS_LOG_INF("resource info null \n");
        return NULL;
    }
	
    scenes = info->scenes;
	SYS_LOG_INF("scene id 0x%x, info sum %d \n", scene_id, info->sum);
    for ( i = 0; i < info->sum; i++ )
    {   	
    	//SYS_LOG_INF("scene_item 0x%x\n", scenes[i].scene_id);
        if ( scenes[i].scene_id == scene_id )
        {
        	
			return &scenes[i];
        }
    }

    SYS_LOG_INF("cannot find scene id: 0x%x \n", scene_id);
    return NULL;
}


int32_t res_manager_set_pictures_regular(resource_info_t* info, uint32_t scene_id, uint32_t group_id, uint32_t subgroup_id, uint32_t* id, uint32_t num)
{
	regular_info_t* item;
	uint8_t* offset;
	uint32_t magic;

	magic = scene_id + group_id + subgroup_id;

	item = regular_info_list;
	while(item != NULL)
	{
		if(item->magic == magic && item->num == num)
		{
			//FIXME:we ignore sty_path(aka.source) here for simplicity
			if(memcmp(item->id, id, num*sizeof(uint32_t))==0)
			{
				//got a match
				return 0;
			}
		}

		item = item->next;
	}

	item = (regular_info_t*)res_mem_alloc(RES_MEM_POOL_SCENE, sizeof(regular_info_t)+num*sizeof(uint32_t));
	if(item == NULL)
	{
		SYS_LOG_INF("error: resource buffer not enough for regular info\n");
		res_manager_dump_info();
		return -1;
	}
	memset(item, 0, sizeof(regular_info_t)+num*sizeof(uint32_t));
	
	item->magic = magic;
	item->scene_id = scene_id;
	offset = (uint8_t*)item;
	offset += sizeof(regular_info_t);
	item->id = (uint32_t*)offset;
	memcpy(item->id, id, num*sizeof(uint32_t));
	item->num = num;
	item->next = regular_info_list;
	regular_info_list = item;	
	return 0;
}

int32_t res_manager_clear_regular_pictures(const uint8_t* sty_path, uint32_t scene_id)
{
	regular_info_t* regular = regular_info_list;
	regular_info_t* prev = NULL;
	regular_info_t* found = NULL;
	buf_block_t* item;

	while(regular != NULL)
	{
		if(regular->scene_id == scene_id)
		{		
			item = bitmap_buffer.head;
			while(item != NULL)
			{
				//clear regular flag
				if(item->regular_info == (uint32_t)regular)
				{
					item->regular_info = 0;
				}
				item = item->next;
			}

			found = regular;
			regular = found->next;
			if(found == regular_info_list)
			{
				regular_info_list = regular;
			}
			res_mem_free(RES_MEM_POOL_SCENE, found);
		}
		else
		{
			prev = regular;
			regular = regular->next;
		}
	}

	return 0;
}

void _unload_scene_bitmaps(uint32_t scene_id)
{
	compact_buffer_t* buffer = NULL;
	compact_buffer_t* prev_buf= NULL;
	compact_buffer_t* found;
	buf_block_t* item;
	buf_block_t* prev;
	uint8_t* buffer_end;

	SYS_LOG_INF("\n\n ###### _unload_scene_bitmaps 0x%x \n", scene_id);
	if(scene_id == 0)
	{
		return;
	}

	os_mutex_lock(&bitmap_cache_mutex, OS_FOREVER);
	buffer = bitmap_buffer.compact_buffer_list;
	while(buffer != NULL)
	{
		if(buffer->scene_id == scene_id)
		{
			//check regular
			item = (buf_block_t*)buffer->addr;
			if(buffer->offset != 0 && item->regular_info != 0)
			{
				prev_buf = buffer;
				buffer = buffer->next;	
				continue;
			}
			
			if(buffer->offset == 0 && buffer->free_size == sizeof(buf_block_t))
			{
				//pseudo nodes
				SYS_LOG_INF("empty preload scene 0x%x\n", buffer->scene_id);
			}
			else
			{
	//			SYS_LOG_INF("testalloc compact unload 0x%x, buffer %p, addr %p\n", scene_id, buffer, buffer->addr);
				//clear buffer nodes from bitmap list
				buffer_end = buffer->addr + buffer->offset -1;
				item = bitmap_buffer.head;
				prev = bitmap_buffer.head;
				while(item != NULL)
				{
					if(((void*)item >= (void*)buffer->addr) && ((void*)item <= (void*)buffer_end))
					{
						if(item->size == sizeof(buf_block_t) && item->addr != NULL)
						{
							SYS_LOG_DBG("%d ui mem free %d\n", __LINE__, item->id);
							res_mem_free_block(item->addr);
							ui_mem_total--;
						}
					
						if(item == bitmap_buffer.head)
						{
							bitmap_buffer.head = item->next;
						}
						else
						{
							prev->next = item->next;
						}
					}
					else
					{
						prev = item;
					}
					item = item->next;
				}
			}
			
			//release scene data
			if(buffer == bitmap_buffer.compact_buffer_list)
			{
				bitmap_buffer.compact_buffer_list = buffer->next;
			}
			else
			{
				prev_buf->next = buffer->next;
			}

			found = buffer;
			buffer = found->next;
			if(found->free_size + found->offset == screen_bitmap_size)
			{
				res_mem_free_block(found->addr);
				ui_mem_total--;
			}
			else
			{
				res_mem_free(RES_MEM_POOL_BMP, found->addr);
			}

#if RES_MEM_DEBUG
			if(res_mem_check()<0)
			{
				SYS_LOG_INF("%s %d found addr 0x%x\n", __FILE__, __LINE__, found->addr);
				res_mem_dump();
			}
#endif		

			res_array_free(found);

		}
		else
		{
			prev_buf = buffer;
			buffer = buffer->next;
		}
	}

	SYS_LOG_INF("exit\n");
	os_mutex_unlock(&bitmap_cache_mutex);
}


void _unload_scene(uint32_t id, resource_scene_t* scene)
{
	_unload_scene_bitmaps(id);
	
	_free_resource_scene_buffer(scene);
}

void res_manager_unload_scene(uint32_t id, resource_scene_t* scene)
{
	if(scene != NULL)
	{
		_unload_scene(id, scene);
	}
	else if(id > 0)
	{
		_unload_scene_bitmaps(id);
	}
}

void _unload_bitmap(resource_bitmap_t* bitmap)
{
	if(bitmap == NULL)
	{
		SYS_LOG_INF("%s %d: error: unload null resource \n", __func__, __LINE__);
		return;
	}
	os_mutex_lock(&bitmap_cache_mutex, OS_FOREVER);
	if(bitmap->regular_info == 0 && bitmap->buffer != NULL)
	{
		_free_resource_bitmap_buffer(bitmap->buffer);
	}
	os_mutex_unlock(&bitmap_cache_mutex);
}

void _unload_string(resource_text_t* text)
{
	if(text == NULL)
	{
		SYS_LOG_INF("%s %d: error: unload null resource \n", __func__, __LINE__);
		return;
	}
	_free_resource_text_buffer(text->buffer);
}

static int _search_res_id_in_files(resource_info_t* info, resource_bitmap_t* bitmap, uint32_t* bmp_pos, uint32_t* compress_size)
{
	int low, high, mid;
	uint32_t id = bitmap->sty_data->id;
	
	if(info->pic_search_param == NULL)
	{
		return -1;
	}

	low = 0;
	high = info->pic_search_max_volume-1;
	mid = (info->pic_search_max_volume-1)/2;

	//SYS_LOG_INF("id %d, start %d, end %d\n", id, info->pic_search_param[mid].id_start, info->pic_search_param[mid].id_end);
	while(id < info->pic_search_param[mid].id_start || id > info->pic_search_param[mid].id_end)
	{
		if(id < info->pic_search_param[mid].id_start)
		{
			high = mid - 1;
		}
		else
		{
			low = mid + 1;			
		}

		if(low > high)
		{
			//not found
			return -1;
		}
		mid = (low+high)/2;
	}

	id -= info->pic_search_param[mid].id_start;
	*bmp_pos = info->pic_search_param[mid].pic_offsets[id];
	*compress_size = info->pic_search_param[mid].compress_size[id];
	return mid;
}

int32_t _load_bitmap(resource_info_t* info, resource_bitmap_t* bitmap, uint32_t force_ref)
{
	int32_t ret;
	int32_t bmp_size;
	int32_t compress_size = 0;
	uint8_t *compress_buf = NULL;
	struct fs_file_t* pic_fp;
	uint32_t bmp_pos = 0;
	uint8_t  jpeg_out_format = HAL_JPEG_OUT_RGB565;

	if((info == NULL) || (bitmap == NULL))
	{
		SYS_LOG_INF("error: invalid param to load bitmap \n");
		return -1;
	}

	os_strace_u32(SYS_TRACE_ID_RES_BMP_LOAD_0, (uint32_t)bitmap->sty_data->id);
	os_mutex_lock(&bitmap_cache_mutex, OS_FOREVER);

	if(_get_resource_bitmap_map(info, bitmap) == 0)
	{
		//bitmap directly mapped from file
		os_mutex_unlock(&bitmap_cache_mutex);
		os_strace_end_call_u32(SYS_TRACE_ID_RES_BMP_LOAD_0, (uint32_t)bitmap->sty_data->id);
		return 0;
	}

#if RES_MEM_DEBUG
	if(res_mem_check()<0)
	{
		SYS_LOG_INF("%s %d\n", __FILE__, __LINE__);
		res_mem_dump();
	}
#endif

	//bitmap->buffer = _try_resource_bitmap_buffer((uint32_t)info, bitmap->id, &bitmap->width, &bitmap->height, &bitmap->bytes_per_pixel, &bitmap->format, force_ref);
	bitmap->buffer = _try_resource_bitmap_buffer((uint32_t)info, bitmap, force_ref);
	if(bitmap->buffer != NULL)
	{
		//got bitmap from bitmap cache
		os_mutex_unlock(&bitmap_cache_mutex);
		os_strace_end_call_u32(SYS_TRACE_ID_RES_BMP_LOAD_0, (uint32_t)bitmap->sty_data->id);
		return 0;
	}

	if (bitmap->sty_data->format == RESOURCE_BITMAP_FORMAT_JPEG) {
#ifdef CONFIG_LV_COLOR_DEPTH_32
		bitmap->sty_data->bytes_per_pixel = 3;
		jpeg_out_format = HAL_JPEG_OUT_RGB888;
#else
		bitmap->sty_data->bytes_per_pixel = 2;
		jpeg_out_format = HAL_JPEG_OUT_RGB565;
#endif
	}

	if (bitmap->sty_data->format == RESOURCE_BITMAP_FORMAT_ETC2_EAC) {
		bmp_size = ((bitmap->sty_data->width + 0x3) & ~0x3) *
		           ((bitmap->sty_data->height + 0x3) & ~0x3);
	} else if (bitmap->sty_data->format == RESOURCE_BITMAP_FORMAT_INDEX8) {
		bmp_size = bitmap->sty_data->width * bitmap->sty_data->height + 1024 + 4;
	} else if (bitmap->sty_data->format == RESOURCE_BITMAP_FORMAT_LVGL_INDEX8) {
		bmp_size = bitmap->sty_data->width * bitmap->sty_data->height + 1024;
	} else if (bitmap->sty_data->format == RESOURCE_BITMAP_FORMAT_INDEX4) {
		bmp_size = ((bitmap->sty_data->width + 0x1) >> 1) * bitmap->sty_data->height + 64;
	} else {
		bmp_size = bitmap->sty_data->width * bitmap->sty_data->height *
		           bitmap->sty_data->bytes_per_pixel;
	}

	bitmap->buffer = _get_resource_bitmap_buffer((uint32_t)info, bitmap, bmp_size, force_ref);
	if(bitmap->buffer == NULL)
	{
		SYS_LOG_INF("error: no buffer to load bitmap \n");
		os_mutex_unlock(&bitmap_cache_mutex);
		os_strace_end_call_u32(SYS_TRACE_ID_RES_BMP_LOAD_0, (uint32_t)bitmap->sty_data->id);
		return -1;
	}
	os_strace_end_call_u32(SYS_TRACE_ID_RES_BMP_LOAD_0, (uint32_t)bitmap->sty_data->id);	

	if(res_debug_load_bitmap_is_on())
	{
		SYS_LOG_INF("styid 0x%x, id %d, wh %d, %d, addr %p\n", bitmap->sty_data->sty_id, bitmap->sty_data->id, 
					bitmap->sty_data->width, bitmap->sty_data->height, bitmap->buffer);
	}

	os_strace_u32(SYS_TRACE_ID_RES_BMP_LOAD_1, (uint32_t)bitmap->sty_data->id);

	ret = _search_res_id_in_files(info, bitmap, &bmp_pos, &compress_size);
	if(ret <= 0)
	{
		pic_fp = &info->pic_fp;
	}
	else
	{
		pic_fp = &info->pic_search_param[ret].res_fp;
	}
	
//	SYS_LOG_INF("\n pres_entry length %d, type %d, offset 0x%x \n", pres_entry->length, pres_entry->type, pres_entry->offset);
#if !defined(CONFIG_RES_MANAGER_USE_STYLE_MMAP)||defined(CONFIG_SIMULATOR)
	fs_seek(pic_fp, bmp_pos, FS_SEEK_SET);
#endif
	//compress_size = bitmap->sty_data->compress_size;
	if (compress_size > 0)
	{
#if !defined(CONFIG_RES_MANAGER_USE_STYLE_MMAP)||defined(CONFIG_SIMULATOR)	
		compress_buf = (uint8_t*)res_mem_alloc(RES_MEM_POOL_BMP, compress_size);
		if(compress_buf == NULL)
		{
			SYS_LOG_INF("error: no buffer to load compressed bitmap \n");
			os_mutex_unlock(&bitmap_cache_mutex);
			os_strace_end_call_u32(SYS_TRACE_ID_RES_BMP_LOAD_1, (uint32_t)bitmap->sty_data->id);
			res_manager_dump_info();
			return -1;
		}
		
		ret = fs_read(pic_fp, compress_buf, compress_size);
		if(ret < compress_size)
		{
			SYS_LOG_INF("bitmap read error %d\n", ret);
		}
#else
		compress_buf = info->pic_res_mmap_addr + bmp_pos;
#endif
		os_strace_end_call_u32(SYS_TRACE_ID_RES_BMP_LOAD_1, (uint32_t)bitmap->sty_data->id);	
		os_strace_u32(SYS_TRACE_ID_RES_BMP_LOAD_2, (uint32_t)bitmap->sty_data->id);
		if(ret == compress_size)
		{
#ifndef CONFIG_LVGL_USE_IMG_DECODER_ACTS
#ifdef CONFIG_JPEG_HAL
			if (bitmap->sty_data->format == RESOURCE_BITMAP_FORMAT_JPEG) {
				ret = jpg_decode(compress_buf, compress_size, bitmap->buffer, jpeg_out_format, bitmap->sty_data->width, 0, 0, bitmap->sty_data->width, bitmap->sty_data->height);
			}
			else
#endif
#endif
			{
#ifndef CONFIG_SIMULATOR
				ret = p_brom_misc_api->p_decompress(compress_buf, bitmap->buffer, compress_size, bmp_size);
#else
				ret = LZ4_decompress_safe(compress_buf, bitmap->buffer, compress_size, bmp_size);
#endif
			}
		}

		if ((bitmap->sty_data->format != RESOURCE_BITMAP_FORMAT_INDEX8 && ret < bmp_size) ||
			(bitmap->sty_data->format == RESOURCE_BITMAP_FORMAT_INDEX8 && ret <= bitmap->sty_data->width * bitmap->sty_data->height + 4)){
			SYS_LOG_INF("bmp dump pos for %s: 0x%x\n", info->sty_path, bmp_pos);
			for (int i = 0; i < 4; i++) {
				SYS_LOG_INF("%d: 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n", i, compress_buf[8*i], compress_buf[8*i+1], compress_buf[8*i+2],
					compress_buf[8*i+3], compress_buf[8*i+4], compress_buf[8*i+5], compress_buf[8*i+6], compress_buf[8*i+7]);
			}
		} else {
			ret = bmp_size; /* for RESOURCE_BITMAP_FORMAT_INDEX8 */
		}
#if !defined(CONFIG_RES_MANAGER_USE_STYLE_MMAP)||defined(CONFIG_SIMULATOR)		
		res_mem_free(RES_MEM_POOL_BMP, compress_buf);
#endif
		os_strace_end_call_u32(SYS_TRACE_ID_RES_BMP_LOAD_2, (uint32_t)bitmap->sty_data->id);
	}
	else
	{
		ret = fs_read(pic_fp, bitmap->buffer, bmp_size);
		os_strace_end_call_u32(SYS_TRACE_ID_RES_BMP_LOAD_1, (uint32_t)bitmap->sty_data->id);	
	}
	
	if(ret < bmp_size)
	{
		SYS_LOG_INF("bitmap load error %d, compress_buf %p, compress_size %d, styid 0x%x, id %d, w %d, h %d, bmp_size %d, buffer %p, bmp_pos 0x%x\n", 
			ret, compress_buf, compress_size, bitmap->sty_data->sty_id, bitmap->sty_data->id, bitmap->sty_data->width, bitmap->sty_data->height, 
			bmp_size, bitmap->buffer, bmp_pos);
	}	
	
	mem_dcache_clean(bitmap->buffer, bmp_size);	
	
#if RES_MEM_DEBUG
	if(res_mem_check()<0)
	{
		SYS_LOG_INF("%s %d\n", __FILE__, __LINE__);
		res_mem_dump();
	}
#endif		

	os_mutex_unlock(&bitmap_cache_mutex);
	return 0;
}

int _load_string(resource_info_t* info, resource_text_t* text)
{
	int ret;
    res_head_t res_head;
    res_entry_t res_entry;

	if((info == NULL) || (text == NULL))
	{
		SYS_LOG_INF("error: invalid param to load text \n");
		return -1;
	}
	text->buffer = _try_resource_text_buffer((uint32_t)info, text->sty_data->id);
	if(text->buffer != NULL)
	{
		//got string buffer from cache
		return 0;
	}

	fs_seek(&info->text_fp, 0, FS_SEEK_SET);
	memset(&res_head, 0, sizeof(res_head));
	ret = fs_read(&info->text_fp, &res_head, sizeof(res_head));
    if (ret < sizeof(res_head) || res_head.version != 2)
    {
        //support utf8 only for now
        SYS_LOG_INF("error: unsupported encoding %d\n", res_head.version);
        return -1;
    }

    memset(&res_entry, 0, sizeof(res_entry_t));
	fs_seek(&info->text_fp,(int)(text->sty_data->id * (int)sizeof(res_entry_t)) , FS_SEEK_SET);
	ret = fs_read(&info->text_fp, &res_entry, sizeof(res_entry_t));
    if(ret < sizeof(res_entry_t))
    {
    	SYS_LOG_INF("error: cannot find string resource in %s, id %d\n", info->str_path, text->sty_data->id);
    	return -1;
    }

//	SYS_LOG_INF("offset %d, length %d", res_entry.offset, res_entry.length);
	fs_seek(&info->text_fp, res_entry.offset, FS_SEEK_SET);

    text->buffer = _get_resource_text_buffer((uint32_t)info, text->sty_data->id, res_entry.length+1);
	if(text->buffer == NULL)
	{
		SYS_LOG_INF("error: cannot get text buffer for %s : id %d, offset %d, length %d\n", info->str_path, text->sty_data->id, res_entry.offset, res_entry.length);
		return -1;
	}
	
//	SYS_LOG_INF("text buffer 0x%x\n", text->buffer);
    memset(text->buffer, 0, res_entry.length+1);
	ret = fs_read(&info->text_fp, text->buffer, res_entry.length);
	if(ret < res_entry.length)
	{
		SYS_LOG_INF("error: cannot read string in %s for resource id %d, offset %d, length %d\n", info->str_path, text->sty_data->id, res_entry.offset, res_entry.length);
		return -1;
	}

	return 0;
}

uint32_t _check_resource_is_regular(uint32_t res_magic, uint32_t res_sty_id)
{
	regular_info_t* regular = regular_info_list;
	uint32_t i;

	while(regular != NULL)
	{
		if(regular->magic+res_sty_id == res_magic)
		{
			uint32_t* id = regular->id;
			for(i=0;i<regular->num;i++)
			{
				if(res_sty_id == id[i])
				{
					return (uint32_t)regular;
				}
			}
		}

		regular = regular->next;
	}

	return 0;
}

void* res_manager_get_scene_child(resource_info_t* res_info, resource_scene_t* scene, uint32_t id)
{
    uint32_t i;
    resource_t* resource;
	char* buf = NULL;   //地址不对齐,不能用数据类型指针。
	int ret;

    if ( scene == NULL )
    {
    	SYS_LOG_INF("null scene \n");
        return NULL;
    }

    buf = (char*)res_info->sty_data + scene->child_offset;
	resource = (resource_t*)buf;

//	SYS_LOG_INF("resource sum %d, child offset %d, LF 0x%x\n", scene->resource_sum, scene->child_offset, id);
    for ( i = 0; i < scene->resource_sum; i++ )
    {
	   	//SYS_LOG_INF("resource id 0x%x, offset 0x%x",resource->id, resource->offset);
        if ( resource->id == id )
        {
            break;
        }

        buf = res_info->sty_data + resource->offset;
		resource = (resource_t*)buf;
    }

    if(i >= scene->resource_sum)
    {
    	SYS_LOG_INF("%s %d: error: cannot find resource 0x%x \n", __func__, __LINE__, id);
    	return NULL;
    }

//	SYS_LOG_INF("resource->type 0x%x", resource.type);
    if(resource->type == RESOURCE_TYPE_GROUP)
    {
		//buf is now on group resource start
    	resource_group_t* res = (resource_group_t*)res_array_alloc(RES_MEM_SIMPLE_INNER, sizeof(resource_group_t));
    	if(res == NULL)
    	{
    		SYS_LOG_INF("%s %d: error: no space for resource \n", __func__, __LINE__);
    		return NULL;
    	}
		sty_group_t* group = (sty_group_t*)resource;
		res->sty_data = group;		
		return res;
    }

    if(resource->type == RESOURCE_TYPE_PICTURE)
    {
    	//buf is now on resource start
    	resource_bitmap_t* res = (resource_bitmap_t*)res_array_alloc(RES_MEM_SIMPLE_INNER, sizeof(resource_bitmap_t));
    	if(res == NULL)
    	{
    		SYS_LOG_INF("%s %d: error: no space for resource \n", __func__, __LINE__);
    		return NULL;
    	}
		memset(res, 0, sizeof(resource_bitmap_t));		
		sty_picture_t* pic = (sty_picture_t*)resource;
		res->sty_data = pic;
		res->regular_info = 0;
//		SYS_LOG_INF("pic w %d, h %d, id 0x%x", res->width, res->height, res->id);
    	ret = _load_bitmap(res_info, res, 1);
		if(ret < 0)
		{
			SYS_LOG_INF("%s %d: get scene child bitmap faild\n", __func__, __LINE__);
			res_manager_release_resource(res);
			res = NULL;
		}
		return res;
    }

    if(resource->type == RESOURCE_TYPE_TEXT)
    {
    	//buf is now on resource start
    	resource_text_t* res = (resource_text_t*)res_array_alloc(RES_MEM_SIMPLE_INNER, sizeof(resource_text_t));
    	if(res == NULL)
    	{
    		SYS_LOG_INF("%s %d: error: no space for resource \n", __func__, __LINE__);
    		return NULL;
    	}
		memset(res, 0, sizeof(resource_text_t));
		sty_string_t* str = (sty_string_t*)resource;
		res->sty_data = str;
//		SYS_LOG_INF("str size %d, id 0x%x", res->font_size, res->id);
    	ret = _load_string(res_info, res);
		if(ret < 0)
		{
			res_manager_release_resource(res);
			res = NULL;
		}
		return res;
    }

	if(resource->type == RESOURCE_TYPE_PICREGION)
	{
		resource_picregion_t* res = (resource_picregion_t*)res_array_alloc(RES_MEM_SIMPLE_INNER, sizeof(resource_picregion_t));
		if(res == NULL)
		{
    		SYS_LOG_INF("%s %d: error: no space for resource \n", __func__, __LINE__);
    		return NULL;
		}
		sty_picregion_t* picreg = (sty_picregion_t*)resource;
		res->sty_data = picreg;
		res->regular_info = 0;
		return res;
	}
	return NULL;
}

void* res_manager_get_group_child(resource_info_t* res_info, resource_group_t* resgroup, uint32_t id )
{
    unsigned int i;
	resource_t* resource;
	char*buf;
	int ret;

    if ( resgroup == NULL )
    {
        SYS_LOG_INF("invalid group \n");
        return NULL;
    }

    buf = (char*)res_info->sty_data + resgroup->sty_data->child_offset;
	resource = (resource_t*)buf;

//	SYS_LOG_INF("resource sum %d, search id 0x%x\n", resgroup->sty_data->resource_sum, id);
    for ( i = 0; i < resgroup->sty_data->resource_sum; i++ )
    {
//    	SYS_LOG_INF("\n ### resource id 0x%x\n", resource->id);
        if ( resource->id == id )
        {
            break;
        }

        buf = res_info->sty_data + resource->offset;
		resource = (resource_t*)buf;
    }

    if(i >= resgroup->sty_data->resource_sum)
    {
    	SYS_LOG_INF("%s %d: cant find resource 0x%x \n", __func__, __LINE__, id);
    	return NULL;
    }

//	SYS_LOG_INF("resource.type 0x%x", resource.type);
    if(resource->type == RESOURCE_TYPE_GROUP)
    {
		//buf is now on group resource start
    	resource_group_t* res = (resource_group_t*)res_array_alloc(RES_MEM_SIMPLE_INNER, sizeof(resource_group_t));
    	if(res == NULL)
    	{
    		SYS_LOG_INF("%s %d: error: no space for resource \n", __func__, __LINE__);
    		return NULL;
    	}
		memset(res, 0, sizeof(resource_group_t));
		sty_group_t* group = (sty_group_t*)resource;
		res->sty_data = group;
		return res;

    }

    if(resource->type == RESOURCE_TYPE_PICTURE)
    {
    	//buf is now on resource start
    	resource_bitmap_t* res = (resource_bitmap_t*)res_array_alloc(RES_MEM_SIMPLE_INNER, sizeof(resource_bitmap_t));
    	if(res == NULL)
    	{
    		SYS_LOG_INF("%s %d: error: no space for resource \n", __func__, __LINE__);
    		return NULL;
    	}
		memset(res, 0, sizeof(resource_bitmap_t));		
		sty_picture_t* pic = (sty_picture_t*)resource;
		res->sty_data = pic;
//		SYS_LOG_INF("pic w %d, h %d, id 0x%x", res->width, res->height, res->id);
		res->regular_info = 0;
    	ret = _load_bitmap(res_info, res, 1);
		if(ret < 0)
		{
			SYS_LOG_INF("%s %d: get group child bitmap faild\n", __func__, __LINE__);
			res_manager_release_resource(res);
			res = NULL;
		}
		return res;
    }

    if(resource->type == RESOURCE_TYPE_TEXT)
    {
    	//buf is now on resource start
    	resource_text_t* res = (resource_text_t*)res_array_alloc(RES_MEM_SIMPLE_INNER, sizeof(resource_text_t));
    	if(res == NULL)
    	{
    		SYS_LOG_INF("%s %d: error: no space for resource \n", __func__, __LINE__);
    		return NULL;
    	}
		memset(res, 0, sizeof(resource_text_t));
		sty_string_t* str = (sty_string_t*)resource;
		res->sty_data = str;
//		SYS_LOG_INF("str size %d, id 0x%x", res->font_size, res->id);
    	ret = _load_string(res_info, res);
		if(ret < 0)
		{
			res_manager_release_resource(res);
			res = NULL;
		}

		return res;
    }

	if(resource->type == RESOURCE_TYPE_PICREGION)
	{
		resource_picregion_t* res = (resource_picregion_t*)res_array_alloc(RES_MEM_SIMPLE_INNER, sizeof(resource_picregion_t));
		if(res == NULL)
		{
    		SYS_LOG_INF("%s %d: error: no space for resource \n", __func__, __LINE__);
    		return NULL;
		}
		sty_picregion_t* picreg = (sty_picregion_t*)resource;
		res->sty_data = picreg;
		res->regular_info = 0;
		return res;
	}
	return NULL;
}

resource_bitmap_t* res_manager_load_frame_from_picregion(resource_info_t* info, resource_picregion_t* picreg, uint32_t frame)
{
	resource_bitmap_t* bitmap;
	uint8_t* buf;
	int32_t ret;

	if(info == NULL || picreg == NULL)
	{
        SYS_LOG_INF("invalid picreg \n");
        return NULL;
	}

	bitmap = (resource_bitmap_t*)res_array_alloc(RES_MEM_SIMPLE_INNER, sizeof(resource_bitmap_t));
	if(bitmap == NULL)
	{
        SYS_LOG_INF("no space for frame loading \n");
        return NULL;
	}
	buf = info->sty_data + picreg->sty_data->id_offset + sizeof(sty_picture_t)*frame;
	bitmap->sty_data = (sty_picture_t*)buf;
	bitmap->regular_info = picreg->regular_info;

	ret = _load_bitmap(info, bitmap, 1);
	if(ret < 0)
	{
		SYS_LOG_INF("picregion load frame faild \n");
		res_manager_release_resource(bitmap);
		bitmap = NULL;
	}

	return bitmap;
}


void res_manager_release_resource(void* resource)
{
	uint32_t type = *((uint32_t*)(*((uint32_t*)(resource))));

	if(type == RESOURCE_TYPE_GROUP)
	{
		res_array_free(resource);
	}
	else if(type == RESOURCE_TYPE_PICTURE)
	{
		resource_bitmap_t* bitmap = (resource_bitmap_t*)resource;
		_unload_bitmap(bitmap);
		res_array_free(resource);
	}
	else if(type == RESOURCE_TYPE_TEXT)
	{
		resource_text_t* text = (resource_text_t*)resource;
		_unload_string(text);
		res_array_free(resource);
	}
	else if(type == RESOURCE_TYPE_PICREGION)
	{
		resource_picregion_t* picreg = (resource_picregion_t*)resource;
		res_array_free(picreg);
	}
}

void res_manager_free_resource_structure(void* resource)
{
	if(resource != NULL)
	{
		res_array_free(resource);
	}
}

void res_manager_free_bitmap_data(void* data)
{
	if(data != NULL)
	{
		os_mutex_lock(&bitmap_cache_mutex, OS_FOREVER);
		_free_resource_bitmap_buffer(data);
		os_mutex_unlock(&bitmap_cache_mutex);
	}
}

void res_manager_free_text_data(void* data)
{
	if(data != NULL)
	{
		_free_resource_text_buffer(data);
	}
}

int32_t res_manager_preload_bitmap(resource_info_t* res_info, resource_bitmap_t* bitmap)
{
	int32_t ret;
	ret = _load_bitmap(res_info, bitmap, 0);
	if(ret < 0)
	{
		SYS_LOG_INF("preload bitmap error 0x%x, %p\n", bitmap->sty_data->id, bitmap->sty_data);
		return -1;
	}
	else
	{
		//SYS_LOG_INF("preload success 0x%x\n", bitmap->sty_data->id);
		return 0;
	}

}

int32_t res_manager_preload_bitmap_compact(uint32_t scene_id, resource_info_t* res_info, resource_bitmap_t* bitmap)
{
	int32_t ret;

//	SYS_LOG_INF("\n res_manager_preload_bitmap_compact scene_id 0x%x\n", scene_id);
	ret = _load_bitmap(res_info, bitmap, scene_id);
	if(ret < 0)
	{
		SYS_LOG_INF("preload bitmap compact error scene 0x%x, 0x%x\n", scene_id, bitmap->sty_data->id);
		return -1;
	}
	else
	{
		//SYS_LOG_INF("preload success 0x%x\n", bitmap->sty_data->id);
		return 0;
	}

}


int32_t res_manager_load_bitmap(resource_info_t* res_info, resource_bitmap_t* bitmap)
{
	int32_t ret;

	ret = _load_bitmap(res_info, bitmap, 1);
	if(ret < 0)
	{
		SYS_LOG_INF("load bitmap error 0x%x\n", bitmap->sty_data->sty_id);
		return -1;
	}
	else
	{
		return 0;
	}

}

uint32_t res_manager_get_bitmap_buf_block_unit_size(void)
{
	return sizeof(buf_block_t);
}

int32_t res_manager_init_compact_buffer(uint32_t scene_id, size_t size)
{
	compact_buffer_t* ret;
	os_mutex_lock(&bitmap_cache_mutex, OS_FOREVER);
	
	ret = _init_compact_buffer(scene_id, size);
	if(ret == NULL)
	{
		SYS_LOG_INF("alloc compact buffer failed: 0x%x, %d\n", scene_id, size);
		os_mutex_unlock(&bitmap_cache_mutex);
		return -1;
	}

	os_mutex_unlock(&bitmap_cache_mutex);
	return 0;
}

void* res_manager_preload_from_scene(resource_info_t* res_info, resource_scene_t* scene, uint32_t id)
{
	uint32_t i;
	resource_t* resource;
	char* buf = NULL;	//地址不对齐,不能用数据类型指针。

	if ( scene == NULL )
	{
		SYS_LOG_INF("%s %d: null scene to preload \n", __func__, __LINE__);
		return NULL;
	}

	buf = (char*)res_info->sty_data + scene->child_offset;
	resource = (resource_t*)buf;

//	SYS_LOG_INF("resource sum %d, child offset %d", scene->resource_sum, scene->child_offset);
	for ( i = 0; i < scene->resource_sum; i++ )
	{
//		SYS_LOG_INF("resource id 0x%x, offset 0x%x",resource.id, resource.offset);
		if ( resource->id == id )
		{
			break;
		}

		buf = res_info->sty_data + resource->offset;
		resource = (resource_t*)buf;
	}

	if(i >= scene->resource_sum)
	{
		SYS_LOG_INF("%s %d: error: cannot find resource 0x%x in scene 0x%x\n", __func__, __LINE__, id, scene->scene_id);
		return NULL;
	}


    if(resource->type == RESOURCE_TYPE_GROUP)
    {
		//buf is now on group resource start
		resource_group_t* res = (resource_group_t*)res_array_alloc(RES_MEM_SIMPLE_INNER, sizeof(resource_group_t));
		if(res == NULL)
		{
			SYS_LOG_INF("%s %d: error: no space for resource \n", __func__, __LINE__);
			return NULL;
		}
		sty_group_t* group = (sty_group_t*)resource;
		res->sty_data = group;		

		return res;
    }

	if(resource->type == RESOURCE_TYPE_PICREGION)
	{
		resource_picregion_t* res = (resource_picregion_t*)res_array_alloc(RES_MEM_SIMPLE_INNER, sizeof(resource_picregion_t));
		if(res == NULL)
		{
    		SYS_LOG_INF("%s %d: error: no space for resource \n", __func__, __LINE__);
    		return NULL;
		}
		sty_picregion_t* picreg = (sty_picregion_t*)resource;
		res->sty_data = picreg;
		res->regular_info = _check_resource_is_regular(picreg->magic, picreg->sty_id);
		return res;
	}	

	//	SYS_LOG_INF("resource->type 0x%x", resource.type);
	if(resource->type == RESOURCE_TYPE_PICTURE)
	{
    	//buf is now on resource start
		resource_bitmap_t* res = (resource_bitmap_t*)res_array_alloc(RES_MEM_SIMPLE_INNER, sizeof(resource_bitmap_t));
		if(res == NULL)
		{
			SYS_LOG_INF("%s %d: error: no space for resource \n", __func__, __LINE__);
			return NULL;
		}
		memset(res, 0, sizeof(resource_bitmap_t));		
		sty_picture_t* pic = (sty_picture_t*)resource;
		res->sty_data = pic;

		res->regular_info = _check_resource_is_regular(pic->magic, pic->sty_id);
//		SYS_LOG_INF("scene 0x%x, id 0x%x, regular 0x%x", scene->scene_id, id, res->regular_info);

#if RES_MEM_DEBUG
		if(res_mem_check()<0)
		{
			SYS_LOG_INF("%s %d\n", __FILE__, __LINE__);
			res_mem_dump();
		}
#endif		

		return res;
	}

//	SYS_LOG_INF("wrong type to preload");
	return NULL;
}

resource_bitmap_t* res_manager_preload_from_group(resource_info_t* res_info, resource_group_t* group, uint32_t scene_id, uint32_t id)
{
	uint32_t i;
	resource_t* resource;
	char* buf = NULL;	//地址不对齐,不能用数据类型指针。

	if ( group == NULL )
	{
		SYS_LOG_INF("%s %d: null scene to preload \n", __func__, __LINE__);
		return NULL;
	}

	buf = (char*)res_info->sty_data + group->sty_data->child_offset;
	resource = (resource_t*)buf;

//	SYS_LOG_INF("resource sum %d, search id 0x%x\n", resgroup->resource_sum, id);
	for ( i = 0; i < group->sty_data->resource_sum; i++ )
	{
//		SYS_LOG_INF("\n ### resource id 0x%x\n", resource->id);
		if ( resource->id == id )
		{
			break;
		}

		buf = res_info->sty_data + resource->offset;
		resource = (resource_t*)buf;
	}

	if(i >= group->sty_data->resource_sum)
	{
		SYS_LOG_INF("%s %d: cant find resource 0x%x \n", __func__, __LINE__, id);
		return NULL;
	}


//	SYS_LOG_INF("resource->type 0x%x", resource.type);
	if(resource->type == RESOURCE_TYPE_PICTURE)
	{
		//buf is now on resource start
		resource_bitmap_t* res = (resource_bitmap_t*)res_array_alloc(RES_MEM_SIMPLE_INNER, sizeof(resource_bitmap_t));
		if(res == NULL)
		{
			SYS_LOG_INF("%s %d: error: no space for resource to preload\n", __func__, __LINE__);
			return NULL;
		}
		memset(res, 0, sizeof(resource_bitmap_t));
		sty_picture_t* pic = (sty_picture_t*)resource;
		res->sty_data = pic;

		res->regular_info = _check_resource_is_regular(pic->magic, pic->sty_id);
//		SYS_LOG_INF("scene 0x%x, id 0x%x, regular 0x%x", scene_id, id, res->regular_info);
#if RES_MEM_DEBUG
		if(res_mem_check()<0)
		{
			SYS_LOG_INF("%s %d\n", __FILE__, __LINE__);
			res_mem_dump();
		}
#endif		

		return res;
	}

//	SYS_LOG_INF("wrong type to preload");
	return NULL;

}

resource_bitmap_t* res_manager_preload_from_picregion(resource_info_t* res_info, resource_picregion_t* picreg, uint32_t frame)
{
	resource_bitmap_t* bitmap;
	uint8_t* buf;

	if(res_info == NULL || picreg == NULL)
	{
        SYS_LOG_INF("invalid picreg for preload \n");
        return NULL;
	}

	bitmap = (resource_bitmap_t*)res_array_alloc(RES_MEM_SIMPLE_INNER, sizeof(resource_bitmap_t));
	if(bitmap == NULL)
	{
        SYS_LOG_INF("no space for frame preloading \n");
        return NULL;
	}
	
	buf = res_info->sty_data + picreg->sty_data->id_offset + sizeof(sty_picture_t)*frame;
	bitmap->sty_data = (sty_picture_t*)buf;
	bitmap->regular_info = picreg->regular_info;

	return bitmap;

}


void* res_manager_preload_next_group_child(resource_info_t * info, resource_group_t* group, int* count, uint32_t* offset, uint32_t scene_id, uint32_t pargroup_id)
{
    resource_t* resource;
	char* buf = NULL;   //地址不对齐,不能用数据类型指针。
	uint32_t cur_count = *count;
	uint32_t next_offset = *offset;

	if(group == NULL)
	{
		SYS_LOG_INF("invalid param for res_manager_preload_next_group_child\n");
		return NULL;
	}

	if(group->sty_data->resource_sum == 0)
	{
		return NULL;
	}

	if(cur_count == 0)
	{
		buf = (char*)info->sty_data + group->sty_data->child_offset;
		resource = (resource_t*)buf;
		
		*count = 1;
		*offset = resource->offset;
	}
	else if(cur_count >= group->sty_data->resource_sum)
	{
		//reach the last one
		return NULL;
	}
	else
	{
		buf = info->sty_data + next_offset;
		resource = (resource_t*)buf;
		cur_count++;
		next_offset = resource->offset;
		*count = cur_count;
		*offset = next_offset;
	}
	if(resource->type == RESOURCE_TYPE_GROUP)
	{
		//buf is now on group resource start
		resource_group_t* res = (resource_group_t*)res_array_alloc(RES_MEM_SIMPLE_INNER, sizeof(resource_group_t));
		if(res == NULL)
		{
			SYS_LOG_INF("%s %d: error: no space for resource \n", __func__, __LINE__);
			return NULL;
		}
	
		sty_group_t* group = (sty_group_t*)resource;
		res->sty_data = group;

		return res;
	}

	if(resource->type == RESOURCE_TYPE_PICREGION)
	{
		resource_picregion_t* res = (resource_picregion_t*)res_array_alloc(RES_MEM_SIMPLE_INNER, sizeof(resource_picregion_t));
		if(res == NULL)
		{
			SYS_LOG_INF("%s %d: error: no space for resource \n", __func__, __LINE__);
			return NULL;
		}

		sty_picregion_t* picreg = (sty_picregion_t*)resource;
		res->sty_data = picreg;
		res->regular_info = _check_resource_is_regular(picreg->magic, picreg->sty_id);
		return res;
	}

	if(resource->type == RESOURCE_TYPE_PICTURE)
	{
		//buf is now on resource start
		resource_bitmap_t* res = (resource_bitmap_t*)res_array_alloc(RES_MEM_SIMPLE_INNER, sizeof(resource_bitmap_t));
		if(res == NULL)
		{
			SYS_LOG_INF("%s %d: error: no space for resource to preload \n", __func__, __LINE__);
			return NULL;
		}
		memset(res, 0, sizeof(resource_bitmap_t));
		sty_picture_t* pic = (sty_picture_t*)resource;
		res->sty_data = pic;
		res->regular_info = _check_resource_is_regular(pic->magic, pic->sty_id);

//		SYS_LOG_INF("pic w %d, h %d, id 0x%x", res->width, res->height, res->id);
//		SYS_LOG_INF("scene 0x%x, id 0x%x, regular 0x%x", scene_id, resource->id, res->regular_info);

		return res;
	}

	//ignore text
	return NULL;
}

void* res_manager_preload_next_scene_child(resource_info_t* info, resource_scene_t* scene, uint32_t* count, uint32_t* offset)
{
    resource_t* resource;
	uint8_t* buf = NULL;   //地址不对齐,不能用数据类型指针。
	uint32_t cur_count = *count;
	uint32_t next_offset = (uint32_t)*offset;

	if(scene == NULL)
	{
		SYS_LOG_INF("invalid param for res_manager_preload_next_scene_child\n");
		return NULL;
	}

	if(scene->resource_sum == 0)
	{
		return NULL;
	}	

	if(cur_count == 0)
	{
		buf = (uint8_t*)info->sty_data + scene->child_offset;
		resource = (resource_t*)buf;
		*count = 1;
		*offset = resource->offset;
	}
	else if(cur_count >= scene->resource_sum)
	{
		//reach the last one
		return NULL;
	}
	else
	{
		buf = (uint8_t*)info->sty_data + next_offset;
		resource = (resource_t*)buf;
		cur_count++;
		next_offset = resource->offset;
		*count = cur_count;
		*offset = next_offset;
	}

    if(resource->type == RESOURCE_TYPE_GROUP)
    {
		//buf is now on group resource start
    	resource_group_t* res = (resource_group_t*)res_array_alloc(RES_MEM_SIMPLE_INNER, sizeof(resource_group_t));
    	if(res == NULL)
    	{
    		SYS_LOG_INF("%s %d: error: no space for resource \n", __func__, __LINE__);
    		return NULL;
    	}
	
		sty_group_t* group = (sty_group_t*)resource;
		res->sty_data = group;	

		return res;
    }

	if(resource->type == RESOURCE_TYPE_PICREGION)
	{
		resource_picregion_t* res = (resource_picregion_t*)res_array_alloc(RES_MEM_SIMPLE_INNER, sizeof(resource_picregion_t));
		if(res == NULL)
		{
    		SYS_LOG_INF("%s %d: error: no space for resource \n", __func__, __LINE__);
    		return NULL;
		}

		sty_picregion_t* picreg = (sty_picregion_t*)resource;
		res->sty_data = picreg;
		res->regular_info = _check_resource_is_regular(picreg->magic, picreg->sty_id);		
		return res;
	}

	if(resource->type == RESOURCE_TYPE_PICTURE)
	{
		//buf is now on resource start
		resource_bitmap_t* res = (resource_bitmap_t*)res_array_alloc(RES_MEM_SIMPLE_INNER, sizeof(resource_bitmap_t));
		if(res == NULL)
		{
			SYS_LOG_INF("%s %d: error: no space for resource to preload \n", __func__, __LINE__);
			return NULL;
		}
		memset(res, 0, sizeof(resource_bitmap_t));
		
		sty_picture_t* pic = (sty_picture_t*)resource;
		res->sty_data = pic;
 		res->regular_info = _check_resource_is_regular(pic->magic, pic->sty_id);
//		SYS_LOG_INF("scene 0x%x, id 0x%x, regular 0x%x", cur_scene_id, resource->id, res->regular_info);
		return res;
	}

	//ignore text;
	return NULL;
}

void res_manager_preload_finish_check(uint32_t scene_id)
{
	compact_buffer_t* buffer;

	os_strace_u32(SYS_TRACE_ID_RES_CHECK_PRELOAD, (uint32_t)scene_id);	
	os_mutex_lock(&bitmap_cache_mutex, OS_FOREVER);

	buffer = bitmap_buffer.compact_buffer_list;
	while(buffer != NULL)
	{
		if(buffer->scene_id == scene_id)
		{
			mem_dcache_clean(buffer->addr, buffer->offset);			
		}
		buffer = buffer->next;	
	}

	os_mutex_unlock(&bitmap_cache_mutex);
	os_strace_end_call_u32(SYS_TRACE_ID_RES_CHECK_PRELOAD, (uint32_t)scene_id);	
}

uint32_t res_manager_scene_is_loaded(uint32_t scene_id)
{
	compact_buffer_t* buffer = bitmap_buffer.compact_buffer_list;
	buf_block_t* item;

	while(buffer)
	{
//		SYS_LOG_DBG("buffer->scene_id 0x%x, scene_id 0x%x\n", buffer->scene_id, scene_id);
		if(buffer->scene_id == scene_id)
		{
			item = (buf_block_t*)buffer->addr;
			if(item->regular_info == 0)
			{
				return 1;
			}
		}

		buffer = buffer->next;
	}

	return 0;
}

#ifdef CONFIG_RES_MANAGER_IMG_DECODER
#include <lvgl/lvgl.h>
#define RAW_RES_DATA_SIZE	(sizeof(resource_bitmap_t))

static lv_img_cf_t _get_res_img_cf(const resource_bitmap_t *sty)
{
	lv_img_cf_t cf; 

	switch (sty->sty_data->format) {
	case RESOURCE_BITMAP_FORMAT_ARGB8888:
		cf = LV_IMG_CF_ARGB_8888;
		break;
	case RESOURCE_BITMAP_FORMAT_RGB565:
	case RESOURCE_BITMAP_FORMAT_JPEG:	
		cf = LV_IMG_CF_RGB_565;
		break;
	case RESOURCE_BITMAP_FORMAT_ARGB8565:
		cf = LV_IMG_CF_ARGB_8565;
		break;
	case RESOURCE_BITMAP_FORMAT_A8:
		cf = LV_IMG_CF_ALPHA_8BIT;
		break;
	case RESOURCE_BITMAP_FORMAT_ARGB6666:
		cf = LV_IMG_CF_ARGB_6666;
		break;
	case RESOURCE_BITMAP_FORMAT_ARGB1555:
		cf = LV_IMG_CF_ARGB_1555;
		break;
	case RESOURCE_BITMAP_FORMAT_INDEX8:
		cf = LV_IMG_CF_INDEXED_8BIT_ACTS;
		break;
	case RESOURCE_BITMAP_FORMAT_LVGL_INDEX8:
		cf = LV_IMG_CF_INDEXED_8BIT;
		break;
	case RESOURCE_BITMAP_FORMAT_INDEX4:
		cf = LV_IMG_CF_INDEXED_4BIT;
		break;
	case RESOURCE_BITMAP_FORMAT_ETC2_EAC:
		cf = LV_IMG_CF_ETC2_EAC;
		break;
	case RESOURCE_BITMAP_FORMAT_RGB888:
	case RESOURCE_BITMAP_FORMAT_RAW:
	default:
		cf = LV_IMG_CF_UNKNOWN;
	}

	return cf;
}

static int32_t _load_bitmap_for_decoder(resource_info_t* info, resource_bitmap_t* bitmap)
{
	int32_t ret;
	int32_t bmp_size;
	int32_t compress_size = 0;
	uint8_t *compress_buf = NULL;
	struct fs_file_t* pic_fp;
	uint32_t bmp_pos = 0;

	if(bitmap == NULL)
	{
		SYS_LOG_INF("error: invalid param to load bitmap \n");
		return -1;
	}

	if(_get_resource_bitmap_map(info, bitmap) == 0)
	{
		//bitmap directly mapped from file
		return 0;
	}
#if RES_MEM_DEBUG
	SYS_LOG_INF("decode bitmap id %d, w %d, height %d, bpp %d\n", bitmap->sty_data->id, bitmap->sty_data->width, bitmap->sty_data->height, bitmap->sty_data->bytes_per_pixel);
#endif
	//bmp_size = bitmap->sty_data->width * bitmap->sty_data->height * bitmap->sty_data->bytes_per_pixel;
	if (bitmap->sty_data->format == RESOURCE_BITMAP_FORMAT_ETC2_EAC) {
		bmp_size = ((bitmap->sty_data->width + 0x3) & ~0x3) *
		           ((bitmap->sty_data->height + 0x3) & ~0x3);
	} else if (bitmap->sty_data->format == RESOURCE_BITMAP_FORMAT_INDEX8) {
		bmp_size = bitmap->sty_data->width * bitmap->sty_data->height + 1024 + 4;
	} else if (bitmap->sty_data->format == RESOURCE_BITMAP_FORMAT_LVGL_INDEX8) {
		bmp_size = bitmap->sty_data->width * bitmap->sty_data->height + 1024;
	} else if (bitmap->sty_data->format == RESOURCE_BITMAP_FORMAT_INDEX4) {
		bmp_size = ((bitmap->sty_data->width + 0x1) >> 1) * bitmap->sty_data->height + 64;
	} else {
		bmp_size = bitmap->sty_data->width * bitmap->sty_data->height *
		           bitmap->sty_data->bytes_per_pixel;
	}

	bitmap->buffer = _get_resource_bitmap_buffer(0, bitmap, bmp_size, 1);
	if(bitmap->buffer == NULL)
	{
		SYS_LOG_INF("error: no buffer to load bitmap \n");
		return -2;
	}

	ret = _search_res_id_in_files(info, bitmap, &bmp_pos, &compress_size);
	if(ret <= 0)
	{
		pic_fp = &info->pic_fp;
	}
	else
	{
		pic_fp = &info->pic_search_param[ret].res_fp;
	}
	
#if !defined(CONFIG_RES_MANAGER_USE_STYLE_MMAP)||defined(CONFIG_SIMULATOR)
	fs_seek(pic_fp, bmp_pos, FS_SEEK_SET);
#endif
	if (compress_size > 0)
	{
#if !defined(CONFIG_RES_MANAGER_USE_STYLE_MMAP)||defined(CONFIG_SIMULATOR)	
		compress_buf = (uint8_t*)res_mem_alloc(RES_MEM_POOL_BMP, compress_size);
		if(compress_buf == NULL)
		{
			SYS_LOG_INF("error: no buffer to load compressed bitmap \n");
			_free_resource_bitmap_buffer(bitmap->buffer);
			bitmap->buffer = NULL;
			res_manager_dump_info();
			return -2;
		}
		
		ret = fs_read(pic_fp, compress_buf, compress_size);
		if(ret < compress_size)
		{
			SYS_LOG_INF("bitmap read error %d\n", ret);
		}
#else
		compress_buf = info->pic_res_mmap_addr + bmp_pos;
#endif
		if(ret == compress_size)
		{
#ifndef CONFIG_LVGL_USE_IMG_DECODER_ACTS
#ifdef CONFIG_JPEG_HAL
			if (*(uint32_t*)compress_buf == JPEG_FLAG) {
#if RES_MEM_DEBUG
				SYS_LOG_INF("jpg decode\n");
#endif
				ret = jpg_decode(compress_buf, compress_size, bitmap->buffer, 1, bitmap->sty_data->width, 0, 0, bitmap->sty_data->width, bitmap->sty_data->height);
			}
			else
#endif
#endif
			{
#ifndef CONFIG_SIMULATOR
#if RES_MEM_DEBUG
				SYS_LOG_INF("brom decompress\n");
#endif
				ret = p_brom_misc_api->p_decompress(compress_buf, bitmap->buffer, compress_size, bmp_size);
#else
				ret = LZ4_decompress_safe(compress_buf, bitmap->buffer, compress_size, bmp_size);
#endif
			}
		}

		if ((bitmap->sty_data->format != RESOURCE_BITMAP_FORMAT_INDEX8 && ret < bmp_size) ||
			(bitmap->sty_data->format == RESOURCE_BITMAP_FORMAT_INDEX8 && ret <= bitmap->sty_data->width * bitmap->sty_data->height + 4)){
			SYS_LOG_INF("bmp dump pos for %s: 0x%x\n", info->sty_path, bmp_pos);
			for (int i = 0; i < 4; i++) {
				SYS_LOG_INF("%d: 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n", i, compress_buf[8*i], compress_buf[8*i+1], compress_buf[8*i+2],
					compress_buf[8*i+3], compress_buf[8*i+4], compress_buf[8*i+5], compress_buf[8*i+6], compress_buf[8*i+7]);
			}
		} else {
			ret = bmp_size; /* for RESOURCE_BITMAP_FORMAT_INDEX8 */
		}
#if !defined(CONFIG_RES_MANAGER_USE_STYLE_MMAP)||defined(CONFIG_SIMULATOR)		
		res_mem_free(RES_MEM_POOL_BMP, compress_buf);
#endif
	}
	else
	{
		ret = fs_read(pic_fp, bitmap->buffer, bmp_size);
	}
	
	if(ret < bmp_size)
	{
		SYS_LOG_INF("decoder bitmap load error %d, compress_buf %p, id %d, w %d, h %d, bmp_size %d\n", 
					ret, compress_buf, bitmap->sty_data->id, bitmap->sty_data->width, bitmap->sty_data->height, bmp_size);
		SYS_LOG_INF("decoder bitmap compress size %d, sty compress size %d, bmp pos %d, sty bmp pos\n", 
					compress_size, bitmap->sty_data->compress_size, bmp_pos, bitmap->sty_data->bmp_pos);
	}	
	
	mem_dcache_clean(bitmap->buffer, bmp_size);	
	
	return 0;
}

typedef struct
{
	int pic_id;
	uint8_t* data;
	uint32_t time_to_open;
	int life;
	int force;
}decoder_res_cache_entry_t;

#define DECODER_RES_CACHE_AGING		1
#define DECODER_RES_CACHE_LIFE_LIMIT	1000

static decoder_res_cache_entry_t* decoder_res_cache = NULL;
static int cache_entry_cnt = CONFIG_RES_MANAGER_LVGL_RES_CACHE_MAX;

static uint32_t sys_cycle;
static uint32_t sys_time_ms;


#ifdef CONFIG_SIMULATOR
#include <Windows.h> 
#endif
static uint32_t _tick_get()
{
#ifndef CONFIG_SIMULATOR
	uint32_t cycle = k_cycle_get_32();
	uint32_t delta_ms = k_cyc_to_ms_floor32(cycle - sys_cycle);

	sys_cycle += delta_ms * (sys_clock_hw_cycles_per_sec() / 1000);
	sys_time_ms += delta_ms;

	return sys_time_ms;
#else
	return GetTickCount();
#endif
}

static uint32_t _tick_elaps(uint32_t prev_tick)
{
    uint32_t act_time = _tick_get();

    /*If there is no overflow in sys_time simple subtract*/
    if(act_time >= prev_tick) {
        prev_tick = act_time - prev_tick;
    }
    else {
        prev_tick = UINT32_MAX - prev_tick + 1;
        prev_tick += act_time;
    }

    return prev_tick;
}

static int _add_to_decoder_res_cache(resource_bitmap_t* bitmap, decoder_res_cache_entry_t** cache_entry, int force)
{
	int i;
	decoder_res_cache_entry_t* cache = NULL;
	decoder_res_cache_entry_t* cached_src = NULL;

	if(cache_entry_cnt == 0)
	{
		//decoder res cache not inited
		SYS_LOG_INF("decoder res cache not inited \n");
		return -1;
	}

	if(decoder_res_cache == NULL)
	{
		decoder_res_cache = (decoder_res_cache_entry_t*)res_mem_alloc(RES_MEM_POOL_BMP, sizeof(decoder_res_cache_entry_t)*cache_entry_cnt);
		if(!decoder_res_cache)
		{
			SYS_LOG_INF("init decoder res cache failed \n");
			return -1;
		}
		memset(decoder_res_cache, 0, sizeof(decoder_res_cache_entry_t)*cache_entry_cnt);
	}

	cache = decoder_res_cache;
	for(i=0;i<cache_entry_cnt;i++)
	{
        if(cache[i].life > INT32_MIN + DECODER_RES_CACHE_AGING) 
		{
            cache[i].life -= DECODER_RES_CACHE_AGING;		
		}
	}

	for(i=0;i<cache_entry_cnt;i++)
	{
		if(cache[i].pic_id == bitmap->sty_data->id)
		{
			//found cached pic
			cached_src = &cache[i];
            cached_src->life += cached_src->time_to_open;
            if(cached_src->life > DECODER_RES_CACHE_LIFE_LIMIT) 
			{
				cached_src->life = DECODER_RES_CACHE_LIFE_LIMIT;
			}
			break;
		}
	}

	if(cached_src) 
	{
		bitmap->buffer = cached_src->data;
		if(force == 1)
		{
			cached_src->force = 1;
		}
		*cache_entry = cached_src;
		return 1;
	}

    cached_src = &cache[0];
    for(i = 1; i < cache_entry_cnt; i++) {
        if(cache[i].life < cached_src->life && cache[i].force == 0) {
            cached_src = &cache[i];
        }
    }
/*
	SYS_LOG_INF("cache life 0-7 %d,  %d,  %d,  %d,  %d,  %d,  %d,  %d\n", 
				cache[0].life, cache[1].life, cache[2].life, cache[3].life, cache[4].life, cache[5].life, cache[6].life, cache[7].life);
	SYS_LOG_INF("cache life 8-15 %d,  %d,  %d,  %d,  %d,  %d,  %d,  %d\n", 
				cache[8].life, cache[9].life, cache[10].life, cache[11].life, cache[12].life, cache[13].life, cache[14].life, cache[15].life);
*/
	if(cached_src->data != NULL)
	{
		//FIXME: how to close decoder dsc
		_free_resource_bitmap_buffer(cached_src->data);
		memset(cached_src, 0, sizeof(decoder_res_cache_entry_t));
	}

	if(force == 1)
	{
		cached_src->force = 1;
	}
	*cache_entry = cached_src;

	return 0;
}

static void _clear_decoder_res_cache(void)
{
	int i;
	decoder_res_cache_entry_t* cache_entry = decoder_res_cache;

	if(cache_entry == NULL)
	{
		return;
	}

	for(i = 0; i < cache_entry_cnt; i++)
	{
		//FIXME: do we need to consider reserve forced cache?
		if(cache_entry[i].data != NULL)
		{
			_free_resource_bitmap_buffer(cache_entry[i].data);
		}
		memset(&cache_entry[i], 0, sizeof(decoder_res_cache_entry_t));
	}

	return;
}

static int _free_one_cache_entry(resource_bitmap_t* bitmap, decoder_res_cache_entry_t* cached_src)
{
	decoder_res_cache_entry_t* cache = decoder_res_cache;
    decoder_res_cache_entry_t * inv_src = NULL;
    int k, j;

    for (k = 0; k < cache_entry_cnt; k++)
    {
        if (cache[k].data != NULL && cached_src != &cache[k] && cache[k].force == 0)
        {
            inv_src = &cache[k];
            break;
        }
    }

    if (inv_src == NULL)
    {
        //whole cache cleared out but no enough space
        return -1;
    }

    if (k < cache_entry_cnt - 1)
    {
        for (j = k + 1; j < cache_entry_cnt; j++) 
		{
            if (cached_src != &cache[j] && cache[j].data != NULL && cache[j].life < inv_src->life && cache[j].force == 0) 
			{
                inv_src = &cache[j];
            }
        }
    }

	_free_resource_bitmap_buffer(inv_src->data);
    memset(inv_src, 0, sizeof(decoder_res_cache_entry_t));
    return 0;
}

void res_manager_clear_decoder_cache(void)
{
	_clear_decoder_res_cache();
}

int res_manager_decode_bitmap_to_img_dsc(void* raw, void* decoded)
{
	resource_bitmap_t bitmap;
	lv_img_dsc_t* raw_img = (lv_img_dsc_t*)raw;
	lv_img_dsc_t* decoded_img = (lv_img_dsc_t*)decoded;
	int ret;

	if((raw_img->header.cf != LV_IMG_CF_RAW && raw_img->header.cf != LV_IMG_CF_RAW_ALPHA) ||
		(raw_img->data_size != RAW_RES_DATA_SIZE))
	{
		SYS_LOG_ERR("not a raw res img ");
		return -1;
	}

	memcpy(&bitmap, raw_img->data, raw_img->data_size);
	bitmap.buffer = NULL;

	ret = res_manager_load_bitmap_for_decoder(&bitmap, 1);
	if(ret < 0)
	{
		SYS_LOG_ERR("load bitmap failed in res_manager_decode_bitmap_to_img_dsc\n");
		return -1;
	}

	decoded_img->header.cf = _get_res_img_cf(&bitmap);
	decoded_img->header.always_zero = 0;
	decoded_img->header.w = bitmap.sty_data->width;
	decoded_img->header.h = bitmap.sty_data->height;	
	decoded_img->data = bitmap.buffer;
	decoded_img->data_size = bitmap.sty_data->width * bitmap.sty_data->height * bitmap.sty_data->bytes_per_pixel;

	return 0;
}

int res_manager_load_bitmap_for_decoder(resource_bitmap_t* bitmap, int force)
{
	resource_info_t* info = (resource_info_t*)bitmap->sty_data->magic;
	int ret;
	decoder_res_cache_entry_t* cache_item = NULL;

	if(info->reference == 0)
	{
		ret = _init_pic_search_param(info, info->sty_path);	
		if(ret < 0)
		{
			SYS_LOG_INF("init img resource failed\n");
			return -1;
		}
		info->reference = 1;
	}

	ret = _add_to_decoder_res_cache(bitmap, &cache_item, force);
	if(ret < 0)
	{
		SYS_LOG_ERR("add to decoder res cache failed\n");
		return -1;		
	}

	if(ret > 0)
	{
		//found in cache, add life or sth.
		bitmap->buffer = cache_item->data;
#if RES_MEM_DEBUG
		SYS_LOG_INF("bitmap->buffer cached %p\n", bitmap->buffer);
#endif
		return 0;
	}

	uint32_t t_start  = _tick_get();
	ret = _load_bitmap_for_decoder(info, bitmap);
	while(ret == -2)
	{
		//res mem not enough, release some unforced cache
		ret = _free_one_cache_entry(bitmap, cache_item);
		if(ret < 0)
		{
			SYS_LOG_INF("no enough res cache mem\n");
			break;
		}

		ret = _load_bitmap_for_decoder(info, bitmap);
	}

	if(ret < 0)
	{
		//other load bitmap error, return error
		SYS_LOG_INF("load img resource failed\n");
		if(cache_item)
		{
			memset(cache_item, 0, sizeof(decoder_res_cache_entry_t));
			cache_item->life = INT32_MIN;
		}
		return ret;
	}

	if(cache_item)
	{
		cache_item->pic_id = bitmap->sty_data->id;
		cache_item->data = bitmap->buffer;
		cache_item->life = 0;
		if(cache_item->time_to_open == 0)
		{
			cache_item->time_to_open = _tick_elaps(t_start);
		}

		if(cache_item->time_to_open == 0)
		{
			cache_item->time_to_open = 1;
		}

	    bitmap->buffer = cache_item->data;
	    SYS_LOG_INF("bitmap->buffer %p\n", bitmap->buffer);
	}

	return 0;
}

void res_manager_free_bitmap_for_decoder(void* ptr)
{
	int i;
	decoder_res_cache_entry_t* cache_entry = decoder_res_cache;

	if(cache_entry == NULL || ptr == NULL)
	{
		return;
	}

	for(i=0;i<cache_entry_cnt;i++)
	{
		if(cache_entry[i].data == ptr)
		{
			if(cache_entry[i].force == 1)
			{
				cache_entry[i].force = 0;
			}

			if(cache_entry[i].life > 0)
			{
				cache_entry[i].life = 0;
			}

			break;
		}
	}
	
	//mem block buffer need to release immediately for following big pics, or they will alloc in normal res mem
	if(res_mem_is_block(ptr))
	{
		SYS_LOG_INF("free decoded %p\n", ptr);
		_free_resource_bitmap_buffer(ptr);
		memset(&cache_entry[i], 0, sizeof(decoder_res_cache_entry_t));
	}

}


static int _find_id_from_key(uint8_t* key)
{
	int low, high, mid;
	int ret;

	low = 1;
	high = current_string_res_cnt;
	mid = (current_string_res_cnt)/2;

	while(low <= high)
	{
		ret = strcmp(key, RES_STRING_ID_DIC[mid].key);
		if(ret < 0)
		{
			high = mid - 1;
		}
		else if(ret > 0)
		{
			low = mid + 1;			
		}
		else
		{
			break;
		}

		mid = (low+high)/2;
	}

	if(low <= high)
	{
		return RES_STRING_ID_DIC[mid].value;
	}

	return -1;
}

int res_manager_set_current_string_res(const uint8_t** string_res, uint32_t string_cnt)
{
	if(string_res == NULL)
	{
		return -1;
	}

	current_string_res = string_res;
	current_string_res_cnt = string_cnt;
	return 0;
}

uint8_t* res_manager_get_string(uint8_t* key)
{
	int id = 1;
	
	if(!current_string_res)
	{
		SYS_LOG_ERR("current string resource not inited\n");
		return NULL;
	}

	id = _find_id_from_key(key);

	if(id > 0 && id <= current_string_res_cnt)
	{
		return (uint8_t*)current_string_res[id-1];
	}

	return NULL;
}

uint8_t* res_manager_get_string_from_id(int id)
{
	if(!current_string_res)
	{
		SYS_LOG_ERR("current string resource not inited\n");
		return NULL;
	}

	if(id >= 0 && id < current_string_res_cnt)
	{
		return (uint8_t*)current_string_res[RES_STRING_ID_DIC[id+1].value-1];
	}

	return NULL;
}

#else
int res_manager_decode_bitmap_to_img_dsc(void* raw, void* decoded)
{
	return 0;
}
int res_manager_load_bitmap_for_decoder(resource_bitmap_t* bitmap)
{
	return 0;
}
void res_manager_free_bitmap_for_decoder(void* ptr)
{
	return;
}
int res_manager_set_current_string_res(const uint8_t** string_res, uint32_t string_cnt)
{
	return 0;
}
uint8_t* res_manager_get_string(uint8_t* key)
{
	return NULL;
}
uint8_t* res_manager_get_string_from_id(int id)
{
	return NULL;
}
void res_manager_clear_decoder_cache(void)
{
	return;
}
#endif

void res_manager_dump_info(void)
{
	compact_buffer_t* citem;
	buf_block_t* bitem;
	uint32_t mem_peak;

	//mem dump
	res_mem_dump();	

	//mem peak dump
	mem_peak = res_mem_get_mem_peak();
	if(mem_peak > 0)
	{
		SYS_LOG_INF("res mem peak size is %d\n", mem_peak);
	}
	else
	{
		SYS_LOG_INF("res mem peak statistic not enabled\n");
	}

	//ui mem info
	SYS_LOG_INF("full screen bitmap total %d\n", ui_mem_total);

	//compact buffer dump();
	citem = bitmap_buffer.compact_buffer_list;
	while(citem != NULL)
	{
		SYS_LOG_INF("compact buffer sceneid 0x%x, addr %p, size %d, freesize %d \n", citem->scene_id, citem->addr, citem->offset, citem->free_size);
		citem = citem->next;
	}
	
	//bitmap dump();
	bitem = bitmap_buffer.head;
	while(bitem != NULL)
	{
		SYS_LOG_INF("bitmap buffer id %d, width %d, height %d, addr %p, size %d, ref %d \n", bitem->id, bitem->width, bitem->height, bitem->addr, bitem->size, bitem->ref);
		bitem = bitem->next;
	}

	//txt dump()
	bitem = text_buffer.head;
	while(bitem != NULL)
	{
		SYS_LOG_INF("txt buffer id %d, addr %p \n", bitem->id, bitem->addr);
		bitem = bitem->next;
	}
	
}

#ifdef CONFIG_RES_MANAGER_ENABLE_MEM_LEAK_DEBUG
void res_manager_compact_buffer_check(uint32_t scene_id)
{
	compact_buffer_t* citem;
	citem = bitmap_buffer.compact_buffer_list;
	while(citem != NULL)
	{
		if(citem->scene_id != scene_id)
		{
			SYS_LOG_INF("RES LEAK WARNING: scene 0x%x compact buffer exsit when layout scene 0x%x\n", citem->scene_id, scene_id);
		}
		citem = citem->next;
	}
	
}
#endif