s9xcommand_t S9xGetCommandT()

in cores/snes/controls.cpp [1242:1666]


s9xcommand_t S9xGetCommandT (const char *name)
{
	s9xcommand_t	cmd;
	int				i, j;
	const char		*s;

	memset(&cmd, 0, sizeof(cmd));
	cmd.type         = S9xBadMapping;
	cmd.multi_press  = 0;
	cmd.button_norpt = 0;

	if (!strcmp(name, "None"))
		cmd.type = S9xNoMapping;
	else
	if (!strncmp(name, "Joypad", 6))
	{
		if (name[6] < '1' || name[6] > '8' || name[7] != ' ')
			return (cmd);

		if (!strncmp(name + 8, "Axis ", 5))
		{
			cmd.axis.joypad.idx = name[6] - '1';
			s = name + 13;

			if (!strncmp(s, "Left/Right ", 11))	{ j = 0; i = 0; s += 11; }
			else
			if (!strncmp(s, "Right/Left ", 11))	{ j = 0; i = 1; s += 11; }
			else
			if (!strncmp(s, "Up/Down ",     8))	{ j = 1; i = 0; s +=  8; }
			else
			if (!strncmp(s, "Down/Up ",     8))	{ j = 1; i = 1; s +=  8; }
			else
			if (!strncmp(s, "Y/A ",         4))	{ j = 2; i = 0; s +=  4; }
			else
			if (!strncmp(s, "A/Y ",         4))	{ j = 2; i = 1; s +=  4; }
			else
			if (!strncmp(s, "X/B ",         4))	{ j = 3; i = 0; s +=  4; }
			else
			if (!strncmp(s, "B/X ",         4))	{ j = 3; i = 1; s +=  4; }
			else
			if (!strncmp(s, "L/R ",         4))	{ j = 4; i = 0; s +=  4; }
			else
			if (!strncmp(s, "R/L ",         4))	{ j = 4; i = 1; s +=  4; }
			else
				return (cmd);

			cmd.axis.joypad.axis      = j;
			cmd.axis.joypad.invert    = i;
			i = get_threshold(&s);
			if (i < 0)
				return (cmd);
			cmd.axis.joypad.threshold = (i - 1) * 256 / 1000;

			cmd.type = S9xAxisJoypad;
		}
		else
		{
			cmd.button.joypad.idx = name[6] - '1';
			s = name + 8;
			i = 0;

			if ((cmd.button.joypad.toggle = strncmp(s, "Toggle", 6) ? 0 : 1))	s += i = 6;
			if ((cmd.button.joypad.sticky = strncmp(s, "Sticky", 6) ? 0 : 1))	s += i = 6;
			if ((cmd.button.joypad.turbo  = strncmp(s, "Turbo",  5) ? 0 : 1))	s += i = 5;

			if (cmd.button.joypad.toggle && !(cmd.button.joypad.sticky || cmd.button.joypad.turbo))
				return (cmd);

			if (i)
			{
				if (*s != ' ')
					return (cmd);
				s++;
			}

			i = 0;

			if (!strncmp(s, "Up",     2))	{ i |= SNES_UP_MASK;     s += 2; if (*s == '+') s++; }
			if (!strncmp(s, "Down",   4))	{ i |= SNES_DOWN_MASK;   s += 4; if (*s == '+') s++; }
			if (!strncmp(s, "Left",   4))	{ i |= SNES_LEFT_MASK;   s += 4; if (*s == '+') s++; }
			if (!strncmp(s, "Right",  5))	{ i |= SNES_RIGHT_MASK;  s += 5; if (*s == '+') s++; }

			if (*s == 'A')	{ i |= SNES_A_MASK;  s++; if (*s == '+') s++; }
			if (*s == 'B')	{ i |= SNES_B_MASK;  s++; if (*s == '+') s++; }
			if (*s == 'X')	{ i |= SNES_X_MASK;  s++; if (*s == '+') s++; }
			if (*s == 'Y')	{ i |= SNES_Y_MASK;  s++; if (*s == '+') s++; }
			if (*s == 'L')	{ i |= SNES_TL_MASK; s++; if (*s == '+') s++; }
			if (*s == 'R')	{ i |= SNES_TR_MASK; s++; if (*s == '+') s++; }

			if (!strncmp(s, "Start",  5))	{ i |= SNES_START_MASK;  s += 5; if (*s == '+') s++; }
			if (!strncmp(s, "Select", 6))	{ i |= SNES_SELECT_MASK; s += 6; }

			if (i == 0 || *s != 0 || *(s - 1) == '+')
				return (cmd);

			cmd.button.joypad.buttons = i;

			cmd.type = S9xButtonJoypad;
		}
	}
	else
	if (!strncmp(name, "Mouse", 5))
	{
		if (name[5] < '1' || name[5] > '2' || name[6] != ' ')
			return (cmd);

		cmd.button.mouse.idx = name[5] - '1';
		s = name + 7;
		i = 0;

		if ((cmd.button.mouse.left  = (*s == 'L')))	s += i = 1;
		if ((cmd.button.mouse.right = (*s == 'R')))	s += i = 1;

		if (i == 0 || *s != 0)
			return (cmd);

		cmd.type = S9xButtonMouse;
	}
	else
	if (!strncmp(name, "Superscope ", 11))
	{
		s = name + 11;
		i = 0;

		if ((cmd.button.scope.aim_offscreen     = strncmp(s, "AimOffscreen", 12) ? 0 : 1))	{ s += i = 12; if (*s == ' ') s++; else if (*s != 0) return (cmd); }
		if ((cmd.button.scope.fire              = strncmp(s, "Fire",          4) ? 0 : 1))	{ s += i =  4; if (*s == '+') s++; }
		if ((cmd.button.scope.cursor            = strncmp(s, "Cursor",        6) ? 0 : 1))	{ s += i =  6; if (*s == '+') s++; }
		if ((cmd.button.scope.turbo             = strncmp(s, "ToggleTurbo",  11) ? 0 : 1))	{ s += i = 11; if (*s == '+') s++; }
		if ((cmd.button.scope.pause             = strncmp(s, "Pause",         5) ? 0 : 1))	{ s += i =  5; }

		if (i == 0 || *s != 0 || *(s - 1) == '+')
			return (cmd);

		cmd.type = S9xButtonSuperscope;
	}
	else
	if (!strncmp(name, "Justifier", 9))
	{
		if (name[9] < '1' || name[9] > '2' || name[10] != ' ')
			return (cmd);

		cmd.button.justifier.idx = name[9] - '1';
		s = name + 11;
		i = 0;

		if ((cmd.button.justifier.aim_offscreen = strncmp(s, "AimOffscreen", 12) ? 0 : 1))	{ s += i = 12; if (*s == ' ') s++; else if (*s != 0) return (cmd); }
		if ((cmd.button.justifier.trigger       = strncmp(s, "Trigger",       7) ? 0 : 1))	{ s += i =  7; if (*s == '+') s++; }
		if ((cmd.button.justifier.start         = strncmp(s, "Start",         5) ? 0 : 1))	{ s += i =  5; }

		if (i == 0 || *s != 0 || *(s - 1) == '+')
			return (cmd);

		cmd.type = S9xButtonJustifier;
	}
	else
	if (!strncmp(name, "Pointer ", 8))
	{
		s = name + 8;
		i = 0;

		if ((cmd.pointer.aim_mouse0     = strncmp(s, "Mouse1",      6) ? 0 : 1))	{ s += i =  6; if (*s == '+') s++; }
		if ((cmd.pointer.aim_mouse1     = strncmp(s, "Mouse2",      6) ? 0 : 1))	{ s += i =  6; if (*s == '+') s++; }
		if ((cmd.pointer.aim_scope      = strncmp(s, "Superscope", 10) ? 0 : 1))	{ s += i = 10; if (*s == '+') s++; }
		if ((cmd.pointer.aim_justifier0 = strncmp(s, "Justifier1", 10) ? 0 : 1))	{ s += i = 10; if (*s == '+') s++; }
		if ((cmd.pointer.aim_justifier1 = strncmp(s, "Justifier2", 10) ? 0 : 1))	{ s += i = 10; }

		if (i == 0 || *s != 0 || *(s - 1) == '+')
			return (cmd);

		cmd.type = S9xPointer;
	}
	else
	if (!strncmp(name, "ButtonToPointer ", 16))
	{
		if (name[16] < '1' || name[16] > '8')
			return (cmd);

		cmd.button.pointer.idx = name[16] - '1';
		s = name + 17;
		i = 0;

		if ((cmd.button.pointer.UD = (*s == 'u' ? -1 : (*s == 'd' ? 1 : 0))))	s += i = 1;
		if ((cmd.button.pointer.LR = (*s == 'l' ? -1 : (*s == 'r' ? 1 : 0))))	s += i = 1;

		if (i == 0 || *(s++) != ' ')
			return (cmd);

		for (i = 0; i < 4; i++)
			if (!strcmp(s, speed_names[i]))
				break;
		if (i > 3)
			return (cmd);

		cmd.button.pointer.speed_type = i;

		cmd.type = S9xButtonPseudopointer;
	}
	else
	if (!strncmp(name, "AxisToPointer ", 14))
	{
		if (name[14] < '1' || name[14] > '8')
			return (cmd);

		cmd.axis.pointer.idx = name[14] - '1';
		s= name + 15;
		i = 0;

		if (*s == 'h')
			cmd.axis.pointer.HV = 0;
		else
		if (*s == 'v')
			cmd.axis.pointer.HV = 1;
		else
			return (cmd);

		if (s[1] != ' ')
			return (cmd);

		s += 2;
		if ((cmd.axis.pointer.invert = *s == '-'))
			s++;

		for (i = 0; i < 4; i++)
			if (!strcmp(s, speed_names[i]))
				break;
		if (i > 3)
			return (cmd);

		cmd.axis.pointer.speed_type = i;

		cmd.type = S9xAxisPseudopointer;
	}
	else
	if (!strncmp(name, "AxisToButtons ", 14))
	{
		s = name + 14;

		if (s[0] == '0')
		{
			if (s[1] != '/')
				return (cmd);

			cmd.axis.button.negbutton = 0;
			s += 2;
		}
		else
		{
			i = 0;
			do
			{
				if (*s < '0' || *s > '9')
					return (cmd);

				i = i * 10 + *s - '0';
				if (i > 255)
					return (cmd);
			}
			while (*++s != '/');

			cmd.axis.button.negbutton = i;
			s++;
		}

		if (s[0] == '0')
		{
			if (s[1] != ' ')
				return (cmd);

			cmd.axis.button.posbutton = 0;
			s += 2;
		}
		else
		{
			i = 0;
			do
			{
				if (*s < '0' || *s > '9')
					return (cmd);

				i = i * 10 + *s - '0';
				if (i > 255)
					return (cmd);
			}
			while (*++s != ' ');

			cmd.axis.button.posbutton = i;
			s++;
		}

		i = get_threshold(&s);
		if (i < 0)
			return (cmd);
		cmd.axis.button.threshold = (i - 1) * 256 / 1000;

		cmd.type = S9xAxisPseudobuttons;
	}
	else
	if (!strncmp(name, "MULTI#", 6))
	{
		i = strtol(name + 6, (char **) &s, 10);
		if (s != NULL && *s != '\0')
			return (cmd);
		if (i >= (int) multis.size())
			return (cmd);

		cmd.button.multi_idx = i;
		cmd.type = S9xButtonMulti;
	}
	else
	if (((name[0] == '+' && name[1] == '{') || name[0] == '{') && name[strlen(name) - 1] == '}')
	{
		if (multis.size() > 2147483640)
		{
			fprintf(stderr, "Too many multis!");
			return (cmd);
		}

		string	x;
		int		n;

		j = 2;
		for (i = (name[0] == '+') ? 2 : 1; name[i] != '\0'; i++)
		{
			if (name[i] == ',' || name[i] == ';')
			{
				if (name[i] == ';')
					j++;
				if (++j > 2147483640)
				{
					fprintf(stderr, "Multi too long!");
					return (cmd);
				}
			}

			if (name[i] == '{')
				return (cmd);
		}

		s9xcommand_t	*c = (s9xcommand_t *) calloc(j, sizeof(s9xcommand_t));
		if (c == NULL)
		{
			perror("malloc error while parsing multi");
			return (cmd);
		}

		n = 0;
		i = (name[0] == '+') ? 2 : 1;

		do
		{
			if (name[i] == ';')
			{
				c[n].type         = S9xNoMapping;
				c[n].multi_press  = 0;
				c[n].button_norpt = 0;

				j = i;
			}
			else
			if (name[i] == ',')
			{
				free(c);
				return (cmd);
			}
			else
			{
				uint8	press = 0;

				if (name[0] == '+')
				{
					if (name[i] == '+')
						press = 1;
					else
					if (name[i] == '-')
						press = 2;
					else
					{
						free(c);
						return (cmd);
					}

					i++;
				}

				for (j = i; name[j] != ';' && name[j] != ',' && name[j] != '}'; j++) ;

				x.assign(name + i, j - i);
				c[n] = S9xGetCommandT(x.c_str());
				c[n].multi_press = press;

				if (maptype(c[n].type) != MAP_BUTTON)
				{
					free(c);
					return (cmd);
				}

				if (name[j] == ';')
					j--;
			}

			i = j + 1;
			n++;
		}
		while (name[i] != '\0');

		c[n].type        = S9xNoMapping;
		c[n].multi_press = 3;

		multis.push_back(c);

		cmd.button.multi_idx = multis.size() - 1;
		cmd.type = S9xButtonMulti;
	}
	else
	{
		i = findstr(name, command_names, LAST_COMMAND);
		if (i < 0)
			return (cmd);

		cmd.type = S9xButtonCommand;
		cmd.button.command = i;
	}

	return (cmd);
}