⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gameswf_action.cpp

📁 一个开源的Flash 播放器,可以在Windows/Linux 上运行
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	{		if (fn.nargs < 1)		{			log_error("key_remove_listener needs one argument (the listener object)\n");			return;		}		as_object_interface*	listener = fn.arg(0).to_object();		if (listener == NULL)		{			log_error("key_remove_listener passed a NULL object; ignored\n");			return;		}		key_as_object*	ko = (key_as_object*) (as_object*) fn.this_ptr;		assert(ko);		ko->remove_listener(listener);	}	void key_init()	{		// Create built-in key object.		as_object*	key_obj = new key_as_object;		// constants#define KEY_CONST(k) key_obj->set_member(#k, key::k)		KEY_CONST(BACKSPACE);		KEY_CONST(CAPSLOCK);		KEY_CONST(CONTROL);		KEY_CONST(DELETEKEY);		KEY_CONST(DOWN);		KEY_CONST(END);		KEY_CONST(ENTER);		KEY_CONST(ESCAPE);		KEY_CONST(HOME);		KEY_CONST(INSERT);		KEY_CONST(LEFT);		KEY_CONST(PGDN);		KEY_CONST(PGUP);		KEY_CONST(RIGHT);		KEY_CONST(SHIFT);		KEY_CONST(SPACE);		KEY_CONST(TAB);		KEY_CONST(UP);		// methods		key_obj->set_member("addListener", &key_add_listener);		key_obj->set_member("getAscii", &key_get_ascii);		key_obj->set_member("getCode", &key_get_code);		key_obj->set_member("isDown", &key_is_down);		key_obj->set_member("isToggled", &key_is_toggled);		key_obj->set_member("removeListener", &key_remove_listener);		s_global->set_member("Key", key_obj);	}	void	notify_key_event(key::code k, bool down)	// External interface for the host to report key events.	{		action_init();	// @@ put this in some global init somewhere else...		static tu_string	key_obj_name("Key");		as_value	kval;		s_global->get_member(key_obj_name, &kval);		if (kval.get_type() == as_value::OBJECT)		{			key_as_object*	ko = (key_as_object*) kval.to_object();			assert(ko);			if (down) ko->set_key_down(k);			else ko->set_key_up(k);		}		else		{			log_error("gameswf::notify_key_event(): no Key built-in\n");		}	}		//	// global init	//	void	as_global_trace(const fn_call& fn)	{		assert(fn.nargs >= 1);		// Special case for objects: try the toString() method.		if (fn.arg(0).get_type() == as_value::OBJECT)		{			as_object_interface* obj = fn.arg(0).to_object();			assert(obj);			as_value method;			if (obj->get_member("toString", &method)			    && method.is_function())			{				as_value result = call_method0(method, fn.env, obj);				log_msg("%s\n", result.to_string());				return;			}		}		// Log our argument.		//		// @@ what if we get extra args?		//		// @@ Array gets special treatment.		const char* arg0 = fn.arg(0).to_string();		log_msg("%s\n", arg0);	}	void	as_global_sound_ctor(const fn_call& fn)	// Constructor for ActionScript class Sound.	{		smart_ptr<as_object>	sound_obj(new sound_as_object);		// methods		sound_obj->set_member("attachSound", &sound_attach);		sound_obj->set_member("start", &sound_start);		sound_obj->set_member("stop", &sound_stop);		fn.result->set_as_object_interface(sound_obj.get_ptr());	}	void	as_global_object_ctor(const fn_call& fn)	// Constructor for ActionScript class Object.	{		fn.result->set_as_object_interface(new as_object);	}	void	as_global_array_ctor(const fn_call& fn)	// Constructor for ActionScript class Array.	{		smart_ptr<as_array_object>	ao = new as_array_object;		if (fn.nargs == 0)		{			// Empty array.		}		else if (fn.nargs == 1			 && fn.arg(0).get_type() == as_value::NUMBER)		{			// Create an empty array with the given number of undefined elements.			//			// @@ TODO set length property; no need to			// actually create the elements now, since			// they're undefined.		}		else		{			// Use the arguments as initializers.			as_value	index_number;			for (int i = 0; i < fn.nargs; i++)			{				index_number.set_int(i);				ao->set_member(index_number.to_string(), fn.arg(i));			}			// @@ TODO set length property		}		fn.result->set_as_object_interface(ao.get_ptr());	}	void	as_global_assetpropflags(const fn_call& fn)	// ASSetPropFlags function	{		const int version = fn.env->get_target()->get_movie_definition()->get_version();		// Check the arguments		assert(fn.nargs == 3 || fn.nargs == 4);		assert((version == 5) ? (fn.nargs == 3) : true);		// object		as_object_interface* const obj = fn.arg(0).to_object();		assert(obj != NULL);		// list of child names		as_object_interface* props = fn.arg(1).to_object();		if (props == NULL) {			// tulrich: this fires in test_ASSetPropFlags -- is it correct?			assert(fn.arg(1).get_type() == as_value::NULLTYPE);		}		// a number which represents three bitwise flags which		// are used to determine whether the list of child names should be hidden,		// un-hidden, protected from over-write, un-protected from over-write,		// protected from deletion and un-protected from deletion		int set_true = int(fn.arg(2).to_number()) & as_prop_flags::as_prop_flags_mask;		// Is another integer bitmask that works like set_true,		// except it sets the attributes to false. The		// set_false bitmask is applied before set_true is applied		// ASSetPropFlags was exposed in Flash 5, however the fourth argument 'set_false'		// was not required as it always defaulted to the value '~0'. 		int set_false = (fn.nargs == 3 ? 				 (version == 5 ? ~0 : 0) : int(fn.arg(3).to_number()))			& as_prop_flags::as_prop_flags_mask;		// Evan: it seems that if set_true == 0 and set_false == 0, this function		// acts as if the parameters where (object, null, 0x1, 0) ...		if (set_false == 0 && set_true == 0)		{			props = NULL;			set_false = 0;			set_true = 0x1;		}		if (props == NULL)		{			// Take all the members of the object			as_object* object = (as_object*) obj;			stringi_hash<as_member>::const_iterator it = object->m_members.begin();			while (it != object->m_members.end())			{				as_member member = it.get_value();				as_prop_flags f = member.get_member_flags();				const int oldflags = f.get_flags();				const int newflags = f.set_flags(set_true, set_false);				member.set_member_flags(f);				object->m_members.set(it.get_key(), member);				++it;			}			if (object->m_prototype != NULL)			{				const as_object* prototype = (as_object*) object->m_prototype;				it = prototype->m_members.begin();				while (it != prototype->m_members.end())				{					as_member member = it.get_value();					as_prop_flags f = member.get_member_flags();					const int oldflags = f.get_flags();					const int newflags = f.set_flags(set_true, set_false);					member.set_member_flags(f);					object->m_members.set(it.get_key(), member);					++it;				}			}		} else {			as_object* object = (as_object*) obj;			as_object* object_props = (as_object*) props;			stringi_hash<as_member>::iterator it = object_props->m_members.begin();			while(it != object_props->m_members.end())			{				const tu_stringi key = (it.get_value()).get_member_value().to_string();				stringi_hash<as_member>::iterator it2 = object->m_members.find(key);				if (it2 != object->m_members.end())				{					as_member member = it2.get_value();					as_prop_flags f = member.get_member_flags();					const int oldflags = f.get_flags();					const int newflags = f.set_flags(set_true, set_false);					member.set_member_flags(f);					object->m_members.set((it.get_value()).get_member_value().to_string(), member);				}				++it;			}		}	}	void	action_init()	// Create/hook built-ins.	{		if (s_inited == false)		{			s_inited = true;			// @@ s_global should really be a			// client-visible player object, which			// contains one or more actual movie			// instances.  We're currently just hacking it			// in as an app-global mutable object :(			assert(s_global == NULL);			s_global = new as_object;			s_global->set_member("trace", as_value(as_global_trace));			s_global->set_member("Object", as_value(as_global_object_ctor));			s_global->set_member("Sound", as_value(as_global_sound_ctor));			s_global->set_member("Array", as_value(as_global_array_ctor));			s_global->set_member("TextFormat", as_value(textformat_new));#ifdef HAVE_LIBXML			s_global->set_member("XML", as_value(xml_new));			//s_global->set_member("XML", as_value(xmlsocket_xml_new));			s_global->set_member("XMLSocket", as_value(xmlsocket_new));#endif // HAVE_LIBXML			s_global->set_member("MovieClipLoader", as_value(moviecliploader_new));			s_global->set_member("String", as_value(string_ctor));			// ASSetPropFlags			s_global->set_member("ASSetPropFlags", as_global_assetpropflags);			math_init();			key_init();		}	}	void	action_clear()	{		if (s_inited)		{			s_inited = false;			s_global->clear();			s_global = NULL;		}	}	//	// properties by number	//	static const tu_string	s_property_names[] =	{		tu_string("_x"),		tu_string("_y"),		tu_string("_xscale"),		tu_string("_yscale"),		tu_string("_currentframe"),		tu_string("_totalframes"),		tu_string("_alpha"),		tu_string("_visible"),		tu_string("_width"),		tu_string("_height"),		tu_string("_rotation"),		tu_string("_target"),		tu_string("_framesloaded"),		tu_string("_name"),		tu_string("_droptarget"),		tu_string("_url"),		tu_string("_highquality"),		tu_string("_focusrect"),		tu_string("_soundbuftime"),		tu_string("@@ mystery quality member"),		tu_string("_xmouse"),		tu_string("_ymouse"),	};	static as_value	get_property(as_object_interface* obj, int prop_number)	{		as_value	val;		if (prop_number >= 0 && prop_number < int(sizeof(s_property_names)/sizeof(s_property_names[0])))		{			obj->get_member(s_property_names[prop_number], &val);		}		else		{			log_error("error: invalid property query, property number %d\n", prop_number);		}		return val;	}	static void	set_property(as_object_interface* obj, int prop_number, const as_value& val)	{		if (prop_number >= 0 && prop_number < int(sizeof(s_property_names)/sizeof(s_property_names[0])))		{			obj->set_member(s_property_names[prop_number], val);		}		else		{			log_error("error: invalid set_property, property number %d\n", prop_number);		}	}	//	// do_action	//	// Thin wrapper around action_buffer.	struct do_action : public execute_tag	{		action_buffer	m_buf;		void	read(stream* in)		{			m_buf.read(in);		}		virtual void	execute(movie* m)		{			m->add_action_buffer(&m_buf);		}		// Don't override because actions should not be replayed when seeking the movie.		//void	execute_state(movie* m) {}		virtual bool	is_action_tag() const		// Tell the caller that we are an action tag.		{			return true;		}	};	void	do_action_loader(stream* in, int tag_type, movie_definition_sub* m)	{		IF_VERBOSE_PARSE(log_msg("tag %d: do_action_loader\n", tag_type));		IF_VERBOSE_ACTION(log_msg("-- actions in frame %d\n", m->get_loading_frame()));		assert(in);		assert(tag_type == 12);		assert(m);				do_action*	da = new do_action;		da->read(in);		m->add_execute_tag(da);	}		//	// do_init_action	//	void	do_init_action_loader(stream* in, int tag_type, movie_definition_sub* m)	{		assert(tag_type == 59);		int	sprite_character_id = in->read_u16();		IF_VERBOSE_PARSE(log_msg("  tag %d: do_init_action_loader\n", tag_type));		IF_VERBOSE_ACTION(log_msg("  -- init actions for sprite %d\n", sprite_character_id));		do_action*	da = new do_action;		da->read(in);		m->add_init_action(sprite_character_id, da);	}	//	// action_buffer	//	// Disassemble one instruction to the log.	static void	log_disasm(const unsigned char* instruction_data);	action_buffer::action_buffer()		:		m_decl_dict_processed_at(-1)	{	}	void	action_buffer::read(stream* in)	{		// Read action bytes.		for (;;)		{			int	instruction_start = m_buffer.size();			int	pc = m_buffer.size();			int	action_id = in->read_u8();			m_buffer.push_back(action_id);			if (action_id & 0x80)			{				// Action contains extra data.  Read it.				int	length = in->read_u16();				m_buffer.push_back(length & 0x0FF);				m_buffer.push_back((length >> 8) & 0x0FF);				for (int i = 0; i < length; i++)				{					unsigned char	b = in->read_u8();					m_buffer.push_back(b);				}			}			IF_VERBOSE_ACTION(log_msg("%4d\t", pc); log_disasm(&m_buffer[instruction_start]); );			if (action_id == 0)			{				// end of action buffer.				break;			}		}	}	void	action_buffer::process_decl_dict(int start_pc, int stop_pc)	// Interpret the decl_dict opcode.  Don't read stop_pc or	// later.  A dictionary is some static strings embedded in the	// action buffer; there should only be one dictionary per	// action buffer.	//	// NOTE: Normally the dictionary is declared as the first	// action in an action buffer, but I've seen what looks like	// some form of copy protection that amounts to:	//	// <start of action buffer>	//          push true	//          branch_if_true label	//          decl_dict   [0]   // this is never executed, but has lots of orphan data declared in the opcode	// label:   // (embedded inside the previous opcode; looks like an invalid jump)	//          ... "protected" code here, including the real decl_dict opcode ...

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -