static inline uint32_t getfield(uint32_t w, int n, int s)
{
	return (w >> s) & (((uint32_t)1 << n) - 1);
}

static inline int32_t argvi(gfxd_macro_t *m, int idx)
{
	return m->arg[idx].value.i;
}

static inline uint32_t argvu(gfxd_macro_t *m, int idx)
{
	return m->arg[idx].value.u;
}

static inline float argvf(gfxd_macro_t *m, int idx)
{
	return m->arg[idx].value.f;
}

static inline void argi(gfxd_macro_t *m, int idx, const char *name,
	int32_t value, int type)
{
	m->arg[idx].type = type;
	m->arg[idx].name = name;
	m->arg[idx].value.i = value;
	m->arg[idx].bad = 0;
}

static inline void argu(gfxd_macro_t *m, int idx, const char *name,
	uint32_t value, int type)
{
	m->arg[idx].type = type;
	m->arg[idx].name = name;
	m->arg[idx].value.u = value;
	m->arg[idx].bad = 0;
}

static inline void argf(gfxd_macro_t *m, int idx, const char *name,
	float value, int type)
{
	m->arg[idx].type = type;
	m->arg[idx].name = name;
	m->arg[idx].value.f = value;
	m->arg[idx].bad = 0;
}

static inline void badarg(gfxd_macro_t *m, int idx)
{
	m->arg[idx].bad = 1;
}

UCFUNC int32_t sx(uint32_t n, int bits)
{
	int32_t smin = (int32_t)1 << (bits - 1);
	int32_t smax = (int32_t)1 << bits;
	int32_t i = n;
	if (i < smin)
		return i;
	else
		return i - smax;
}

UCFUNC int d_Invalid(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_Invalid;
	argu(m, 0, "hi", hi, gfxd_Word);
	argu(m, 1, "lo", lo, gfxd_Word);
	return -1;
}

UCFUNC int d_DPFillRectangle(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_DPFillRectangle;
	argu(m, 0, "ulx", getfield(lo, 10, 14), gfxd_Coordi);
	argu(m, 1, "uly", getfield(lo, 10, 2), gfxd_Coordi);
	argu(m, 2, "lrx", getfield(hi, 10, 14), gfxd_Coordi);
	argu(m, 3, "lry", getfield(hi, 10, 2), gfxd_Coordi);
	return 0;
}

UCFUNC int d_DPFullSync(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_DPFullSync;
	return 0;
}

UCFUNC int d_DPLoadSync(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_DPLoadSync;
	return 0;
}

UCFUNC int d_DPTileSync(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_DPTileSync;
	return 0;
}

UCFUNC int d_DPPipeSync(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_DPPipeSync;
	return 0;
}

UCFUNC int c_DPLoadTLUT_pal16(gfxd_macro_t *m, gfxd_macro_t *m_list,
	int n_macro)
{
	if (n_macro < 6)
		return -1;
	if (m_list[0].id != gfxd_DPSetTextureImage
		|| argvi(&m_list[0], 0) != G_IM_FMT_RGBA
		|| argvi(&m_list[0], 1) != G_IM_SIZ_16b
		|| argvi(&m_list[0], 2) != 1)
	{
		return -1;
	}
	uint32_t dram = argvu(&m_list[0], 3);
	if (m_list[1].id != gfxd_DPTileSync)
		return -1;
	if (m_list[2].id != gfxd_DPSetTile
		|| argvi(&m_list[2], 0) != 0
		|| argvi(&m_list[2], 1) != 0
		|| argvi(&m_list[2], 2) != 0
		|| argvu(&m_list[2], 3) < 0x100
		|| argvu(&m_list[2], 3) % 0x10 != 0
		|| argvi(&m_list[2], 4) != G_TX_LOADTILE
		|| argvi(&m_list[2], 5) != 0
		|| argvu(&m_list[2], 6) != 0
		|| argvi(&m_list[2], 7) != 0
		|| argvi(&m_list[2], 8) != 0
		|| argvu(&m_list[2], 9) != 0
		|| argvi(&m_list[2], 10) != 0
		|| argvi(&m_list[2], 11) != 0)
	{
		return -1;
	}
	int pal = (argvu(&m_list[2], 3) - 0x100) / 0x10;
	if (m_list[3].id != gfxd_DPLoadSync)
		return -1;
	if (m_list[4].id != gfxd_DPLoadTLUTCmd
		|| argvi(&m_list[4], 0) != G_TX_LOADTILE
		|| argvi(&m_list[4], 1) != 15)
	{
		return -1;
	}
	if (m_list[5].id != gfxd_DPPipeSync)
		return -1;
	m->id = gfxd_DPLoadTLUT_pal16;
	argi(m, 0, "pal", pal, gfxd_Pal);
	argu(m, 1, "dram", dram, gfxd_Tlut);
	return 0;
}

UCFUNC int c_DPLoadTLUT_pal256(gfxd_macro_t *m, gfxd_macro_t *m_list,
	int n_macro)
{
	if (n_macro < 6)
		return -1;
	if (m_list[0].id != gfxd_DPSetTextureImage
		|| argvi(&m_list[0], 0) != G_IM_FMT_RGBA
		|| argvi(&m_list[0], 1) != G_IM_SIZ_16b
		|| argvi(&m_list[0], 2) != 1)
	{
		return -1;
	}
	uint32_t dram = argvu(&m_list[0], 3);
	if (m_list[1].id != gfxd_DPTileSync)
		return -1;
	if (m_list[2].id != gfxd_DPSetTile
		|| argvi(&m_list[2], 0) != 0
		|| argvi(&m_list[2], 1) != 0
		|| argvi(&m_list[2], 2) != 0
		|| argvu(&m_list[2], 3) != 0x100
		|| argvi(&m_list[2], 4) != G_TX_LOADTILE
		|| argvi(&m_list[2], 5) != 0
		|| argvu(&m_list[2], 6) != 0
		|| argvi(&m_list[2], 7) != 0
		|| argvi(&m_list[2], 8) != 0
		|| argvu(&m_list[2], 9) != 0
		|| argvi(&m_list[2], 10) != 0
		|| argvi(&m_list[2], 11) != 0)
	{
		return -1;
	}
	if (m_list[3].id != gfxd_DPLoadSync)
		return -1;
	if (m_list[4].id != gfxd_DPLoadTLUTCmd
		|| argvi(&m_list[4], 0) != G_TX_LOADTILE
		|| argvi(&m_list[4], 1) != 255)
	{
		return -1;
	}
	if (m_list[5].id != gfxd_DPPipeSync)
		return -1;
	m->id = gfxd_DPLoadTLUT_pal256;
	argu(m, 0, "dram", dram, gfxd_Tlut);
	return 0;
}

UCFUNC int c_ltb(gfxd_macro_t *m, gfxd_macro_t *m_list, int n_macro, int id,
	int mdxt, int mtmem, int mrt, int myuv, int m4b)
{
	if (n_macro < 7)
		return -1;
	if (m_list[0].id != gfxd_DPSetTextureImage || argvi(&m_list[0], 2) != 1)
		return -1;
	g_ifmt_t fmt = argvi(&m_list[0], 0);
	g_isiz_t ldsiz = argvi(&m_list[0], 1);
	uint32_t timg = argvu(&m_list[0], 3);
	if (myuv && fmt != G_IM_FMT_YUV)
		return -1;
	if (m_list[1].id != gfxd_DPSetTile
		|| argvi(&m_list[1], 0) != fmt
		|| argvi(&m_list[1], 1) != ldsiz
		|| argvi(&m_list[1], 2) != 0
		|| argvi(&m_list[1], 4) != G_TX_LOADTILE
		|| argvi(&m_list[1], 5) != 0)
	{
		return -1;
	}
	uint32_t tmem = argvu(&m_list[1], 3);
	unsigned cms = argvu(&m_list[1], 9);
	unsigned cmt = argvu(&m_list[1], 6);
	int masks = argvi(&m_list[1], 10);
	int maskt = argvi(&m_list[1], 7);
	int shifts = argvi(&m_list[1], 11);
	int shiftt = argvi(&m_list[1], 8);
	if (m_list[2].id != gfxd_DPLoadSync)
		return -1;
	if (m_list[3].id != gfxd_DPLoadBlock
		|| argvi(&m_list[3], 0) != G_TX_LOADTILE
		|| argvu(&m_list[3], 1) != 0
		|| argvu(&m_list[3], 2) != 0)
	{
		return -1;
	}
	qu102_t ldlrs = argvu(&m_list[3], 3);
	unsigned lddxt = argvu(&m_list[3], 4);
	if (m_list[4].id != gfxd_DPPipeSync)
		return -1;
	if (m_list[5].id != gfxd_DPSetTile
		|| argvi(&m_list[5], 0) != fmt
		|| G_SIZ_LDSIZ(argvi(&m_list[5], 1)) != ldsiz
		|| argvu(&m_list[5], 3) != tmem
		|| argvu(&m_list[5], 6) != cmt
		|| argvi(&m_list[5], 7) != maskt
		|| argvi(&m_list[5], 8) != shiftt
		|| argvu(&m_list[5], 9) != cms
		|| argvi(&m_list[5], 10) != masks
		|| argvi(&m_list[5], 11) != shifts)
	{
		return -1;
	}
	int siz = argvi(&m_list[5], 1);
	int rdline = argvi(&m_list[5], 2);
	int rt = argvi(&m_list[5], 4);
	int pal = argvi(&m_list[5], 5);
	if (m4b && siz != G_IM_SIZ_4b)
		return -1;
	if (!(mrt && rt != G_TX_RENDERTILE && tmem == 0)
		&& (tmem != 0) != mtmem)
	{
		return -1;
	}
	if ((rt != G_TX_RENDERTILE) != mrt)
		return -1;
	if (m_list[6].id != gfxd_DPSetTileSize
		|| argvi(&m_list[6], 0) != rt
		|| argvu(&m_list[6], 1) != 0
		|| argvu(&m_list[6], 2) != 0
		|| (argvu(&m_list[6], 3) & 3)
		|| (argvu(&m_list[6], 4) & 3))
	{
		return -1;
	}
	int width = (argvu(&m_list[6], 3) >> 2) + 1;
	int height = (argvu(&m_list[6], 4) >> 2) + 1;
	unsigned lrs = G_LDBLK_TXL(G_LTB_LRS(width, height, siz));
	unsigned dxt = 0;
	if (!mdxt)
		dxt = G_DXT(siz, width);
	int line;
	if (myuv)
		line = (width + 7) / 8;
	else
		line = (width * G_SIZ_LDBITS(siz) + 63) / 64;
	if (ldlrs != lrs || lddxt != dxt || rdline != line)
		return -1;

	m->id = id;
	int i = 0;
	argu(m, i++, "timg", timg, gfxd_Timg);
	if (mtmem)
		argu(m, i++, "tmem", tmem, gfxd_Tmem);
	if (mrt)
		argi(m, i++, "rtile", rt, gfxd_Tile);
	argi(m, i++, "fmt", fmt, gfxd_Fmt);
	if (!m4b)
		argi(m, i++, "siz", siz, gfxd_Siz);
	argi(m, i++, "width", width, gfxd_Dim);
	argi(m, i++, "height", height, gfxd_Dim);
	argi(m, i++, "pal", pal, gfxd_Pal);
	argu(m, i++, "cms", cms, gfxd_Cm);
	argu(m, i++, "cmt", cmt, gfxd_Cm);
	argi(m, i++, "masks", masks, gfxd_Tm);
	argi(m, i++, "maskt", maskt, gfxd_Tm);
	argi(m, i++, "shifts", shifts, gfxd_Ts);
	argi(m, i++, "shiftt", shiftt, gfxd_Ts);
	return 0;
}

UCFUNC int c_DPLoadMultiBlockYuvS(gfxd_macro_t *m, gfxd_macro_t *m_list,
	int n_macro)
{
	return c_ltb(m, m_list, n_macro, gfxd_DPLoadMultiBlockYuvS, 1, 1, 1, 1, 0);
}

UCFUNC int c_DPLoadMultiBlockYuv(gfxd_macro_t *m, gfxd_macro_t *m_list,
	int n_macro)
{
	return c_ltb(m, m_list, n_macro, gfxd_DPLoadMultiBlockYuv, 0, 1, 1, 1, 0);
}

UCFUNC int c_DPLoadMultiBlock_4bS(gfxd_macro_t *m, gfxd_macro_t *m_list,
	int n_macro)
{
	return c_ltb(m, m_list, n_macro, gfxd_DPLoadMultiBlock_4bS, 1, 1, 1, 0, 1);
}

UCFUNC int c_DPLoadMultiBlock_4b(gfxd_macro_t *m, gfxd_macro_t *m_list,
	int n_macro)
{
	return c_ltb(m, m_list, n_macro, gfxd_DPLoadMultiBlock_4b, 0, 1, 1, 0, 1);
}

UCFUNC int c_DPLoadMultiBlockS(gfxd_macro_t *m, gfxd_macro_t *m_list,
	int n_macro)
{
	return c_ltb(m, m_list, n_macro, gfxd_DPLoadMultiBlockS, 1, 1, 1, 0, 0);
}

UCFUNC int c_DPLoadMultiBlock(gfxd_macro_t *m, gfxd_macro_t *m_list,
	int n_macro)
{
	return c_ltb(m, m_list, n_macro, gfxd_DPLoadMultiBlock, 0, 1, 1, 0, 0);
}

UCFUNC int c__DPLoadTextureBlockYuvS(gfxd_macro_t *m, gfxd_macro_t *m_list,
	int n_macro)
{
	return c_ltb(m, m_list, n_macro, gfxd__DPLoadTextureBlockYuvS, 1, 1, 0, 1, 0);
}

UCFUNC int c__DPLoadTextureBlockYuv(gfxd_macro_t *m, gfxd_macro_t *m_list,
	int n_macro)
{
	return c_ltb(m, m_list, n_macro, gfxd__DPLoadTextureBlockYuv, 0, 1, 0, 1, 0);
}

UCFUNC int c__DPLoadTextureBlock_4bS(gfxd_macro_t *m, gfxd_macro_t *m_list,
	int n_macro)
{
	return c_ltb(m, m_list, n_macro, gfxd__DPLoadTextureBlock_4bS, 1, 1, 0, 0, 1);
}

UCFUNC int c__DPLoadTextureBlock_4b(gfxd_macro_t *m, gfxd_macro_t *m_list,
	int n_macro)
{
	return c_ltb(m, m_list, n_macro, gfxd__DPLoadTextureBlock_4b, 0, 1, 0, 0, 1);
}

UCFUNC int c__DPLoadTextureBlockS(gfxd_macro_t *m, gfxd_macro_t *m_list,
	int n_macro)
{
	return c_ltb(m, m_list, n_macro, gfxd__DPLoadTextureBlockS, 1, 1, 0, 0, 0);
}

UCFUNC int c__DPLoadTextureBlock(gfxd_macro_t *m, gfxd_macro_t *m_list,
	int n_macro)
{
	return c_ltb(m, m_list, n_macro, gfxd__DPLoadTextureBlock, 0, 1, 0, 0, 0);
}

UCFUNC int c_DPLoadTextureBlockYuvS(gfxd_macro_t *m, gfxd_macro_t *m_list,
	int n_macro)
{
	return c_ltb(m, m_list, n_macro, gfxd_DPLoadTextureBlockYuvS, 1, 0, 0, 1, 0);
}

UCFUNC int c_DPLoadTextureBlockYuv(gfxd_macro_t *m, gfxd_macro_t *m_list,
	int n_macro)
{
	return c_ltb(m, m_list, n_macro, gfxd_DPLoadTextureBlockYuv, 0, 0, 0, 1, 0);
}

UCFUNC int c_DPLoadTextureBlock_4bS(gfxd_macro_t *m, gfxd_macro_t *m_list,
	int n_macro)
{
	return c_ltb(m, m_list, n_macro, gfxd_DPLoadTextureBlock_4bS, 1, 0, 0, 0, 1);
}

UCFUNC int c_DPLoadTextureBlock_4b(gfxd_macro_t *m, gfxd_macro_t *m_list,
	int n_macro)
{
	return c_ltb(m, m_list, n_macro, gfxd_DPLoadTextureBlock_4b, 0, 0, 0, 0, 1);
}

UCFUNC int c_DPLoadTextureBlockS(gfxd_macro_t *m, gfxd_macro_t *m_list,
	int n_macro)
{
	return c_ltb(m, m_list, n_macro, gfxd_DPLoadTextureBlockS, 1, 0, 0, 0, 0);
}

UCFUNC int c_DPLoadTextureBlock(gfxd_macro_t *m, gfxd_macro_t *m_list,
	int n_macro)
{
	return c_ltb(m, m_list, n_macro, gfxd_DPLoadTextureBlock, 0, 0, 0, 0, 0);
}

UCFUNC int c_ltt(gfxd_macro_t *m, gfxd_macro_t *m_list, int n_macro, int id,
	int mtmem, int mrt, int myuv, int m4b)
{
	if (n_macro < 7)
		return -1;
	if (m_list[0].id != gfxd_DPSetTextureImage)
		return -1;
	g_ifmt_t fmt = argvi(&m_list[0], 0);
	g_isiz_t ldsiz = argvi(&m_list[0], 1);
	int width = argvi(&m_list[0], 2);
	if (m4b)
	{
		if (ldsiz != G_IM_SIZ_8b)
			return -1;
		width *= 2;
	}
	uint32_t timg = argvu(&m_list[0], 3);
	if (myuv && fmt != G_IM_FMT_YUV)
		return -1;
	if (m_list[1].id != gfxd_DPSetTile
		|| argvi(&m_list[1], 0) != fmt
		|| argvi(&m_list[1], 1) != ldsiz
		|| argvi(&m_list[1], 4) != G_TX_LOADTILE
		|| argvi(&m_list[1], 5) != 0)
	{
		return -1;
	}
	int ldline = argvi(&m_list[1], 2);
	uint32_t tmem = argvu(&m_list[1], 3);
	unsigned cms = argvu(&m_list[1], 9);
	unsigned cmt = argvu(&m_list[1], 6);
	int masks = argvi(&m_list[1], 10);
	int maskt = argvi(&m_list[1], 7);
	int shifts = argvi(&m_list[1], 11);
	int shiftt = argvi(&m_list[1], 8);
	if (m_list[2].id != gfxd_DPLoadSync)
		return -1;
	if (m_list[3].id != gfxd_DPLoadTile
		|| argvi(&m_list[3], 0) != G_TX_LOADTILE
		|| (argvu(&m_list[3], 1) & 1)
		|| (argvu(&m_list[3], 2) & 3)
		|| (argvu(&m_list[3], 3) & 1)
		|| (argvu(&m_list[3], 4) & 3))
	{
		return -1;
	}
	qu102_t lduls = argvu(&m_list[3], 1);
	qu102_t ldult = argvu(&m_list[3], 2);
	qu102_t ldlrs = argvu(&m_list[3], 3);
	qu102_t ldlrt = argvu(&m_list[3], 4);
	if (m_list[4].id != gfxd_DPPipeSync)
		return -1;
	if (m_list[5].id != gfxd_DPSetTile
		|| argvi(&m_list[5], 0) != fmt
		|| argvi(&m_list[5], 2) != ldline
		|| argvu(&m_list[5], 3) != tmem
		|| argvu(&m_list[5], 6) != cmt
		|| argvi(&m_list[5], 7) != maskt
		|| argvi(&m_list[5], 8) != shiftt
		|| argvu(&m_list[5], 9) != cms
		|| argvi(&m_list[5], 10) != masks
		|| argvi(&m_list[5], 11) != shifts)
	{
		return -1;
	}
	int siz = argvi(&m_list[5], 1);
	int rt = argvi(&m_list[5], 4);
	int pal = argvi(&m_list[5], 5);
	if (m4b)
	{
		if (siz != G_IM_SIZ_4b)
			return -1;
	}
	else if (siz != ldsiz)
		return -1;
	if (!(mrt && rt != G_TX_RENDERTILE && tmem == 0)
		&& (tmem != 0) != mtmem)
	{
		return -1;
	}
	if ((rt != G_TX_RENDERTILE) != mrt)
		return -1;
	if (m_list[6].id != gfxd_DPSetTileSize
		|| argvi(&m_list[6], 0) != rt
		|| (argvu(&m_list[6], 1) & 3)
		|| (argvu(&m_list[6], 2) & 3)
		|| (argvu(&m_list[6], 3) & 3)
		|| (argvu(&m_list[6], 4) & 3))
	{
		return -1;
	}
	unsigned uls = argvu(&m_list[6], 1) >> 2;
	unsigned ult = argvu(&m_list[6], 2) >> 2;
	unsigned lrs = argvu(&m_list[6], 3) >> 2;
	unsigned lrt = argvu(&m_list[6], 4) >> 2;
	int line;
	if (myuv)
		line = ((lrs - uls + 1) + 7) / 8;
	else if (m4b)
		line = ((lrs - uls + 1) / 2 + 7) / 8;
	else
		line = ((lrs - uls + 1) * G_SIZ_LDBITS(siz) + 63) / 64;
	if (m4b)
	{
		if (lduls != qu102(uls) / 2 || ldlrs != qu102(lrs) / 2)
			return -1;
	}
	else if (lduls != qu102(uls) || ldlrs != qu102(lrs))
		return -1;
	if (ldult != qu102(ult) || ldlrt != qu102(lrt) || ldline != line)
		return -1;
	m->id = id;
	int i = 0;
	argu(m, i++, "timg", timg, gfxd_Timg);
	if (mtmem)
		argu(m, i++, "tmem", tmem, gfxd_Tmem);
	if (mrt)
		argi(m, i++, "rtile", rt, gfxd_Tile);
	argi(m, i++, "fmt", fmt, gfxd_Fmt);
	if (!m4b)
		argi(m, i++, "siz", siz, gfxd_Siz);
	argi(m, i++, "width", width, gfxd_Dim);
	argi(m, i++, "height", 0, gfxd_Dim);
	argu(m, i++, "uls", uls, gfxd_Coordi);
	argu(m, i++, "ult", ult, gfxd_Coordi);
	argu(m, i++, "lrs", lrs, gfxd_Coordi);
	argu(m, i++, "lrt", lrt, gfxd_Coordi);
	argi(m, i++, "pal", pal, gfxd_Pal);
	argu(m, i++, "cms", cms, gfxd_Cm);
	argu(m, i++, "cmt", cmt, gfxd_Cm);
	argi(m, i++, "masks", masks, gfxd_Tm);
	argi(m, i++, "maskt", maskt, gfxd_Tm);
	argi(m, i++, "shifts", shifts, gfxd_Ts);
	argi(m, i++, "shiftt", shiftt, gfxd_Ts);
	return 0;
}

UCFUNC int c_DPLoadMultiTileYuv(gfxd_macro_t *m, gfxd_macro_t *m_list,
	int n_macro)
{
	return c_ltt(m, m_list, n_macro, gfxd_DPLoadMultiTileYuv, 1, 1, 1, 0);
}

UCFUNC int c_DPLoadMultiTile_4b(gfxd_macro_t *m, gfxd_macro_t *m_list,
	int n_macro)
{
	return c_ltt(m, m_list, n_macro, gfxd_DPLoadMultiTile_4b, 1, 1, 0, 1);
}

UCFUNC int c_DPLoadMultiTile(gfxd_macro_t *m, gfxd_macro_t *m_list, int n_macro)
{
	return c_ltt(m, m_list, n_macro, gfxd_DPLoadMultiTile, 1, 1, 0, 0);
}

UCFUNC int c__DPLoadTextureTileYuv(gfxd_macro_t *m, gfxd_macro_t *m_list,
	int n_macro)
{
	return c_ltt(m, m_list, n_macro, gfxd__DPLoadTextureTileYuv, 1, 0, 1, 0);
}

UCFUNC int c__DPLoadTextureTile_4b(gfxd_macro_t *m, gfxd_macro_t *m_list,
	int n_macro)
{
	return c_ltt(m, m_list, n_macro, gfxd__DPLoadTextureTile_4b, 1, 0, 0, 1);
}

UCFUNC int c__DPLoadTextureTile(gfxd_macro_t *m, gfxd_macro_t *m_list,
	int n_macro)
{
	return c_ltt(m, m_list, n_macro, gfxd__DPLoadTextureTile, 1, 0, 0, 0);
}

UCFUNC int c_DPLoadTextureTileYuv(gfxd_macro_t *m, gfxd_macro_t *m_list,
	int n_macro)
{
	return c_ltt(m, m_list, n_macro, gfxd_DPLoadTextureTileYuv, 0, 0, 1, 0);
}

UCFUNC int c_DPLoadTextureTile_4b(gfxd_macro_t *m, gfxd_macro_t *m_list,
	int n_macro)
{
	return c_ltt(m, m_list, n_macro, gfxd_DPLoadTextureTile_4b, 0, 0, 0, 1);
}

UCFUNC int c_DPLoadTextureTile(gfxd_macro_t *m, gfxd_macro_t *m_list,
	int n_macro)
{
	return c_ltt(m, m_list, n_macro, gfxd_DPLoadTextureTile, 0, 0, 0, 0);
}

UCFUNC int d_DPLoadBlock(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_DPLoadBlock;
	argi(m, 0, "tile", getfield(lo, 3, 24), gfxd_Tile);
	argu(m, 1, "uls", getfield(hi, 12, 12), gfxd_Coordi);
	argu(m, 2, "ult", getfield(hi, 12, 0), gfxd_Coordi);
	argu(m, 3, "lrs", getfield(lo, 12, 12), gfxd_Coordi);
	argu(m, 4, "dxt", getfield(lo, 12, 0), gfxd_Dxt);
	if (argvu(m, 3) > G_TX_LDBLK_MAX_TXL) {
		badarg(m, 3);
		return -1;
	}
	else {
		return 0;
	}
}

UCFUNC int d_DPNoOp(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_DPNoOp;
	return 0;
}

UCFUNC int d_DPNoOpTag(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	if (lo == 0)
		return d_DPNoOp(m, hi, lo);
	else
	{
		m->id = gfxd_DPNoOpTag;
		argu(m, 0, "tag", lo, gfxd_Tag);
		return 0;
	}
}

UCFUNC int d_DPPipelineMode(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_DPPipelineMode;
	argu(m, 0, "mode", lo, gfxd_Pm);
	return 0;
}

UCFUNC int d_DPSetBlendColor(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_DPSetBlendColor;
	argu(m, 0, "r", getfield(lo, 8, 24), gfxd_Colorpart);
	argu(m, 1, "g", getfield(lo, 8, 16), gfxd_Colorpart);
	argu(m, 2, "b", getfield(lo, 8, 8), gfxd_Colorpart);
	argu(m, 3, "a", getfield(lo, 8, 0), gfxd_Colorpart);
	return 0;
}

UCFUNC int d_DPSetEnvColor(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_DPSetEnvColor;
	argu(m, 0, "r", getfield(lo, 8, 24), gfxd_Colorpart);
	argu(m, 1, "g", getfield(lo, 8, 16), gfxd_Colorpart);
	argu(m, 2, "b", getfield(lo, 8, 8), gfxd_Colorpart);
	argu(m, 3, "a", getfield(lo, 8, 0), gfxd_Colorpart);
	return 0;
}

UCFUNC int d_DPSetFillColor(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_DPSetFillColor;
	argu(m, 0, "c", lo, gfxd_Color);
	return 0;
}

UCFUNC int d_DPSetFogColor(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_DPSetFogColor;
	argu(m, 0, "r", getfield(lo, 8, 24), gfxd_Colorpart);
	argu(m, 1, "g", getfield(lo, 8, 16), gfxd_Colorpart);
	argu(m, 2, "b", getfield(lo, 8, 8), gfxd_Colorpart);
	argu(m, 3, "a", getfield(lo, 8, 0), gfxd_Colorpart);
	return 0;
}

UCFUNC int d_DPSetPrimColor(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_DPSetPrimColor;
	argu(m, 0, "m", getfield(hi, 8, 8), gfxd_Lodfrac);
	argu(m, 1, "l", getfield(hi, 8, 0), gfxd_Lodfrac);
	argu(m, 2, "r", getfield(lo, 8, 24), gfxd_Colorpart);
	argu(m, 3, "g", getfield(lo, 8, 16), gfxd_Colorpart);
	argu(m, 4, "b", getfield(lo, 8, 8), gfxd_Colorpart);
	argu(m, 5, "a", getfield(lo, 8, 0), gfxd_Colorpart);
	return 0;
}

UCFUNC int d_DPSetColorImage(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_DPSetColorImage;
	argi(m, 0, "fmt", getfield(hi, 3, 21), gfxd_Fmt);
	argi(m, 1, "siz", getfield(hi, 2, 19), gfxd_Siz);
	argi(m, 2, "width", getfield(hi, 12, 0) + 1, gfxd_Dim);
	argu(m, 3, "cimg", lo, gfxd_Cimg);
	return 0;
}

UCFUNC int d_DPSetDepthImage(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_DPSetDepthImage;
	argu(m, 0, "zimg", lo, gfxd_Zimg);
	return 0;
}

UCFUNC int d_DPSetTextureImage(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_DPSetTextureImage;
	argi(m, 0, "fmt", getfield(hi, 3, 21), gfxd_Fmt);
	argi(m, 1, "siz", getfield(hi, 2, 19), gfxd_Siz);
	argi(m, 2, "width", getfield(hi, 12, 0) + 1, gfxd_Dim);
	argu(m, 3, "timg", lo, gfxd_Timg);
	return 0;
}

UCFUNC int d_DPSetAlphaCompare(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_DPSetAlphaCompare;
	argu(m, 0, "mode", lo, gfxd_Ac);
	return 0;
}

UCFUNC int d_DPSetAlphaDither(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_DPSetAlphaDither;
	argu(m, 0, "mode", lo, gfxd_Ad);
	return 0;
}

UCFUNC int d_DPSetColorDither(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_DPSetColorDither;
	argu(m, 0, "mode", lo, gfxd_Cd);
	return 0;
}

UCFUNC void cc_unpack(struct cc_mode *m0, struct cc_mode *m1, uint32_t hi,
			uint32_t lo)
{
	m0->a = getfield(hi, 4, 20);
	m0->b = getfield(lo, 4, 28);
	m0->c = getfield(hi, 5, 15);
	m0->d = getfield(lo, 3, 15);
	m0->Aa = getfield(hi, 3, 12);
	m0->Ab = getfield(lo, 3, 12);
	m0->Ac = getfield(hi, 3, 9);
	m0->Ad = getfield(lo, 3, 9);
	m1->a = getfield(hi, 4, 5);
	m1->b = getfield(lo, 4, 24);
	m1->c = getfield(hi, 5, 0);
	m1->d = getfield(lo, 3, 6);
	m1->Aa = getfield(lo, 3, 21);
	m1->Ab = getfield(lo, 3, 3);
	m1->Ac = getfield(lo, 3, 18);
	m1->Ad = getfield(lo, 3, 0);
}

UCFUNC int cc_lookup(const struct cc_mode *m)
{
	struct cc_mode m_norm = *m;
	if (m_norm.a > 0x7) m_norm.a = G_CCMUX_0;
	if (m_norm.b > 0x7) m_norm.b = G_CCMUX_0;
	if (m_norm.c > 0xF) m_norm.c = G_CCMUX_0;
	if (m_norm.d > 0x6) m_norm.d = G_CCMUX_0;
	m = &m_norm;
	int n_presets = sizeof(cc_presets) / sizeof(*cc_presets);
	for (int i = 0; i < n_presets; i++)
	{
		const struct cc_mode *p = &cc_presets[i].mode;
		if (m->a == p->a
			&& m->b == p->b
			&& m->c == p->c
			&& m->d == p->d
			&& m->Aa == p->Aa
			&& m->Ab == p->Ab
			&& m->Ac == p->Ac
			&& m->Ad == p->Ad)
		{
			return i;
		}
	}
	return -1;
}

UCFUNC int d_DPSetCombineMode(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_DPSetCombineMode;
	struct cc_mode m0;
	struct cc_mode m1;
	cc_unpack(&m0, &m1, hi, lo);
	int p0 = cc_lookup(&m0);
	int p1 = cc_lookup(&m1);
	argi(m, 0, "mode1", p0, gfxd_Ccpre);
	argi(m, 1, "mode2", p1, gfxd_Ccpre);
	int ret = 0;
	if (p0 == -1)
	{
		badarg(m, 0);
		ret = -1;
	}
	if (p1 == -1)
	{
		badarg(m, 1);
		ret = -1;
	}
	return ret;
}

UCFUNC int d_DPSetCombineLERP(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	struct cc_mode m0;
	struct cc_mode m1;
	cc_unpack(&m0, &m1, hi, lo);
	int p0 = cc_lookup(&m0);
	int p1 = cc_lookup(&m1);
	if (p0 != -1 && p1 != -1)
		return d_DPSetCombineMode(m, hi, lo);
	else
	{
		m->id = gfxd_DPSetCombineLERP;
		argi(m, 0, "a0", m0.a, gfxd_Ccmuxa);
		argi(m, 1, "b0", m0.b, gfxd_Ccmuxb);
		argi(m, 2, "c0", m0.c, gfxd_Ccmuxc);
		argi(m, 3, "d0", m0.d, gfxd_Ccmuxd);
		argi(m, 4, "Aa0", m0.Aa, gfxd_Acmuxabd);
		argi(m, 5, "Ab0", m0.Ab, gfxd_Acmuxabd);
		argi(m, 6, "Ac0", m0.Ac, gfxd_Acmuxc);
		argi(m, 7, "Ad0", m0.Ad, gfxd_Acmuxabd);
		argi(m, 8, "a1", m1.a, gfxd_Ccmuxa);
		argi(m, 9, "b1", m1.b, gfxd_Ccmuxb);
		argi(m, 10, "c1", m1.c, gfxd_Ccmuxc);
		argi(m, 11, "d1", m1.d, gfxd_Ccmuxd);
		argi(m, 12, "Aa1", m1.Aa, gfxd_Acmuxabd);
		argi(m, 13, "Ab1", m1.Ab, gfxd_Acmuxabd);
		argi(m, 14, "Ac1", m1.Ac, gfxd_Acmuxc);
		argi(m, 15, "Ad1", m1.Ad, gfxd_Acmuxabd);
		return 0;
	}
}

UCFUNC int d_DPSetConvert(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_DPSetConvert;
	argi(m, 0, "k0", sx(getfield(hi, 9, 13), 9), gfxd_Cv);
	argi(m, 1, "k1", sx(getfield(hi, 9, 4), 9), gfxd_Cv);
	argi(m, 2, "k2", sx((getfield(hi, 4, 0) << 5) | getfield(lo, 5, 27), 9),
		gfxd_Cv);
	argi(m, 3, "k3", sx(getfield(lo, 9, 18), 9), gfxd_Cv);
	argi(m, 4, "k4", sx(getfield(lo, 9, 9), 9), gfxd_Cv);
	argi(m, 5, "k5", sx(getfield(lo, 9, 0), 9), gfxd_Cv);
	return 0;
}

UCFUNC int d_DPSetTextureConvert(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_DPSetTextureConvert;
	argu(m, 0, "mode", lo, gfxd_Tc);
	return 0;
}

UCFUNC int d_DPSetCycleType(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_DPSetCycleType;
	argu(m, 0, "mode", lo, gfxd_Cyc);
	return 0;
}

UCFUNC int d_DPSetDepthSource(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_DPSetDepthSource;
	argu(m, 0, "mode", lo, gfxd_Zs);
	return 0;
}

UCFUNC int d_DPSetCombineKey(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_DPSetCombineKey;
	argu(m, 0, "mode", lo, gfxd_Ck);
	return 0;
}

UCFUNC int d_DPSetKeyGB(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_DPSetKeyGB;
	argu(m, 0, "cG", getfield(lo, 8, 24), gfxd_Color);
	argu(m, 1, "sG", getfield(lo, 8, 16), gfxd_Keyscale);
	argi(m, 2, "wG", sx(getfield(hi, 12, 12), 12), gfxd_Keywidth);
	argu(m, 3, "cB", getfield(lo, 8, 8), gfxd_Color);
	argu(m, 4, "sB", getfield(lo, 8, 0), gfxd_Keyscale);
	argi(m, 5, "wB", sx(getfield(hi, 12, 0), 12), gfxd_Keywidth);
	return 0;
}

UCFUNC int d_DPSetKeyR(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_DPSetKeyR;
	argu(m, 0, "cR", getfield(lo, 8, 8), gfxd_Color);
	argu(m, 1, "sR", getfield(lo, 8, 0), gfxd_Keyscale);
	argi(m, 2, "wR", sx(getfield(lo, 12, 16), 12), gfxd_Keywidth);
	return 0;
}

UCFUNC int d_DPSetPrimDepth(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_DPSetPrimDepth;
	argi(m, 0, "z", sx(getfield(lo, 16, 16), 16), gfxd_Zi);
	argi(m, 1, "dz", sx(getfield(lo, 16, 0), 16), gfxd_Zi);
	return 0;
}

UCFUNC int d_DPSetRenderMode(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_DPSetRenderMode;
	argu(m, 0, "mode1", lo, gfxd_Rm1);
	argu(m, 1, "mode2", lo, gfxd_Rm2);
	return 0;
}

UCFUNC int d_DPSetScissor(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_DPSetScissor;
	argi(m, 0, "mode", getfield(lo, 2, 24), gfxd_Sc);
	argu(m, 1, "ulx", getfield(hi, 10, 14), gfxd_Coordi);
	argu(m, 2, "uly", getfield(hi, 10, 2), gfxd_Coordi);
	argu(m, 3, "lrx", getfield(lo, 10, 14), gfxd_Coordi);
	argu(m, 4, "lry", getfield(lo, 10, 2), gfxd_Coordi);
	return 0;
}

UCFUNC int d_DPSetScissorFrac(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	qu102_t ulx = getfield(hi, 12, 12);
	qu102_t uly = getfield(hi, 12, 0);
	qu102_t lrx = getfield(lo, 12, 12);
	qu102_t lry = getfield(lo, 12, 0);
	if ((ulx & 3) || (uly & 3) || (lrx & 3) || (lry & 3))
	{
		m->id = gfxd_DPSetScissorFrac;
		argi(m, 0, "mode", getfield(lo, 2, 24), gfxd_Sc);
		argu(m, 1, "ulx", ulx, gfxd_Coordq);
		argu(m, 2, "uly", uly, gfxd_Coordq);
		argu(m, 3, "lrx", lrx, gfxd_Coordq);
		argu(m, 4, "lry", lry, gfxd_Coordq);
		return 0;
	}
	else
		return d_DPSetScissor(m, hi, lo);
}

UCFUNC int d_DPSetTextureDetail(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_DPSetTextureDetail;
	argu(m, 0, "mode", lo, gfxd_Td);
	return 0;
}

UCFUNC int d_DPSetTextureFilter(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_DPSetTextureFilter;
	argu(m, 0, "mode", lo, gfxd_Tf);
	return 0;
}

UCFUNC int d_DPSetTextureLOD(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_DPSetTextureLOD;
	argu(m, 0, "mode", lo, gfxd_Tl);
	return 0;
}

UCFUNC int d_DPSetTextureLUT(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_DPSetTextureLUT;
	argu(m, 0, "mode", lo, gfxd_Tt);
	return 0;
}

UCFUNC int d_DPSetTexturePersp(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_DPSetTexturePersp;
	argu(m, 0, "mode", lo, gfxd_Tp);
	return 0;
}

UCFUNC int d_DPSetTile(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_DPSetTile;
	argi(m, 0, "fmt", getfield(hi, 3, 21), gfxd_Fmt);
	argi(m, 1, "siz", getfield(hi, 2, 19), gfxd_Siz);
	argi(m, 2, "line", getfield(hi, 9, 9), gfxd_Line);
	argu(m, 3, "tmem", getfield(hi, 9, 0), gfxd_Tmem);
	argi(m, 4, "tile", getfield(lo, 3, 24), gfxd_Tile);
	argi(m, 5, "pal", getfield(lo, 4, 20), gfxd_Pal);
	argu(m, 6, "cmt", getfield(lo, 2, 18), gfxd_Cm);
	argi(m, 7, "maskt", getfield(lo, 4, 14), gfxd_Tm);
	argi(m, 8, "shiftt", getfield(lo, 4, 10), gfxd_Ts);
	argu(m, 9, "cms", getfield(lo, 2, 8), gfxd_Cm);
	argi(m, 10, "masks", getfield(lo, 4, 4), gfxd_Tm);
	argi(m, 11, "shifts", getfield(lo, 4, 0), gfxd_Ts);
	return 0;
}

UCFUNC int d_DPSetTileSize(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_DPSetTileSize;
	argi(m, 0, "tile", getfield(lo, 3, 24), gfxd_Tile);
	argu(m, 1, "uls", getfield(hi, 12, 12), gfxd_Coordq);
	argu(m, 2, "ult", getfield(hi, 12, 0), gfxd_Coordq);
	argu(m, 3, "lrs", getfield(lo, 12, 12), gfxd_Coordq);
	argu(m, 4, "lrt", getfield(lo, 12, 0), gfxd_Coordq);
	return 0;
}

#if defined(F3D_GBI)
UCFUNC int d_SP1Triangle(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_SP1Triangle;
	int n0 = getfield(lo, 8, 16);
	int n1 = getfield(lo, 8, 8);
	int n2 = getfield(lo, 8, 0);
	argi(m, 0, "v0", n0 / 10, gfxd_Vtx);
	argi(m, 1, "v1", n1 / 10, gfxd_Vtx);
	argi(m, 2, "v2", n2 / 10, gfxd_Vtx);
	argi(m, 3, "flag", getfield(lo, 8, 24), gfxd_Vtxflag);
	int ret = 0;
	if (n0 % 10 != 0)
	{
		badarg(m, 0);
		ret = -1;
	}
	if (n1 % 10 != 0)
	{
		badarg(m, 1);
		ret = -1;
	}
	if (n2 % 10 != 0)
	{
		badarg(m, 2);
		ret = -1;
	}
	return ret;
}
#elif defined(F3DEX_GBI)
UCFUNC int d_SP1Triangle(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_SP1Triangle;
	int n0 = getfield(lo, 8, 16);
	int n1 = getfield(lo, 8, 8);
	int n2 = getfield(lo, 8, 0);
	argi(m, 0, "v0", n0 / 2, gfxd_Vtx);
	argi(m, 1, "v1", n1 / 2, gfxd_Vtx);
	argi(m, 2, "v2", n2 / 2, gfxd_Vtx);
	argi(m, 3, "flag", 0, gfxd_Vtxflag);
	int ret = 0;
	if (n0 % 2 != 0)
	{
		badarg(m, 0);
		ret = -1;
	}
	if (n1 % 2 != 0)
	{
		badarg(m, 1);
		ret = -1;
	}
	if (n2 % 2 != 0)
	{
		badarg(m, 2);
		ret = -1;
	}
	return ret;
}
#elif defined(F3DEX_GBI_2)
UCFUNC int d_SP1Triangle(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_SP1Triangle;
	int n0 = getfield(hi, 8, 16);
	int n1 = getfield(hi, 8, 8);
	int n2 = getfield(hi, 8, 0);
	argi(m, 0, "v0", n0 / 2, gfxd_Vtx);
	argi(m, 1, "v1", n1 / 2, gfxd_Vtx);
	argi(m, 2, "v2", n2 / 2, gfxd_Vtx);
	argi(m, 3, "flag", 0, gfxd_Vtxflag);
	int ret = 0;
	if (n0 % 2 != 0)
	{
		badarg(m, 0);
		ret = -1;
	}
	if (n1 % 2 != 0)
	{
		badarg(m, 1);
		ret = -1;
	}
	if (n2 % 2 != 0)
	{
		badarg(m, 2);
		ret = -1;
	}
	return ret;
}
#endif

#if defined(F3DEX_GBI) || defined(F3DEX_GBI_2)
UCFUNC int d_SP1Quadrangle(gfxd_macro_t *m, uint32_t hi, uint32_t lo);
UCFUNC int d_SP2Triangles(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	int n00 = getfield(hi, 8, 16);
	int n01 = getfield(hi, 8, 8);
	int n02 = getfield(hi, 8, 0);
	int n10 = getfield(lo, 8, 16);
	int n11 = getfield(lo, 8, 8);
	int n12 = getfield(lo, 8, 0);
#if defined(F3DEX_GBI)
	if (n00 == n10 && n02 == n11)
		return d_SP1Quadrangle(m, hi, lo);
#endif
	m->id = gfxd_SP2Triangles;
	argi(m, 0, "v00", n00 / 2, gfxd_Vtx);
	argi(m, 1, "v01", n01 / 2, gfxd_Vtx);
	argi(m, 2, "v02", n02 / 2, gfxd_Vtx);
	argi(m, 3, "flag0", 0, gfxd_Vtxflag);
	argi(m, 4, "v10", n10 / 2, gfxd_Vtx);
	argi(m, 5, "v11", n11 / 2, gfxd_Vtx);
	argi(m, 6, "v12", n12 / 2, gfxd_Vtx);
	argi(m, 7, "flag1", 0, gfxd_Vtxflag);
	int ret = 0;
	if (n00 % 2 != 0)
	{
		badarg(m, 0);
		ret = -1;
	}
	if (n01 % 2 != 0)
	{
		badarg(m, 1);
		ret = -1;
	}
	if (n02 % 2 != 0)
	{
		badarg(m, 2);
		ret = -1;
	}
	if (n10 % 2 != 0)
	{
		badarg(m, 4);
		ret = -1;
	}
	if (n11 % 2 != 0)
	{
		badarg(m, 5);
		ret = -1;
	}
	if (n12 % 2 != 0)
	{
		badarg(m, 6);
		ret = -1;
	}
	return ret;
}

UCFUNC int d_SP1Quadrangle(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_SP1Quadrangle;
	int n00 = getfield(hi, 8, 16);
	int n01 = getfield(hi, 8, 8);
	int n02 = getfield(hi, 8, 0);
	int n10 = getfield(lo, 8, 16);
	int n11 = getfield(lo, 8, 8);
	int n12 = getfield(lo, 8, 0);
	int v00 = n00 / 2;
	int v01 = n01 / 2;
	int v02 = n02 / 2;
	int v10 = n10 / 2;
	int v11 = n11 / 2;
	int v12 = n12 / 2;
	argi(m, 0, "v0", v00, gfxd_Vtx);
	argi(m, 1, "v1", v01, gfxd_Vtx);
	argi(m, 2, "v2", v11, gfxd_Vtx);
	argi(m, 3, "v3", v12, gfxd_Vtx);
	argi(m, 4, "flag", 0, gfxd_Vtxflag);
	int ret = 0;
	if (v00 != v10 || n00 % 2 != 0 || n10 % 2 != 0)
	{
		badarg(m, 0);
		ret = -1;
	}
	if (n01 % 2 != 0)
	{
		badarg(m, 1);
		ret = -1;
	}
	if (v02 != v11 || n02 % 2 != 0 || n11 % 2 != 0)
	{
		badarg(m, 2);
		ret = -1;
	}
	if (n12 % 2 != 0)
	{
		badarg(m, 3);
		ret = -1;
	}
	return ret;
}

UCFUNC int c_SPBranchLessZraw(gfxd_macro_t *m, gfxd_macro_t *m_list,
	int n_macro)
{
	if (n_macro < 2)
		return -1;
	if (m_list[0].id != gfxd_DPHalf1)
		return -1;
	uint32_t branchdl = argvu(&m_list[0], 0);
	if (m_list[1].id != gfxd_BranchZ)
		return -1;
	int32_t vtx = argvi(&m_list[1], 0);
	int32_t zval = argvi(&m_list[1], 1);
	m->id = gfxd_SPBranchLessZraw;
	argu(m, 0, "dl", branchdl, gfxd_Dl);
	argi(m, 1, "vtx", vtx, gfxd_Vtx);
	argi(m, 2, "zval", zval, gfxd_Zraw);
	return 0;
}
#endif

UCFUNC int d_SPBranchList(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_SPBranchList;
	argu(m, 0, "dl", lo, gfxd_Dl);
	return 0;
}

UCFUNC int c_SPClipRatio(gfxd_macro_t *m, gfxd_macro_t *m_list, int n_macro)
{
	if (n_macro < 4)
		return -1;
	if (m_list[0].id != gfxd_MoveWd
		|| argvi(&m_list[0], 0) != G_MW_CLIP
		|| argvu(&m_list[0], 1) != G_MWO_CLIP_RNX)
	{
		return -1;
	}
	uint32_t r = argvu(&m_list[0], 2);
	if (m_list[1].id != gfxd_MoveWd
		|| argvi(&m_list[1], 0) != G_MW_CLIP
		|| argvu(&m_list[1], 1) != G_MWO_CLIP_RNY
		|| argvu(&m_list[1], 2) != r)
	{
		return -1;
	}
	if (m_list[2].id != gfxd_MoveWd
		|| argvi(&m_list[2], 0) != G_MW_CLIP
		|| argvu(&m_list[2], 1) != G_MWO_CLIP_RPX
		|| ((uint32_t)1 << 16) - argvu(&m_list[2], 2) != r)
	{
		return -1;
	}
	if (m_list[3].id != gfxd_MoveWd
		|| argvi(&m_list[3], 0) != G_MW_CLIP
		|| argvu(&m_list[3], 1) != G_MWO_CLIP_RPY
		|| ((uint32_t)1 << 16) - argvu(&m_list[3], 2) != r)
	{
		return -1;
	}
	m->id = gfxd_SPClipRatio;
	argi(m, 0, "r", r, gfxd_Cr);
	return 0;
}

#if defined(F3D_GBI)
UCFUNC int d_SPCullDisplayList(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_SPCullDisplayList;
	int n0 = getfield(hi, 24, 0);
	int nn = getfield(lo, 16, 0);
	argi(m, 0, "v0", n0 / 40, gfxd_Vtx);
	argi(m, 1, "vn", nn / 40 - 1, gfxd_Num);
	int ret = 0;
	if (n0 % 40 != 0)
	{
		badarg(m, 0);
		ret = -1;
	}
	if (nn % 40 != 0)
	{
		badarg(m, 1);
		ret = -1;
	}
	return ret;
}
#elif defined(F3DEX_GBI) || defined(F3DEX_GBI_2)
UCFUNC int d_SPCullDisplayList(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_SPCullDisplayList;
	int n0 = getfield(hi, 16, 0);
	int nn = getfield(lo, 16, 0);
	argi(m, 0, "v0", n0 / 2, gfxd_Vtx);
	argi(m, 1, "vn", nn / 2, gfxd_Num);
	int ret = 0;
	if (n0 % 2 != 0)
	{
		badarg(m, 0);
		ret = -1;
	}
	if (nn % 2 != 0)
	{
		badarg(m, 1);
		ret = -1;
	}
	return ret;
}
#endif

UCFUNC int d_SPDisplayList(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_SPDisplayList;
	argu(m, 0, "dl", lo, gfxd_Dl);
	return 0;
}

UCFUNC int d_SPEndDisplayList(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_SPEndDisplayList;
	return 0;
}

UCFUNC int d_SPFogFactor(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_SPFogFactor;
	argi(m, 0, "fm", sx(getfield(lo, 16, 16), 16), gfxd_Fogz);
	argi(m, 1, "fo", sx(getfield(lo, 16, 0), 16), gfxd_Fogz);
	return 0;
}

UCFUNC int d_SPFogPosition(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	int x = sx(getfield(lo, 16, 16), 16);
	int y = sx(getfield(lo, 16, 0), 16);
	if (x == 0)
		return d_SPFogFactor(m, hi, lo);
	else
	{
		int d = 128000 / x;
		int yd = y * d;
		if (yd > 0)
			yd += 255;
		else if (yd < 0)
			yd -= 255;
		int min = 500 - yd / 256;
		int max = d + min;

		if (min >= 0 && min <= 1000 && max >= 0 && max <= 1000)
		{
			m->id = gfxd_SPFogPosition;
			argi(m, 0, "min", min, gfxd_Fogp);
			argi(m, 1, "max", max, gfxd_Fogp);
			return 0;
		}
		else
			return d_SPFogFactor(m, hi, lo);
	}
}

#if defined(F3D_GBI) || defined(F3DEX_GBI)
UCFUNC int c_SPForceMatrix(gfxd_macro_t *m, gfxd_macro_t *m_list, int n_macro)
{
	if (n_macro < 4)
		return -1;
	for (int i = 0; i < 4; i++)
		if (m_list[i].id != gfxd_MoveMem
			|| argvu(&m_list[i], 0) != 16
			|| argvu(&m_list[i], 2) != argvu(&m_list[0], 2) + i * 16)
		{
			return -1;
		}
	if (argvi(&m_list[0], 1) != G_MV_MATRIX_1
		|| argvi(&m_list[1], 1) != G_MV_MATRIX_2
		|| argvi(&m_list[2], 1) != G_MV_MATRIX_3
		|| argvi(&m_list[3], 1) != G_MV_MATRIX_4)
	{
		return -1;
	}
	uint32_t mptr = argvu(&m_list[0], 2);
	m->id = gfxd_SPForceMatrix;
	argu(m, 0, "mptr", mptr, gfxd_Mtxptr);
	return 0;
}
#elif defined(F3DEX_GBI_2)
UCFUNC int c_SPForceMatrix(gfxd_macro_t *m, gfxd_macro_t *m_list, int n_macro)
{
	if (n_macro < 2)
		return -1;
	if (m_list[0].id != gfxd_MoveMem
		|| argvu(&m_list[0], 0) != sizeof(Mtx)
		|| argvi(&m_list[0], 1) != G_MV_MATRIX
		|| argvu(&m_list[0], 2) != 0)
	{
		return -1;
	}
	uint32_t mptr = argvu(&m_list[0], 3);
	if (m_list[1].id != gfxd_MoveWd
		|| argvi(&m_list[1], 0) != G_MW_FORCEMTX
		|| argvu(&m_list[1], 1) != 0
		|| argvu(&m_list[1], 2) != 0x10000)
	{
		return -1;
	}
	m->id = gfxd_SPForceMatrix;
	argu(m, 0, "mptr", mptr, gfxd_Mtxptr);
	return 0;
}
#endif

UCFUNC int d_SPSetGeometryMode(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_SPSetGeometryMode;
	argu(m, 0, "mode", lo, gfxd_Gm);
	return 0;
}

UCFUNC int d_SPClearGeometryMode(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_SPClearGeometryMode;
#if defined(F3D_GBI) || defined(F3DEX_GBI)
	argu(m, 0, "mode", lo, gfxd_Gm);
#elif defined(F3DEX_GBI_2)
	argu(m, 0, "mode", getfield(~hi, 24, 0), gfxd_Gm);
#endif
	return 0;
}

#if defined(F3D_GBI) || defined(F3DEX_GBI)
UCFUNC int c_SPLoadGeometryMode(gfxd_macro_t *m, gfxd_macro_t *m_list,
	int n_macro)
{
	if (n_macro < 2)
		return -1;
	if (m_list[0].id != gfxd_SPClearGeometryMode
		|| argvu(&m_list[0], 0) != 0xFFFFFFFF
		|| m_list[1].id != gfxd_SPSetGeometryMode)
	{
		return -1;
	}
	uint32_t mode = argvu(&m_list[1], 0);
	m->id = gfxd_SPLoadGeometryMode;
	argu(m, 0, "mode", mode, gfxd_Gm);
	return 0;
}
#elif defined(F3DEX_GBI_2)
UCFUNC int d_SPLoadGeometryMode(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_SPLoadGeometryMode;
	argu(m, 0, "mode", lo, gfxd_Gm);
	return 0;
}
#endif

#if defined(F3D_GBI) || defined(F3DEX_GBI)
UCFUNC int d_SPInsertMatrix(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_SPInsertMatrix;
	argu(m, 0, "where", getfield(hi, 16, 8), gfxd_Mwo_matrix);
	argu(m, 1, "val", lo, gfxd_Word);
	return 0;
}
#endif

#if defined(F3D_GBI)
UCFUNC int d_SPLine3D(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_SPLine3D;
	int n0 = getfield(lo, 8, 16);
	int n1 = getfield(lo, 8, 8);
	argi(m, 0, "v0", n0 / 10, gfxd_Vtx);
	argi(m, 1, "v1", n1 / 10, gfxd_Vtx);
	argi(m, 2, "flag", getfield(lo, 8, 24), gfxd_Vtxflag);
	int ret = 0;
	if (n0 % 10 != 0)
	{
		badarg(m, 0);
		ret = -1;
	}
	if (n1 % 10 != 0)
	{
		badarg(m, 1);
		ret = -1;
	}
	return ret;
}
#elif defined(F3DEX_GBI)
UCFUNC int d_SPLine3D(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_SPLine3D;
	int n0 = getfield(lo, 8, 16);
	int n1 = getfield(lo, 8, 8);
	argi(m, 0, "v0", n0 / 2, gfxd_Vtx);
	argi(m, 1, "v1", n1 / 2, gfxd_Vtx);
	argi(m, 2, "flag", 0, gfxd_Vtxflag);
	int ret = 0;
	if (n0 % 2 != 0)
	{
		badarg(m, 0);
		ret = -1;
	}
	if (n1 % 2 != 0)
	{
		badarg(m, 1);
		ret = -1;
	}
	return ret;
}
#elif defined(F3DEX_GBI_2)
UCFUNC int d_SPLine3D(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_SPLine3D;
	int n0 = getfield(hi, 8, 16);
	int n1 = getfield(hi, 8, 8);
	argi(m, 0, "v0", n0 / 2, gfxd_Vtx);
	argi(m, 1, "v1", n1 / 2, gfxd_Vtx);
	argi(m, 2, "flag", 0, gfxd_Vtxflag);
	int ret = 0;
	if (n0 % 2 != 0)
	{
		badarg(m, 0);
		ret = -1;
	}
	if (n1 % 2 != 0)
	{
		badarg(m, 1);
		ret = -1;
	}
	return ret;
}
#endif

#if defined(F3D_GBI)
UCFUNC int d_SPLineW3D(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	int wd = getfield(lo, 8, 0);
	if (wd == 0)
		return d_SPLine3D(m, hi, lo);
	else
	{
		m->id = gfxd_SPLineW3D;
		int n0 = getfield(lo, 8, 16);
		int n1 = getfield(lo, 8, 8);
		argi(m, 0, "v0", n0 / 10, gfxd_Vtx);
		argi(m, 1, "v1", n1 / 10, gfxd_Vtx);
		argi(m, 2, "wd", wd, gfxd_Linewd);
		argi(m, 3, "flag", getfield(lo, 8, 24), gfxd_Vtxflag);
		int ret = 0;
		if (n0 % 10 != 0)
		{
			badarg(m, 0);
			ret = -1;
		}
		if (n1 % 10 != 0)
		{
			badarg(m, 1);
			ret = -1;
		}
		return ret;
	}
}
#elif defined(F3DEX_GBI) || defined(F3DEX_GBI_2)
UCFUNC int d_SPLineW3D(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	int wd = getfield(hi, 8, 0);
	if (wd == 0)
		return d_SPLine3D(m, hi, lo);
	else
	{
		m->id = gfxd_SPLineW3D;
		int n0 = getfield(hi, 8, 16);
		int n1 = getfield(hi, 8, 8);
		argi(m, 0, "v0", n0 / 2, gfxd_Vtx);
		argi(m, 1, "v1", n1 / 2, gfxd_Vtx);
		argi(m, 2, "wd", wd, gfxd_Linewd);
		argi(m, 3, "flag", 0, gfxd_Vtxflag);
		int ret = 0;
		if (n0 % 2 != 0)
		{
			badarg(m, 0);
			ret = -1;
		}
		if (n1 % 2 != 0)
		{
			badarg(m, 1);
			ret = -1;
		}
		return ret;
	}
}
#endif

#if defined(F3DEX_GBI) || defined(F3DEX_GBI_2)
UCFUNC int c_SPLoadUcode(gfxd_macro_t *m, gfxd_macro_t *m_list, int n_macro)
{
	if (n_macro < 2)
		return -1;
	if (m_list[0].id != gfxd_DPHalf1)
		return -1;
	uint32_t uc_dstart = argvu(&m_list[0], 0);
	if (m_list[1].id != gfxd_LoadUcode)
		return -1;
	uint32_t uc_start = argvu(&m_list[1], 0);
	uint32_t uc_dsize = argvu(&m_list[1], 1);
	if (uc_dsize != 0x800)
		return -1;
	m->id = gfxd_SPLoadUcode;
	argu(m, 0, "uc_start", uc_start, gfxd_Uctext);
	argu(m, 1, "uc_dstart", uc_dstart, gfxd_Ucdata);
	return 0;
}
#endif

UCFUNC int d_SPLookAtX(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_SPLookAtX;
	argu(m, 0, "l", lo, gfxd_Lookatptr);
	return 0;
}

UCFUNC int d_SPLookAtY(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_SPLookAtY;
	argu(m, 0, "l", lo, gfxd_Lookatptr);
	return 0;
}

UCFUNC int c_SPLookAt(gfxd_macro_t *m, gfxd_macro_t *m_list, int n_macro)
{
	if (n_macro < 2)
		return -1;
	if (m_list[0].id != gfxd_SPLookAtX)
		return -1;
	uint32_t l = argvu(&m_list[0], 0);
	if (m_list[1].id != gfxd_SPLookAtY || argvu(&m_list[1], 0) != l + 0x10)
		return -1;
	m->id = gfxd_SPLookAt;
	argu(m, 0, "l", l, gfxd_Lookatptr);
	return 0;
}

#if defined(F3D_GBI) || defined(F3DEX_GBI)
UCFUNC int d_SPMatrix(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_SPMatrix;
	int x = getfield(hi, 16, 0);
	argu(m, 0, "matrix", lo, gfxd_Mtxptr);
	argi(m, 1, "param", getfield(hi, 8, 16), gfxd_Mtxparam);
	if (x != sizeof(Mtx))
		return -1;
	else
		return 0;
}
#elif defined(F3DEX_GBI_2)
UCFUNC int d_SPMatrix(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_SPMatrix;
	int x = getfield(hi, 5, 19);
	argu(m, 0, "matrix", lo, gfxd_Mtxptr);
	argi(m, 1, "param", getfield(hi, 8, 0) ^ G_MTX_PUSH, gfxd_Mtxparam);
	if (x != (sizeof(Mtx) - 1) / 8)
		return -1;
	else
		return 0;
}
#endif

#if defined(F3D_GBI) || (defined(F3D_BETA) && defined(F3DEX_GBI))
UCFUNC int d_SPModifyVertex(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_SPModifyVertex;
	int offset = getfield(hi, 16, 8);
	argi(m, 0, "vtx", offset / 40, gfxd_Vtx);
	argu(m, 1, "where", offset % 40, gfxd_Mwo_point);
	argu(m, 2, "val", lo, gfxd_Word);
	return 0;
}
#elif defined(F3DEX_GBI) || defined(F3DEX_GBI_2)
UCFUNC int d_SPModifyVertex(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_SPModifyVertex;
	int vtx = getfield(hi, 16, 0);
	argi(m, 0, "vtx", vtx / 2, gfxd_Vtx);
	argu(m, 1, "where", getfield(hi, 8, 16), gfxd_Mwo_point);
	argu(m, 2, "val", lo, gfxd_Word);
	int ret = 0;
	if (vtx % 2 != 0)
	{
		badarg(m, 0);
		ret = -1;
	}
	return ret;
}
#endif

UCFUNC int d_SPPerspNormalize(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_SPPerspNormalize;
	argu(m, 0, "scale", getfield(lo, 16, 0), gfxd_Wscale);
	return 0;
}

UCFUNC int d_SPPopMatrix(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_SPPopMatrix;
#if defined(F3D_GBI) || defined(F3DEX_GBI)
	argi(m, 0, "param", lo, gfxd_Mtxstack);
#elif defined(F3DEX_GBI_2)
	argi(m, 0, "param", G_MTX_MODELVIEW, gfxd_Mtxstack);
#endif
	return 0;
}

#if defined(F3DEX_GBI_2)
UCFUNC int d_SPPopMatrixN(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	int len = (getfield(hi, 5, 19) + 1) * 8;
	int ofs = getfield(hi, 8, 8) * 8;
	int idx = getfield(hi, 8, 0);
	int n = lo / sizeof(Mtx);
	if (lo % sizeof(Mtx) == 0
		&& len == sizeof(Mtx)
		&& ofs == 0
		&& idx == 2
		&& n == 1)
	{
		return d_SPPopMatrix(m, hi, lo);
	}
	m->id = gfxd_SPPopMatrixN;
	argi(m, 0, "param", G_MTX_MODELVIEW, gfxd_Mtxstack);
	argi(m, 1, "num", n, gfxd_Num);
	int ret = 0;
	if (lo % sizeof(Mtx) != 0)
	{
		badarg(m, 1);
		ret = -1;
	}
	if (len != sizeof(Mtx) || ofs != 0 || idx != 2)
		ret = -1;
	return ret;
}
#endif

UCFUNC int d_SPSegment(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_SPSegment;
#if defined(F3D_GBI) || defined(F3DEX_GBI)
	int offset = getfield(hi, 16, 8);
#elif defined(F3DEX_GBI_2)
	int offset = getfield(hi, 16, 0);
#endif
	argu(m, 0, "seg", offset / 4, gfxd_Seg);
	argu(m, 1, "base", lo, gfxd_Segptr);
	int ret = 0;
	if (offset % 4 != 0)
	{
		badarg(m, 0);
		ret = -1;
	}
	return ret;
}

UCFUNC int c_SPSetLightsN(gfxd_macro_t *m, gfxd_macro_t *m_list, int n_macro,
	int id, int numlights)
{
	if (n_macro < 2 + numlights)
		return -1;
	if (m_list[0].id != gfxd_SPNumLights || argvi(&m_list[0], 0) != numlights)
		return -1;
	int a = 1 + numlights;
	if (m_list[a].id != gfxd_SPLight || argvi(&m_list[a], 1) != a)
		return -1;
	uint32_t l = argvu(&m_list[a], 0);
	for (int i = 1; i <= numlights; i++)
	{
		int offset = sizeof(Ambient) + sizeof(Light) * (i - 1);
		if (m_list[i].id != gfxd_SPLight
			|| argvu(&m_list[i], 0) != l + offset
			|| argvi(&m_list[i], 1) != i)
		{
			return -1;
		}
	}
	m->id = id;
	argu(m, 0, "l", l, gfxd_Lightsn);
	return 0;
}

UCFUNC int c_SPSetLights1(gfxd_macro_t *m, gfxd_macro_t *m_list, int n_macro)
{
	return c_SPSetLightsN(m, m_list, n_macro, gfxd_SPSetLights1, NUMLIGHTS_1);
}

UCFUNC int c_SPSetLights2(gfxd_macro_t *m, gfxd_macro_t *m_list, int n_macro)
{
	return c_SPSetLightsN(m, m_list, n_macro, gfxd_SPSetLights2, NUMLIGHTS_2);
}

UCFUNC int c_SPSetLights3(gfxd_macro_t *m, gfxd_macro_t *m_list, int n_macro)
{
	return c_SPSetLightsN(m, m_list, n_macro, gfxd_SPSetLights3, NUMLIGHTS_3);
}

UCFUNC int c_SPSetLights4(gfxd_macro_t *m, gfxd_macro_t *m_list, int n_macro)
{
	return c_SPSetLightsN(m, m_list, n_macro, gfxd_SPSetLights4, NUMLIGHTS_4);
}

UCFUNC int c_SPSetLights5(gfxd_macro_t *m, gfxd_macro_t *m_list, int n_macro)
{
	return c_SPSetLightsN(m, m_list, n_macro, gfxd_SPSetLights5, NUMLIGHTS_5);
}

UCFUNC int c_SPSetLights6(gfxd_macro_t *m, gfxd_macro_t *m_list, int n_macro)
{
	return c_SPSetLightsN(m, m_list, n_macro, gfxd_SPSetLights6, NUMLIGHTS_6);
}

UCFUNC int c_SPSetLights7(gfxd_macro_t *m, gfxd_macro_t *m_list, int n_macro)
{
	return c_SPSetLightsN(m, m_list, n_macro, gfxd_SPSetLights7, NUMLIGHTS_7);
}

#if defined(F3D_GBI) || defined(F3DEX_GBI)
UCFUNC int d_SPNumLights(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_SPNumLights;
	argi(m, 0, "n", (lo - 0x80000000) / 32 - 1, gfxd_Numlights);
	int ret = 0;
	if (lo < 0x80000040 || lo % 32 != 0)
	{
		badarg(m, 0);
		ret = -1;
	}
	return ret;
}
#elif defined(F3DEX_GBI_2)
UCFUNC int d_SPNumLights(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_SPNumLights;
	argi(m, 0, "n", lo / 24, gfxd_Numlights);
	int ret = 0;
	if (lo < 24 || lo % 24 != 0)
	{
		badarg(m, 0);
		ret = -1;
	}
	return ret;
}
#endif

#if defined(F3D_GBI) || defined(F3DEX_GBI)
UCFUNC int d_SPLight(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	int n = (getfield(hi, 8, 16) - G_MV_L0) / 2 + 1;
	m->id = gfxd_SPLight;
	argu(m, 0, "l", lo, gfxd_Lightptr);
	argi(m, 1, "n", n, gfxd_Num);
	return 0;
}
#elif defined(F3DEX_GBI_2)
UCFUNC int d_SPLight(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	int n = (getfield(hi, 8, 8) * 8 / 24) - 1;
	m->id = gfxd_SPLight;
	argu(m, 0, "l", lo, gfxd_Lightptr);
	argi(m, 1, "n", n, gfxd_Num);
	return 0;
}
#endif

UCFUNC int c_SPLightColor(gfxd_macro_t *m, gfxd_macro_t *m_list, int n_macro)
{
	if (n_macro < 2)
		return -1;
	if (m_list[0].id != gfxd_MoveWd
		|| argvi(&m_list[0], 0) != G_MW_LIGHTCOL
		|| argvu(&m_list[0], 1) % 0x18 != 0
		|| argvu(&m_list[0], 1) > G_MWO_aLIGHT_8)
	{
		return -1;
	}
	uint32_t offset = argvu(&m_list[0], 1);
	uint32_t packedcolor = argvu(&m_list[0], 2);
	if (m_list[1].id != gfxd_MoveWd
		|| argvi(&m_list[1], 0) != G_MW_LIGHTCOL
		|| argvu(&m_list[1], 1) != offset + 4
		|| argvu(&m_list[1], 2) != packedcolor)
	{
		return -1;
	}
	m->id = gfxd_SPLightColor;
	argi(m, 0, "n", offset / 0x18 + 1, gfxd_Lightnum);
	argu(m, 1, "c", packedcolor, gfxd_Color);
	return 0;
}

UCFUNC int d_SPTexture(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_SPTexture;
	argu(m, 0, "sc", getfield(lo, 16, 16), gfxd_Tcscale);
	argu(m, 1, "tc", getfield(lo, 16, 0), gfxd_Tcscale);
	argi(m, 2, "level", getfield(hi, 3, 11), gfxd_Num);
	argi(m, 3, "tile", getfield(hi, 3, 8), gfxd_Tile);
#if defined(F3D_GBI) || defined(F3DEX_GBI)
	argi(m, 4, "on", getfield(hi, 8, 0), gfxd_Switch);
#elif defined(F3DEX_GBI_2)
	argi(m, 4, "on", getfield(hi, 7, 1), gfxd_Switch);
#endif
	return 0;
}

UCFUNC int c_SPTextureRectangle(gfxd_macro_t *m, gfxd_macro_t *m_list,
	int n_macro)
{
	if (n_macro < 3)
		return -1;
	if (m_list[0].id != gfxd_TexRect)
		return -1;
	qu102_t ulx = argvu(&m_list[0], 0);
	qu102_t uly = argvu(&m_list[0], 1);
	qu102_t lrx = argvu(&m_list[0], 2);
	qu102_t lry = argvu(&m_list[0], 3);
	int tile = argvi(&m_list[0], 4);
	if (m_list[1].id != gfxd_DPHalf1)
		return -1;
	qs105_t s = sx(getfield(argvu(&m_list[1], 0), 16, 16), 16);
	qs105_t t = sx(getfield(argvu(&m_list[1], 0), 16, 0), 16);
	if (m_list[2].id != gfxd_DPHalf2)
		return -1;
	qs510_t dsdx = sx(getfield(argvu(&m_list[2], 0), 16, 16), 16);
	qs510_t dtdy = sx(getfield(argvu(&m_list[2], 0), 16, 0), 16);
	m->id = gfxd_SPTextureRectangle;
	argu(m, 0, "ulx", ulx, gfxd_Coordq);
	argu(m, 1, "uly", uly, gfxd_Coordq);
	argu(m, 2, "lrx", lrx, gfxd_Coordq);
	argu(m, 3, "lry", lry, gfxd_Coordq);
	argi(m, 4, "tile", tile, gfxd_Tile);
	argi(m, 5, "s", s, gfxd_St);
	argi(m, 6, "t", t, gfxd_St);
	argi(m, 7, "dsdx", dsdx, gfxd_Stdelta);
	argi(m, 8, "dtdy", dtdy, gfxd_Stdelta);
	return 0;
}

UCFUNC int c_SPTextureRectangleFlip(gfxd_macro_t *m, gfxd_macro_t *m_list,
	int n_macro)
{
	if (n_macro < 3)
		return -1;
	if (m_list[0].id != gfxd_TexRectFlip)
		return -1;
	qu102_t ulx = argvu(&m_list[0], 0);
	qu102_t uly = argvu(&m_list[0], 1);
	qu102_t lrx = argvu(&m_list[0], 2);
	qu102_t lry = argvu(&m_list[0], 3);
	int tile = argvi(&m_list[0], 4);
	if (m_list[1].id != gfxd_DPHalf1)
		return -1;
	qs105_t s = sx(getfield(argvu(&m_list[1], 0), 16, 16), 16);
	qs105_t t = sx(getfield(argvu(&m_list[1], 0), 16, 0), 16);
	if (m_list[2].id != gfxd_DPHalf2)
		return -1;
	qs510_t dsdx = sx(getfield(argvu(&m_list[2], 0), 16, 16), 16);
	qs510_t dtdy = sx(getfield(argvu(&m_list[2], 0), 16, 0), 16);
	m->id = gfxd_SPTextureRectangleFlip;
	argu(m, 0, "ulx", ulx, gfxd_Coordq);
	argu(m, 1, "uly", uly, gfxd_Coordq);
	argu(m, 2, "lrx", lrx, gfxd_Coordq);
	argu(m, 3, "lry", lry, gfxd_Coordq);
	argi(m, 4, "tile", tile, gfxd_Tile);
	argi(m, 5, "s", s, gfxd_St);
	argi(m, 6, "t", t, gfxd_St);
	argi(m, 7, "dsdx", dsdx, gfxd_Stdelta);
	argi(m, 8, "dtdy", dtdy, gfxd_Stdelta);
	return 0;
}

#if defined(F3D_GBI)
UCFUNC int d_SPVertex(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_SPVertex;
	int n = getfield(hi, 4, 20) + 1;
	int v0 = getfield(hi, 4, 16);
	int size = getfield(hi, 16, 0);
	argu(m, 0, "v", lo, gfxd_Vtxptr);
	argi(m, 1, "n", n, gfxd_Num);
	argi(m, 2, "v0", v0, gfxd_Vtx);
	int ret = 0;
	if (size != sizeof(Vtx) * n)
	{
		badarg(m, 1);
		ret = -1;
	}
	return ret;
}
#elif defined(F3DEX_GBI)
UCFUNC int d_SPVertex(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_SPVertex;
	int n = getfield(hi, 6, 10);
	int v0 = getfield(hi, 8, 16);
	int size = getfield(hi, 10, 0);
	argu(m, 0, "v", lo, gfxd_Vtxptr);
	argi(m, 1, "n", n, gfxd_Num);
	argi(m, 2, "v0", v0 / 2, gfxd_Vtx);
	int ret = 0;
	if (size != sizeof(Vtx) * n - 1)
	{
		badarg(m, 1);
		ret = -1;
	}
	if (v0 % 2 != 0)
	{
		badarg(m, 2);
		ret = -1;
	}
	return ret;
}
#elif defined(F3DEX_GBI_2)
UCFUNC int d_SPVertex(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_SPVertex;
	int n = getfield(hi, 8, 12);
	int v0 = getfield(hi, 7, 1) - n;
	argu(m, 0, "v", lo, gfxd_Vtxptr);
	argi(m, 1, "n", n, gfxd_Num);
	argi(m, 2, "v0", v0, gfxd_Vtx);
	return 0;
}
#endif

UCFUNC int d_SPViewport(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_SPViewport;
	argu(m, 0, "v", lo, gfxd_Vpptr);
	return 0;
}

UCFUNC int d_DPLoadTLUTCmd(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_DPLoadTLUTCmd;
	argi(m, 0, "tile", getfield(lo, 3, 24), gfxd_Tile);
	argi(m, 1, "count", getfield(lo, 10, 14), gfxd_Num);
	return 0;
}

UCFUNC int c_DPLoadTLUT(gfxd_macro_t *m, gfxd_macro_t *m_list, int n_macro)
{
	if (n_macro < 6)
		return -1;
	if (m_list[0].id != gfxd_DPSetTextureImage
		|| argvi(&m_list[0], 0) != G_IM_FMT_RGBA
		|| argvi(&m_list[0], 1) != G_IM_SIZ_16b
		|| argvi(&m_list[0], 2) != 1)
	{
		return -1;
	}
	uint32_t dram = argvu(&m_list[0], 3);
	if (m_list[1].id != gfxd_DPTileSync)
		return -1;
	if (m_list[2].id != gfxd_DPSetTile
		|| argvi(&m_list[2], 0) != 0
		|| argvi(&m_list[2], 1) != 0
		|| argvi(&m_list[2], 2) != 0
		|| argvi(&m_list[2], 4) != G_TX_LOADTILE
		|| argvi(&m_list[2], 5) != 0
		|| argvu(&m_list[2], 6) != 0
		|| argvi(&m_list[2], 7) != 0
		|| argvi(&m_list[2], 8) != 0
		|| argvu(&m_list[2], 9) != 0
		|| argvi(&m_list[2], 10) != 0
		|| argvi(&m_list[2], 11) != 0)
	{
		return -1;
	}
	uint32_t tmem = argvu(&m_list[2], 3);
	if (m_list[3].id != gfxd_DPLoadSync)
		return -1;
	if (m_list[4].id != gfxd_DPLoadTLUTCmd ||
		argvi(&m_list[4], 0) != G_TX_LOADTILE)
		return -1;
	int count = argvi(&m_list[4], 1) + 1;
	if (m_list[5].id != gfxd_DPPipeSync)
		return -1;
	m->id = gfxd_DPLoadTLUT;
	argi(m, 0, "count", count, gfxd_Num);
	argu(m, 1, "tmem", tmem, gfxd_Tmem);
	argu(m, 2, "dram", dram, gfxd_Tlut);
	return 0;
}

#if defined(F3DEX_GBI) || defined(F3DEX_GBI_2)
UCFUNC int d_BranchZ(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_BranchZ;
	int na = getfield(hi, 12, 12);
	int nb = getfield(hi, 12, 0);
	int32_t zval;
	if (lo > 0x7FFFFFFF)
		zval = INT32_MIN + (int32_t)(lo & 0x7FFFFFFF);
	else
		zval = lo;
	argi(m, 0, "vtx", nb / 2, gfxd_Vtx);
	argi(m, 1, "zval", zval, gfxd_Zraw);
	int ret = 0;
	if (nb % 2 != 0 || na / 5 != nb / 2 || na % 5 != 0)
	{
		badarg(m, 0);
		ret = -1;
	}
	return ret;
}
#endif

UCFUNC int d_DisplayList(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	int flag = getfield(hi, 8, 16);
	if (flag == 0)
		return d_SPDisplayList(m, hi, lo);
	else if (flag == 1)
		return d_SPBranchList(m, hi, lo);
	else
	{
		m->id = gfxd_DisplayList;
		argu(m, 0, "dl", lo, gfxd_Dl);
		argi(m, 1, "flag", flag, gfxd_Dlflag);
		return 0;
	}
}

UCFUNC int d_DPHalf1(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_DPHalf1;
	argu(m, 0, "hi", lo, gfxd_Word);
	return 0;
}

UCFUNC int d_DPHalf2(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_DPHalf2;
	argu(m, 0, "lo", lo, gfxd_Word);
	return 0;
}

UCFUNC int c_DPWord(gfxd_macro_t *m, gfxd_macro_t *m_list, int n_macro)
{
	if (n_macro < 2)
		return -1;
	if (m_list[0].id != gfxd_DPHalf1 || m_list[1].id != gfxd_DPHalf2)
		return -1;
	uint32_t wordhi = argvu(&m_list[0], 0);
	uint32_t wordlo = argvu(&m_list[1], 0);
	m->id = gfxd_DPWord;
	argu(m, 0, "wordhi", wordhi, gfxd_Word);
	argu(m, 1, "wordlo", wordlo, gfxd_Word);
	return 0;
}

UCFUNC int d_DPLoadTile(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_DPLoadTile;
	argi(m, 0, "tile", getfield(lo, 3, 24), gfxd_Tile);
	argu(m, 1, "uls", getfield(hi, 12, 12), gfxd_Coordq);
	argu(m, 2, "ult", getfield(hi, 12, 0), gfxd_Coordq);
	argu(m, 3, "lrs", getfield(lo, 12, 12), gfxd_Coordq);
	argu(m, 4, "lrt", getfield(lo, 12, 0), gfxd_Coordq);
	return 0;
}

#if defined(F3DEX_GBI_2)
UCFUNC int d_SPGeometryMode(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	uint32_t clearbits = getfield(~hi, 24, 0);
	uint32_t setbits = lo;
	if (clearbits == 0 && setbits != 0)
		return d_SPSetGeometryMode(m, hi, lo);
	else if (clearbits != 0 && setbits == 0)
		return d_SPClearGeometryMode(m, hi, lo);
	else if (clearbits == 0x00FFFFFF)
		return d_SPLoadGeometryMode(m, hi, lo);
	else
	{
		m->id = gfxd_SPGeometryMode;
		argu(m, 0, "c", clearbits, gfxd_Gm);
		argu(m, 1, "s", setbits, gfxd_Gm);
		return 0;
	}
}
#endif

UCFUNC int d_SPSetOtherMode(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_SPSetOtherMode;
	int opc = getfield(hi, 8, 24);
#if defined(F3D_GBI) || defined(F3DEX_GBI)
	int length = getfield(hi, 8, 0);
	int shift = getfield(hi, 8, 8);
#elif defined(F3DEX_GBI_2)
	int length = getfield(hi, 8, 0) + 1;
	int shift = 32 - (getfield(hi, 8, 8) + length);
#endif
	argi(m, 0, "opc", opc, gfxd_Opcode);
	argi(m, 1, "sft", shift, gfxd_Sftlo);
	argi(m, 2, "len", length, gfxd_Num);
	if (opc == G_SETOTHERMODE_H)
		argu(m, 3, "mode", lo, gfxd_Othermodehi);
	else if (opc == G_SETOTHERMODE_L)
		argu(m, 3, "mode", lo, gfxd_Othermodelo);
	else
		argu(m, 3, "mode", lo, gfxd_Word);
	return 0;
}

UCFUNC int d_SPSetOtherModeLo(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
#if defined(F3D_GBI) || defined(F3DEX_GBI)
	int length = getfield(hi, 8, 0);
	int shift = getfield(hi, 8, 8);
#elif defined(F3DEX_GBI_2)
	int length = getfield(hi, 8, 0) + 1;
	int shift = 32 - (getfield(hi, 8, 8) + length);
#endif
	if (shift == G_MDSFT_ALPHACOMPARE && length == G_MDSIZ_ALPHACOMPARE)
		return d_DPSetAlphaCompare(m, hi, lo);
	else if (shift == G_MDSFT_ZSRCSEL && length == G_MDSIZ_ZSRCSEL)
		return d_DPSetDepthSource(m, hi, lo);
	else if (shift == G_MDSFT_RENDERMODE && length == G_MDSIZ_RENDERMODE)
		return d_DPSetRenderMode(m, hi, lo);
	else if (config.emit_ext_macro)
	{
		m->id = gfxd_SPSetOtherModeLo;
		argi(m, 0, "sft", shift, gfxd_Sftlo);
		argi(m, 1, "len", length, gfxd_Num);
		argu(m, 2, "mode", lo, gfxd_Othermodelo);
		return 0;
	}
	else
		return d_SPSetOtherMode(m, hi, lo);
}

UCFUNC int d_SPSetOtherModeHi(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
#if defined(F3D_GBI) || defined(F3DEX_GBI)
	int length = getfield(hi, 8, 0);
	int shift = getfield(hi, 8, 8);
#elif defined(F3DEX_GBI_2)
	int length = getfield(hi, 8, 0) + 1;
	int shift = 32 - (getfield(hi, 8, 8) + length);
#endif
	if (shift == G_MDSFT_ALPHADITHER && length == G_MDSIZ_ALPHADITHER)
		return d_DPSetAlphaDither(m, hi, lo);
	else if (shift == G_MDSFT_RGBDITHER && length == G_MDSIZ_RGBDITHER)
		return d_DPSetColorDither(m, hi, lo);
	else if (shift == G_MDSFT_COMBKEY && length == G_MDSIZ_COMBKEY)
		return d_DPSetCombineKey(m, hi, lo);
	else if (shift == G_MDSFT_TEXTCONV && length == G_MDSIZ_TEXTCONV)
		return d_DPSetTextureConvert(m, hi, lo);
	else if (shift == G_MDSFT_TEXTFILT && length == G_MDSIZ_TEXTFILT)
		return d_DPSetTextureFilter(m, hi, lo);
	else if (shift == G_MDSFT_TEXTLUT && length == G_MDSIZ_TEXTLUT)
		return d_DPSetTextureLUT(m, hi, lo);
	else if (shift == G_MDSFT_TEXTLOD && length == G_MDSIZ_TEXTLOD)
		return d_DPSetTextureLOD(m, hi, lo);
	else if (shift == G_MDSFT_TEXTDETAIL && length == G_MDSIZ_TEXTDETAIL)
		return d_DPSetTextureDetail(m, hi, lo);
	else if (shift == G_MDSFT_TEXTPERSP && length == G_MDSIZ_TEXTPERSP)
		return d_DPSetTexturePersp(m, hi, lo);
	else if (shift == G_MDSFT_CYCLETYPE && length == G_MDSIZ_CYCLETYPE)
		return d_DPSetCycleType(m, hi, lo);
	else if (shift == G_MDSFT_PIPELINE && length == G_MDSIZ_PIPELINE)
		return d_DPPipelineMode(m, hi, lo);
	else if (config.emit_ext_macro)
	{
		m->id = gfxd_SPSetOtherModeHi;
		argi(m, 0, "sft", shift, gfxd_Sfthi);
		argi(m, 1, "len", length, gfxd_Num);
		argu(m, 2, "mode", lo, gfxd_Othermodehi);
		return 0;
	}
	else
		return d_SPSetOtherMode(m, hi, lo);
}

UCFUNC int d_DPSetOtherMode(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_DPSetOtherMode;
	argu(m, 0, "hi", getfield(hi, 24, 0), gfxd_Othermodehi);
	argu(m, 1, "lo", lo, gfxd_Othermodelo);
	return 0;
}

UCFUNC int d_MoveWd(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
#if defined(F3D_GBI) || defined(F3DEX_GBI)
	int index = getfield(hi, 8, 0);
	int offset = getfield(hi, 16, 8);
#elif defined(F3DEX_GBI_2)
	int index = getfield(hi, 8, 16);
	int offset = getfield(hi, 16, 0);
#endif
	if (index == G_MW_FOG && offset == G_MWO_FOG)
		return d_SPFogPosition(m, hi, lo);
#if !(defined(F3D_BETA) && (defined(F3D_GBI) || defined(F3DEX_GBI)))
	else if (index == G_MW_PERSPNORM && offset == 0)
		return d_SPPerspNormalize(m, hi, lo);
#endif
	else if (index == G_MW_SEGMENT)
		return d_SPSegment(m, hi, lo);
	else if (index == G_MW_NUMLIGHT && offset == G_MWO_NUMLIGHT)
		return d_SPNumLights(m, hi, lo);
#if defined(F3D_GBI) || (defined(F3D_BETA) && defined(F3DEX_GBI))
	else if (index == G_MW_POINTS)
		return d_SPModifyVertex(m, hi, lo);
#endif
#if defined(F3D_GBI) || defined(F3DEX_GBI)
	else if (index == G_MW_MATRIX)
		return d_SPInsertMatrix(m, hi, lo);
#endif
	else
	{
		m->id = gfxd_MoveWd;
		argi(m, 0, "index", index, gfxd_Mw);
		if (index == G_MW_MATRIX)
			argu(m, 1, "offset", offset, gfxd_Mwo_matrix);
		else if (index == G_MW_CLIP)
			argu(m, 1, "offset", offset, gfxd_Mwo_clip);
		else if (index == G_MW_LIGHTCOL)
			argu(m, 1, "offset", offset, gfxd_Mwo_lightcol);
		else
			argu(m, 1, "offset", offset, gfxd_Mwo);
		argu(m, 2, "value", lo, gfxd_Word);
	}
	return 0;
}

#if defined(F3D_GBI) || defined(F3DEX_GBI)
UCFUNC int d_MoveMem(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	int size = getfield(hi, 16, 0);
	int index = getfield(hi, 8, 16);
	if (size == sizeof(Light)
		&& index >= G_MV_L0
		&& index <= G_MV_L7
		&& index % 2 == 0)
	{
		return d_SPLight(m, hi, lo);
	}
	else if (size == sizeof(Light) && index == G_MV_LOOKATX)
		return d_SPLookAtX(m, hi, lo);
	else if (size == sizeof(Light) && index == G_MV_LOOKATY)
		return d_SPLookAtY(m, hi, lo);
	else if (size == sizeof(Vp) && index == G_MV_VIEWPORT)
		return d_SPViewport(m, hi, lo);
	else
	{
		m->id = gfxd_MoveMem;
		argu(m, 0, "size", size, gfxd_Size);
		argi(m, 1, "index", index, gfxd_Mv);
		argu(m, 2, "dram", lo, gfxd_Dram);
		return 0;
	}
}
#elif defined(F3DEX_GBI_2)
UCFUNC int d_MoveMem(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	int size = (getfield(hi, 5, 19) + 1) * 8;
	int index = getfield(hi, 8, 0);
	int offset = getfield(hi, 8, 8) * 8;
	if (size == sizeof(Light)
		&& index == G_MV_LIGHT
		&& offset >= G_MVO_L0
		&& offset <= G_MVO_L7
		&& offset % 0x18 == 0)
	{
		return d_SPLight(m, hi, lo);
	}
	else if (size == sizeof(Light)
			&& index == G_MV_LIGHT
			&& offset == G_MVO_LOOKATX)
	{
		return d_SPLookAtX(m, hi, lo);
	}
	else if (size == sizeof(Light)
			&& index == G_MV_LIGHT
			&& offset == G_MVO_LOOKATY)
	{
		return d_SPLookAtY(m, hi, lo);
	}
	else if (size == sizeof(Vp)
			&& index == G_MV_VIEWPORT
			&& offset == 0)
	{
		return d_SPViewport(m, hi, lo);
	}
	else
	{
		m->id = gfxd_MoveMem;
		argu(m, 0, "size", size, gfxd_Size);
		argi(m, 1, "index", index, gfxd_Mv);
		argu(m, 2, "offset", offset, gfxd_Size);
		argu(m, 3, "dram", lo, gfxd_Dram);
		return 0;
	}
}
#endif

#if defined(F3DEX_GBI_2)
UCFUNC int d_SPDmaRead(gfxd_macro_t *m, uint32_t hi, uint32_t lo);
UCFUNC int d_SPDmaWrite(gfxd_macro_t *m, uint32_t hi, uint32_t lo);
UCFUNC int d_SPDma_io(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	int flag = getfield(hi, 1, 23);
	if (flag == 0)
		return d_SPDmaRead(m, hi, lo);
	else if (flag == 1)
		return d_SPDmaWrite(m, hi, lo);
	else
	{
		m->id = gfxd_SPDma_io;
		argi(m, 0, "flag", flag, gfxd_Dmaflag);
		argu(m, 1, "dmem", getfield(hi, 10, 13) * 8, gfxd_Dmem);
		argu(m, 2, "dram", lo, gfxd_Dram);
		argu(m, 3, "size", getfield(hi, 12, 10) + 1, gfxd_Size);
		return 0;
	}
}

UCFUNC int d_SPDmaRead(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_SPDmaRead;
	argu(m, 0, "dmem", getfield(hi, 10, 13) * 8, gfxd_Dmem);
	argu(m, 1, "dram", lo, gfxd_Dram);
	argu(m, 2, "size", getfield(hi, 12, 10) + 1, gfxd_Size);
	return 0;
}

UCFUNC int d_SPDmaWrite(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_SPDmaWrite;
	argu(m, 0, "dmem", getfield(hi, 10, 13) * 8, gfxd_Dmem);
	argu(m, 1, "dram", lo, gfxd_Dram);
	argu(m, 2, "size", getfield(hi, 12, 10) + 1, gfxd_Size);
	return 0;
}
#endif

#if defined(F3DEX_GBI) || defined(F3DEX_GBI_2)
UCFUNC int d_LoadUcode(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_LoadUcode;
	argu(m, 0, "uc_start", lo, gfxd_Uctext);
	argu(m, 1, "uc_dsize", getfield(hi, 16, 0) + 1, gfxd_Size);
	return 0;
}

UCFUNC int c_SPLoadUcodeEx(gfxd_macro_t *m, gfxd_macro_t *m_list, int n_macro)
{
	if (n_macro < 2)
		return -1;
	if (m_list[0].id != gfxd_DPHalf1)
		return -1;
	uint32_t uc_dstart = argvu(&m_list[0], 0);
	if (m_list[1].id != gfxd_LoadUcode)
		return -1;
	uint32_t uc_start = argvu(&m_list[1], 0);
	uint32_t uc_dsize = argvu(&m_list[1], 1);
	m->id = gfxd_SPLoadUcodeEx;
	argu(m, 0, "uc_start", uc_start, gfxd_Uctext);
	argu(m, 1, "uc_dstart", uc_dstart, gfxd_Ucdata);
	argu(m, 2, "uc_dsize", uc_dsize, gfxd_Size);
	return 0;
}
#endif

UCFUNC int d_TexRect(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_TexRect;
	argu(m, 0, "ulx", getfield(lo, 12, 12), gfxd_Coordq);
	argu(m, 1, "uly", getfield(lo, 12, 0), gfxd_Coordq);
	argu(m, 2, "lrx", getfield(hi, 12, 12), gfxd_Coordq);
	argu(m, 3, "lry", getfield(hi, 12, 0), gfxd_Coordq);
	argi(m, 4, "tile", getfield(lo, 3, 24), gfxd_Tile);
	return 0;
}

UCFUNC int d_TexRectFlip(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_TexRectFlip;
	argu(m, 0, "ulx", getfield(lo, 12, 12), gfxd_Coordq);
	argu(m, 1, "uly", getfield(lo, 12, 0), gfxd_Coordq);
	argu(m, 2, "lrx", getfield(hi, 12, 12), gfxd_Coordq);
	argu(m, 3, "lry", getfield(hi, 12, 0), gfxd_Coordq);
	argi(m, 4, "tile", getfield(lo, 3, 24), gfxd_Tile);
	return 0;
}

UCFUNC int d_SPNoOp(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_SPNoOp;
	return 0;
}

#if defined(F3DEX_GBI_2)
UCFUNC int d_Special3(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_Special3;
	argu(m, 0, "hi", getfield(hi, 24, 0), gfxd_Word);
	argu(m, 1, "lo", lo, gfxd_Word);
	return 0;
}

UCFUNC int d_Special2(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_Special2;
	argu(m, 0, "hi", getfield(hi, 24, 0), gfxd_Word);
	argu(m, 1, "lo", lo, gfxd_Word);
	return 0;
}

UCFUNC int d_Special1(gfxd_macro_t *m, uint32_t hi, uint32_t lo)
{
	m->id = gfxd_Special1;
	argu(m, 0, "hi", getfield(hi, 24, 0), gfxd_Word);
	argu(m, 1, "lo", lo, gfxd_Word);
	return 0;
}
#endif
