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

📄 gameswf_action.cpp

📁 一个开源的Flash 播放器,可以在Windows/Linux 上运行
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	//          <end of the dummy decl_dict [0] opcode>	//	// So we just interpret the first decl_dict we come to, and	// cache the results.  If we ever hit a different decl_dict in	// the same action_buffer, then we log an error and ignore it.	{		assert(stop_pc <= m_buffer.size());		if (m_decl_dict_processed_at == start_pc)		{			// We've already processed this decl_dict.			int	count = m_buffer[start_pc + 3] | (m_buffer[start_pc + 4] << 8);			assert(m_dictionary.size() == count);			UNUSED(count);			return;		}		if (m_decl_dict_processed_at != -1)		{			log_error("error: process_decl_dict(%d, %d): decl_dict was already processed at %d\n",				  start_pc,				  stop_pc,				  m_decl_dict_processed_at);			return;		}		m_decl_dict_processed_at = start_pc;		// Actual processing.		int	i = start_pc;		int	length = m_buffer[i + 1] | (m_buffer[i + 2] << 8);		int	count = m_buffer[i + 3] | (m_buffer[i + 4] << 8);		i += 2;		UNUSED(length);		assert(start_pc + 3 + length == stop_pc);		m_dictionary.resize(count);		// Index the strings.		for (int ct = 0; ct < count; ct++)		{			// Point into the current action buffer.			m_dictionary[ct] = (const char*) &m_buffer[3 + i];			while (m_buffer[3 + i])			{				// safety check.				if (i >= stop_pc)				{					log_error("error: action buffer dict length exceeded\n");					// Jam something into the remaining (invalid) entries.					while (ct < count)					{						m_dictionary[ct] = "<invalid>";						ct++;					}					return;				}				i++;			}			i++;		}	}	void	action_buffer::execute(as_environment* env)	// Interpret the actions in this action buffer, and evaluate	// them in the given environment.  Execute our whole buffer,	// without any arguments passed in.	{		int	local_stack_top = env->get_local_frame_top();		env->add_frame_barrier();		array<with_stack_entry>	empty_with_stack;		execute(env, 0, m_buffer.size(), NULL, empty_with_stack, false /* not function2 */);		env->set_local_frame_top(local_stack_top);	}	void	action_buffer::execute(		as_environment* env,		int start_pc,		int exec_bytes,		as_value* retval,		const array<with_stack_entry>& initial_with_stack,		bool is_function2)	// Interpret the specified subset of the actions in our	// buffer.  Caller is responsible for cleaning up our local	// stack frame (it may have passed its arguments in via the	// local stack frame).	// 	// The is_function2 flag determines whether to use global or local registers.	{		action_init();	// @@ stick this somewhere else; need some global static init function		assert(env);		array<with_stack_entry>	with_stack(initial_with_stack);		// Some corner case behaviors depend on the SWF file version.		int version = env->get_target()->get_movie_definition()->get_version();#if 0		// Check the time		if (periodic_events.expired()) {			periodic_events.poll_event_handlers(env);		}#endif				movie*	original_target = env->get_target();		UNUSED(original_target);		// Avoid warnings.		int	stop_pc = start_pc + exec_bytes;		for (int pc = start_pc; pc < stop_pc; )		{			// Cleanup any expired "with" blocks.			while (with_stack.size() > 0			       && pc >= with_stack.back().m_block_end_pc)			{				// Drop this stack element				with_stack.resize(with_stack.size() - 1);			}			// Get the opcode.			int	action_id = m_buffer[pc];			if ((action_id & 0x80) == 0)			{				IF_VERBOSE_ACTION(log_msg("EX:\t"); log_disasm(&m_buffer[pc]));				// IF_VERBOSE_ACTION(log_msg("Action ID is: 0x%x\n", action_id));							// Simple action; no extra data.				switch (action_id)				{				default:					break;				case 0x00:	// end of actions.					return;				case 0x04:	// next frame.					env->get_target()->goto_frame(env->get_target()->get_current_frame() + 1);					break;				case 0x05:	// prev frame.					env->get_target()->goto_frame(env->get_target()->get_current_frame() - 1);					break;				case 0x06:	// action play					env->get_target()->set_play_state(movie::PLAY);					break;				case 0x07:	// action stop					env->get_target()->set_play_state(movie::STOP);					break;				case 0x08:	// toggle quality				case 0x09:	// stop sounds					break;				case 0x0A:	// add				{					env->top(1) += env->top(0);					env->drop(1);					break;				}				case 0x0B:	// subtract				{					env->top(1) -= env->top(0);					env->drop(1);					break;				}				case 0x0C:	// multiply				{					env->top(1) *= env->top(0);					env->drop(1);					break;				}				case 0x0D:	// divide				{					env->top(1) /= env->top(0);					env->drop(1);					break;				}				case 0x0E:	// equal				{					env->top(1).set_bool(env->top(1) == env->top(0));					env->drop(1);					break;				}				case 0x0F:	// less than				{					env->top(1).set_bool(env->top(1) < env->top(0));					env->drop(1);					break;				}				case 0x10:	// logical and				{					env->top(1).set_bool(env->top(1).to_bool() && env->top(0).to_bool());					env->drop(1);					break;				}				case 0x11:	// logical or				{					env->top(1).set_bool(env->top(1).to_bool() && env->top(0).to_bool());					env->drop(1);					break;				}				case 0x12:	// logical not				{					env->top(0).set_bool(! env->top(0).to_bool());					break;				}				case 0x13:	// string equal				{					env->top(1).set_bool(env->top(1).to_tu_string() == env->top(0).to_tu_string());					env->drop(1);					break;				}				case 0x14:	// string length				{					env->top(0).set_int(env->top(0).to_tu_string_versioned(version).utf8_length());					break;				}				case 0x15:	// substring				{					int	size = int(env->top(0).to_number());					int	base = int(env->top(1).to_number()) - 1;  // 1-based indices					const tu_string&	str = env->top(2).to_tu_string_versioned(version);					// Keep base within range.					base = iclamp(base, 0, str.length());					// Truncate if necessary.					size = imin(str.length() - base, size);					// @@ This can be done without new allocations if we get dirtier w/ internals					// of as_value and tu_string...					tu_string	new_string = str.c_str() + base;					new_string.resize(size);					env->drop(2);					env->top(0).set_tu_string(new_string);					break;				}				case 0x17:	// pop				{					env->drop(1);					break;				}				case 0x18:	// int				{					env->top(0).set_int(int(floor(env->top(0).to_number())));					break;				}				case 0x1C:	// get variable				{					as_value var_name = env->pop();					tu_string var_string = var_name.to_tu_string();					as_value variable = env->get_variable(var_string, with_stack);					env->push(variable);					if (variable.to_object() == NULL) {						IF_VERBOSE_ACTION(log_msg("-- get var: %s=%s\n",									  var_string.c_str(),									  variable.to_tu_string().c_str()));					} else {						IF_VERBOSE_ACTION(log_msg("-- get var: %s=%s at %p\n",									  var_string.c_str(),									  variable.to_tu_string().c_str(), variable.to_object()));					}										break;				}				case 0x1D:	// set variable				{					env->set_variable(env->top(1).to_tu_string(), env->top(0), with_stack);					IF_VERBOSE_ACTION(log_msg("-- set var: %s \n",								  env->top(1).to_tu_string().c_str()));					env->drop(2);					break;				}				case 0x20:	// set target expression				{					as_object_interface* target_object = env->top(0).to_object();					IF_VERBOSE_ACTION(log_msg("-- ActionSetTarget2: %s (%d)",								  ((character *) target_object)->m_name.c_str(),								  ((character *) target_object)->m_id));					movie* target = env->find_target(target_object);					env->set_target (target);					break;				}				case 0x21:	// string concat				{					env->top(1).convert_to_string_versioned(version);					env->top(1).string_concat(env->top(0).to_tu_string_versioned(version));					env->drop(1);					break;				}				case 0x22:	// get property				{					movie*	target = env->find_target(env->top(1));					if (target)					{						env->top(1) = get_property(target, (int) env->top(0).to_number());					}					else					{						env->top(1) = as_value();					}					env->drop(1);					break;				}				case 0x23:	// set property				{					movie*	target = env->find_target(env->top(2));					if (target)					{						set_property(target, (int) env->top(1).to_number(), env->top(0));					}					env->drop(3);					break;				}				case 0x24:	// duplicate clip (sprite?)				{					env->get_target()->clone_display_object(						env->top(2).to_tu_string(),						env->top(1).to_tu_string(),						(int) env->top(0).to_number());					env->drop(3);					break;				}				case 0x25:	// remove clip					env->get_target()->remove_display_object(env->top(0).to_tu_string());					env->drop(1);					break;				case 0x26:	// trace				{					// Log the stack val.					as_global_trace(fn_call(&env->top(0), NULL, env, 1, env->get_top_index()));					env->drop(1);					break;				}				case 0x27:	// start drag movie				{					movie::drag_state	st;					st.m_character = env->find_target(env->top(0));					if (st.m_character == NULL)					{						log_error("error: start_drag of invalid target '%s'.\n",							  env->top(0).to_string());					}					st.m_lock_center = env->top(1).to_bool();					st.m_bound = env->top(2).to_bool();					if (st.m_bound)					{						st.m_bound_x0 = (float) env->top(6).to_number();						st.m_bound_y0 = (float) env->top(5).to_number();						st.m_bound_x1 = (float) env->top(4).to_number();						st.m_bound_y1 = (float) env->top(3).to_number();						env->drop(4);					}					env->drop(3);					movie*	root_movie = env->get_target()->get_root_movie();					assert(root_movie);					if (root_movie && st.m_character)					{						root_movie->set_drag_state(st);					}										break;				}				case 0x28:	// stop drag movie				{					movie*	root_movie = env->get_target()->get_root_movie();					assert(root_movie);					root_movie->stop_drag();					break;				}				case 0x29:	// string less than				{					env->top(1).set_bool(env->top(1).to_tu_string() < env->top(0).to_tu_string());					break;				}				case 0x2A:	// throw				{					log_error("todo opcode: %02X\n", action_id);					break;				}				case 0x2B:	// cast_object				{					// TODO					//					// Pop o1, pop s2					// Make sure o1 is an instance of s2.					// If the cast succeeds, push o1, else push NULL.					//					// The cast doesn't appear to coerce at all, it's more					// like a dynamic_cast<> in C++ I think.					log_error("todo opcode: %02X\n", action_id);					break;				}				case 0x2C:	// implements				{					// Declare that a class s1 implements one or more					// interfaces (i2 == number of interfaces, s3..sn are the names					// of the interfaces).					log_error("todo opcode: %02X\n", action_id);					break;				}				case 0x30:	// random				{					int	max = int(env->top(0).to_number());					if (max < 1) max = 1;					env->top(0).set_int(tu_random::next_random() % max);					break;				}				case 0x31:	// mb length				{					// @@ TODO					log_error("todo opcode: %02X\n", action_id);					break;				}				case 0x32:	// ord				{					// ASCII code of first character					env->top(0).set_int(env->top(0).to_string()[0]);					break;				}				case 0x33:	// chr				{					char	buf[2];					buf[0] = int(env->top(0).to_number());					buf[1] = 0;					env->top(0).set_string(buf);					break;				}				case 0x34:	// get timer					// Push milliseconds since we started playing.					env->push(floorf(env->m_target->get_timer() * 1000.0f));					break;				case 0x35:	// mb substring				{					// @@ TODO					log_error("todo opcode: %02X\n", action_id);					break;				}				case 0x37:	// mb chr				{					// @@ TODO					log_error("todo opcode: %02X\n", action_id);					break;				}				case 0x3A:	// delete				{					// @@ TODO										// Apparently this can be used to remove properties from					// an object?					log_error("todo opcode: %02X\n", action_id);					break;				}				case 0x3B:	// delete2				{					// @@ tulrich: delete is not valid here!  Do we actually just want to 					// NULL out the object pointer in the environment (to drop the ref)?					// Should at least check the ref count before deleting anything!!!//					as_value	obj_name = env->pop();					as_value obj_ptr = env->get_variable_raw(env->top(0).to_tu_string(), with_stack);///x					delete obj_ptr.to_object();// 	 				log_error("%08X\n", obj_ptr.to_object());					log_error("todo opcode: %02X\n", action_id);					break;				}				case 0x3C:	// set local				{					as_value	value = env->pop();					as_value	varname = env->pop();					env->set_local(varname.to_tu_string(), value);					break;				}				case 0x3D:	// call function				{					as_value	function;					if (env->top(0).get_type() == as_value::STRING)					{						// Function is a string; lookup the function.						const tu_string&	function_name = env->top(0).to_tu_string();						function = env->get_variable(function_name, with_stack);						if (function.get_type() != as_value::C_FUNCTION						    && function.get_type() != as_value::AS_FUNCTION)						{

⌨️ 快捷键说明

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