Пример #1
0
uint32 zz_vfs_pkg::get_size (const char * filename_in) const
{
	//ZZ_LOG("vfs_pkg: get_size(%s):\n", filename);
	uint32 read_size;
	zz_slash_converter filename(filename_in);

	assert(pkg_system_);
	if (!pkg_system_) {
		ZZ_LOG("vfs_pkg: get_size(%s) failed. invalid pkg_system_.\n", filename);
		return 0;
	}

	VHANDLE fsystem = pkg_system_->get_filesystem();
	
	read_size = VGetFileLength(fsystem, filename);
	
	assert(read_size < MAX_FILESIZE);
	if (read_size >= MAX_FILESIZE) {
		ZZ_LOG("vfs_pkg: get_size(%s) failed. read_size = %d.\n",
			filename, read_size);
		read_size = 0;
	}

	//ZZ_LOG("vfs_pkg: get_size() lock_count_(%d)\n", lock_count_);

	return read_size;
}
Пример #2
0
bool zz_vfs_pkg_system::open_filesystem (const char * filesystem_name_in)
{
	assert(filesystem_name_in);

	if (filesystem_name_in[0] == '\0') {
		ZZ_LOG("vfs_pkg_system: open_filesystem(%s) failed. not a valid name.\n", filesystem_name_in);
		return false;
	}

	assert(!fsystem_);
	if (fsystem_) {
		ZZ_LOG("vfs_pkg_system: open_filesystem(%s) failed. already opened\n", filesystem_name_in);
		close_filesystem();
	}
	//ZZ_LOG("vfs_pkg: open_filesystem(%s)\n", filesystem_name);

	zz_slash_converter filesystem_name(filesystem_name_in);

	fsystem_ = OpenVFS(filesystem_name, "mr"); // memory-mapped io read

	assert(fsystem_);

	if (!fsystem_) {
		ZZ_LOG("vfs_pkg_system: open_filesystem(%s) failed. cannot open.\n", filesystem_name);
		return false;
	}
	return true;
}
Пример #3
0
// create managed objects
bool zz_font_d3d::init_device_objects ()
{
	if (!znzin) return true;
	if (!znzin->renderer) return true;
	if (!znzin->renderer->is_a(ZZ_RUNTIME_TYPE(zz_renderer_d3d))) return false;

	_d3d_device = ((zz_renderer_d3d*)(znzin->renderer))->get_device();
	if (!_d3d_device) return true;

	D3DXFONT_DESC fontDesc;

	ZeroMemory( &fontDesc, sizeof( D3DXFONT_DESC ) );

    HDC hDC = GetDC( NULL );
    _logical_pixels_y = GetDeviceCaps( hDC, LOGPIXELSY );
    ReleaseDC( NULL, hDC );
	font_height = (unsigned int)MulDiv( font_size, _logical_pixels_y, 72 ); // why minus in other documents? -MulDiv(?)

	fontDesc.Height					= font_height;
	fontDesc.Width					= 0;
	fontDesc.Weight					= this->get_bold() ? FW_BOLD : FW_THIN; 
	fontDesc.MipLevels				= 1;
	fontDesc.Italic						= this->get_italic();
	fontDesc.CharSet					= this->font_charset;
	fontDesc.OutputPrecision		= OUT_DEFAULT_PRECIS;	
	fontDesc.Quality					= PROOF_QUALITY;
	fontDesc.PitchAndFamily		= FIXED_PITCH | FF_MODERN;
	strcpy( fontDesc.FaceName, font_name.get() );

	HRESULT hr;

	try {
		if (FAILED(hr = D3DXCreateFontIndirect( _d3d_device, &fontDesc, &_d3d_font))) {
			ZZ_LOG("zz_font_d3d: init_device_objects(%s, %d, %d) failed. [%s]\n",
				font_name.get(), font_height, font_charset,
				zz_renderer_d3d::get_hresult_string(hr) );
			zz_msgbox(zz_error::get_text(zz_error::MSG_ERROR), zz_error::get_text(zz_error::CREATE_FONT_FAIL));
			
			strcat(znzin->sysinfo.video_string," <Font failed>");

			zz_msgboxf(zz_error::get_text(zz_error::MSG_ERROR), zz_error::get_text(zz_error::MSG_EXIT_D3DERROR), znzin->sysinfo.video_string);
			exit(EXIT_FAILURE);
			return false;
		}
	}
	catch (...) {
		ZZ_LOG("font_d3d: createfont failed. [%x, %d, %s, %x, %x]\n",
			this, fontDesc.Height, fontDesc.FaceName, _d3d_device, &_d3d_font);
		throw;
	}

	if (_num_font_textures > 0) {
		_d3d_font_texture.init_device_objects();
		_d3d_font_texture.create(*this); // zhotest
	}

	return true;
}
Пример #4
0
void * zz_mem::malloc (size_t size) 
{ 
	if (!_started) {
		void * p = ::malloc(size);
		ZZ_LOG("mem: mem not started. malloc(%x:%d) done.\n", p, size);
		return p;
	}

#ifdef ZZ_MEM_USE_MULTITHREAD
	zz_autolock<zz_critical_section> locker(_cs);
#endif // ZZ_MEM_USE_MULTITHREAD

	void * p;

	if (_used + size > _total) {
		ZZ_LOG("mem: cannot allocate memory(size:%d bytes out of total %d bytes)!\n", size, _total);
		assert(!"out of memory");
		return NULL;
	}

	_used += size;

	//_max = (_used > _max) ? _used : _max;
	if (_used > _max) {
		_max = _used;
		//ZZ_LOG("mem::malloc() _max = %d\n", _max);
	}
	
#ifdef ZZ_MEM_NEWDELETE_ON
	p = new char[size];
#else // ZZ_MEM_NEWDELETE_ON

	p = ::malloc(size);
#endif
	
	//ZZ_LOG("mem: allocated %d bytes (0x%x)\n", size, p);
	//status();

	// CAUTION: break on here to catch memory leak by index ( _count == XXX )
	_mem_info info;
	info.index = _count++;
	info.size = size;

	if (_mem_map.insert(p, info) == _mem_map.end()) {
		assert(!"mem:malloc() failed.");
		ZZ_LOG("mem:malloc() failed.\n");
		status();
		return NULL;
	}
	//_mem_map.insert(zz_mem_map::value_type(p, size));
	return p;
}
Пример #5
0
uint32 zz_vfs_pkg::read_ (char * buf, const uint32 size)
{
	assert(size < MAX_FILESIZE);
	uint32 read_size = 0;
	if (fp_) {
		#define KEYSIZE 0x1000
		long Mpointer = vftell(fp_) % KEYSIZE;
		read_size = vfread(buf, 1, size, fp_);
		if(fp_->btEncrypted==0x90)
		{
			size_t spt;
			spt = fp_->sFileName.find_last_of("/\\");
			std::string hashstring1 = fp_->sFileName.substr(spt+1, (fp_->sFileName.length()-spt));
			unsigned long key = StrToHashKey(hashstring1.c_str());
			char crypttable[KEYSIZE];
			DWORD *EAX=reinterpret_cast<DWORD*>(crypttable);
			DWORD EDI=0;
			DWORD ECX = key;
			DWORD EDX = key+1;
			ECX = ECX*4+1;
			for(int i = 0; i < 0x400; i++)
			{
				EDI=ECX*EDX;
				*((DWORD*)EAX) = EDI;
				EAX++;
				ECX+=4;
				EDX++;
			}

			for(size_t k=0;k<read_size;k++)
			{
				*((char*)buf+k)^= crypttable[Mpointer];
				Mpointer++; Mpointer %= KEYSIZE;
			}
		}
	}
	else {
		ZZ_LOG("vfs_pkg: read_() failed. invalid fp_.\n");
		return 0;
	}

	assert(read_size < MAX_FILESIZE);
	if (read_size >= MAX_FILESIZE) {
		ZZ_LOG("vfs_pkg: read_(%s) failed. read_size = %d.\n",
			filename_.get(), read_size);
		read_size = 0;
	}
	return read_size;
}
Пример #6
0
// @return 0 for stop application, 1 for ignoring assert
int _zz_assert ( const char * msg, const char * filename, int linenum )
{
	static char buffer[1024];

	static std::map< std::string, std::vector<int> > name_num;


	zz_string onlyname;
	zz_path::extract_name_ext(zz_string(filename), onlyname);

	// search history, and if found, skip this assert
	if (name_num.find(std::string(onlyname.get())) != name_num.end()) { // found
		std::vector<int>& numlist = name_num[onlyname.get()];
		if (std::find(numlist.begin(), numlist.end(), linenum) != numlist.end()) { // found
			return 1; // ignore this assert as this is already in history.
		}
	}

	sprintf(buffer, "%s\r\n\r\n[%s:#%d]\r\nver. %s", msg, onlyname.get(), linenum, ZZ_VERSION_STRING );
	ZZ_LOG("assert: failed. %s\n", buffer);
	zz_log::flush();

	// popup message and get response from user
	if (zz_popup_message( buffer )) { // user selected "ignore" button, log into history
		// insert into history
		name_num[std::string(onlyname.get())].push_back( linenum );
		return 1; // ignore this assert
	}
	return 0; // stop application!
}
Пример #7
0
void zz_font_d3d::draw_text_prim_offset (const zz_font_text& text_item, float offsetx, float offsety)
{
	zz_assert(!text_item.to_texture);
	zz_assert(text_item.msg.get());
	zz_assert(text_item.msg.size());
	zz_assert(_d3d_font);
	
	if (!_d3d_font)
		return;

	zz_renderer_d3d * r = (zz_renderer_d3d *)(znzin->renderer);

	assert(r->is_a(ZZ_RUNTIME_TYPE(zz_renderer_d3d)));

	LPD3DXSPRITE sprite = r->get_sprite();
	zz_assert(sprite);
	HRESULT hr;

	D3DXMATRIX saved_tm;
	D3DXMATRIX new_tm;

	zz_assert(r->sprite_began());

	r->flush_sprite();
	r->get_sprite_transform((float*)&saved_tm); // save tm

	// adjust offset
	new_tm = saved_tm;

	// assert not-zero-scale
	assert(saved_tm._11 != 0);
	assert(saved_tm._22 != 0);
	assert(saved_tm._33 != 0);

	// we does not support rotation
	assert(saved_tm._12 == 0);
	assert(saved_tm._13 == 0);
	assert(saved_tm._21 == 0);
	assert(saved_tm._23 == 0);
	assert(saved_tm._31 == 0);
	assert(saved_tm._32 == 0);
	new_tm._41 += offsetx * saved_tm._11;
	new_tm._42 += offsety * saved_tm._22;

	r->set_sprite_transform((float*)&new_tm);

	RECT rect = text_item.rect;
	if (FAILED(hr = _draw_text(
		sprite,
		text_item.msg.get(), -1,
		&rect, 
		text_item.format,
		text_item.color )))
	{
		ZZ_LOG("font_d3d: DrawText() failed\n", zz_renderer_d3d::get_hresult_string(hr));
	}

	sprite->SetTransform(&saved_tm); // restore tm
}
void zz_font_texture_d3d::clear_text_texture (const zz_font_text& text)
{
	const RECT& rect = text.tex_rect;

	D3DCOLOR clearcolor = text.color & 0x00FFFFFF;

	FONT_TEXT_VERTEX_DIFFUSE vertices[4] =
    {
		D3DXVECTOR4((float)rect.left - .5f,		(float)rect.bottom - .5f,	1.0f, 1.0f), clearcolor, 
		D3DXVECTOR4((float)rect.right - .5f,	(float)rect.bottom - .5f,	1.0f, 1.0f), clearcolor,
		D3DXVECTOR4((float)rect.right - .5f,	(float)rect.top - .5f,			1.0f, 1.0f), clearcolor,
		D3DXVECTOR4((float)rect.left - .5f,		(float)rect.top - .5f,			1.0f, 1.0f), clearcolor,
    };

	zz_renderer * r = znzin->renderer;
	{
		r->enable_alpha_blend(false, ZZ_BT_NORMAL);
		r->enable_alpha_test(false);

		r->set_cullmode(zz_render_state::ZZ_CULLMODE_CW);

		r->enable_zbuffer(false);
		r->enable_zwrite(false);

		r->set_texture_stage_state( 0, ZZ_TSS_COLOROP, ZZ_TOP_SELECTARG1 );
		r->set_texture_stage_state( 0, ZZ_TSS_COLORARG1, ZZ_TA_DIFFUSE );

		r->set_texture_stage_state( 1, ZZ_TSS_COLOROP, ZZ_TOP_DISABLE );
		r->set_texture_stage_state( 0, ZZ_TSS_ALPHAOP, ZZ_TOP_DISABLE );
	}

	// set transform
  	_device->SetFVF( FONT_TEXT_VERTEX_DIFFUSE::FVF );
	try {
		_device->DrawPrimitiveUP( D3DPT_TRIANGLEFAN, 2, vertices, sizeof(FONT_TEXT_VERTEX_DIFFUSE) );
	}
	catch (...) {
		// do nothing. maybe device lost state
		ZZ_LOG("font_texture_d3d: clear_text_texture(). dp exception\n");
	}

	// restore
	{
		r->enable_zbuffer(true);
		r->enable_zwrite(true);
		r->enable_alpha_blend(true, ZZ_BT_NORMAL);
		r->enable_alpha_test(true, 0, ZZ_CMP_GREATER);
		r->set_cullmode(zz_render_state::ZZ_CULLMODE_NONE);
		
		// wrap0 0
		r->set_texture_stage_state(0, ZZ_TSS_COLOROP, ZZ_TOP_MODULATE );
		r->set_texture_stage_state( 0, ZZ_TSS_COLORARG1, ZZ_TA_TEXTURE );
		r->set_texture_stage_state( 0, ZZ_TSS_COLORARG2, ZZ_TA_DIFFUSE );

		r->set_texture_stage_state( 0, ZZ_TSS_ALPHAOP, ZZ_TOP_MODULATE);
		r->set_texture_stage_state( 0, ZZ_TSS_ALPHAARG1, ZZ_TA_TEXTURE );
		r->set_texture_stage_state( 0, ZZ_TSS_ALPHAARG2, ZZ_TA_DIFFUSE );
	}
}
Пример #9
0
void zz_mem::status() 
{
	ZZ_LOG("mem: status(): total(%dM:%d) = used(%dM:%d) + free(%dM:%d). max(%dM:%d)\n", 
		_total/1000000, _total,
		_used/1000000, _used,
		(_total - _used)/1000000, _total - _used,
		_max/1000000, _max);
}
// create rendertarget texture and surface
bool zz_font_texture_d3d::restore_device_objects ()
{
	if (tex_height <= 0) return true;
	if (tex_width <= 0) return true;


	if (!znzin) return true;
	if (!znzin->renderer) return true;

	zz_renderer_d3d * r = static_cast<zz_renderer_d3d*>(znzin->renderer);
	if (!r->is_a(ZZ_RUNTIME_TYPE(zz_renderer_d3d))) return false;

	_device = r->get_device();
	if (!_device) return true;

	HRESULT hr;

	// create rendertarget texture
	if (FAILED(hr = _device->CreateTexture(
		tex_width, tex_height, 1, // level
		D3DUSAGE_RENDERTARGET,
		D3DFMT_A8R8G8B8,
		D3DPOOL_DEFAULT, // rendertarget must set this to D3DPOOL_DEFAULT
		&_texture, NULL)))
	{
		zz_render_state * rs = znzin->get_rs();
		if (rs) {
			ZZ_LOG("font_texture_d3d: createtexture(%dx%d)-(%dx%dx%d) failed(%s)\n",
				tex_width, tex_height,
				rs->buffer_width, rs->buffer_height, rs->buffer_depth,
				zz_renderer_d3d::get_hresult_string(hr));
		}
		else {
			ZZ_LOG("font_texture_d3d: createtexture() failed(%s). no rs\n", zz_renderer_d3d::get_hresult_string(hr));
		}
		return false;
	}

	// get texture surface
	if (FAILED(hr = _texture->GetSurfaceLevel(0, &_surface))) {
		zz_assert(0);
		return false;
	}

	return true;
}
Пример #11
0
void zz_mem::confirm ()
{
#ifdef ZZ_WIN32_CRTDBG
	if (_CrtDumpMemoryLeaks() == TRUE) {
		ZZ_LOG("mem: memory leaked!!!\n");
	}
#endif // ZZ_WIN32_CRTDBG

	if (_used != 0) {
		ZZ_LOG("mem: end failed. memory leak\n");
		for (zz_mem_map::iterator it = _mem_map.begin(); it != _mem_map.end(); it++) {
			ZZ_LOG("%d ", it.value()->index);
		}
		ZZ_LOG(" not freed.\n");
	}
	else {
		ZZ_LOG("mem: end.\n");
	}
}
Пример #12
0
//--------------------------------------------------------------------------------
// detach target
//--------------------------------------------------------------------------------
bool zz_camera_follow::detach_target (void)
{
	if (!target_) {
		ZZ_LOG("camera_follow: detach_target() failed. no target\n");
		return false;
	}
	target_ = NULL;
	is_dirty_ = true;
	return true;
}
Пример #13
0
bool zz_skeleton::set_path (const char * path_in)
{
	assert(!path_.get());
	assert(path_in);
	if (path_.get()) {
		ZZ_LOG("skeleton: [%s:%s]->set_path(%s) failed. already have a path(%s).\n", get_name(), path_in, path_.get());
		return false;
	}
	path_.set(path_in);
	return true;
}
Пример #14
0
bool zz_view_d3d::attach_window ()
{
	znzin->renderer->set_view(znzin->view);

	try {
		if (!znzin->renderer->initialize()) {
			return false;
		}
	}
	catch (const char * log) {
		ZZ_LOG(log);
		ZZ_LOG("view_d3d: attach_window() failed. iNiTfAiL\n");
		strcat(znzin->sysinfo.video_string," <Window Create failed>");
		zz_msgboxf(zz_error::get_text(zz_error::MSG_ERROR), zz_error::get_text(zz_error::MSG_EXIT_D3DERROR), znzin->sysinfo.video_string);
		exit(EXIT_FAILURE);
	}
	
	znzin->timer_start();
	return true;
}
Пример #15
0
void zz_mem::free (void * p) 
{ 
	if (!_started) {
		ZZ_LOG("mem: mem not started. free(%x) done.\n", p);
		return ::free(p);
	}

#ifdef ZZ_MEM_USE_MULTITHREAD
	zz_autolock<zz_critical_section> locker(_cs);
#endif // ZZ_MEM_USE_MULTITHREAD

	int size;
	zz_mem_map::iterator the_iterator;

    the_iterator = _mem_map.find(p);
    if (the_iterator == _mem_map.end()) {
		assert(!"mem:free() failed.");
		ZZ_LOG("mem:free() failed.\n");
        return;
    }
    
#ifdef ZZ_MEM_NEWDELETE_ON
	delete [] p;
#else
	::free(p);
#endif // ZZ_MEM_NEWDELETE_ON
	
	p = NULL;

	size = int(the_iterator.value()->size);
	//size = (*the_iterator).second;

	//ZZ_LOG("mem: freed %d bytes\n", size);
	//ZZ_LOG("mem: freed %d[index = %d] bytes\n", size, the_iterator.value()->index);
	_used -= size;

	_mem_map.erase(the_iterator);
	
	//status();
}
Пример #16
0
uint32 zz_vfs_pkg::get_size () const
{
	//ZZ_LOG("vfs_pkg: get_size:\n");
	uint32 read_size = 0;

	if (!fp_) {
		ZZ_LOG("vfs_pkg: get_size(%s) failed. invalid fp_.\n", filename_.get());
		return 0;
	}

	assert(fp_);
	read_size = vfgetsize(fp_);
	
	assert(read_size < MAX_FILESIZE);
	if (read_size >= MAX_FILESIZE) {
		ZZ_LOG("vfs_pkg: get_size(%s) failed. read_size = %d.\n",
			filename_.get(), read_size);
		read_size = 0;
	}

	return uint32(read_size);
}
// render texture for text into screen for debugging purpose
void zz_font_texture_d3d::render_text_texture (void)
{
	float eps_width = 0; //.5f/float(tex_width);
	float eps_height = 0; // .5f/float(tex_height);

    FONT_TEXT_VERTEX4_TEXTURE vertices[4] =
    {
		D3DXVECTOR4(-.5f,								200.f - 0.5f,									.5f,		1.0f), 0xFF0000FF, eps_width,		eps_height,
		D3DXVECTOR4(float(tex_width) - .5f,	200.f - 0.5f,									.5f,		1.0f), 0xFF0000FF, 1.0f + eps_width,	eps_height,
		D3DXVECTOR4(float(tex_width) - .5f,	200.f + float(tex_height) - .5f,		.5f,		1.0f), 0xFF0000FF, 1.0f + eps_width,	1.0f + eps_height,
		D3DXVECTOR4(-.5f,								200.f + float(tex_height) - .5f,		.5f,		1.0f), 0xFF0000FF, eps_width,	1.0f + eps_height,
    };

	assert(_device);

	{
		zz_renderer_d3d * r = static_cast<zz_renderer_d3d*>(znzin->renderer);
		assert(r);

		r->init_sprite_state();

		r->enable_alpha_blend(true, ZZ_BT_NORMAL);
		r->enable_alpha_test(false);

		r->set_vertex_shader(ZZ_HANDLE_NULL);
		r->set_pixel_shader(ZZ_HANDLE_NULL);

		r->enable_zbuffer(false);
		r->enable_zwrite(false);

		r->set_texture_stage_state(0, ZZ_TSS_COLOROP, ZZ_TOP_SELECTARG1 );
		r->set_texture_stage_state( 0, ZZ_TSS_COLORARG1, ZZ_TA_TEXTURE);

		r->set_texture_stage_state( 1, ZZ_TSS_COLOROP, ZZ_TOP_DISABLE );
		r->set_texture_stage_state( 0, ZZ_TSS_ALPHAOP, ZZ_TOP_DISABLE );

		r->invalidate_texture( 0 );
	}

	// set transform
  	_device->SetFVF( FONT_TEXT_VERTEX4_TEXTURE::FVF );
	_device->SetTexture( 0, _texture );  

	try {
		_device->DrawPrimitiveUP( D3DPT_TRIANGLEFAN, 2, vertices, sizeof(FONT_TEXT_VERTEX4_TEXTURE) );
	}
	catch (...) {
		ZZ_LOG("font_texture_d3d: render_text_texture(). dp exception\n");
		// do nothing. maybe device lost state
	}
}
Пример #18
0
// CAUTION: if the same texture exists, return true.
bool zz_texture::load_real (zz_texture * tex)
{
	assert(!ZZ_HANDLE_IS_VALID(tex->handle));

	tex->handle = znzin->renderer->create_texture(tex);

#ifdef LOG_TEXTURE
	ZZ_LOG("texture: create_texture(%s-%dx%d, %d)\n",
		tex->get_path(), tex->get_width(), tex->get_width(), tex->handle);
#endif		

	assert(ZZ_HANDLE_IS_VALID(tex->handle));

	return true;
}
Пример #19
0
bool zz_vfs_pkg_system::set_filesystem (VHANDLE fsystem_in)
{
	assert(!fsystem_in);

	if (fsystem_) {
		close_filesystem();
	}

	fsystem_ = fsystem_in;

	if (!fsystem_) {
		ZZ_LOG("vfs_pkg_system: set_filesystem() failed. invalid fsystem_.\n");
		return false;
	}
	return true;
}
Пример #20
0
bool zz_vfs_pkg::exist (const char * filename_in) const
{
	//ZZ_LOG("vfs_pkg: exist:\n");
	bool ret = false;

	zz_slash_converter filename(filename_in);
	if (!pkg_system_) {
		ZZ_LOG("vfs_pkg: exist(%s) failed. invalid pkg_system_.\n", filename);
		ret = false;
	}

	VHANDLE fsystem = pkg_system_->get_filesystem();
	assert(fsystem);
	
	ret = VFileExists(fsystem, filename);
	
	return ret;
}
Пример #21
0
//--------------------------------------------------------------------------------
// attach target
//--------------------------------------------------------------------------------
bool zz_camera_follow::attach_target (zz_model * target_vis)
{
	if (!target_vis) {
		ZZ_LOG("camera_follow: attach_target() failed. target not found\n");
		return false;
	}

	if (target_ == target_vis) return true;

	target_ = target_vis;
	
	get_target_pos(final_.target_pos);

	look_at(final_.target_pos + INITIAL_CAMERA_POS_AT_ATTACH, final_.target_pos, vec3(0, 0, 1));
	newly_attached_ = true;
	final_.camera_pos = get_eye();
	last_.camera_pos = final_.camera_pos;
	last_.target_pos = final_.target_pos;
	is_dirty_ = true;
	return true;
}
Пример #22
0
void zz_mem::begin ()
{
	if (_started) return;

#ifdef ZZ_MEM_USE_MULTITHREAD
	_cs = new zz_critical_section;
#endif // ZZ_MEM_USE_MULTITHREAD

	_started = true;

	ZZ_LOG("mem: begin. total %d byte available.\n", _total);

#ifdef ZZ_WIN32_CRTDBG
	//// crt debug flag setting
	//_CrtSetDbgFlag(
	//	_CRTDBG_ALLOC_MEM_DF
	//	| _CRTDBG_LEAK_CHECK_DF
	//	// | _CRTDBG_CHECK_ALWAYS_DF
	//	// | _CRTDBG_CHECK_EVERY_16_DF
	//	);
#endif // ZZ_WIN32_CRTDBG
}
Пример #23
0
// destroy managed/systemmem/scratch pool objects
bool zz_texture::delete_device_objects ()
{
	if (!res.is_delete_device_objects()) { // skip default
		return true;
	}

	if (!res.get_created()) {
		zz_assert(handle == ZZ_HANDLE_NULL);
		return true;
	}

#ifdef LOG_TEXTURE
	ZZ_LOG("texture: destroy_texture1(%s-%dx%d, %d)\n",
		get_path(), get_width(), get_width(), handle);
#endif

	znzin->renderer->destroy_texture(this);

	res.make_uncreated();
	handle = ZZ_HANDLE_NULL;
	
	return true;
}
Пример #24
0
LPDIRECTSOUND3DBUFFER zz_sound::get_free_buffer ()
{
	LPDIRECTSOUND3DBUFFER pDS3DB;
	LPDIRECTSOUNDBUFFER pDSB;
	DWORD dwStatus = 0;

	for( DWORD i=0; i< this->num_buffers; i++ )
    {
		pDSB = pSound->GetBuffer(i);
        if( pDSB )
        {  
            dwStatus = 0;
            pDSB->GetStatus( &dwStatus );
			if ( ( dwStatus & DSBSTATUS_PLAYING ) == 0 ) {
				if (FAILED(pSound->Get3DBufferInterface( i, &pDS3DB ))) {
					ZZ_LOG("sound: get_free_buffer() failed. Get3DBufferInterface() failed.\n");
					return NULL;
				}
				return pDS3DB;
			}  
        }
    }
	return NULL;
}
Пример #25
0
INT zz_font_d3d::_draw_text ( LPD3DXSPRITE pSprite, const char * pString, INT Count, LPRECT pRect, DWORD Format, D3DCOLOR Color )
{
	assert(_d3d_font);
	INT result;
	
	try {
		result = _d3d_font->DrawText( pSprite, pString, Count, pRect, Format, Color );
	}
	catch (...) {
		result = -1; // error
		ZZ_LOG("font_d3d: exception occured in _draw_text(%x, %s, %d)", pSprite, pString, Count);
		// reset sprite and font
		zz_renderer_d3d * r = static_cast<zz_renderer_d3d *>(znzin->renderer);
		r->recreate_default_sprite();

		// we dont't know that we should recreate font itself when the exception was occured rendering sprite
		// so, we keep font-recreating in comments until we find that the exception occures in font, too.
#if (0) // uncomment this if exception is still occured here.
		unload();
		load();
#endif
	}
	return result;
}
Пример #26
0
// If time_to_update is zero, all accumulated time info is ignored. it means *new start*!!.
// When last frame was so heavy, we should refresh it.
// If not, we will get slow frames in a while.
void zz_manager::update (zz_time time_to_update)
{
	if ((exit_line.size() == 0) && (entrance_line.size() == 0)) return;
	
	sort_waitings(); // sort lines

	if (!znzin->get_rs()->use_delayed_loading) {
		exit_line.flush_n_pop((int)exit_line.size());
		entrance_line.flush_n_pop((int)entrance_line.size());
		entrance_time_accumulated = 0;
		exit_time_accumulated = 0;
		return;
	}
	
	if (time_to_update == 0) { // initialize acculumated
		entrance_time_accumulated = 0;
		exit_time_accumulated = 0;
	}
	else {
		// distribute time
		entrance_time_accumulated += 1 + time_to_update/10;
		exit_time_accumulated += 1 + time_to_update/10;
	}
	zz_node * node;
	zz_time t;
	zz_time time_weight;

	//--------------------------------------------------------------------------------
	// for exit
	node = exit_line.back();	
	t = ZZ_TIME_TO_MSEC(exit_time_accumulated);
	time_weight = (!node) ? t : static_cast<zz_time>(node->get_load_weight());

	// not to unload reusing nodes, bound to max_flush
	int max_flush = (exit_line.size() > num_reuse) ? (exit_line.size() - num_reuse) : 0;

	try {
		while ((max_flush-- > 0) && node && (t > time_weight)) {
			//ZZ_LOG("manager: [%s]->update() exit->flush(%s)\n", get_name(), node ? node->get_name() : "(null)");
			exit_line.flush_n_pop(1);
			
			node = exit_line.back();

			if (!node) continue; // skip if no node

			exit_time_accumulated -= ZZ_MSEC_TO_TIME(t);
			t = ZZ_TIME_TO_MSEC(exit_time_accumulated);

			time_weight = static_cast<zz_time>(node->get_load_weight());
		}
	}
	catch (...) {
		if (node) {
			ZZ_LOG("manager: [%s]->update() exit->flush(%s) failed.\n", get_name(), node->get_name());
		}
		else {
			ZZ_LOG("manager: [%s]->update() exit->flush() failed.\n", get_name());
		}
		throw;
	}
	//--------------------------------------------------------------------------------

	//--------------------------------------------------------------------------------
	// for entrance
	node = entrance_line.back();
	t = ZZ_TIME_TO_MSEC(entrance_time_accumulated);
	time_weight = (!node) ? t : static_cast<zz_time>(node->get_load_weight());

	try {
		while (node && (t > time_weight)) {
			//ZZ_LOG("manager: [%s]->update() entrance->flush(%s)\n", get_name(), node ? node->get_name() : "(null)");
			if (entrance_line.flush_node(node)) {
				entrance_time_accumulated -= ZZ_MSEC_TO_TIME(t);
				entrance_line.pop();
			}
			else { // not loaded, so reinsert to front
				entrance_line.pop();
				entrance_line.push(node); // re-insert
			}

			node = entrance_line.back();

			if (!node) continue; // skip if no node

			t = ZZ_TIME_TO_MSEC(entrance_time_accumulated);

			time_weight = static_cast<zz_time>(node->get_load_weight());
		}
	}
	catch (...) {
		if (node) {
			ZZ_LOG("manager: [%s]->update() entrance->flush(%s) failed.\n", get_name(), node->get_name());
		}
		else {
			ZZ_LOG("manager: [%s]->update() entrance->flush() failed.\n", get_name());
		}
		 throw;
	}
	//--------------------------------------------------------------------------------
}
Пример #27
0
bool zz_vfs_pkg::open (const char * filename_in, const zz_vfs_mode mode)
{
	if(mode==ZZ_VFS_WRITE) return false;
	//ZZ_LOG("vfs_pkg:open(%s)\n", filename);
	//ZZ_PROFILER_INSTALL(vfs_pkg_open);
	zz_assert(filename_in);
	zz_assert(filename_in[0]);

	zz_slash_converter filename(filename_in);

	if (fp_) {
		close();
	}

	assert(!fp_);
	if (!pkg_system_) {
		ZZ_LOG("vfs_pkg: open(%s) failed. invalid pkg_system_.\n", filename.get());
		return false;
	}

	//ZZ_LOG("vfs_pkg: open(%s)\n", filename);
	VHANDLE fsystem = pkg_system_->get_filesystem();

//	switch (mode) {
//		case zz_vfs::ZZ_VFS_READ:
			fp_ = VOpenFile(filename, fsystem);

			zz_assertf( fp_, "vfs_pkg: open(%s) failed.", filename.get() );

			filename_.set(filename);
			//check if it is encrypted
			fp_->btEncrypted=0;
			//if(fp_->btFileType==0){
			size_t spt;
			spt = fp_->sFileName.find_last_of("/\\");
			std::string hashstring1 = fp_->sFileName.substr(spt+1, (fp_->sFileName.length()-spt));
			//OutputDebugString(hashstring1.c_str());
			unsigned long key = StrToHashKey(hashstring1.c_str());
			char crypttable[16];
			DWORD *EAX=reinterpret_cast<DWORD*>(crypttable);
			DWORD EDI=0;
			DWORD ECX = key;
			DWORD EDX = key+1;
			ECX = ECX*4+1;
			for(int i = 0; i < 4; i++)
			{
				EDI=ECX*EDX;
				*((DWORD*)EAX) = EDI;
				EAX++;
				ECX+=4;
				EDX++;
			}
			vfseek(fp_, 0, VFSEEK_END);
			long off_set = vftell(fp_);
			if(off_set>16)
			{
				off_set-=16;
				vfseek(fp_,off_set, VFSEEK_SET);
				char buffer[16];
				vfread(&buffer,1,16,fp_);
				if(buffer[0]==crypttable[0]){
					if(buffer[1]==crypttable[1]){
						if(buffer[2]==crypttable[2]){
							if(buffer[3]==crypttable[3]){
								if(buffer[4]==crypttable[4]){
									if(buffer[5]==crypttable[5]){
										if(buffer[6]==crypttable[6]){
											if(buffer[7]==crypttable[7]){
												if(buffer[8]==crypttable[8]){
													if(buffer[9]==crypttable[9]){
														if(buffer[10]==crypttable[10]){
															if(buffer[11]==crypttable[11]){
																if(buffer[12]==crypttable[12]){
																	if(buffer[13]==crypttable[13]){
																		if(buffer[14]==crypttable[14]){
																			if(buffer[15]==crypttable[15]){
																				fp_->btEncrypted=0x90;
																				fp_->lEndOff-=16;
																				//MessageBox(0,fp_->sFileName.c_str()," is encrypted",0);
																			}
																		}
																	}
																}
															}
														}
													}
												}
											}
										}
									}
								}
							}
						}
					}
				}
			}
			vfseek(fp_,0, VFSEEK_SET);
//			break;
//		case zz_vfs::ZZ_VFS_WRITE:
			// not implemented yet!!!
//			break;
//	}
	
	if (!fp_) {
		return false;
	}
	return true;
}
Пример #28
0
void zz_material_terrain::set_alpha_stage (int pass, bool use_lightmap, bool use_shadowmap)
{
	bool use_alpha_fog = znzin->get_rs()->use_alpha_fog;

	// check alpha fog
	if (use_lightmap) {
		if (use_shadowmap) {
			if (use_alpha_fog) {
				if (alpha_state == MS_ALPHA_LIGHT_SHADOW_FOG) return;
				alpha_state = MS_ALPHA_LIGHT_SHADOW_FOG;
			}
			else {
				if (alpha_state == MS_ALPHA_LIGHT_SHADOW) return;
				alpha_state = MS_ALPHA_LIGHT_SHADOW;
			}
		}
		else {
			if (use_alpha_fog) {
				if (alpha_state == MS_ALPHA_LIGHT_FOG) return;
				alpha_state = MS_ALPHA_LIGHT_FOG;
			}
			else {
				if (alpha_state == MS_ALPHA_LIGHT) return;
				alpha_state = MS_ALPHA_LIGHT;
			}
		}
	}
	else {
		if (use_shadowmap) {
			if (use_alpha_fog) {
				if (alpha_state == MS_ALPHA_SHADOW_FOG) return;
				alpha_state = MS_ALPHA_SHADOW_FOG;
			}
			else {
				if (alpha_state == MS_ALPHA_SHADOW) return;
				alpha_state = MS_ALPHA_SHADOW;
			}
		}
		else {
			if (use_alpha_fog) {
				if (alpha_state == MS_ALPHA_FOG) return;
				alpha_state = MS_ALPHA_FOG;
			}
			else {
				if (alpha_state == MS_ALPHA) return;
				alpha_state = MS_ALPHA;
			}
		}
	}

	// set blend style
	if (!s_renderstate->use_multipass) { // if one pass
		if (use_alpha_fog) {
			s_renderer->enable_alpha_blend(true, ZZ_BT_CUSTOM);
			s_renderer->set_blend_type(ZZ_BLEND_SRCALPHA, ZZ_BLEND_INVSRCALPHA, ZZ_BLENDOP_ADD);
			s_renderer->enable_alpha_test(false);

			s_renderer->set_texture_stage_state(0, ZZ_TSS_ALPHAARG1, ZZ_TA_DIFFUSE);
			s_renderer->set_texture_stage_state(0, ZZ_TSS_ALPHAOP,   ZZ_TOP_SELECTARG1);
			s_renderer->set_texture_stage_state(1, ZZ_TSS_ALPHAOP,   ZZ_TOP_DISABLE); 
		}
		else {
			s_renderer->enable_alpha_blend(false, ZZ_BT_NORMAL);
			s_renderer->enable_alpha_test(false);
			s_renderer->set_texture_stage_state(0, ZZ_TSS_ALPHAOP,   ZZ_TOP_DISABLE);
		}
	}
	else { // multi pass
		if (pass == 0) {
			if (use_alpha_fog) {
				//s_renderer->enable_alpha_blend(true, ZZ_BT_CUSTOM);
				s_renderer->enable_alpha_blend(true, ZZ_BT_NORMAL); // SRCALPHA, INVSRCALPHA
				s_renderer->enable_alpha_test(false);

				// CAUTION: geforce4 mx. must be over 2-stage alpha operation.
				// why? i dont know.
				// if not using over 2-stage, then we cannot alpha blending by diffuse.
				s_renderer->set_texture_stage_state(0, ZZ_TSS_ALPHAARG1, ZZ_TA_DIFFUSE);
				s_renderer->set_texture_stage_state(0, ZZ_TSS_ALPHAOP,   ZZ_TOP_SELECTARG1);

				s_renderer->set_texture_stage_state(1, ZZ_TSS_ALPHAARG1, ZZ_TA_DIFFUSE);
				s_renderer->set_texture_stage_state(1, ZZ_TSS_ALPHAOP,   ZZ_TOP_SELECTARG1);

				s_renderer->set_texture_stage_state(2, ZZ_TSS_ALPHAOP,   ZZ_TOP_DISABLE); 
			}
			else {
				s_renderer->enable_alpha_blend(false, ZZ_BT_NORMAL);
				s_renderer->enable_alpha_test(false);

				s_renderer->set_texture_stage_state(0, ZZ_TSS_ALPHAOP,   ZZ_TOP_DISABLE);
			}
		}
		else { // if second pass
			s_renderer->enable_alpha_blend(true, ZZ_BT_NONE);
			// modulate
			// final = src*src_blend + dest*dest_blend
			//       = src*(dest_color) + dest*(zero)
			// modulate2x
			// final = src*(dest_color) + dest*(src_color)
			if (use_lightmap) {
				if (s_renderstate->lightmap_blend_style == ZZ_TOP_MODULATE) {
					s_renderer->set_blend_type(ZZ_BLEND_DESTCOLOR, ZZ_BLEND_ZERO, ZZ_BLENDOP_ADD); // modulate1x
				}
				else if (s_renderstate->lightmap_blend_style == ZZ_TOP_MODULATE2X) { // default MODULATE2X
					s_renderer->set_blend_type(ZZ_BLEND_DESTCOLOR, ZZ_BLEND_SRCCOLOR, ZZ_BLENDOP_ADD); // modulate2x
				}
				else {
					ZZ_LOG("material_terrain: invalid lightmap_blend_style");
					// set default
					s_renderer->set_blend_type(ZZ_BLEND_DESTCOLOR, ZZ_BLEND_SRCCOLOR, ZZ_BLENDOP_ADD); // modulate2x
				}
			}
			else { // only shadowmap
				assert(use_shadowmap);
				// shadowmap test
				s_renderer->enable_alpha_blend(true, ZZ_BT_NONE);
				if (s_renderstate->use_blackshadowmap) {
					s_renderer->set_blend_type(ZZ_BLEND_ONE, ZZ_BLEND_ONE, ZZ_BLENDOP_REVSUBTRACT); // = SUBTRACT
				}
				else {
					s_renderer->set_blend_type(ZZ_BLEND_ZERO, ZZ_BLEND_SRCCOLOR, ZZ_BLENDOP_ADD); // MODULATE
				}
			}

			// alpha texture stage setup
			s_renderer->set_texture_stage_state(0, ZZ_TSS_ALPHAOP,   ZZ_TOP_DISABLE);
		}
	}
}
Пример #29
0
// TGA image file load
// name : filename, pixels : data
// width : TGA width, height : TGA height
// format : pixel size ( 24 or 32 )
bool zz_targa_load (const char * name, byte **pixels, int * width, int * height, int * format)
{
    int columns, rows, numPixels;
    byte * pixbuf;
    int row, column;
    char buf_char;

	zz_vfs fin;

    byte * targa_rgba;

    zz_targa_header targa_header;

    if (!fin.open(name, zz_vfs::ZZ_VFS_READ))
        return false;

	targa_header.id_length = fin.read_char(buf_char);
    targa_header.colormap_type = fin.read_char(buf_char);
	targa_header.image_type = fin.read_char(buf_char);
	fin.read_uint16(targa_header.colormap_index);
    fin.read_uint16(targa_header.colormap_length);
    targa_header.colormap_size = fin.read_char(buf_char);
    fin.read_uint16(targa_header.x_origin);
    fin.read_uint16(targa_header.y_origin);
    fin.read_uint16(targa_header.width);
    fin.read_uint16(targa_header.height);
    targa_header.pixel_size = fin.read_char(buf_char);
    targa_header.attributes = fin.read_char(buf_char);

    if (targa_header.image_type!=2 && targa_header.image_type!=10)
        ZZ_LOG("LoadTGA: Only type 2 and 10 targa RGB images supported\n");

    if (targa_header.colormap_type !=0 || (targa_header.pixel_size!=32 && targa_header.pixel_size!=24))
        ZZ_LOG("Texture_LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n");

    *format = targa_header.pixel_size;

    columns = targa_header.width;
    rows = targa_header.height;
    numPixels = columns * rows;

    if (width)
        *width = columns;
    if (height)
        *height = rows;

    targa_rgba = zz_new byte[numPixels*4];
    //  targa_rgba = new unsigned char[numPixels*4];
    *pixels = targa_rgba;

    if (targa_header.id_length != 0)
		fin.seek(targa_header.id_length, zz_vfs::ZZ_VFS_SEEK_CUR); // skip TARGA image comment

    if (targa_header.image_type==2) {  // Uncompressed, RGB images
        for(row=rows-1; row>=0; row--) {
            pixbuf = targa_rgba + row*columns*4;
            for(column=0; column<columns; column++) {
                uchar red,green,blue,alphabyte;
                switch (targa_header.pixel_size) {
                    case 24:
                        fin.read_uchar(blue);
                        fin.read_uchar(green);
                        fin.read_uchar(red);
                        *pixbuf++ = red;
                        *pixbuf++ = green;
                        *pixbuf++ = blue;
                        *pixbuf++ = 255;
                        break;
                    case 32:
                        fin.read_uchar(blue);
                        fin.read_uchar(green);
                        fin.read_uchar(red);
                        fin.read_uchar(alphabyte);
                        *pixbuf++ = red;
                        *pixbuf++ = green;
                        *pixbuf++ = blue;
                        *pixbuf++ = alphabyte;
                        break;
                }
            }
        }
    }
    else if (targa_header.image_type==10) {   // Runlength encoded RGB images
        uchar red,green,blue,alphabyte,packetHeader,packetSize,j;
        for(row=rows-1; row>=0; row--) {
            pixbuf = targa_rgba + row*columns*4;
            for(column=0; column<columns; ) {
                fin.read_uchar(packetHeader);
                packetSize = 1 + (packetHeader & 0x7f);
                if (packetHeader & 0x80) {        // run-length packet
                    switch (targa_header.pixel_size) {
                        case 24:
							fin.read_uchar(blue);
							fin.read_uchar(green);
							fin.read_uchar(red);
                            alphabyte = 255;
                            break;
                        case 32:
                            fin.read_uchar(blue);
							fin.read_uchar(green);
							fin.read_uchar(red);
                            fin.read_uchar(alphabyte);
                            break;
                    }
                    for(j=0;j<packetSize;j++) {
                        *pixbuf++=red;
                        *pixbuf++=green;
                        *pixbuf++=blue;
                        *pixbuf++=alphabyte;
                        column++;
                        if (column==columns) { // run spans across rows
                            column=0;
                            if (row>0)
                                row--;
                            else
                                goto breakOut;
                            pixbuf = targa_rgba + row*columns*4;
                        }
                    }
                }
                else {                            // non run-length packet
                    for(j=0;j<packetSize;j++) {
                        switch (targa_header.pixel_size) {
                            case 24:                                                        
								fin.read_uchar(blue);
								fin.read_uchar(green);
								fin.read_uchar(red);
								*pixbuf++ = red;
                                *pixbuf++ = green;
                                *pixbuf++ = blue;
                                *pixbuf++ = 255;
                                break;
                            case 32:
								fin.read_char((char&)blue);
								fin.read_char((char&)green);
								fin.read_char((char&)red);
								fin.read_char((char&)alphabyte);
                                *pixbuf++ = red;
                                *pixbuf++ = green;
                                *pixbuf++ = blue;
                                *pixbuf++ = alphabyte;
                                break;
                        }
                        column++;
                        if (column==columns) { // pixel packet run spans across rows
                            column=0;
                            if (row>0)
                                row--;
                            else
                                goto breakOut;
                            pixbuf = targa_rgba + row*columns*4;
                        }                                               
                    }
                }
            }
breakOut:;
        }
    }
    fin.close();
    return true;
}
Пример #30
0
bool zz_skeleton::load_skeleton (const char * path_in)
{
	zz_vfs_pkg skel_file;
	char magic_number[8];
	uint32 parent_id = 0;
	
	if (skel_file.open(path_in) == false) {
		ZZ_LOG("skeleton: load_skeleton(%s) file open failed\n", path_in);
		return false;
	}
	
	// header section
	skel_file.read_string(magic_number, 7);
	int version = 3;
	if (strncmp(magic_number, ZZ_ZMD_VERSION2, 7) == 0) {
		version = 2;
	}
	else if (strncmp(magic_number, ZZ_ZMD_VERSION3, 7) == 0) {
		version = 3;
	}
	else {
		ZZ_LOG("skeleton: load_skeleton(%s) failed. [%s] version required\n",
			path_in, ZZ_ZMD_VERSION3);
		return false;
	}

	uint32 num_bones;
	char name[ZZ_MAX_STRING];
	uint32 i;

	skel_file.read_uint32(num_bones);
	vec3 translation;
	quat rotation;

	assert(num_bones < MAX_NUM_BONES);
	if (num_bones >= MAX_NUM_BONES) {
		ZZ_LOG("skeleton: load_skeleton(%s) failed. num_bones(%d)\n", path_in, num_bones);
		num_bones = 0;
	}

	nodes.reserve(num_bones);

	// read each bone
	for (i = 0; i < num_bones; i++) {
		// set name
		skel_file.read_uint32(parent_id);
		skel_file.read_string(name);

		// set translation
		skel_file.read_float3(translation.vec_array);
		translation.x *= ZZ_SCALE_IN;
		translation.y *= ZZ_SCALE_IN;
		translation.z *= ZZ_SCALE_IN;

		// set skeleton rotation
		skel_file.read_float(rotation.w);
		skel_file.read_float(rotation.x);
		skel_file.read_float(rotation.y);
		skel_file.read_float(rotation.z);

		// set nodes
		nodes.push_back(zz_skeleton_node());
		nodes[i].bone_name.set(name);
		nodes[i].translation = translation;
		nodes[i].rotation    = rotation;
		nodes[i].parent_id   = parent_id;

		if (parent_id == i) { // this is root bone
			root_bone_index_ = i;
		}
#ifdef LOG_SKELETON_INFO
		ZZ_LOG("skeleton: read_bone(%d, %s)\n", i, name);
#endif // LOG_SKELETON_INFO
	}
	if (root_bone_index_ < 0) {
		ZZ_LOG("skeleton: load_skeleton(%s) failed. cannot find root bone.\n", name);
		root_bone_index_ = 0;
	}

	// read dummy nodes
	uint32 num_dummies;
	zz_dummy_node dummy;

	skel_file.read_uint32(num_dummies);
	
	assert(num_dummies < MAX_NUM_DUMMIES);
	if (num_dummies >= MAX_NUM_DUMMIES) {
		ZZ_LOG("skeleton: load_skeleton(%s) failed. num_dummies(%d)\n", path_in, num_dummies);
		num_dummies = 0;
	}

	// prepare dummies
	dummies.reserve(num_dummies + 1); // + 1 means extra added dummy
	rotation = quat_id;
	for (i = 0; i < num_dummies; i++) {
		skel_file.read_string(name);
		skel_file.read_uint32(parent_id);
		skel_file.read_float3(translation.vec_array);
		if (version == 3) { // version3 includes dummy rotation
			skel_file.read_float(rotation.w);
			skel_file.read_float(rotation.x);
			skel_file.read_float(rotation.y);
			skel_file.read_float(rotation.z);
		}
		translation.x *= ZZ_SCALE_IN;
		translation.y *= ZZ_SCALE_IN;
		translation.z *= ZZ_SCALE_IN;

		dummies.push_back(zz_dummy_node());
		dummies[i].dummy_name.set(name);
		dummies[i].parent_id = static_cast<int>(parent_id);
		dummies[i].translation = translation;
		dummies[i].rotation = rotation;

		const char * parent_name = nodes[parent_id].bone_name.get();
#ifdef LOG_SKELETON_INFO
		ZZ_LOG("skeleton: read_dummy(%s:%d). parent=(%s:%d)\n",	name, i, parent_name, parent_id);
#endif
	}

	// add extra root bone dummy
	dummies.push_back(zz_dummy_node());
	dummies[num_dummies].dummy_name.set("_p1");
	dummies[num_dummies].parent_id = 0;
	dummies[num_dummies].translation = vec3_null;
	dummies[num_dummies].rotation = quat_id;

	set_path(path_in);

#ifdef LOG_SKELETON_INFO
	ZZ_LOG("skeleton: load_skeleton(%s). filename(%s), num_bones(%d), num_dummies(%d)\n",
		get_name(), path_in, num_bones, num_dummies);
#endif

	skel_file.close();

	return true;
}