diff --git a/tools/Makefile b/tools/Makefile index d1b77333..f1bd20ee 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -1,10 +1,13 @@ CC := gcc -CFLAGS := -I . -Wall -Wextra -Wno-unused-parameter -pedantic -std=c99 -O3 -s -PROGRAMS := iplfontutil n64graphics n64crc patch_libultra_math +CFLAGS := -I . -Wall -Wextra -Wno-unused-parameter -pedantic -O3 -s +PROGRAMS := iplfontutil n64graphics n64crc patch_libultra_math gfxdis_f3dex2 iplfontutil_SOURCES := iplfontutil.c iplfontutil_CFLAGS := -O2 # faster compile time +gfxdis_f3dex2_SOURCES := gfxdis/gfxdis.c gfxdis/main.c +gfxdis_f3dex2_CFLAGS := -DF3DEX_GBI_2 -Igfxdis/include/ -Igfxdis/ -O2 -std=gnu99 -Wno-pedantic + n64crc_SOURCES := n64crc.c n64crc_CFLAGS := -O2 # faster compile time diff --git a/tools/gfxdis/gfxdis.c b/tools/gfxdis/gfxdis.c new file mode 100644 index 00000000..e01d3827 --- /dev/null +++ b/tools/gfxdis/gfxdis.c @@ -0,0 +1,4983 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "gfxdis.h" + +#define MDMASK(md) ((((uint32_t)1<>(s))&(((uint32_t)1<<(n))-1)) +#define strapp(s) ({int n=(s);p+=n;buf+=n;}) +#define strappf(fmt,...) ({int n=sprintf(buf,fmt,##__VA_ARGS__);p+=n;buf+=n;}) + +struct gfxdis_cfg gfxdis_cfg = +{ + .dis_invd = 0, + .use_q = 1, + .dec_color = 0, +}; + +int gfx_insn_dis(struct gfx_insn *insn, Gfx *gfx) +{ + uint32_t hi = btoh32(gfx->hi); + uint32_t lo = btoh32(gfx->lo); + memset(insn, 0, sizeof(*insn)); + int opcode = getfield(hi, 8, 24); + enum gfx_insn_def def = GFX_ID_INVD; + for (int i = 0; i < GFX_ID_MAX; ++i) { + struct gfx_insn_info *info = &gfx_insn_info[i]; + if (info->type == GFX_IT_OP && info->opcode == opcode) { + def = i; + break; + } + } + return ((gfx_insn_dis_t)gfx_insn_info[def].handler)(insn, hi, lo); +} + +int gfx_insn_col(struct gfx_insn *insn, int n_insn) +{ + int opcode = gfx_insn_info[insn->def].opcode; + for (int i = 0; i < GFX_ID_MAX; ++i) { + struct gfx_insn_info *info = &gfx_insn_info[i]; + if (info->type == GFX_IT_MULTIMACRO && info->opcode == opcode) { + int n = ((gfx_insn_col_t)info->handler)(insn, n_insn); + if (n != 0) + return n; + } + } + return 0; +} + +char *gfx_insn_str(struct gfx_insn *insn, char *buf) +{ + struct gfx_insn_info *info = &gfx_insn_info[insn->def]; + if (insn->def == GFX_ID_INVD) + buf += sprintf(buf, "(%s){", info->name); + else + buf += sprintf(buf, "%s(", info->name); + for (int i = 0; i < info->n_args; ++i) { + if (i > 0) + buf += sprintf(buf, ", "); + if (insn->strarg[i]) + buf += insn->strarg[i](buf, insn->arg[i]); + else + buf += sprintf(buf, "%" PRIi32, (int32_t)insn->arg[i]); + } + if (insn->def == GFX_ID_INVD) + buf += sprintf(buf, "}"); + else + buf += sprintf(buf, ")"); + return buf; +} + +char *gfx_insn_str_dyn(struct gfx_insn *insn, const char *arg, char *buf) +{ + struct gfx_insn_info *info = &gfx_insn_info[insn->def]; + if (insn->def == GFX_ID_INVD) + buf += sprintf(buf, "%s = (%s){", arg, info->name); + else { + if (strncmp(info->name, "gs", 2) == 0) + buf += sprintf(buf, "g%s(%s", &info->name[2], arg); + else if (strncmp(info->name, "_gs", 3) == 0) + buf += sprintf(buf, "_g%s(%s", &info->name[3], arg); + if (info->n_args > 0) + buf += sprintf(buf, ", "); + } + for (int i = 0; i < info->n_args; ++i) { + if (i > 0) + buf += sprintf(buf, ", "); + if (insn->strarg[i]) + buf += insn->strarg[i](buf, insn->arg[i]); + else + buf += sprintf(buf, "%" PRIi32, (int32_t)insn->arg[i]); + } + if (insn->def == GFX_ID_INVD) + buf += sprintf(buf, "}"); + else + buf += sprintf(buf, ")"); + return buf; +} + +int gfx_dis(struct vector *insn_vect, Gfx *gfx, int max) +{ + struct gfx_insn insn; + vector_init(insn_vect, sizeof(insn)); + int result = 0; + while ((insn_vect->size < max || max < 0) && + ((result = gfx_insn_dis(&insn, gfx++)) == 0 || gfxdis_cfg.dis_invd)) + { + if (!vector_push_back(insn_vect, 1, &insn)) + return -1; + if (insn.def == GFX_ID_SPBRANCHLIST || insn.def == GFX_ID_SPENDDISPLAYLIST) + break; + } + for (int i = 0; i < insn_vect->size; ++i) { + int n = gfx_insn_col(vector_at(insn_vect, i), insn_vect->size - i); + vector_erase(insn_vect, insn_vect->size - n, n); + } + return result && !gfxdis_cfg.dis_invd; +} + +static int32_t sx(uint32_t n, int bits) +{ + if (n & ((uint32_t)1 << (bits - 1))) + n |= ~(((uint32_t)1 << bits) - 1); + return n; +} + +static int strarg_x8(char *buf, uint32_t arg) +{ + return sprintf(buf, "0x%02" PRIX8, (uint8_t)arg); +} + +static int strarg_x16(char *buf, uint32_t arg) +{ + return sprintf(buf, "0x%04" PRIX16, (uint16_t)arg); +} + +static int strarg_x32(char *buf, uint32_t arg) +{ + return sprintf(buf, "0x%08" PRIX32, arg); +} + +#if defined(F3DEX_GBI) || defined(F3DEX_GBI_2) +static int strarg_f(char *buf, uint32_t arg) +{ + union + { + uint32_t u32; + float f; + } reint_f; + reint_f.u32 = arg; + return sprintf(buf, "%g", reint_f.f); +} +#endif + +static int strarg_color(char *buf, uint32_t arg) +{ + if (gfxdis_cfg.dec_color) + return sprintf(buf, "%u", arg); + else + return sprintf(buf, "0x%02" PRIX8, (uint8_t)arg); +} + +static int strarg_qu08(char *buf, uint32_t arg) +{ + if (arg == 0) + return sprintf(buf, "0"); + else if (gfxdis_cfg.use_q) + return sprintf(buf, "qu08(%g)", arg / 256.f); + else + return sprintf(buf, "0x%02" PRIX32, arg); +} + +static int strarg_qu016(char *buf, uint32_t arg) +{ + if (arg == 0) + return sprintf(buf, "0"); + else if (gfxdis_cfg.use_q) + return sprintf(buf, "qu016(%g)", arg / 65536.f); + else + return sprintf(buf, "0x%04" PRIX32, arg); +} + +static int strarg_qs48(char *buf, uint32_t arg) +{ + if (arg == 0) + return sprintf(buf, "0"); + else if (gfxdis_cfg.use_q) + return sprintf(buf, "qs48(%g)", (int32_t)arg / 256.f); + else { + if ((int32_t)arg < 0) + return sprintf(buf, "-0x%04" PRIX32, -arg); + else + return sprintf(buf, "0x%04" PRIX32, arg); + } +} + +static int strarg_qs510(char *buf, uint32_t arg) +{ + if (arg == 0) + return sprintf(buf, "0"); + else if (gfxdis_cfg.use_q) + return sprintf(buf, "qs510(%g)", (int32_t)arg / 1024.f); + else { + if ((int32_t)arg < 0) + return sprintf(buf, "-0x%04" PRIX32, -arg); + else + return sprintf(buf, "0x%04" PRIX32, arg); + } +} + +static int strarg_qu102(char *buf, uint32_t arg) +{ + if (arg == 0) + return sprintf(buf, "0"); + else if (gfxdis_cfg.use_q) + return sprintf(buf, "qu102(%g)", arg / 4.f); + else + return sprintf(buf, "0x%04" PRIX32, arg); +} + +static int strarg_qs105(char *buf, uint32_t arg) +{ + if (arg == 0) + return sprintf(buf, "0"); + else if (gfxdis_cfg.use_q) + return sprintf(buf, "qs105(%g)", (int32_t)arg / 32.f); + else { + if ((int32_t)arg < 0) + return sprintf(buf, "-0x%04" PRIX32, -arg); + else + return sprintf(buf, "0x%04" PRIX32, arg); + } +} + +static int strarg_invd(char *buf, uint32_t arg) +{ + return sprintf(buf, "%" PRIi32 " /* INVALID */", (int32_t)arg); +} + +static int strarg_fmt(char *buf, uint32_t arg) +{ + switch (arg) { + case G_IM_FMT_RGBA : return sprintf(buf, "G_IM_FMT_RGBA"); + case G_IM_FMT_YUV : return sprintf(buf, "G_IM_FMT_YUV"); + case G_IM_FMT_CI : return sprintf(buf, "G_IM_FMT_CI"); + case G_IM_FMT_IA : return sprintf(buf, "G_IM_FMT_IA"); + case G_IM_FMT_I : return sprintf(buf, "G_IM_FMT_I"); + default : return sprintf(buf, "%" PRIi32, (int32_t)arg); + } +} + +static int strarg_siz(char *buf, uint32_t arg) +{ + switch (arg) { + case G_IM_SIZ_4b : return sprintf(buf, "G_IM_SIZ_4b"); + case G_IM_SIZ_8b : return sprintf(buf, "G_IM_SIZ_8b"); + case G_IM_SIZ_16b : return sprintf(buf, "G_IM_SIZ_16b"); + case G_IM_SIZ_32b : return sprintf(buf, "G_IM_SIZ_32b"); + default : return sprintf(buf, "%" PRIi32, (int32_t)arg); + } +} + +static int strarg_cm(char *buf, uint32_t arg) +{ + int p = 0; + if (arg & G_TX_MIRROR) + strappf("G_TX_MIRROR"); + else + strappf("G_TX_NOMIRROR"); + if (arg & G_TX_CLAMP) + strappf(" | G_TX_CLAMP"); + else + strappf(" | G_TX_WRAP"); + return p; +} + +static int strarg_tm(char *buf, uint32_t arg) +{ + if (arg == 0) + return sprintf(buf, "G_TX_NOMASK"); + else + return sprintf(buf, "%" PRIi32, (int32_t)arg); +} + +static int strarg_ts(char *buf, uint32_t arg) +{ + if (arg == 0) + return sprintf(buf, "G_TX_NOLOD"); + else + return sprintf(buf, "%" PRIi32, (int32_t)arg); +} + +static int strarg_switch(char *buf, uint32_t arg) +{ + switch (arg) { + case G_ON : return sprintf(buf, "G_ON"); + case G_OFF : return sprintf(buf, "G_OFF"); + default : return sprintf(buf, "%" PRIi32, (int32_t)arg); + } +} + +static int strarg_tile(char *buf, uint32_t arg) +{ + if (arg == G_TX_LOADTILE) + return sprintf(buf, "G_TX_LOADTILE"); + else if (arg == G_TX_RENDERTILE) + return sprintf(buf, "G_TX_RENDERTILE"); + else + return sprintf(buf, "%u", arg); +} + +static int strarg_gm(char *buf, uint32_t arg) +{ + int p = 0; + if (arg & G_ZBUFFER) + strappf("G_ZBUFFER"); + if (arg & G_TEXTURE_ENABLE) { + if (p > 0) + strappf(" | "); + strappf("G_TEXTURE_ENABLE"); + } + if (arg & G_SHADE) { + if (p > 0) + strappf(" | "); + strappf("G_SHADE"); + } + if ((arg & G_CULL_BOTH) == G_CULL_BOTH) { + if (p > 0) + strappf(" | "); + strappf("G_CULL_BOTH"); + } + else { + if (arg & G_CULL_FRONT) { + if (p > 0) + strappf(" | "); + strappf("G_CULL_FRONT"); + } + if (arg & G_CULL_BACK) { + if (p > 0) + strappf(" | "); + strappf("G_CULL_BACK"); + } + } + if (arg & G_FOG) { + if (p > 0) + strappf(" | "); + strappf("G_FOG"); + } + if (arg & G_LIGHTING) { + if (p > 0) + strappf(" | "); + strappf("G_LIGHTING"); + } + if (arg & G_TEXTURE_GEN) { + if (p > 0) + strappf(" | "); + strappf("G_TEXTURE_GEN"); + } + if (arg & G_TEXTURE_GEN_LINEAR) { + if (p > 0) + strappf(" | "); + strappf("G_TEXTURE_GEN_LINEAR"); + } + if (arg & G_LOD) { + if (p > 0) + strappf(" | "); + strappf("G_LOD"); + } + if (arg & G_SHADING_SMOOTH) { + if (p > 0) + strappf(" | "); + strappf("G_SHADING_SMOOTH"); + } + if (arg & G_CLIPPING) { + if (p > 0) + strappf(" | "); + strappf("G_CLIPPING"); + } + arg = arg & ~(G_ZBUFFER | G_TEXTURE_ENABLE | G_SHADE | G_CULL_BOTH | G_FOG | + G_LIGHTING | G_TEXTURE_GEN | G_TEXTURE_GEN_LINEAR | G_LOD | + G_SHADING_SMOOTH | G_CLIPPING); + if (arg) { + if (p > 0) + strappf(" | "); + strappf("0x%08" PRIX32, arg); + } + return p; +} + +static int strarg_sftlo(char *buf, uint32_t arg) +{ + switch (arg) { + case G_MDSFT_ALPHACOMPARE : return sprintf(buf, "G_MDSFT_ALPHACOMPARE"); + case G_MDSFT_ZSRCSEL : return sprintf(buf, "G_MDSFT_ZSRCSEL"); + case G_MDSFT_RENDERMODE : return sprintf(buf, "G_MDSFT_RENDERMODE"); + default : return sprintf(buf, "%" PRIi32, (int32_t)arg); + } +} + +static int rm_mode_str(char *buf, uint32_t arg) +{ + int p = 0; + if (arg & AA_EN) + strappf("AA_EN"); + if (arg & Z_CMP) { + if (p > 0) + strappf(" | "); + strappf("Z_CMP"); + } + if (arg & Z_UPD) { + if (p > 0) + strappf(" | "); + strappf("Z_UPD"); + } + if (arg & IM_RD) { + if (p > 0) + strappf(" | "); + strappf("IM_RD"); + } + if (arg & CLR_ON_CVG) { + if (p > 0) + strappf(" | "); + strappf("CLR_ON_CVG"); + } + if (p > 0) + strappf(" | "); + int cvg = arg & 0x00000300; + switch (cvg) { + case CVG_DST_CLAMP : strappf("CVG_DST_CLAMP"); break; + case CVG_DST_WRAP : strappf("CVG_DST_WRAP"); break; + case CVG_DST_FULL : strappf("CVG_DST_FULL"); break; + case CVG_DST_SAVE : strappf("CVG_DST_SAVE"); break; + } + int zmode = arg & 0x00000C00; + switch (zmode) { + case ZMODE_OPA : strappf(" | ZMODE_OPA"); break; + case ZMODE_INTER : strappf(" | ZMODE_INTER"); break; + case ZMODE_XLU : strappf(" | ZMODE_XLU"); break; + case ZMODE_DEC : strappf(" | ZMODE_DEC"); break; + } + if (arg & CVG_X_ALPHA) + strappf(" | CVG_X_ALPHA"); + if (arg & ALPHA_CVG_SEL) + strappf(" | ALPHA_CVG_SEL"); + if (arg & FORCE_BL) + strappf(" | FORCE_BL"); + return p; +} + +static int rm_cbl_str(char *buf, uint32_t arg, int c) +{ + int p = 0; + if (c == 2) + arg <<= 2; + int bp = (arg >> 30) & 0b11; + switch (bp) { + case G_BL_CLR_IN : strappf("GBL_c%i(G_BL_CLR_IN", c); break; + case G_BL_CLR_MEM : strappf("GBL_c%i(G_BL_CLR_MEM", c); break; + case G_BL_CLR_BL : strappf("GBL_c%i(G_BL_CLR_BL", c); break; + case G_BL_CLR_FOG : strappf("GBL_c%i(G_BL_CLR_FOG", c); break; + } + int ba = (arg >> 26) & 0b11; + switch (ba) { + case G_BL_A_IN : strappf(", G_BL_A_IN"); break; + case G_BL_A_FOG : strappf(", G_BL_A_FOG"); break; + case G_BL_A_SHADE : strappf(", G_BL_A_SHADE"); break; + case G_BL_0 : strappf(", G_BL_0"); break; + } + int bm = (arg >> 22) & 0b11; + switch (bm) { + case G_BL_CLR_IN : strappf(", G_BL_CLR_IN"); break; + case G_BL_CLR_MEM : strappf(", G_BL_CLR_MEM"); break; + case G_BL_CLR_BL : strappf(", G_BL_CLR_BL"); break; + case G_BL_CLR_FOG : strappf(", G_BL_CLR_FOG"); break; + } + int bb = (arg >> 18) & 0b11; + switch (bb) { + case G_BL_1MA : strappf(", G_BL_1MA)"); break; + case G_BL_A_MEM : strappf(", G_BL_A_MEM)"); break; + case G_BL_1 : strappf(", G_BL_1)"); break; + case G_BL_0 : strappf(", G_BL_0)"); break; + } + return p; +} + +struct rm_preset +{ + uint32_t rm; + const char *name; +}; + +static struct rm_preset rm_presets[] = +{ + {G_RM_OPA_SURF, "G_RM_OPA_SURF"}, + {G_RM_OPA_SURF2, "G_RM_OPA_SURF2"}, + {G_RM_AA_OPA_SURF, "G_RM_AA_OPA_SURF"}, + {G_RM_AA_OPA_SURF2, "G_RM_AA_OPA_SURF2"}, + {G_RM_RA_OPA_SURF, "G_RM_RA_OPA_SURF"}, + {G_RM_RA_OPA_SURF2, "G_RM_RA_OPA_SURF2"}, + {G_RM_ZB_OPA_SURF, "G_RM_ZB_OPA_SURF"}, + {G_RM_ZB_OPA_SURF2, "G_RM_ZB_OPA_SURF2"}, + {G_RM_AA_ZB_OPA_SURF, "G_RM_AA_ZB_OPA_SURF"}, + {G_RM_AA_ZB_OPA_SURF2, "G_RM_AA_ZB_OPA_SURF2"}, + {G_RM_RA_ZB_OPA_SURF, "G_RM_RA_ZB_OPA_SURF"}, + {G_RM_RA_ZB_OPA_SURF2, "G_RM_RA_ZB_OPA_SURF2"}, + {G_RM_XLU_SURF, "G_RM_XLU_SURF"}, + {G_RM_XLU_SURF2, "G_RM_XLU_SURF2"}, + {G_RM_AA_XLU_SURF, "G_RM_AA_XLU_SURF"}, + {G_RM_AA_XLU_SURF2, "G_RM_AA_XLU_SURF2"}, + {G_RM_ZB_XLU_SURF, "G_RM_ZB_XLU_SURF"}, + {G_RM_ZB_XLU_SURF2, "G_RM_ZB_XLU_SURF2"}, + {G_RM_AA_ZB_XLU_SURF, "G_RM_AA_ZB_XLU_SURF"}, + {G_RM_AA_ZB_XLU_SURF2, "G_RM_AA_ZB_XLU_SURF2"}, + {G_RM_ZB_OPA_DECAL, "G_RM_ZB_OPA_DECAL"}, + {G_RM_ZB_OPA_DECAL2, "G_RM_ZB_OPA_DECAL2"}, + {G_RM_AA_ZB_OPA_DECAL, "G_RM_AA_ZB_OPA_DECAL"}, + {G_RM_AA_ZB_OPA_DECAL2, "G_RM_AA_ZB_OPA_DECAL2"}, + {G_RM_RA_ZB_OPA_DECAL, "G_RM_RA_ZB_OPA_DECAL"}, + {G_RM_RA_ZB_OPA_DECAL2, "G_RM_RA_ZB_OPA_DECAL2"}, + {G_RM_ZB_XLU_DECAL, "G_RM_ZB_XLU_DECAL"}, + {G_RM_ZB_XLU_DECAL2, "G_RM_ZB_XLU_DECAL2"}, + {G_RM_AA_ZB_XLU_DECAL, "G_RM_AA_ZB_XLU_DECAL"}, + {G_RM_AA_ZB_XLU_DECAL2, "G_RM_AA_ZB_XLU_DECAL2"}, + {G_RM_AA_ZB_OPA_INTER, "G_RM_AA_ZB_OPA_INTER"}, + {G_RM_AA_ZB_OPA_INTER2, "G_RM_AA_ZB_OPA_INTER2"}, + {G_RM_RA_ZB_OPA_INTER, "G_RM_RA_ZB_OPA_INTER"}, + {G_RM_RA_ZB_OPA_INTER2, "G_RM_RA_ZB_OPA_INTER2"}, + {G_RM_AA_ZB_XLU_INTER, "G_RM_AA_ZB_XLU_INTER"}, + {G_RM_AA_ZB_XLU_INTER2, "G_RM_AA_ZB_XLU_INTER2"}, + {G_RM_AA_XLU_LINE, "G_RM_AA_XLU_LINE"}, + {G_RM_AA_XLU_LINE2, "G_RM_AA_XLU_LINE2"}, + {G_RM_AA_ZB_XLU_LINE, "G_RM_AA_ZB_XLU_LINE"}, + {G_RM_AA_ZB_XLU_LINE2, "G_RM_AA_ZB_XLU_LINE2"}, + {G_RM_AA_DEC_LINE, "G_RM_AA_DEC_LINE"}, + {G_RM_AA_DEC_LINE2, "G_RM_AA_DEC_LINE2"}, + {G_RM_AA_ZB_DEC_LINE, "G_RM_AA_ZB_DEC_LINE"}, + {G_RM_AA_ZB_DEC_LINE2, "G_RM_AA_ZB_DEC_LINE2"}, + {G_RM_TEX_EDGE, "G_RM_TEX_EDGE"}, + {G_RM_TEX_EDGE2, "G_RM_TEX_EDGE2"}, + {G_RM_AA_TEX_EDGE, "G_RM_AA_TEX_EDGE"}, + {G_RM_AA_TEX_EDGE2, "G_RM_AA_TEX_EDGE2"}, + {G_RM_AA_ZB_TEX_EDGE, "G_RM_AA_ZB_TEX_EDGE"}, + {G_RM_AA_ZB_TEX_EDGE2, "G_RM_AA_ZB_TEX_EDGE2"}, + {G_RM_AA_ZB_TEX_INTER, "G_RM_AA_ZB_TEX_INTER"}, + {G_RM_AA_ZB_TEX_INTER2, "G_RM_AA_ZB_TEX_INTER2"}, + {G_RM_AA_SUB_SURF, "G_RM_AA_SUB_SURF"}, + {G_RM_AA_SUB_SURF2, "G_RM_AA_SUB_SURF2"}, + {G_RM_AA_ZB_SUB_SURF, "G_RM_AA_ZB_SUB_SURF"}, + {G_RM_AA_ZB_SUB_SURF2, "G_RM_AA_ZB_SUB_SURF2"}, + {G_RM_PCL_SURF, "G_RM_PCL_SURF"}, + {G_RM_PCL_SURF2, "G_RM_PCL_SURF2"}, + {G_RM_AA_PCL_SURF, "G_RM_AA_PCL_SURF"}, + {G_RM_AA_PCL_SURF2, "G_RM_AA_PCL_SURF2"}, + {G_RM_ZB_PCL_SURF, "G_RM_ZB_PCL_SURF"}, + {G_RM_ZB_PCL_SURF2, "G_RM_ZB_PCL_SURF2"}, + {G_RM_AA_ZB_PCL_SURF, "G_RM_AA_ZB_PCL_SURF"}, + {G_RM_AA_ZB_PCL_SURF2, "G_RM_AA_ZB_PCL_SURF2"}, + {G_RM_AA_OPA_TERR, "G_RM_AA_OPA_TERR"}, + {G_RM_AA_OPA_TERR2, "G_RM_AA_OPA_TERR2"}, + {G_RM_AA_ZB_OPA_TERR, "G_RM_AA_ZB_OPA_TERR"}, + {G_RM_AA_ZB_OPA_TERR2, "G_RM_AA_ZB_OPA_TERR2"}, + {G_RM_AA_TEX_TERR, "G_RM_AA_TEX_TERR"}, + {G_RM_AA_TEX_TERR2, "G_RM_AA_TEX_TERR2"}, + {G_RM_AA_ZB_TEX_TERR, "G_RM_AA_ZB_TEX_TERR"}, + {G_RM_AA_ZB_TEX_TERR2, "G_RM_AA_ZB_TEX_TERR2"}, + {G_RM_AA_SUB_TERR, "G_RM_AA_SUB_TERR"}, + {G_RM_AA_SUB_TERR2, "G_RM_AA_SUB_TERR2"}, + {G_RM_AA_ZB_SUB_TERR, "G_RM_AA_ZB_SUB_TERR"}, + {G_RM_AA_ZB_SUB_TERR2, "G_RM_AA_ZB_SUB_TERR2"}, + {G_RM_CLD_SURF, "G_RM_CLD_SURF"}, + {G_RM_CLD_SURF2, "G_RM_CLD_SURF2"}, + {G_RM_ZB_CLD_SURF, "G_RM_ZB_CLD_SURF"}, + {G_RM_ZB_CLD_SURF2, "G_RM_ZB_CLD_SURF2"}, + {G_RM_ZB_OVL_SURF, "G_RM_ZB_OVL_SURF"}, + {G_RM_ZB_OVL_SURF2, "G_RM_ZB_OVL_SURF2"}, + {G_RM_ADD, "G_RM_ADD"}, + {G_RM_ADD2, "G_RM_ADD2"}, + {G_RM_VISCVG, "G_RM_VISCVG"}, + {G_RM_VISCVG2, "G_RM_VISCVG2"}, + {G_RM_OPA_CI, "G_RM_OPA_CI"}, + {G_RM_OPA_CI2, "G_RM_OPA_CI2"}, + {G_RM_RA_SPRITE, "G_RM_RA_SPRITE"}, + {G_RM_RA_SPRITE2, "G_RM_RA_SPRITE2"}, +}; + +static struct rm_preset bl1_presets[] = +{ + {G_RM_FOG_SHADE_A, "G_RM_FOG_SHADE_A"}, + {G_RM_FOG_PRIM_A, "G_RM_FOG_PRIM_A"}, + {G_RM_PASS, "G_RM_PASS"}, + {G_RM_NOOP, "G_RM_NOOP"}, +}; + +static struct rm_preset bl2_presets[] = +{ + {G_RM_NOOP2, "G_RM_NOOP2"}, +}; + +static int othermodelo_str(char *buf, uint32_t arg, uint32_t which) +{ + int p = 0; + uint32_t rm_c1_mask = MDMASK_RM_C1; + uint32_t rm_c2_mask = MDMASK_RM_C2; + uint32_t rm_mode_lo = MDMASK_RM_LO; + uint32_t rm_mask = rm_c1_mask | rm_c2_mask | rm_mode_lo; + struct rm_preset *pre_c1 = NULL; + struct rm_preset *pre_c2 = NULL; + int n_rm_presets = sizeof(rm_presets) / sizeof(*rm_presets); + for (int i = 0; i < n_rm_presets; ++i) { + struct rm_preset *pre = &rm_presets[i]; + uint32_t rm_c1 = arg & (rm_c1_mask | rm_mode_lo | (pre->rm & ~rm_mask)); + if (!pre_c1 && rm_c1 == pre->rm) + pre_c1 = pre; + uint32_t rm_c2 = arg & (rm_c2_mask | rm_mode_lo | (pre->rm & ~rm_mask)); + if (!pre_c2 && rm_c2 == pre->rm) + pre_c2 = pre; + } + if (!pre_c1 || !pre_c2 || pre_c1 + 1 != pre_c2) { + int n_bl1_presets = sizeof(bl1_presets) / sizeof(*bl1_presets); + for (int i = 0; i < n_bl1_presets; ++i) { + struct rm_preset *pre = &bl1_presets[i]; + uint32_t rm_c1 = arg & (rm_c1_mask | (pre->rm & ~rm_mask)); + if (rm_c1 == pre->rm) { + pre_c1 = pre; + break; + } + } + int n_bl2_presets = sizeof(bl2_presets) / sizeof(*bl2_presets); + for (int i = 0; i < n_bl2_presets; ++i) { + struct rm_preset *pre = &bl2_presets[i]; + uint32_t rm_c2 = arg & (rm_c2_mask | (pre->rm & ~rm_mask)); + if (rm_c2 == pre->rm) { + pre_c2 = pre; + break; + } + } + } + uint32_t pre_rm = 0; + if (pre_c1) + pre_rm |= pre_c1->rm; + if (pre_c2) + pre_rm |= pre_c2->rm; + uint32_t ac_mask = MDMASK(ALPHACOMPARE); + if (((arg & ~pre_rm) | which) & ac_mask) { + uint32_t ac = arg & ac_mask; + switch (ac) { + case G_AC_NONE : strappf("G_AC_NONE"); break; + case G_AC_THRESHOLD : strappf("G_AC_THRESHOLD"); break; + case G_AC_DITHER : strappf("G_AC_DITHER"); break; + default : strapp(strarg_x32(buf, ac)); break; + } + } + uint32_t zs_mask = MDMASK(ZSRCSEL); + if (((arg & ~pre_rm) | which) & zs_mask) { + if (p > 0) + strappf(" | "); + uint32_t zs = arg & zs_mask; + switch (zs) { + case G_ZS_PIXEL : strappf("G_ZS_PIXEL"); break; + case G_ZS_PRIM : strappf("G_ZS_PRIM"); break; + default : strapp(strarg_x32(buf, zs)); break; + } + } + uint32_t rm = arg & (rm_mask | pre_rm); + if (((arg & ~pre_rm) | which) & rm_mode_lo) { + if (p > 0) + strappf(" | "); + strapp(rm_mode_str(buf, rm)); + } + int c = 0; + if (which & rm_c1_mask) + c |= 1; + if (which & rm_c2_mask) + c |= 2; + if (c & 1 || (c == 0 && arg & rm_c1_mask)) { + if (p > 0) + strappf(" | "); + if (pre_c1) + strappf("%s", pre_c1->name); + else + strapp(rm_cbl_str(buf, rm, 1)); + } + if (c & 2 || (c == 0 && arg & rm_c2_mask)) { + if (p > 0) + strappf(" | "); + if (pre_c2) + strappf("%s", pre_c2->name); + else + strapp(rm_cbl_str(buf, rm, 2)); + } + uint32_t unk_mask = ~(rm_mask | ac_mask | zs_mask); + if (arg & unk_mask) { + if (p > 0) + strappf(" | "); + uint32_t unk = arg & unk_mask; + strapp(strarg_x32(buf, unk)); + } + return p; +} + +static int strarg_ac(char *buf, uint32_t arg) +{ + return othermodelo_str(buf, arg, MDMASK(ALPHACOMPARE)); +} + +static int strarg_zs(char *buf, uint32_t arg) +{ + return othermodelo_str(buf, arg, MDMASK(ZSRCSEL)); +} + +static int strarg_rm1(char *buf, uint32_t arg) +{ + return othermodelo_str(buf, arg, MDMASK_RM_C1); +} + +static int strarg_rm2(char *buf, uint32_t arg) +{ + return othermodelo_str(buf, arg, MDMASK_RM_C2); +} + +static int strarg_othermodelo(char *buf, uint32_t arg) +{ + uint32_t mask = MDMASK(ALPHACOMPARE) | MDMASK(ZSRCSEL) | MDMASK_RM_C1 | + MDMASK_RM_C2; + return othermodelo_str(buf, arg, mask); +} + +static int strarg_sfthi(char *buf, uint32_t arg) +{ + switch (arg) { + case G_MDSFT_ALPHADITHER : return sprintf(buf, "G_MDSFT_ALPHADITHER"); + case G_MDSFT_RGBDITHER : return sprintf(buf, "G_MDSFT_RGBDITHER"); + case G_MDSFT_COMBKEY : return sprintf(buf, "G_MDSFT_COMBKEY"); + case G_MDSFT_TEXTCONV : return sprintf(buf, "G_MDSFT_TEXTCONV"); + case G_MDSFT_TEXTFILT : return sprintf(buf, "G_MDSFT_TEXTFILT"); + case G_MDSFT_TEXTLUT : return sprintf(buf, "G_MDSFT_TEXTLUT"); + case G_MDSFT_TEXTLOD : return sprintf(buf, "G_MDSFT_TEXTLOD"); + case G_MDSFT_TEXTDETAIL : return sprintf(buf, "G_MDSFT_TEXTDETAIL"); + case G_MDSFT_TEXTPERSP : return sprintf(buf, "G_MDSFT_TEXTPERSP"); + case G_MDSFT_CYCLETYPE : return sprintf(buf, "G_MDSFT_CYCLETYPE"); + case G_MDSFT_PIPELINE : return sprintf(buf, "G_MDSFT_PIPELINE"); + default : return sprintf(buf, "%" PRIi32, (int32_t)arg); + } +} + +static int othermodehi_str(char *buf, uint32_t arg, uint32_t which) +{ + int p = 0; + uint32_t ad_mask = MDMASK(ALPHADITHER); + if ((arg | which) & ad_mask) { + uint32_t ad = arg & ad_mask; + switch (ad) { + case G_AD_PATTERN : strappf("G_AD_PATTERN"); break; + case G_AD_NOTPATTERN : strappf("G_AD_NOTPATTERN"); break; + case G_AD_NOISE : strappf("G_AD_NOISE"); break; + case G_AD_DISABLE : strappf("G_AD_DISABLE"); break; + default : strapp(strarg_x32(buf, ad)); break; + } + } + uint32_t cd_mask = MDMASK(RGBDITHER); + if ((arg | which) & cd_mask) { + if (p > 0) + strappf(" | "); + uint32_t cd = arg & cd_mask; + switch (cd) { + case G_CD_MAGICSQ : strappf("G_CD_MAGICSQ"); break; + case G_CD_BAYER : strappf("G_CD_BAYER"); break; + case G_CD_NOISE : strappf("G_CD_NOISE"); break; + case G_CD_DISABLE : strappf("G_CD_DISABLE"); break; + default : strapp(strarg_x32(buf, cd)); break; + } + } + uint32_t ck_mask = MDMASK(COMBKEY); + if ((arg | which) & ck_mask) { + if (p > 0) + strappf(" | "); + uint32_t ck = arg & ck_mask; + switch (ck) { + case G_CK_NONE : strappf("G_CK_NONE"); break; + case G_CK_KEY : strappf("G_CK_KEY"); break; + default : strapp(strarg_x32(buf, ck)); break; + } + } + uint32_t tc_mask = MDMASK(TEXTCONV); + if ((arg | which) & tc_mask) { + if (p > 0) + strappf(" | "); + uint32_t tc = arg & tc_mask; + switch (tc) { + case G_TC_CONV : strappf("G_TC_CONV"); break; + case G_TC_FILTCONV : strappf("G_TC_FILTCONV"); break; + case G_TC_FILT : strappf("G_TC_FILT"); break; + default : strapp(strarg_x32(buf, tc)); break; + } + } + uint32_t tf_mask = MDMASK(TEXTFILT); + if ((arg | which) & tf_mask) { + if (p > 0) + strappf(" | "); + uint32_t tf = arg & tf_mask; + switch (tf) { + case G_TF_POINT : strappf("G_TF_POINT"); break; + case G_TF_BILERP : strappf("G_TF_BILERP"); break; + case G_TF_AVERAGE : strappf("G_TF_AVERAGE"); break; + default : strapp(strarg_x32(buf, tf)); break; + } + } + uint32_t tt_mask = MDMASK(TEXTLUT); + if ((arg | which) & tt_mask) { + if (p > 0) + strappf(" | "); + uint32_t tt = arg & tt_mask; + switch (tt) { + case G_TT_NONE : strappf("G_TT_NONE"); break; + case G_TT_RGBA16 : strappf("G_TT_RGBA16"); break; + case G_TT_IA16 : strappf("G_TT_IA16"); break; + default : strapp(strarg_x32(buf, tt)); break; + } + } + uint32_t tl_mask = MDMASK(TEXTLOD); + if ((arg | which) & tl_mask) { + if (p > 0) + strappf(" | "); + uint32_t tl = arg & tl_mask; + switch (tl) { + case G_TL_TILE : strappf("G_TL_TILE"); break; + case G_TL_LOD : strappf("G_TL_LOD"); break; + default : strapp(strarg_x32(buf, tl)); break; + } + } + uint32_t td_mask = MDMASK(TEXTDETAIL); + if ((arg | which) & td_mask) { + if (p > 0) + strappf(" | "); + uint32_t td = arg & td_mask; + switch (td) { + case G_TD_CLAMP : strappf("G_TD_CLAMP"); break; + case G_TD_SHARPEN : strappf("G_TD_SHARPEN"); break; + case G_TD_DETAIL : strappf("G_TD_DETAIL"); break; + default : strapp(strarg_x32(buf, td)); break; + } + } + uint32_t tp_mask = MDMASK(TEXTPERSP); + if ((arg | which) & tp_mask) { + if (p > 0) + strappf(" | "); + uint32_t tp = arg & tp_mask; + switch (tp) { + case G_TP_NONE : strappf("G_TP_NONE"); break; + case G_TP_PERSP : strappf("G_TP_PERSP"); break; + default : strapp(strarg_x32(buf, tp)); break; + } + } + uint32_t cyc_mask = MDMASK(CYCLETYPE); + if ((arg | which) & cyc_mask) { + if (p > 0) + strappf(" | "); + uint32_t cyc = arg & cyc_mask; + switch (cyc) { + case G_CYC_1CYCLE : strappf("G_CYC_1CYCLE"); break; + case G_CYC_2CYCLE : strappf("G_CYC_2CYCLE"); break; + case G_CYC_COPY : strappf("G_CYC_COPY"); break; + case G_CYC_FILL : strappf("G_CYC_FILL"); break; + default : strapp(strarg_x32(buf, cyc)); break; + } + } + uint32_t pm_mask = MDMASK(PIPELINE); + if ((arg | which) & pm_mask) { + if (p > 0) + strappf(" | "); + uint32_t pm = arg & pm_mask; + switch (pm) { + case G_PM_NPRIMITIVE : strappf("G_PM_NPRIMITIVE"); break; + case G_PM_1PRIMITIVE : strappf("G_PM_1PRIMITIVE"); break; + default : strapp(strarg_x32(buf, pm)); break; + } + } + uint32_t unk_mask = ~(ad_mask | cd_mask | ck_mask | tc_mask | tf_mask | + tt_mask | tl_mask | td_mask | tp_mask | cyc_mask | + pm_mask); + if (arg & unk_mask) { + if (p > 0) + strappf(" | "); + uint32_t unk = arg & unk_mask; + strapp(strarg_x32(buf, unk)); + } + return p; +} + +static int strarg_ad(char *buf, uint32_t arg) +{ + return othermodehi_str(buf, arg, MDMASK(ALPHADITHER)); +} + +static int strarg_cd(char *buf, uint32_t arg) +{ + return othermodehi_str(buf, arg, MDMASK(RGBDITHER)); +} + +static int strarg_ck(char *buf, uint32_t arg) +{ + return othermodehi_str(buf, arg, MDMASK(COMBKEY)); +} + +static int strarg_tc(char *buf, uint32_t arg) +{ + return othermodehi_str(buf, arg, MDMASK(TEXTCONV)); +} + +static int strarg_tf(char *buf, uint32_t arg) +{ + return othermodehi_str(buf, arg, MDMASK(TEXTFILT)); +} + +static int strarg_tt(char *buf, uint32_t arg) +{ + return othermodehi_str(buf, arg, MDMASK(TEXTLUT)); +} + +static int strarg_tl(char *buf, uint32_t arg) +{ + return othermodehi_str(buf, arg, MDMASK(TEXTLOD)); +} + +static int strarg_td(char *buf, uint32_t arg) +{ + return othermodehi_str(buf, arg, MDMASK(TEXTDETAIL)); +} + +static int strarg_tp(char *buf, uint32_t arg) +{ + return othermodehi_str(buf, arg, MDMASK(TEXTPERSP)); +} + +static int strarg_cyc(char *buf, uint32_t arg) +{ + return othermodehi_str(buf, arg, MDMASK(CYCLETYPE)); +} + +static int strarg_pm(char *buf, uint32_t arg) +{ + return othermodehi_str(buf, arg, MDMASK(PIPELINE)); +} + +static int strarg_othermodehi(char *buf, uint32_t arg) +{ + uint32_t mask = MDMASK(ALPHADITHER) | MDMASK(RGBDITHER) | MDMASK(COMBKEY) | + MDMASK(TEXTCONV) | MDMASK(TEXTFILT) | MDMASK(TEXTLUT) | + MDMASK(TEXTLOD) | MDMASK(TEXTDETAIL) | MDMASK(TEXTPERSP) | + MDMASK(CYCLETYPE) | MDMASK(PIPELINE); + return othermodehi_str(buf, arg, mask); +} + +static int strarg_cv(char *buf, uint32_t arg) +{ + switch ((int32_t)arg) { + case G_CV_K0 : return sprintf(buf, "G_CV_K0"); + case G_CV_K1 : return sprintf(buf, "G_CV_K1"); + case G_CV_K2 : return sprintf(buf, "G_CV_K2"); + case G_CV_K3 : return sprintf(buf, "G_CV_K3"); + case G_CV_K4 : return sprintf(buf, "G_CV_K4"); + case G_CV_K5 : return sprintf(buf, "G_CV_K5"); + default : return sprintf(buf, "%" PRIi32, (int32_t)arg); + } +} + +static int strarg_ccmuxa(char *buf, uint32_t arg) +{ + switch (arg) { + case G_CCMUX_COMBINED : return sprintf(buf, "COMBINED"); + case G_CCMUX_TEXEL0 : return sprintf(buf, "TEXEL0"); + case G_CCMUX_TEXEL1 : return sprintf(buf, "TEXEL1"); + case G_CCMUX_PRIMITIVE : return sprintf(buf, "PRIMITIVE"); + case G_CCMUX_SHADE : return sprintf(buf, "SHADE"); + case G_CCMUX_ENVIRONMENT : return sprintf(buf, "ENVIRONMENT"); + case G_CCMUX_1 : return sprintf(buf, "1"); + case G_CCMUX_NOISE : return sprintf(buf, "NOISE"); + default : return sprintf(buf, "0"); + } +} + +static int strarg_ccmuxb(char *buf, uint32_t arg) +{ + switch (arg) { + case G_CCMUX_COMBINED : return sprintf(buf, "COMBINED"); + case G_CCMUX_TEXEL0 : return sprintf(buf, "TEXEL0"); + case G_CCMUX_TEXEL1 : return sprintf(buf, "TEXEL1"); + case G_CCMUX_PRIMITIVE : return sprintf(buf, "PRIMITIVE"); + case G_CCMUX_SHADE : return sprintf(buf, "SHADE"); + case G_CCMUX_ENVIRONMENT : return sprintf(buf, "ENVIRONMENT"); + case G_CCMUX_CENTER : return sprintf(buf, "CENTER"); + case G_CCMUX_K4 : return sprintf(buf, "K4"); + default : return sprintf(buf, "0"); + } +} + +static int strarg_ccmuxc(char *buf, uint32_t arg) +{ + switch (arg) { + case G_CCMUX_COMBINED : return sprintf(buf, "COMBINED"); + case G_CCMUX_TEXEL0 : return sprintf(buf, "TEXEL0"); + case G_CCMUX_TEXEL1 : return sprintf(buf, "TEXEL1"); + case G_CCMUX_PRIMITIVE : return sprintf(buf, "PRIMITIVE"); + case G_CCMUX_SHADE : return sprintf(buf, "SHADE"); + case G_CCMUX_ENVIRONMENT : return sprintf(buf, "ENVIRONMENT"); + case G_CCMUX_SCALE : return sprintf(buf, "SCALE"); + case G_CCMUX_COMBINED_ALPHA : return sprintf(buf, "COMBINED_ALPHA"); + case G_CCMUX_TEXEL0_ALPHA : return sprintf(buf, "TEXEL0_ALPHA"); + case G_CCMUX_TEXEL1_ALPHA : return sprintf(buf, "TEXEL1_ALPHA"); + case G_CCMUX_PRIMITIVE_ALPHA : return sprintf(buf, "PRIMITIVE_ALPHA"); + case G_CCMUX_SHADE_ALPHA : return sprintf(buf, "SHADE_ALPHA"); + case G_CCMUX_ENV_ALPHA : return sprintf(buf, "ENV_ALPHA"); + case G_CCMUX_LOD_FRACTION : return sprintf(buf, "LOD_FRACTION"); + case G_CCMUX_PRIM_LOD_FRAC : return sprintf(buf, "PRIM_LOD_FRAC"); + case G_CCMUX_K5 : return sprintf(buf, "K5"); + default : return sprintf(buf, "0"); + } +} + +static int strarg_ccmuxd(char *buf, uint32_t arg) +{ + switch (arg) { + case G_CCMUX_COMBINED : return sprintf(buf, "COMBINED"); + case G_CCMUX_TEXEL0 : return sprintf(buf, "TEXEL0"); + case G_CCMUX_TEXEL1 : return sprintf(buf, "TEXEL1"); + case G_CCMUX_PRIMITIVE : return sprintf(buf, "PRIMITIVE"); + case G_CCMUX_SHADE : return sprintf(buf, "SHADE"); + case G_CCMUX_ENVIRONMENT : return sprintf(buf, "ENVIRONMENT"); + case G_CCMUX_1 : return sprintf(buf, "1"); + default : return sprintf(buf, "0"); + } +} + +static int strarg_acmuxabd(char *buf, uint32_t arg) +{ + switch (arg) { + case G_ACMUX_COMBINED : return sprintf(buf, "COMBINED"); + case G_ACMUX_TEXEL0 : return sprintf(buf, "TEXEL0"); + case G_ACMUX_TEXEL1 : return sprintf(buf, "TEXEL1"); + case G_ACMUX_PRIMITIVE : return sprintf(buf, "PRIMITIVE"); + case G_ACMUX_SHADE : return sprintf(buf, "SHADE"); + case G_ACMUX_ENVIRONMENT : return sprintf(buf, "ENVIRONMENT"); + case G_ACMUX_1 : return sprintf(buf, "1"); + default : return sprintf(buf, "0"); + } +} + +static int strarg_acmuxc(char *buf, uint32_t arg) +{ + switch (arg) { + case G_ACMUX_LOD_FRACTION : return sprintf(buf, "LOD_FRACTION"); + case G_ACMUX_TEXEL0 : return sprintf(buf, "TEXEL0"); + case G_ACMUX_TEXEL1 : return sprintf(buf, "TEXEL1"); + case G_ACMUX_PRIMITIVE : return sprintf(buf, "PRIMITIVE"); + case G_ACMUX_SHADE : return sprintf(buf, "SHADE"); + case G_ACMUX_ENVIRONMENT : return sprintf(buf, "ENVIRONMENT"); + case G_ACMUX_PRIM_LOD_FRAC : return sprintf(buf, "PRIM_LOD_FRAC"); + default : return sprintf(buf, "0"); + } +} + +struct cc_mode +{ + int a; + int b; + int c; + int d; + int Aa; + int Ab; + int Ac; + int Ad; +}; + +struct cc_preset +{ + struct cc_mode mode; + const char *name; +}; + +#define CC_(a,b,c,d,Aa,Ab,Ac,Ad) { \ + G_CCMUX_##a, G_CCMUX_##b, \ + G_CCMUX_##c, G_CCMUX_##d, \ + G_ACMUX_##Aa, G_ACMUX_##Ab, \ + G_ACMUX_##Ac, G_ACMUX_##Ad \ + } +#define CC(m) CC_(m) +static struct cc_preset cc_presets[] = +{ + {CC(G_CC_MODULATEI), "G_CC_MODULATEI"}, + {CC(G_CC_MODULATEIA), "G_CC_MODULATEIA"}, + {CC(G_CC_MODULATEIDECALA), "G_CC_MODULATEIDECALA"}, + {CC(G_CC_MODULATERGB), "G_CC_MODULATERGB"}, + {CC(G_CC_MODULATERGBA), "G_CC_MODULATERGBA"}, + {CC(G_CC_MODULATERGBDECALA), "G_CC_MODULATERGBDECALA"}, + {CC(G_CC_MODULATEI_PRIM), "G_CC_MODULATEI_PRIM"}, + {CC(G_CC_MODULATEIA_PRIM), "G_CC_MODULATEIA_PRIM"}, + {CC(G_CC_MODULATEIDECALA_PRIM), "G_CC_MODULATEIDECALA_PRIM"}, + {CC(G_CC_MODULATERGB_PRIM), "G_CC_MODULATERGB_PRIM"}, + {CC(G_CC_MODULATERGBA_PRIM), "G_CC_MODULATERGBA_PRIM"}, + {CC(G_CC_MODULATERGBDECALA_PRIM), "G_CC_MODULATERGBDECALA_PRIM"}, + {CC(G_CC_DECALRGB), "G_CC_DECALRGB"}, + {CC(G_CC_DECALRGBA), "G_CC_DECALRGBA"}, + {CC(G_CC_BLENDI), "G_CC_BLENDI"}, + {CC(G_CC_BLENDIA), "G_CC_BLENDIA"}, + {CC(G_CC_BLENDIDECALA), "G_CC_BLENDIDECALA"}, + {CC(G_CC_BLENDRGBA), "G_CC_BLENDRGBA"}, + {CC(G_CC_BLENDRGBDECALA), "G_CC_BLENDRGBDECALA"}, + {CC(G_CC_REFLECTRGB), "G_CC_REFLECTRGB"}, + {CC(G_CC_REFLECTRGBDECALA), "G_CC_REFLECTRGBDECALA"}, + {CC(G_CC_HILITERGB), "G_CC_HILITERGB"}, + {CC(G_CC_HILITERGBA), "G_CC_HILITERGBA"}, + {CC(G_CC_HILITERGBDECALA), "G_CC_HILITERGBDECALA"}, + {CC(G_CC_1CYUV2RGB), "G_CC_1CYUV2RGB"}, + {CC(G_CC_PRIMITIVE), "G_CC_PRIMITIVE"}, + {CC(G_CC_SHADE), "G_CC_SHADE"}, + {CC(G_CC_ADDRGB), "G_CC_ADDRGB"}, + {CC(G_CC_ADDRGBDECALA), "G_CC_ADDRGBDECALA"}, + {CC(G_CC_SHADEDECALA), "G_CC_SHADEDECALA"}, + {CC(G_CC_BLENDPE), "G_CC_BLENDPE"}, + {CC(G_CC_BLENDPEDECALA), "G_CC_BLENDPEDECALA"}, + {CC(G_CC_TRILERP), "G_CC_TRILERP"}, + {CC(G_CC_INTERFERENCE), "G_CC_INTERFERENCE"}, + {CC(G_CC_MODULATEI2), "G_CC_MODULATEI2"}, + {CC(G_CC_MODULATEIA2), "G_CC_MODULATEIA2"}, + {CC(G_CC_MODULATERGB2), "G_CC_MODULATERGB2"}, + {CC(G_CC_MODULATERGBA2), "G_CC_MODULATERGBA2"}, + {CC(G_CC_MODULATEI_PRIM2), "G_CC_MODULATEI_PRIM2"}, + {CC(G_CC_MODULATEIA_PRIM2), "G_CC_MODULATEIA_PRIM2"}, + {CC(G_CC_MODULATERGB_PRIM2), "G_CC_MODULATERGB_PRIM2"}, + {CC(G_CC_MODULATERGBA_PRIM2), "G_CC_MODULATERGBA_PRIM2"}, + {CC(G_CC_DECALRGB2), "G_CC_DECALRGB2"}, + {CC(G_CC_BLENDI2), "G_CC_BLENDI2"}, + {CC(G_CC_BLENDIA2), "G_CC_BLENDIA2"}, + {CC(G_CC_HILITERGB2), "G_CC_HILITERGB2"}, + {CC(G_CC_HILITERGBA2), "G_CC_HILITERGBA2"}, + {CC(G_CC_HILITERGBDECALA2), "G_CC_HILITERGBDECALA2"}, + {CC(G_CC_HILITERGBPASSA2), "G_CC_HILITERGBPASSA2"}, + {CC(G_CC_CHROMA_KEY2), "G_CC_CHROMA_KEY2"}, + {CC(G_CC_YUV2RGB), "G_CC_YUV2RGB"}, + {CC(G_CC_PASS2), "G_CC_PASS2"}, +}; +#undef CC_ +#undef CC + +static int strarg_ccpre(char *buf, uint32_t arg) +{ + return sprintf(buf, "%s", cc_presets[arg].name); +} + +static int strarg_sc(char *buf, uint32_t arg) +{ + switch (arg) { + case G_SC_NON_INTERLACE : return sprintf(buf, "G_SC_NON_INTERLACE"); + case G_SC_EVEN_INTERLACE : return sprintf(buf, "G_SC_EVEN_INTERLACE"); + case G_SC_ODD_INTERLACE : return sprintf(buf, "G_SC_ODD_INTERLACE"); + default : return sprintf(buf, "%" PRIi32, (int32_t)arg); + } +} + +#if defined(F3DEX_GBI) || defined(F3DEX_GBI_2) +static int strarg_bz(char *buf, uint32_t arg) +{ + switch (arg) { + case G_BZ_PERSP : return sprintf(buf, "G_BZ_PERSP"); + default : return sprintf(buf, "G_BZ_ORTHO"); + } +} +#endif + +static int strarg_mp(char *buf, uint32_t arg) +{ + int p = 0; + if (arg & G_MTX_PUSH) + strappf("G_MTX_PUSH"); + else + strappf("G_MTX_NOPUSH"); + if (arg & G_MTX_LOAD) + strappf(" | G_MTX_LOAD"); + else + strappf(" | G_MTX_MUL"); + if (arg & G_MTX_PROJECTION) + strappf(" | G_MTX_PROJECTION"); + else + strappf(" | G_MTX_MODELVIEW"); + for (int i = 3; i < 8; ++i) + if (arg & (1 << i)) + strappf(" | 0x%02x", 1 << i); + return p; +} + +static int strarg_ms(char *buf, uint32_t arg) +{ + switch (arg) { + case G_MTX_MODELVIEW : return sprintf(buf, "G_MTX_MODELVIEW"); + case G_MTX_PROJECTION : return sprintf(buf, "G_MTX_PROJECTION"); + default : return sprintf(buf, "%" PRIi32, (int32_t)arg); + } +} + +static int strarg_mw(char *buf, uint32_t arg) +{ + switch (arg) { + case G_MW_MATRIX : return sprintf(buf, "G_MW_MATRIX"); + case G_MW_NUMLIGHT : return sprintf(buf, "G_MW_NUMLIGHT"); + case G_MW_CLIP : return sprintf(buf, "G_MW_CLIP"); + case G_MW_SEGMENT : return sprintf(buf, "G_MW_SEGMENT"); + case G_MW_FOG : return sprintf(buf, "G_MW_FOG"); + case G_MW_LIGHTCOL : return sprintf(buf, "G_MW_LIGHTCOL"); + case G_MW_PERSPNORM : return sprintf(buf, "G_MW_PERSPNORM"); +#if defined(F3D_GBI) || defined(F3DEX_GBI) + case G_MW_POINTS : return sprintf(buf, "G_MW_POINTS"); +#endif +#if defined(F3DEX_GBI_2) + case G_MW_FORCEMTX : return sprintf(buf, "G_MW_FORCEMTX"); +#endif + default : return sprintf(buf, "%" PRIi32, (int32_t)arg); + } +} + +static int strarg_mwo_clip(char *buf, uint32_t arg) +{ + switch (arg) { + case G_MWO_CLIP_RNX : return sprintf(buf, "G_MWO_CLIP_RNX"); + case G_MWO_CLIP_RNY : return sprintf(buf, "G_MWO_CLIP_RNY"); + case G_MWO_CLIP_RPX : return sprintf(buf, "G_MWO_CLIP_RPX"); + case G_MWO_CLIP_RPY : return sprintf(buf, "G_MWO_CLIP_RPY"); + default : return sprintf(buf, "0x%04" PRIX16, (uint16_t)arg); + } +} + +static int strarg_mwo_lightcol(char *buf, uint32_t arg) +{ + switch (arg) { + case G_MWO_aLIGHT_1 : return sprintf(buf, "G_MWO_aLIGHT_1"); + case G_MWO_bLIGHT_1 : return sprintf(buf, "G_MWO_bLIGHT_1"); + case G_MWO_aLIGHT_2 : return sprintf(buf, "G_MWO_aLIGHT_2"); + case G_MWO_bLIGHT_2 : return sprintf(buf, "G_MWO_bLIGHT_2"); + case G_MWO_aLIGHT_3 : return sprintf(buf, "G_MWO_aLIGHT_3"); + case G_MWO_bLIGHT_3 : return sprintf(buf, "G_MWO_bLIGHT_3"); + case G_MWO_aLIGHT_4 : return sprintf(buf, "G_MWO_aLIGHT_4"); + case G_MWO_bLIGHT_4 : return sprintf(buf, "G_MWO_bLIGHT_4"); + case G_MWO_aLIGHT_5 : return sprintf(buf, "G_MWO_aLIGHT_5"); + case G_MWO_bLIGHT_5 : return sprintf(buf, "G_MWO_bLIGHT_5"); + case G_MWO_aLIGHT_6 : return sprintf(buf, "G_MWO_aLIGHT_6"); + case G_MWO_bLIGHT_6 : return sprintf(buf, "G_MWO_bLIGHT_6"); + case G_MWO_aLIGHT_7 : return sprintf(buf, "G_MWO_aLIGHT_7"); + case G_MWO_bLIGHT_7 : return sprintf(buf, "G_MWO_bLIGHT_7"); + case G_MWO_aLIGHT_8 : return sprintf(buf, "G_MWO_aLIGHT_8"); + case G_MWO_bLIGHT_8 : return sprintf(buf, "G_MWO_bLIGHT_8"); + default : return sprintf(buf, "0x%04" PRIX16, (uint16_t)arg); + } +} + +static int strarg_light(char *buf, uint32_t arg) +{ + return sprintf(buf, "LIGHT_%" PRIi32, (int32_t)arg); +} + +static int strarg_lightsn(char *buf, uint32_t arg) +{ + return sprintf(buf, "*(Lightsn*)0x%08" PRIX32, arg); +} + +static int strarg_mwo_matrix(char *buf, uint32_t arg) +{ + switch (arg) { + case G_MWO_MATRIX_XX_XY_I : return sprintf(buf, "G_MWO_MATRIX_XX_XY_I"); + case G_MWO_MATRIX_XZ_XW_I : return sprintf(buf, "G_MWO_MATRIX_XZ_XW_I"); + case G_MWO_MATRIX_YX_YY_I : return sprintf(buf, "G_MWO_MATRIX_YX_YY_I"); + case G_MWO_MATRIX_YZ_YW_I : return sprintf(buf, "G_MWO_MATRIX_YZ_YW_I"); + case G_MWO_MATRIX_ZX_ZY_I : return sprintf(buf, "G_MWO_MATRIX_ZX_ZY_I"); + case G_MWO_MATRIX_ZZ_ZW_I : return sprintf(buf, "G_MWO_MATRIX_ZZ_ZW_I"); + case G_MWO_MATRIX_WX_WY_I : return sprintf(buf, "G_MWO_MATRIX_WX_WY_I"); + case G_MWO_MATRIX_WZ_WW_I : return sprintf(buf, "G_MWO_MATRIX_WZ_WW_I"); + case G_MWO_MATRIX_XX_XY_F : return sprintf(buf, "G_MWO_MATRIX_XX_XY_F"); + case G_MWO_MATRIX_XZ_XW_F : return sprintf(buf, "G_MWO_MATRIX_XZ_XW_F"); + case G_MWO_MATRIX_YX_YY_F : return sprintf(buf, "G_MWO_MATRIX_YX_YY_F"); + case G_MWO_MATRIX_YZ_YW_F : return sprintf(buf, "G_MWO_MATRIX_YZ_YW_F"); + case G_MWO_MATRIX_ZX_ZY_F : return sprintf(buf, "G_MWO_MATRIX_ZX_ZY_F"); + case G_MWO_MATRIX_ZZ_ZW_F : return sprintf(buf, "G_MWO_MATRIX_ZZ_ZW_F"); + case G_MWO_MATRIX_WX_WY_F : return sprintf(buf, "G_MWO_MATRIX_WX_WY_F"); + case G_MWO_MATRIX_WZ_WW_F : return sprintf(buf, "G_MWO_MATRIX_WZ_WW_F"); + default : return sprintf(buf, "0x%04" PRIX16, + (uint16_t)arg); + } +} + +static int strarg_mwo_point(char *buf, uint32_t arg) +{ + switch (arg) { + case G_MWO_POINT_RGBA : return sprintf(buf, "G_MWO_POINT_RGBA"); + case G_MWO_POINT_ST : return sprintf(buf, "G_MWO_POINT_ST"); + case G_MWO_POINT_XYSCREEN : return sprintf(buf, "G_MWO_POINT_XYSCREEN"); + case G_MWO_POINT_ZSCREEN : return sprintf(buf, "G_MWO_POINT_ZSCREEN"); + default : return sprintf(buf, "0x%04" PRIX16, + (uint16_t)arg); + } +} + +static int strarg_mv(char *buf, uint32_t arg) +{ + switch (arg) { + case G_MV_VIEWPORT : return sprintf(buf, "G_MV_VIEWPORT"); +#if defined(F3D_GBI) || defined(F3DEX_GBI) + case G_MV_LOOKATY : return sprintf(buf, "G_MV_LOOKATY"); + case G_MV_LOOKATX : return sprintf(buf, "G_MV_LOOKATX"); + case G_MV_L0 : return sprintf(buf, "G_MV_L0"); + case G_MV_L1 : return sprintf(buf, "G_MV_L1"); + case G_MV_L2 : return sprintf(buf, "G_MV_L2"); + case G_MV_L3 : return sprintf(buf, "G_MV_L3"); + case G_MV_L4 : return sprintf(buf, "G_MV_L4"); + case G_MV_L5 : return sprintf(buf, "G_MV_L5"); + case G_MV_L6 : return sprintf(buf, "G_MV_L6"); + case G_MV_L7 : return sprintf(buf, "G_MV_L7"); + case G_MV_TXTATT : return sprintf(buf, "G_MV_TXTATT"); + case G_MV_MATRIX_2 : return sprintf(buf, "G_MV_MATRIX_2"); + case G_MV_MATRIX_3 : return sprintf(buf, "G_MV_MATRIX_3"); + case G_MV_MATRIX_4 : return sprintf(buf, "G_MV_MATRIX_4"); + case G_MV_MATRIX_1 : return sprintf(buf, "G_MV_MATRIX_1"); +#elif defined(F3DEX_GBI_2) + case G_MV_MMTX : return sprintf(buf, "G_MV_MMTX"); + case G_MV_PMTX : return sprintf(buf, "G_MV_PMTX"); + case G_MV_LIGHT : return sprintf(buf, "G_MV_LIGHT"); + case G_MV_POINT : return sprintf(buf, "G_MV_POINT"); + case G_MV_MATRIX : return sprintf(buf, "G_MV_MATRIX"); +#endif + default : return sprintf(buf, "%" PRIi32, (int32_t)arg); + } +} + +static int strarg_cr(char *buf, uint32_t arg) +{ + switch (arg) { + case FRUSTRATIO_1 : return sprintf(buf, "FRUSTRATIO_1"); + case FRUSTRATIO_2 : return sprintf(buf, "FRUSTRATIO_2"); + case FRUSTRATIO_3 : return sprintf(buf, "FRUSTRATIO_3"); + case FRUSTRATIO_4 : return sprintf(buf, "FRUSTRATIO_4"); + case FRUSTRATIO_5 : return sprintf(buf, "FRUSTRATIO_5"); + case FRUSTRATIO_6 : return sprintf(buf, "FRUSTRATIO_6"); + default : return sprintf(buf, "%" PRIi32, (int32_t)arg); + } +} + +int gfx_dis_invd(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_INVD; + insn->n_gfx = 1; + insn->arg[0] = hi; + insn->arg[1] = lo; + insn->strarg[0] = strarg_x32; + insn->strarg[1] = strarg_x32; + return 1; +} + +int gfx_dis_dpFillRectangle(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_DPFILLRECTANGLE; + insn->n_gfx = 1; + insn->arg[0] = getfield(lo, 10, 14); + insn->arg[1] = getfield(lo, 10, 2); + insn->arg[2] = getfield(hi, 10, 14); + insn->arg[3] = getfield(hi, 10, 2); + return 0; +} + +int gfx_dis_dpFullSync(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_DPFULLSYNC; + insn->n_gfx = 1; + return 0; +} + +int gfx_dis_dpLoadSync(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_DPLOADSYNC; + insn->n_gfx = 1; + return 0; +} + +int gfx_dis_dpTileSync(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_DPTILESYNC; + insn->n_gfx = 1; + return 0; +} + +int gfx_dis_dpPipeSync(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_DPPIPESYNC; + insn->n_gfx = 1; + return 0; +} + +int gfx_col_dpLoadTLUT_pal16(struct gfx_insn *insn, int n_insn) +{ + if (n_insn < 6) + return 0; + if (insn[0].def != GFX_ID_DPSETTEXTUREIMAGE || + insn[0].arg[0] != G_IM_FMT_RGBA || insn[0].arg[1] != G_IM_SIZ_16b || + insn[0].arg[2] != 1) + { + return 0; + } + uint32_t dram = insn[0].arg[3]; + if (insn[1].def != GFX_ID_DPTILESYNC) + return 0; + if (insn[2].def != GFX_ID_DPSETTILE || + insn[2].arg[0] != 0 || insn[2].arg[1] != 0 || insn[2].arg[2] != 0 || + insn[2].arg[3] < 0x100 || insn[2].arg[3] % 0x10 != 0 || + insn[2].arg[4] != G_TX_LOADTILE || insn[2].arg[5] != 0 || + insn[2].arg[6] != 0 || insn[2].arg[7] != 0 || insn[2].arg[8] != 0 || + insn[2].arg[9] != 0 || insn[2].arg[10] != 0 || insn[2].arg[11] != 0) + { + return 0; + } + int pal = (insn[2].arg[3] - 0x100) / 0x10; + if (insn[3].def != GFX_ID_DPLOADSYNC) + return 0; + if (insn[4].def != GFX_ID_DPLOADTLUTCMD || insn[4].arg[0] != G_TX_LOADTILE || + insn[4].arg[1] != 15) + { + return 0; + } + if (insn[5].def != GFX_ID_DPPIPESYNC) + return 0; + memmove(&insn[1], &insn[6], sizeof(*insn) * (n_insn - 6)); + memset(insn, 0, sizeof(*insn)); + insn->def = GFX_ID_DPLOADTLUT_PAL16; + insn->n_gfx = 6; + insn->arg[0] = pal; + insn->arg[1] = dram; + insn->strarg[1] = strarg_x32; + return 5; +} + +int gfx_col_dpLoadTLUT_pal256(struct gfx_insn *insn, int n_insn) +{ + if (n_insn < 6) + return 0; + if (insn[0].def != GFX_ID_DPSETTEXTUREIMAGE || + insn[0].arg[0] != G_IM_FMT_RGBA || insn[0].arg[1] != G_IM_SIZ_16b || + insn[0].arg[2] != 1) + { + return 0; + } + uint32_t dram = insn[0].arg[3]; + if (insn[1].def != GFX_ID_DPTILESYNC) + return 0; + if (insn[2].def != GFX_ID_DPSETTILE || + insn[2].arg[0] != 0 || insn[2].arg[1] != 0 || insn[2].arg[2] != 0 || + insn[2].arg[3] != 0x100 || + insn[2].arg[4] != G_TX_LOADTILE || insn[2].arg[5] != 0 || + insn[2].arg[6] != 0 || insn[2].arg[7] != 0 || insn[2].arg[8] != 0 || + insn[2].arg[9] != 0 || insn[2].arg[10] != 0 || insn[2].arg[11] != 0) + { + return 0; + } + if (insn[3].def != GFX_ID_DPLOADSYNC) + return 0; + if (insn[4].def != GFX_ID_DPLOADTLUTCMD || insn[4].arg[0] != G_TX_LOADTILE || + insn[4].arg[1] != 255) + { + return 0; + } + if (insn[5].def != GFX_ID_DPPIPESYNC) + return 0; + memmove(&insn[1], &insn[6], sizeof(*insn) * (n_insn - 6)); + memset(insn, 0, sizeof(*insn)); + insn->def = GFX_ID_DPLOADTLUT_PAL256; + insn->n_gfx = 6; + insn->arg[0] = dram; + insn->strarg[0] = strarg_x32; + return 5; +} + +static int gfx_col_ltb(struct gfx_insn *insn, int n_insn, + enum gfx_insn_def def, + _Bool mdxt, _Bool mtmem, _Bool mrt, + _Bool myuv, _Bool m4b) +{ + if (n_insn < 7) + return 0; + if (insn[0].def != GFX_ID_DPSETTEXTUREIMAGE || insn[0].arg[2] != 1) + return 0; + g_ifmt_t fmt = insn[0].arg[0]; + g_isiz_t ldsiz = insn[0].arg[1]; + uint32_t timg = insn[0].arg[3]; + if (myuv && fmt != G_IM_FMT_YUV) + return 0; + if (insn[1].def != GFX_ID_DPSETTILE || + insn[1].arg[0] != fmt || insn[1].arg[1] != ldsiz || + insn[1].arg[2] != 0 || insn[1].arg[4] != G_TX_LOADTILE || + insn[1].arg[5] != 0) + { + return 0; + } + uint32_t tmem = insn[1].arg[3]; + int cms = insn[1].arg[9]; + int cmt = insn[1].arg[6]; + int masks = insn[1].arg[10]; + int maskt = insn[1].arg[7]; + int shifts = insn[1].arg[11]; + int shiftt = insn[1].arg[8]; + if (insn[2].def != GFX_ID_DPLOADSYNC) + return 0; + if (insn[3].def != GFX_ID_DPLOADBLOCK || insn[3].arg[0] != G_TX_LOADTILE || + insn[3].arg[1] != 0 || insn[3].arg[2] != 0) + { + return 0; + } + qu102_t ldlrs = insn[3].arg[3]; + int lddxt = insn[3].arg[4]; + if (insn[4].def != GFX_ID_DPPIPESYNC) + return 0; + if (insn[5].def != GFX_ID_DPSETTILE || + insn[5].arg[0] != fmt || G_SIZ_LDSIZ(insn[5].arg[1]) != ldsiz || + insn[5].arg[3] != tmem || + insn[5].arg[6] != cmt || insn[5].arg[7] != maskt || + insn[5].arg[8] != shiftt || insn[5].arg[9] != cms || + insn[5].arg[10] != masks || insn[5].arg[11] != shifts) + { + return 0; + } + int siz = insn[5].arg[1]; + int rdline = insn[5].arg[2]; + int rt = insn[5].arg[4]; + int pal = insn[5].arg[5]; + if (m4b && siz != G_IM_SIZ_4b) + return 0; + if (!(mrt && rt != G_TX_RENDERTILE && tmem == 0x0) && (tmem != 0) != mtmem) + return 0; + if ((rt != G_TX_RENDERTILE) != mrt) + return 0; + if (insn[6].def != GFX_ID_DPSETTILESIZE || insn[6].arg[0] != rt || + insn[6].arg[1] != 0 || insn[6].arg[2] != 0 || + (insn[6].arg[3] & 3) || (insn[6].arg[4] & 3)) + { + return 0; + } + int width = (insn[6].arg[3] >> 2) + 1; + int height = (insn[6].arg[4] >> 2) + 1; + int lrs = ((width * height + 1) * G_SIZ_BITS(siz) - 1) / + G_SIZ_BITS(G_SIZ_LDSIZ(siz)) - 1; + int dxt = 0; + if (!mdxt) { + dxt = (width * G_SIZ_BITS(siz) <= 64 ? (1 << 11) : + ((1 << 11) + width * G_SIZ_BITS(siz) / 64 - 1) / + (width * G_SIZ_BITS(siz) / 64)); + } + 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 0; + memmove(&insn[1], &insn[7], sizeof(*insn) * (n_insn - 7)); + memset(insn, 0, sizeof(*insn)); + insn->def = def; + insn->n_gfx = 7; + int i = 0; + insn->arg[i] = timg; + insn->strarg[i++] = strarg_x32; + if (mtmem) { + insn->arg[i] = tmem; + insn->strarg[i++] = strarg_x16; + } + if (mrt) { + insn->arg[i] = rt; + insn->strarg[i++] = strarg_tile; + } + insn->arg[i] = fmt; + insn->strarg[i++] = strarg_fmt; + if (!m4b) { + insn->arg[i] = siz; + insn->strarg[i++] = strarg_siz; + } + insn->arg[i++] = width; + insn->arg[i++] = height; + insn->arg[i++] = pal; + insn->arg[i] = cms; + insn->strarg[i++] = strarg_cm; + insn->arg[i] = cmt; + insn->strarg[i++] = strarg_cm; + insn->arg[i] = masks; + insn->strarg[i++] = strarg_tm; + insn->arg[i] = maskt; + insn->strarg[i++] = strarg_tm; + insn->arg[i] = shifts; + insn->strarg[i++] = strarg_ts; + insn->arg[i] = shiftt; + insn->strarg[i++] = strarg_ts; + return 6; +} + +int gfx_col_dpLoadMultiBlockYuvS(struct gfx_insn *insn, int n_insn) +{ + return gfx_col_ltb(insn, n_insn, GFX_ID_DPLOADMULTIBLOCKYUVS, 1, 1, 1, 1, 0); +} + +int gfx_col_dpLoadMultiBlockYuv(struct gfx_insn *insn, int n_insn) +{ + return gfx_col_ltb(insn, n_insn, GFX_ID_DPLOADMULTIBLOCKYUV, 0, 1, 1, 1, 0); +} + +int gfx_col_dpLoadMultiBlock_4bS(struct gfx_insn *insn, int n_insn) +{ + return gfx_col_ltb(insn, n_insn, GFX_ID_DPLOADMULTIBLOCK_4BS, 1, 1, 1, 0, 1); +} + +int gfx_col_dpLoadMultiBlock_4b(struct gfx_insn *insn, int n_insn) +{ + return gfx_col_ltb(insn, n_insn, GFX_ID_DPLOADMULTIBLOCK_4B, 0, 1, 1, 0, 1); +} + +int gfx_col_dpLoadMultiBlockS(struct gfx_insn *insn, int n_insn) +{ + return gfx_col_ltb(insn, n_insn, GFX_ID_DPLOADMULTIBLOCKS, 1, 1, 1, 0, 0); +} + +int gfx_col_dpLoadMultiBlock(struct gfx_insn *insn, int n_insn) +{ + return gfx_col_ltb(insn, n_insn, GFX_ID_DPLOADMULTIBLOCK, 0, 1, 1, 0, 0); +} + +int gfx_col__dpLoadTextureBlockYuvS(struct gfx_insn *insn, int n_insn) +{ + return gfx_col_ltb(insn, n_insn, GFX_ID__DPLOADTEXTUREBLOCKYUVS, + 1, 1, 0, 1, 0); +} + +int gfx_col__dpLoadTextureBlockYuv(struct gfx_insn *insn, int n_insn) +{ + return gfx_col_ltb(insn, n_insn, GFX_ID__DPLOADTEXTUREBLOCKYUV, + 0, 1, 0, 1, 0); +} + +int gfx_col__dpLoadTextureBlock_4bS(struct gfx_insn *insn, int n_insn) +{ + return gfx_col_ltb(insn, n_insn, GFX_ID__DPLOADTEXTUREBLOCK_4BS, + 1, 1, 0, 0, 1); +} + +int gfx_col__dpLoadTextureBlock_4b(struct gfx_insn *insn, int n_insn) +{ + return gfx_col_ltb(insn, n_insn, GFX_ID__DPLOADTEXTUREBLOCK_4B, + 0, 1, 0, 0, 1); +} + +int gfx_col__dpLoadTextureBlockS(struct gfx_insn *insn, int n_insn) +{ + return gfx_col_ltb(insn, n_insn, GFX_ID__DPLOADTEXTUREBLOCKS, + 1, 1, 0, 0, 0); +} + +int gfx_col__dpLoadTextureBlock(struct gfx_insn *insn, int n_insn) +{ + return gfx_col_ltb(insn, n_insn, GFX_ID__DPLOADTEXTUREBLOCK, + 0, 1, 0, 0, 0); +} + +int gfx_col_dpLoadTextureBlockYuvS(struct gfx_insn *insn, int n_insn) +{ + return gfx_col_ltb(insn, n_insn, GFX_ID_DPLOADTEXTUREBLOCKYUVS, + 1, 0, 0, 1, 0); +} + +int gfx_col_dpLoadTextureBlockYuv(struct gfx_insn *insn, int n_insn) +{ + return gfx_col_ltb(insn, n_insn, GFX_ID_DPLOADTEXTUREBLOCKYUV, + 0, 0, 0, 1, 0); +} + +int gfx_col_dpLoadTextureBlock_4bS(struct gfx_insn *insn, int n_insn) +{ + return gfx_col_ltb(insn, n_insn, GFX_ID_DPLOADTEXTUREBLOCK_4BS, + 1, 0, 0, 0, 1); +} + +int gfx_col_dpLoadTextureBlock_4b(struct gfx_insn *insn, int n_insn) +{ + return gfx_col_ltb(insn, n_insn, GFX_ID_DPLOADTEXTUREBLOCK_4B, + 0, 0, 0, 0, 1); +} + +int gfx_col_dpLoadTextureBlockS(struct gfx_insn *insn, int n_insn) +{ + return gfx_col_ltb(insn, n_insn, GFX_ID_DPLOADTEXTUREBLOCKS, + 1, 0, 0, 0, 0); +} + +int gfx_col_dpLoadTextureBlock(struct gfx_insn *insn, int n_insn) +{ + return gfx_col_ltb(insn, n_insn, GFX_ID_DPLOADTEXTUREBLOCK, + 0, 0, 0, 0, 0); +} + +static int gfx_col_ltt(struct gfx_insn *insn, int n_insn, + enum gfx_insn_def def, + _Bool mtmem, _Bool mrt, _Bool myuv, _Bool m4b) +{ + if (n_insn < 7) + return 0; + if (insn[0].def != GFX_ID_DPSETTEXTUREIMAGE) + return 0; + g_ifmt_t fmt = insn[0].arg[0]; + g_isiz_t ldsiz = insn[0].arg[1]; + int width = insn[0].arg[2]; + if (m4b) { + if (ldsiz != G_IM_SIZ_8b) + return 0; + width *= 2; + } + uint32_t timg = insn[0].arg[3]; + if (myuv && fmt != G_IM_FMT_YUV) + return 0; + if (insn[1].def != GFX_ID_DPSETTILE || + insn[1].arg[0] != fmt || insn[1].arg[1] != ldsiz || + insn[1].arg[4] != G_TX_LOADTILE || insn[1].arg[5] != 0) + { + return 0; + } + int ldline = insn[1].arg[2]; + uint32_t tmem = insn[1].arg[3]; + int cms = insn[1].arg[9]; + int cmt = insn[1].arg[6]; + int masks = insn[1].arg[10]; + int maskt = insn[1].arg[7]; + int shifts = insn[1].arg[11]; + int shiftt = insn[1].arg[8]; + if (insn[2].def != GFX_ID_DPLOADSYNC) + return 0; + if (insn[3].def != GFX_ID_DPLOADTILE || insn[3].arg[0] != G_TX_LOADTILE || + (insn[3].arg[1] & 1) || (insn[3].arg[2] & 3) || + (insn[3].arg[3] & 1) || (insn[3].arg[4] & 3)) + { + return 0; + } + qu102_t lduls = insn[3].arg[1]; + qu102_t ldult = insn[3].arg[2]; + qu102_t ldlrs = insn[3].arg[3]; + qu102_t ldlrt = insn[3].arg[4]; + if (insn[4].def != GFX_ID_DPPIPESYNC) + return 0; + if (insn[5].def != GFX_ID_DPSETTILE || + insn[5].arg[0] != fmt || insn[5].arg[2] != ldline || + insn[5].arg[3] != tmem || + insn[5].arg[6] != cmt || insn[5].arg[7] != maskt || + insn[5].arg[8] != shiftt || insn[5].arg[9] != cms || + insn[5].arg[10] != masks || insn[5].arg[11] != shifts) + { + return 0; + } + int siz = insn[5].arg[1]; + int rt = insn[5].arg[4]; + int pal = insn[5].arg[5]; + if (m4b) { + if (siz != G_IM_SIZ_4b) + return 0; + } + else if (G_SIZ_LDSIZ(siz) != ldsiz) + return 0; + if (!(mrt && rt != G_TX_RENDERTILE && tmem == 0x0) && (tmem != 0) != mtmem) + return 0; + if ((rt != G_TX_RENDERTILE) != mrt) + return 0; + if (insn[6].def != GFX_ID_DPSETTILESIZE || insn[6].arg[0] != rt || + (insn[6].arg[1] & 3) || (insn[6].arg[2] & 3) || + (insn[6].arg[3] & 3) || (insn[6].arg[4] & 3)) + { + return 0; + } + int uls = insn[6].arg[1] >> 2; + int ult = insn[6].arg[2] >> 2; + int lrs = insn[6].arg[3] >> 2; + int lrt = insn[6].arg[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 0; + } + else if (lduls != qu102(uls) || ldlrs != qu102(lrs)) + return 0; + if (ldult != qu102(ult) || ldlrt != qu102(lrt) || ldline != line) + return 0; + memmove(&insn[1], &insn[7], sizeof(*insn) * (n_insn - 7)); + memset(insn, 0, sizeof(*insn)); + insn->def = def; + insn->n_gfx = 7; + int i = 0; + insn->arg[i] = timg; + insn->strarg[i++] = strarg_x32; + if (mtmem) { + insn->arg[i] = tmem; + insn->strarg[i++] = strarg_x16; + } + if (mrt) { + insn->arg[i] = rt; + insn->strarg[i++] = strarg_tile; + } + insn->arg[i] = fmt; + insn->strarg[i++] = strarg_fmt; + if (!m4b) { + insn->arg[i] = siz; + insn->strarg[i++] = strarg_siz; + } + insn->arg[i++] = width; + insn->arg[i++] = 0; + insn->arg[i++] = uls; + insn->arg[i++] = ult; + insn->arg[i++] = lrs; + insn->arg[i++] = lrt; + insn->arg[i++] = pal; + insn->arg[i] = cms; + insn->strarg[i++] = strarg_cm; + insn->arg[i] = cmt; + insn->strarg[i++] = strarg_cm; + insn->arg[i] = masks; + insn->strarg[i++] = strarg_tm; + insn->arg[i] = maskt; + insn->strarg[i++] = strarg_tm; + insn->arg[i] = shifts; + insn->strarg[i++] = strarg_ts; + insn->arg[i] = shiftt; + insn->strarg[i++] = strarg_ts; + return 6; +} + +int gfx_col_dpLoadMultiTileYuv(struct gfx_insn *insn, int n_insn) +{ + return gfx_col_ltt(insn, n_insn, GFX_ID_DPLOADMULTITILEYUV, 1, 1, 1, 0); +} + +int gfx_col_dpLoadMultiTile_4b(struct gfx_insn *insn, int n_insn) +{ + return gfx_col_ltt(insn, n_insn, GFX_ID_DPLOADMULTITILE_4B, 1, 1, 0, 1); +} + +int gfx_col_dpLoadMultiTile(struct gfx_insn *insn, int n_insn) +{ + return gfx_col_ltt(insn, n_insn, GFX_ID_DPLOADMULTITILE, 1, 1, 0, 0); +} + +int gfx_col__dpLoadTextureTileYuv(struct gfx_insn *insn, int n_insn) +{ + return gfx_col_ltt(insn, n_insn, GFX_ID__DPLOADTEXTURETILEYUV, 1, 0, 1, 0); +} + +int gfx_col__dpLoadTextureTile_4b(struct gfx_insn *insn, int n_insn) +{ + return gfx_col_ltt(insn, n_insn, GFX_ID__DPLOADTEXTURETILE_4B, 1, 0, 0, 1); +} + +int gfx_col__dpLoadTextureTile(struct gfx_insn *insn, int n_insn) +{ + return gfx_col_ltt(insn, n_insn, GFX_ID__DPLOADTEXTURETILE, 1, 0, 0, 0); +} + +int gfx_col_dpLoadTextureTileYuv(struct gfx_insn *insn, int n_insn) +{ + return gfx_col_ltt(insn, n_insn, GFX_ID_DPLOADTEXTURETILEYUV, 0, 0, 1, 0); +} + +int gfx_col_dpLoadTextureTile_4b(struct gfx_insn *insn, int n_insn) +{ + return gfx_col_ltt(insn, n_insn, GFX_ID_DPLOADTEXTURETILE_4B, 0, 0, 0, 1); +} + +int gfx_col_dpLoadTextureTile(struct gfx_insn *insn, int n_insn) +{ + return gfx_col_ltt(insn, n_insn, GFX_ID_DPLOADTEXTURETILE, 0, 0, 0, 0); +} + +int gfx_dis_dpLoadBlock(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_DPLOADBLOCK; + insn->n_gfx = 1; + insn->arg[0] = getfield(lo, 3, 24); + insn->arg[1] = getfield(hi, 12, 12); + insn->arg[2] = getfield(hi, 12, 0); + insn->arg[3] = getfield(lo, 12, 12); + insn->arg[4] = getfield(lo, 12, 0); + insn->strarg[0] = strarg_tile; + return 0; +} + +int gfx_dis_dpNoOp(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_DPNOOP; + insn->n_gfx = 1; + return 0; +} + +int gfx_dis_dpNoOpTag(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + if (lo == 0) + return gfx_dis_dpNoOp(insn, hi, lo); + else { + insn->def = GFX_ID_DPNOOPTAG; + insn->n_gfx = 1; + insn->arg[0] = lo; + insn->strarg[0] = strarg_x32; + return 0; + } +} + +int gfx_dis_dpPipelineMode(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_DPPIPELINEMODE; + insn->n_gfx = 1; + insn->arg[0] = lo; + insn->strarg[0] = strarg_pm; + return 0; +} + +int gfx_dis_dpSetBlendColor(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_DPSETBLENDCOLOR; + insn->n_gfx = 1; + insn->arg[0] = getfield(lo, 8, 24); + insn->arg[1] = getfield(lo, 8, 16); + insn->arg[2] = getfield(lo, 8, 8); + insn->arg[3] = getfield(lo, 8, 0); + insn->strarg[0] = strarg_color; + insn->strarg[1] = strarg_color; + insn->strarg[2] = strarg_color; + insn->strarg[3] = strarg_color; + return 0; +} + +int gfx_dis_dpSetEnvColor(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_DPSETENVCOLOR; + insn->n_gfx = 1; + insn->arg[0] = getfield(lo, 8, 24); + insn->arg[1] = getfield(lo, 8, 16); + insn->arg[2] = getfield(lo, 8, 8); + insn->arg[3] = getfield(lo, 8, 0); + insn->strarg[0] = strarg_color; + insn->strarg[1] = strarg_color; + insn->strarg[2] = strarg_color; + insn->strarg[3] = strarg_color; + return 0; +} + +int gfx_dis_dpSetFillColor(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_DPSETFILLCOLOR; + insn->n_gfx = 1; + insn->arg[0] = lo; + insn->strarg[0] = strarg_x32; + return 0; +} + +int gfx_dis_dpSetFogColor(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_DPSETFOGCOLOR; + insn->n_gfx = 1; + insn->arg[0] = getfield(lo, 8, 24); + insn->arg[1] = getfield(lo, 8, 16); + insn->arg[2] = getfield(lo, 8, 8); + insn->arg[3] = getfield(lo, 8, 0); + insn->strarg[0] = strarg_color; + insn->strarg[1] = strarg_color; + insn->strarg[2] = strarg_color; + insn->strarg[3] = strarg_color; + return 0; +} + +int gfx_dis_dpSetPrimColor(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_DPSETPRIMCOLOR; + insn->n_gfx = 1; + insn->arg[0] = getfield(hi, 8, 8); + insn->arg[1] = getfield(hi, 8, 0); + insn->arg[2] = getfield(lo, 8, 24); + insn->arg[3] = getfield(lo, 8, 16); + insn->arg[4] = getfield(lo, 8, 8); + insn->arg[5] = getfield(lo, 8, 0); + insn->strarg[0] = strarg_qu08; + insn->strarg[1] = strarg_qu08; + insn->strarg[2] = strarg_color; + insn->strarg[3] = strarg_color; + insn->strarg[4] = strarg_color; + insn->strarg[5] = strarg_color; + return 0; +} + +int gfx_dis_dpSetColorImage(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_DPSETCOLORIMAGE; + insn->n_gfx = 1; + insn->arg[0] = getfield(hi, 3, 21); + insn->arg[1] = getfield(hi, 2, 19); + insn->arg[2] = getfield(hi, 12, 0) + 1; + insn->arg[3] = lo; + insn->strarg[0] = strarg_fmt; + insn->strarg[1] = strarg_siz; + insn->strarg[3] = strarg_x32; + return 0; +} + +int gfx_dis_dpSetDepthImage(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_DPSETDEPTHIMAGE; + insn->n_gfx = 1; + insn->arg[0] = lo; + insn->strarg[0] = strarg_x32; + return 0; +} + +int gfx_dis_dpSetTextureImage(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_DPSETTEXTUREIMAGE; + insn->n_gfx = 1; + insn->arg[0] = getfield(hi, 3, 21); + insn->arg[1] = getfield(hi, 2, 19); + insn->arg[2] = getfield(hi, 12, 0) + 1; + insn->arg[3] = lo; + insn->strarg[0] = strarg_fmt; + insn->strarg[1] = strarg_siz; + insn->strarg[3] = strarg_x32; + return 0; +} + +int gfx_dis_dpSetAlphaCompare(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_DPSETALPHACOMPARE; + insn->n_gfx = 1; + insn->arg[0] = lo; + insn->strarg[0] = strarg_ac; + return 0; +} + +int gfx_dis_dpSetAlphaDither(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_DPSETALPHADITHER; + insn->n_gfx = 1; + insn->arg[0] = lo; + insn->strarg[0] = strarg_ad; + return 0; +} + +int gfx_dis_dpSetColorDither(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_DPSETCOLORDITHER; + insn->n_gfx = 1; + insn->arg[0] = lo; + insn->strarg[0] = strarg_cd; + return 0; +} + +static 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); +} + +static int cc_lookup(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) { + 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; +} + +int gfx_dis_dpSetCombineMode(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_DPSETCOMBINEMODE; + insn->n_gfx = 1; + struct cc_mode m0; + struct cc_mode m1; + cc_unpack(&m0, &m1, hi, lo); + int p0 = cc_lookup(&m0); + int p1 = cc_lookup(&m1); + insn->arg[0] = p0; + insn->arg[1] = p1; + insn->strarg[0] = strarg_ccpre; + insn->strarg[1] = strarg_ccpre; + _Bool err = 0; + if (p0 == -1) { + insn->arg[0] = 0; + insn->strarg[0] = strarg_invd; + err = 1; + } + if (p1 == -1) { + insn->arg[1] = 0; + insn->strarg[1] = strarg_invd; + err = 1; + } + return err; +} + +int gfx_dis_dpSetCombineLERP(struct gfx_insn *insn, 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 gfx_dis_dpSetCombineMode(insn, hi, lo); + else { + insn->def = GFX_ID_DPSETCOMBINELERP; + insn->n_gfx = 1; + insn->arg[0] = m0.a; + insn->arg[1] = m0.b; + insn->arg[2] = m0.c; + insn->arg[3] = m0.d; + insn->arg[4] = m0.Aa; + insn->arg[5] = m0.Ab; + insn->arg[6] = m0.Ac; + insn->arg[7] = m0.Ad; + insn->arg[8] = m1.a; + insn->arg[9] = m1.b; + insn->arg[10] = m1.c; + insn->arg[11] = m1.d; + insn->arg[12] = m1.Aa; + insn->arg[13] = m1.Ab; + insn->arg[14] = m1.Ac; + insn->arg[15] = m1.Ad; + insn->strarg[0] = strarg_ccmuxa; + insn->strarg[1] = strarg_ccmuxb; + insn->strarg[2] = strarg_ccmuxc; + insn->strarg[3] = strarg_ccmuxd; + insn->strarg[4] = strarg_acmuxabd; + insn->strarg[5] = strarg_acmuxabd; + insn->strarg[6] = strarg_acmuxc; + insn->strarg[7] = strarg_acmuxabd; + insn->strarg[8] = strarg_ccmuxa; + insn->strarg[9] = strarg_ccmuxb; + insn->strarg[10] = strarg_ccmuxc; + insn->strarg[11] = strarg_ccmuxd; + insn->strarg[12] = strarg_acmuxabd; + insn->strarg[13] = strarg_acmuxabd; + insn->strarg[14] = strarg_acmuxc; + insn->strarg[15] = strarg_acmuxabd; + return 0; + } +} + +int gfx_dis_dpSetConvert(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_DPSETCONVERT; + insn->n_gfx = 1; + insn->arg[0] = sx(getfield(hi, 9, 13), 9); + insn->arg[1] = sx(getfield(hi, 9, 4), 9); + insn->arg[2] = sx((getfield(hi, 4, 0) << 5) | getfield(lo, 5, 27), 9); + insn->arg[3] = sx(getfield(lo, 9, 18), 9); + insn->arg[4] = sx(getfield(lo, 9, 9), 9); + insn->arg[5] = sx(getfield(lo, 9, 0), 9); + insn->strarg[0] = strarg_cv; + insn->strarg[1] = strarg_cv; + insn->strarg[2] = strarg_cv; + insn->strarg[3] = strarg_cv; + insn->strarg[4] = strarg_cv; + insn->strarg[5] = strarg_cv; + return 0; +} + +int gfx_dis_dpSetTextureConvert(struct gfx_insn *insn, + uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_DPSETTEXTURECONVERT; + insn->n_gfx = 1; + insn->arg[0] = lo; + insn->strarg[0] = strarg_tc; + return 0; +} + +int gfx_dis_dpSetCycleType(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_DPSETCYCLETYPE; + insn->n_gfx = 1; + insn->arg[0] = lo; + insn->strarg[0] = strarg_cyc; + return 0; +} + +int gfx_dis_dpSetDepthSource(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_DPSETDEPTHSOURCE; + insn->n_gfx = 1; + insn->arg[0] = lo; + insn->strarg[0] = strarg_zs; + return 0; +} + +int gfx_dis_dpSetCombineKey(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_DPSETCOMBINEKEY; + insn->n_gfx = 1; + insn->arg[0] = lo; + insn->strarg[0] = strarg_ck; + return 0; +} + +int gfx_dis_dpSetKeyGB(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_DPSETKEYGB; + insn->n_gfx = 1; + insn->arg[0] = getfield(lo, 8, 24); + insn->arg[1] = getfield(lo, 8, 16); + insn->arg[2] = sx(getfield(hi, 12, 12), 12); + insn->arg[3] = getfield(lo, 8, 8); + insn->arg[4] = getfield(lo, 8, 0); + insn->arg[5] = sx(getfield(hi, 12, 0), 12); + insn->strarg[0] = strarg_color; + insn->strarg[1] = strarg_color; + insn->strarg[2] = strarg_qs48; + insn->strarg[3] = strarg_color; + insn->strarg[4] = strarg_color; + insn->strarg[5] = strarg_qs48; + return 0; +} + +int gfx_dis_dpSetKeyR(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_DPSETKEYR; + insn->n_gfx = 1; + insn->arg[0] = getfield(lo, 8, 8); + insn->arg[1] = getfield(lo, 8, 0); + insn->arg[2] = sx(getfield(lo, 12, 16), 12); + insn->strarg[0] = strarg_color; + insn->strarg[1] = strarg_color; + insn->strarg[2] = strarg_qs48; + return 0; +} + +int gfx_dis_dpSetPrimDepth(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_DPSETPRIMDEPTH; + insn->n_gfx = 1; + insn->arg[0] = sx(getfield(lo, 16, 16), 16); + insn->arg[1] = sx(getfield(lo, 16, 0), 16); + return 0; +} + +int gfx_dis_dpSetRenderMode(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_DPSETRENDERMODE; + insn->n_gfx = 1; + insn->arg[0] = lo; + insn->arg[1] = lo; + insn->strarg[0] = strarg_rm1; + insn->strarg[1] = strarg_rm2; + return 0; +} + +int gfx_dis_dpSetScissor(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_DPSETSCISSOR; + insn->n_gfx = 1; + insn->arg[0] = getfield(lo, 2, 24); + insn->arg[1] = getfield(hi, 10, 14); + insn->arg[2] = getfield(hi, 10, 2); + insn->arg[3] = getfield(lo, 10, 14); + insn->arg[4] = getfield(lo, 10, 2); + insn->strarg[0] = strarg_sc; + return 0; +} + +int gfx_dis_dpSetScissorFrac(struct gfx_insn *insn, 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 & 0x0003) || (uly & 0x0003) || (lrx & 0x0003) || (lry & 0x0003)) { + insn->def = GFX_ID_DPSETSCISSORFRAC; + insn->n_gfx = 1; + insn->arg[0] = getfield(lo, 2, 24); + insn->arg[1] = ulx; + insn->arg[2] = uly; + insn->arg[3] = lrx; + insn->arg[4] = lry; + insn->strarg[0] = strarg_sc; + insn->strarg[1] = strarg_qu102; + insn->strarg[2] = strarg_qu102; + insn->strarg[3] = strarg_qu102; + insn->strarg[4] = strarg_qu102; + return 0; + } + else + return gfx_dis_dpSetScissor(insn, hi, lo); +} + +int gfx_dis_dpSetTextureDetail(struct gfx_insn *insn, + uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_DPSETTEXTUREDETAIL; + insn->n_gfx = 1; + insn->arg[0] = lo; + insn->strarg[0] = strarg_td; + return 0; +} + +int gfx_dis_dpSetTextureFilter(struct gfx_insn *insn, + uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_DPSETTEXTUREFILTER; + insn->n_gfx = 1; + insn->arg[0] = lo; + insn->strarg[0] = strarg_tf; + return 0; +} + +int gfx_dis_dpSetTextureLOD(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_DPSETTEXTURELOD; + insn->n_gfx = 1; + insn->arg[0] = lo; + insn->strarg[0] = strarg_tl; + return 0; +} + +int gfx_dis_dpSetTextureLUT(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_DPSETTEXTURELUT; + insn->n_gfx = 1; + insn->arg[0] = lo; + insn->strarg[0] = strarg_tt; + return 0; +} + +int gfx_dis_dpSetTexturePersp(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_DPSETTEXTUREPERSP; + insn->n_gfx = 1; + insn->arg[0] = lo; + insn->strarg[0] = strarg_tp; + return 0; +} + +int gfx_dis_dpSetTile(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_DPSETTILE; + insn->n_gfx = 1; + insn->arg[0] = getfield(hi, 3, 21); + insn->arg[1] = getfield(hi, 2, 19); + insn->arg[2] = getfield(hi, 9, 9); + insn->arg[3] = getfield(hi, 9, 0); + insn->arg[4] = getfield(lo, 3, 24); + insn->arg[5] = getfield(lo, 4, 20); + insn->arg[6] = getfield(lo, 2, 18); + insn->arg[7] = getfield(lo, 4, 14); + insn->arg[8] = getfield(lo, 4, 10); + insn->arg[9] = getfield(lo, 2, 8); + insn->arg[10] = getfield(lo, 4, 4); + insn->arg[11] = getfield(lo, 4, 0); + insn->strarg[0] = strarg_fmt; + insn->strarg[1] = strarg_siz; + insn->strarg[3] = strarg_x16; + insn->strarg[4] = strarg_tile; + insn->strarg[6] = strarg_cm; + insn->strarg[7] = strarg_tm; + insn->strarg[8] = strarg_ts; + insn->strarg[9] = strarg_cm; + insn->strarg[10] = strarg_tm; + insn->strarg[11] = strarg_ts; + return 0; +} + +int gfx_dis_dpSetTileSize(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_DPSETTILESIZE; + insn->n_gfx = 1; + insn->arg[0] = getfield(lo, 3, 24); + insn->arg[1] = getfield(hi, 12, 12); + insn->arg[2] = getfield(hi, 12, 0); + insn->arg[3] = getfield(lo, 12, 12); + insn->arg[4] = getfield(lo, 12, 0); + insn->strarg[0] = strarg_tile; + insn->strarg[1] = strarg_qu102; + insn->strarg[2] = strarg_qu102; + insn->strarg[3] = strarg_qu102; + insn->strarg[4] = strarg_qu102; + return 0; +} + +#if defined(F3D_GBI) +int gfx_dis_sp1Triangle(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_SP1TRIANGLE; + insn->n_gfx = 1; + int n0 = getfield(lo, 8, 16); + int n1 = getfield(lo, 8, 8); + int n2 = getfield(lo, 8, 0); + insn->arg[0] = n0 / 10; + insn->arg[1] = n1 / 10; + insn->arg[2] = n2 / 10; + insn->arg[3] = getfield(lo, 8, 24); + _Bool err = 0; + if (n0 % 10 != 0) { + insn->strarg[0] = strarg_invd; + err = 1; + } + if (n1 % 10 != 0) { + insn->strarg[1] = strarg_invd; + err = 1; + } + if (n2 % 10 != 0) { + insn->strarg[2] = strarg_invd; + err = 1; + } + return err; +} +#elif defined(F3DEX_GBI) || defined(F3DEX_GBI_2) +int gfx_dis_sp1Triangle(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_SP1TRIANGLE; + insn->n_gfx = 1; + int n0 = getfield(hi, 8, 16); + int n1 = getfield(hi, 8, 8); + int n2 = getfield(hi, 8, 0); + insn->arg[0] = n0 / 2; + insn->arg[1] = n1 / 2; + insn->arg[2] = n2 / 2; + insn->arg[3] = 0; + _Bool err = 0; + if (n0 % 2 != 0) { + insn->strarg[0] = strarg_invd; + err = 1; + } + if (n1 % 2 != 0) { + insn->strarg[1] = strarg_invd; + err = 1; + } + if (n2 % 2 != 0) { + insn->strarg[2] = strarg_invd; + err = 1; + } + return err; +} + +int gfx_dis_sp2Triangles(struct gfx_insn *insn, 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 gfx_dis_sp1Quadrangle(insn, hi, lo); +#endif + insn->def = GFX_ID_SP2TRIANGLES; + insn->n_gfx = 1; + insn->arg[0] = n00 / 2; + insn->arg[1] = n01 / 2; + insn->arg[2] = n02 / 2; + insn->arg[3] = 0; + insn->arg[4] = n10 / 2; + insn->arg[5] = n11 / 2; + insn->arg[6] = n12 / 2; + insn->arg[7] = 0; + _Bool err = 0; + if (n00 % 2 != 0) { + insn->strarg[0] = strarg_invd; + err = 1; + } + if (n01 % 2 != 0) { + insn->strarg[1] = strarg_invd; + err = 1; + } + if (n02 % 2 != 0) { + insn->strarg[2] = strarg_invd; + err = 1; + } + if (n10 % 2 != 0) { + insn->strarg[4] = strarg_invd; + err = 1; + } + if (n11 % 2 != 0) { + insn->strarg[5] = strarg_invd; + err = 1; + } + if (n12 % 2 != 0) { + insn->strarg[6] = strarg_invd; + err = 1; + } + return err; +} + +int gfx_dis_sp1Quadrangle(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_SP1QUADRANGLE; + insn->n_gfx = 1; + 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; + insn->arg[0] = v00; + insn->arg[1] = v01; + insn->arg[2] = v11; + insn->arg[3] = v12; + insn->arg[4] = 0; + _Bool err = 0; + if (v00 != v10 || n00 % 2 != 0 || n10 % 2 != 0) { + insn->strarg[0] = strarg_invd; + err = 1; + } + if (n01 % 2 != 0) { + insn->strarg[1] = strarg_invd; + err = 1; + } + if (v02 != v11 || n02 % 2 != 0 || n11 % 2 != 0) { + insn->strarg[2] = strarg_invd; + err = 1; + } + if (n12 % 2 != 0) { + insn->strarg[3] = strarg_invd; + err = 1; + } + return err; +} + +int gfx_col_spBranchLessZ(struct gfx_insn *insn, int n_insn) +{ + if (n_insn < 2) + return 0; + if (insn[0].def != GFX_ID_DPHALF1) + return 0; + uint32_t branchdl = insn[0].arg[0]; + if (insn[1].def != GFX_ID_BRANCHZ) + return 0; + int vtx = insn[1].arg[0]; + uint32_t zval = insn[1].arg[1]; + uint32_t near = insn[1].arg[2]; + uint32_t far = insn[1].arg[3]; + int flag = insn[1].arg[4]; + uint32_t zmin = insn[1].arg[5]; + uint32_t zmax = insn[1].arg[6]; + if (zmin != 0 || zmax != 0x3FF) + return 0; + memmove(&insn[1], &insn[2], sizeof(*insn) * (n_insn - 2)); + memset(insn, 0, sizeof(*insn)); + insn->def = GFX_ID_SPBRANCHLESSZ; + insn->n_gfx = 2; + insn->arg[0] = branchdl; + insn->arg[1] = vtx; + insn->arg[2] = zval; + insn->arg[3] = near; + insn->arg[4] = far; + insn->arg[5] = flag; + insn->strarg[0] = strarg_x32; + insn->strarg[2] = strarg_f; + insn->strarg[3] = strarg_f; + insn->strarg[4] = strarg_f; + insn->strarg[4] = strarg_f; + insn->strarg[5] = strarg_bz; + return 1; +} + +int gfx_col_spBranchLessZrg(struct gfx_insn *insn, int n_insn) +{ + if (n_insn < 2) + return 0; + if (insn[0].def != GFX_ID_DPHALF1) + return 0; + uint32_t branchdl = insn[0].arg[0]; + if (insn[1].def != GFX_ID_BRANCHZ) + return 0; + int vtx = insn[1].arg[0]; + uint32_t zval = insn[1].arg[1]; + uint32_t near = insn[1].arg[2]; + uint32_t far = insn[1].arg[3]; + int flag = insn[1].arg[4]; + uint32_t zmin = insn[1].arg[5]; + uint32_t zmax = insn[1].arg[6]; + memmove(&insn[1], &insn[2], sizeof(*insn) * (n_insn - 2)); + memset(insn, 0, sizeof(*insn)); + insn->def = GFX_ID_SPBRANCHLESSZRG; + insn->n_gfx = 2; + insn->arg[0] = branchdl; + insn->arg[1] = vtx; + insn->arg[2] = zval; + insn->arg[3] = near; + insn->arg[4] = far; + insn->arg[5] = flag; + insn->arg[6] = zmin; + insn->arg[7] = zmax; + insn->strarg[0] = strarg_x32; + insn->strarg[2] = strarg_f; + insn->strarg[3] = strarg_f; + insn->strarg[4] = strarg_f; + insn->strarg[5] = strarg_bz; + return 1; +} +#endif + +int gfx_dis_spBranchList(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_SPBRANCHLIST; + insn->n_gfx = 1; + insn->arg[0] = lo; + insn->strarg[0] = strarg_x32; + return 0; +} + +int gfx_col_spClipRatio(struct gfx_insn *insn, int n_insn) +{ + if (n_insn < 4) + return 0; + if (insn[0].def != GFX_ID_MOVEWD || + insn[0].arg[0] != G_MW_CLIP || insn[0].arg[1] != G_MWO_CLIP_RNX) + { + return 0; + } + uint16_t r = insn[0].arg[2]; + if (insn[1].def != GFX_ID_MOVEWD || + insn[1].arg[0] != G_MW_CLIP || insn[1].arg[1] != G_MWO_CLIP_RNY || + (uint16_t)insn[1].arg[2] != r) + { + return 0; + } + if (insn[2].def != GFX_ID_MOVEWD || + insn[2].arg[0] != G_MW_CLIP || insn[2].arg[1] != G_MWO_CLIP_RPX || + (uint16_t)-insn[2].arg[2] != r) + { + return 0; + } + if (insn[3].def != GFX_ID_MOVEWD || + insn[3].arg[0] != G_MW_CLIP || insn[3].arg[1] != G_MWO_CLIP_RPY || + (uint16_t)-insn[3].arg[2] != r) + { + return 0; + } + memmove(&insn[1], &insn[4], sizeof(*insn) * (n_insn - 4)); + memset(insn, 0, sizeof(*insn)); + insn->def = GFX_ID_SPCLIPRATIO; + insn->n_gfx = 4; + insn->arg[0] = r; + insn->strarg[0] = strarg_cr; + return 3; +} + +#if defined(F3D_GBI) +int gfx_dis_spCullDisplayList(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_SPCULLDISPLAYLIST; + insn->n_gfx = 1; + int n0 = getfield(hi, 24, 0); + int nn = getfield(lo, 16, 0); + insn->arg[0] = n0 / 40; + insn->arg[1] = nn / 40 - 1; + _Bool err = 0; + if (n0 % 40 != 0) { + insn->strarg[0] = strarg_invd; + err = 1; + } + if (nn % 40 != 0) { + insn->strarg[1] = strarg_invd; + err = 1; + } + return err; +} +#elif defined(F3DEX_GBI) || defined(F3DEX_GBI_2) +int gfx_dis_spCullDisplayList(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_SPCULLDISPLAYLIST; + insn->n_gfx = 1; + int n0 = getfield(hi, 16, 0); + int nn = getfield(lo, 16, 0); + insn->arg[0] = n0 / 2; + insn->arg[1] = nn / 2; + _Bool err = 0; + if (n0 % 2 != 0) { + insn->strarg[0] = strarg_invd; + err = 1; + } + if (nn % 2 != 0) { + insn->strarg[1] = strarg_invd; + err = 1; + } + return err; +} +#endif + +int gfx_dis_spDisplayList(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_SPDISPLAYLIST; + insn->n_gfx = 1; + insn->arg[0] = lo; + insn->strarg[0] = strarg_x32; + return 0; +} + +int gfx_dis_spEndDisplayList(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_SPENDDISPLAYLIST; + insn->n_gfx = 1; + return 0; +} + +int gfx_dis_spFogPosition(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_SPFOGPOSITION; + insn->n_gfx = 1; + int x = sx(getfield(lo, 16, 16), 16); + int y = sx(getfield(lo, 16, 0), 16); + if (x == 0) { + insn->arg[0] = 0; + insn->arg[1] = 0; + insn->strarg[0] = strarg_invd; + insn->strarg[1] = strarg_invd; + return 1; + } + else { + x = 128000 / x; + int yx = y * x; + if (yx > 0) + yx += 255; + else if (yx < 0) + yx -= 255; + int min = 500 - yx / 256; + int max = x + min; + insn->arg[0] = min; + insn->arg[1] = max; + return 0; + } +} + +#if defined(F3D_GBI) || defined(F3DEX_GBI) +int gfx_col_spForceMatrix(struct gfx_insn *insn, int n_insn) +{ + if (n_insn < 4) + return 0; + for (int i = 0; i < 4; ++i) + if (insn[i].def != GFX_ID_MOVEMEM || insn[i].arg[0] != 16 || + insn[i].arg[2] != insn[0].arg[2] + i * 16) + { + return 0; + } + if (insn[0].arg[1] != G_MV_MATRIX_1 || insn[1].arg[1] != G_MV_MATRIX_2 || + insn[2].arg[1] != G_MV_MATRIX_3 || insn[3].arg[1] != G_MV_MATRIX_4) + { + return 0; + } + uint32_t mptr = insn[0].arg[2]; + memmove(&insn[1], &insn[4], sizeof(*insn) * (n_insn - 4)); + memset(insn, 0, sizeof(*insn)); + insn->def = GFX_ID_SPFORCEMATRIX; + insn->n_gfx = 4; + insn->arg[0] = mptr; + insn->strarg[0] = strarg_x32; + return 3; +} +#elif defined(F3DEX_GBI_2) +int gfx_col_spForceMatrix(struct gfx_insn *insn, int n_insn) +{ + if (n_insn < 2) + return 0; + if (insn[0].def != GFX_ID_MOVEMEM || + insn[0].arg[0] != sizeof(Mtx) || insn[0].arg[1] != G_MV_MATRIX || + insn[0].arg[2] != 0) + { + return 0; + } + uint32_t mptr = insn[0].arg[3]; + if (insn[1].def != GFX_ID_MOVEWD || + insn[1].arg[0] != G_MW_FORCEMTX || insn[1].arg[1] != 0 || + insn[1].arg[2] != 0x10000) + { + return 0; + } + memmove(&insn[1], &insn[2], sizeof(*insn) * (n_insn - 2)); + memset(insn, 0, sizeof(*insn)); + insn->def = GFX_ID_SPFORCEMATRIX; + insn->n_gfx = 2; + insn->arg[0] = mptr; + insn->strarg[0] = strarg_x32; + return 1; +} +#endif + +int gfx_dis_spSetGeometryMode(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_SPSETGEOMETRYMODE; + insn->n_gfx = 1; + insn->arg[0] = lo; + insn->strarg[0] = strarg_gm; + return 0; +} + +int gfx_dis_spClearGeometryMode(struct gfx_insn *insn, + uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_SPCLEARGEOMETRYMODE; + insn->n_gfx = 1; +#if defined(F3D_GBI) || defined(F3DEX_GBI) + insn->arg[0] = lo; +#elif defined(F3DEX_GBI_2) + insn->arg[0] = getfield(~hi, 24, 0); +#endif + insn->strarg[0] = strarg_gm; + return 0; +} + +#if defined(F3D_GBI) || defined(F3DEX_GBI) +int gfx_col_spLoadGeometryMode(struct gfx_insn *insn, int n_insn) +{ + if (n_insn < 2) + return 0; + if (insn[0].def != GFX_ID_SPCLEARGEOMETRYMODE || + insn[0].arg[0] != 0xFFFFFFFF || + insn[1].def != GFX_ID_SPSETGEOMETRYMODE) + { + return 0; + } + uint32_t mode = insn[1].arg[0]; + memmove(&insn[1], &insn[2], sizeof(*insn) * (n_insn - 2)); + memset(insn, 0, sizeof(*insn)); + insn->def = GFX_ID_SPLOADGEOMETRYMODE; + insn->n_gfx = 2; + insn->arg[0] = mode; + insn->strarg[0] = strarg_gm; + return 1; +} +#elif defined(F3DEX_GBI_2) +int gfx_dis_spLoadGeometryMode(struct gfx_insn *insn, + uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_SPLOADGEOMETRYMODE; + insn->n_gfx = 1; + insn->arg[0] = lo; + insn->strarg[0] = strarg_gm; + return 0; +} +#endif + +#if defined(F3D_GBI) || defined(F3DEX_GBI) +int gfx_dis_spInsertMatrix(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_SPINSERTMATRIX; + insn->n_gfx = 1; + insn->arg[0] = getfield(hi, 16, 8); + insn->arg[1] = lo; + insn->strarg[0] = strarg_mwo_matrix; + insn->strarg[1] = strarg_x32; + return 0; +} +#endif + +#if defined(F3D_GBI) +int gfx_dis_spLine3D(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_SPLINE3D; + insn->n_gfx = 1; + int v0 = getfield(lo, 8, 16); + int v1 = getfield(lo, 8, 8); + insn->arg[0] = v0 / 10; + insn->arg[1] = v1 / 10; + insn->arg[2] = getfield(lo, 8, 24); + _Bool err = 0; + if (v0 % 10 != 0) { + insn->strarg[0] = strarg_invd; + err = 1; + } + if (v1 % 10 != 0) { + insn->strarg[1] = strarg_invd; + err = 1; + } + return err; +} +#elif defined(F3DEX_GBI) || defined(F3DEX_GBI_2) +int gfx_dis_spLine3D(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_SPLINE3D; + insn->n_gfx = 1; + int v0 = getfield(hi, 8, 16); + int v1 = getfield(hi, 8, 8); + insn->arg[0] = v0 / 2; + insn->arg[1] = v1 / 2; + insn->arg[2] = 0; + _Bool err = 0; + if (v0 % 2 != 0) { + insn->strarg[0] = strarg_invd; + err = 1; + } + if (v1 % 2 != 0) { + insn->strarg[1] = strarg_invd; + err = 1; + } + return err; +} +#endif + +#if defined(F3D_GBI) +int gfx_dis_spLineW3D(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + int wd = getfield(lo, 8, 0); + if (wd == 0) + return gfx_dis_spLine3D(insn, hi, lo); + else { + insn->def = GFX_ID_SPLINEW3D; + insn->n_gfx = 1; + int v0 = getfield(lo, 8, 16); + int v1 = getfield(lo, 8, 8); + insn->arg[0] = v0 / 10; + insn->arg[1] = v1 / 10; + insn->arg[2] = wd; + insn->arg[3] = getfield(lo, 8, 24); + _Bool err = 0; + if (v0 % 10 != 0) { + insn->strarg[0] = strarg_invd; + err = 1; + } + if (v1 % 10 != 0) { + insn->strarg[1] = strarg_invd; + err = 1; + } + return err; + } +} +#elif defined(F3DEX_GBI) || defined(F3DEX_GBI_2) +int gfx_dis_spLineW3D(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + int wd = getfield(hi, 8, 0); + if (wd == 0) + return gfx_dis_spLine3D(insn, hi, lo); + else { + insn->def = GFX_ID_SPLINEW3D; + insn->n_gfx = 1; + int v0 = getfield(hi, 8, 16); + int v1 = getfield(hi, 8, 8); + insn->arg[0] = v0 / 2; + insn->arg[1] = v1 / 2; + insn->arg[2] = wd; + insn->arg[3] = 0; + _Bool err = 0; + if (v0 % 2 != 0) { + insn->strarg[0] = strarg_invd; + err = 1; + } + if (v1 % 2 != 0) { + insn->strarg[1] = strarg_invd; + err = 1; + } + return err; + } +} +#endif + +#if defined(F3DEX_GBI) || defined(F3DEX_GBI_2) +int gfx_col_spLoadUcode(struct gfx_insn *insn, int n_insn) +{ + if (n_insn < 2) + return 0; + if (insn[0].def != GFX_ID_DPHALF1) + return 0; + uint32_t uc_dstart = insn[0].arg[0]; + if (insn[1].def != GFX_ID_LOADUCODE) + return 0; + uint32_t uc_start = insn[1].arg[0]; + uint32_t uc_dsize = insn[1].arg[1]; + if (uc_dsize != 0x800) + return 0; + memmove(&insn[1], &insn[2], sizeof(*insn) * (n_insn - 2)); + memset(insn, 0, sizeof(*insn)); + insn->def = GFX_ID_SPLOADUCODE; + insn->n_gfx = 2; + insn->arg[0] = uc_start; + insn->arg[1] = uc_dstart; + insn->strarg[0] = strarg_x32; + insn->strarg[1] = strarg_x32; + return 1; +} +#endif + +int gfx_dis_spLookAtX(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_SPLOOKATX; + insn->n_gfx = 1; + insn->arg[0] = lo; + insn->strarg[0] = strarg_x32; + return 0; +} + +int gfx_dis_spLookAtY(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_SPLOOKATY; + insn->n_gfx = 1; + insn->arg[0] = lo; + insn->strarg[0] = strarg_x32; + return 0; +} + +int gfx_col_spLookAt(struct gfx_insn *insn, int n_insn) +{ + if (n_insn < 2) + return 0; + if (insn[0].def != GFX_ID_SPLOOKATX) + return 0; + uint32_t l = insn[0].arg[0]; + if (insn[1].def != GFX_ID_SPLOOKATY || insn[1].arg[0] != l + 0x10) + return 0; + memmove(&insn[1], &insn[2], sizeof(*insn) * (n_insn - 2)); + memset(insn, 0, sizeof(*insn)); + insn->def = GFX_ID_SPLOOKAT; + insn->n_gfx = 2; + insn->arg[0] = l; + insn->strarg[0] = strarg_x32; + return 1; +} + +#if defined(F3D_GBI) || defined(F3DEX_GBI) +int gfx_dis_spMatrix(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_SPMATRIX; + insn->n_gfx = 1; + int x = getfield(hi, 16, 0); + insn->arg[0] = lo; + insn->arg[1] = getfield(hi, 8, 16); + insn->strarg[0] = strarg_x32; + insn->strarg[1] = strarg_mp; + return x != sizeof(Mtx); +} +#elif defined(F3DEX_GBI_2) +int gfx_dis_spMatrix(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_SPMATRIX; + insn->n_gfx = 1; + int x = getfield(hi, 5, 19); + insn->arg[0] = lo; + insn->arg[1] = getfield(hi, 8, 0) ^ G_MTX_PUSH; + insn->strarg[0] = strarg_x32; + insn->strarg[1] = strarg_mp; + return x != (sizeof(Mtx) - 1) / 8; +} +#endif + +#if defined(F3D_GBI) +int gfx_dis_spModifyVertex(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_SPMODIFYVERTEX; + insn->n_gfx = 1; + int offset = getfield(hi, 16, 8); + insn->arg[0] = offset / 40; + insn->arg[1] = offset % 40; + insn->arg[2] = lo; + insn->strarg[1] = strarg_mwo_point; + insn->strarg[2] = strarg_x32; + _Bool err = 0; + if (offset % 40 != G_MWO_POINT_RGBA || + offset % 40 != G_MWO_POINT_ST || + offset % 40 != G_MWO_POINT_XYSCREEN || + offset % 40 != G_MWO_POINT_ZSCREEN) + { + insn->strarg[1] = strarg_invd; + err = 1; + } + return err; +} +#elif defined(F3DEX_GBI) || defined(F3DEX_GBI_2) +int gfx_dis_spModifyVertex(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_SPMODIFYVERTEX; + insn->n_gfx = 1; + int vtx = getfield(hi, 16, 0); + insn->arg[0] = vtx / 2; + insn->arg[1] = getfield(hi, 8, 16); + insn->arg[2] = lo; + insn->strarg[1] = strarg_mwo_point; + insn->strarg[2] = strarg_x32; + _Bool err = 0; + if (vtx % 2 != 0) { + insn->strarg[0] = strarg_invd; + err = 1; + } + return err; +} +#endif + +int gfx_dis_spPerspNormalize(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_SPPERSPNORMALIZE; + insn->n_gfx = 1; + insn->arg[0] = getfield(lo, 16, 0); + insn->strarg[0] = strarg_qu016; + return 0; +} + +int gfx_dis_spPopMatrix(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_SPPOPMATRIX; + insn->n_gfx = 1; +#if defined(F3D_GBI) || defined(F3DEX_GBI) + insn->arg[0] = lo; +#elif defined(F3DEX_GBI_2) + insn->arg[0] = G_MTX_MODELVIEW; +#endif + insn->strarg[0] = strarg_ms; + return 0; +} + +#if defined(F3DEX_GBI_2) +int gfx_dis_spPopMatrixN(struct gfx_insn *insn, 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); + _Bool err = 0; + if (lo % sizeof(Mtx) != 0) { + insn->strarg[1] = strarg_invd; + err = 1; + } + if (len != sizeof(Mtx) || ofs != 0 || idx != 2) + err = 1; + if (n != 1 || err) + { + insn->def = GFX_ID_SPPOPMATRIXN; + insn->n_gfx = 1; + insn->arg[0] = G_MTX_MODELVIEW; + insn->arg[1] = n; + insn->strarg[0] = strarg_ms; + return err; + } + else + return gfx_dis_spPopMatrix(insn, hi, lo); +} +#endif + +int gfx_dis_spSegment(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_SPSEGMENT; + insn->n_gfx = 1; +#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 + insn->arg[0] = offset / 4; + insn->arg[1] = lo; + insn->strarg[0] = strarg_x8; + insn->strarg[1] = strarg_x32; + _Bool err = 0; + if (offset % 4 != 0 || offset > G_MWO_SEGMENT_F) { + insn->strarg[0] = strarg_invd; + err = 1; + } + return err; +} + +static int gfx_col_spSetLights(struct gfx_insn *insn, int n_insn, + enum gfx_insn_def def, int numlights) +{ + int n_col = 2 + numlights; + if (n_insn < n_col) + return 0; + if (insn[0].def != GFX_ID_SPNUMLIGHTS || insn[0].arg[0] != numlights) + return 0; + int a = 1 + numlights; + if (insn[a].def != GFX_ID_SPLIGHT || insn[a].arg[1] != a) + return 0; + uint32_t l = insn[a].arg[0]; + for (int i = 1; i <= numlights; ++i) + if (insn[i].def != GFX_ID_SPLIGHT || + insn[i].arg[0] != l + sizeof(Ambient) + sizeof(Light) * (i - 1) || + insn[i].arg[1] != i) + { + return 0; + } + memmove(&insn[1], &insn[n_col], sizeof(*insn) * (n_insn - n_col)); + memset(insn, 0, sizeof(*insn)); + insn->def = def; + insn->n_gfx = n_col; + insn->arg[0] = MIPS_PHYS_TO_KSEG0(l); + insn->strarg[0] = strarg_lightsn; + return n_col - 1; +} + +int gfx_col_spSetLights1(struct gfx_insn *insn, int n_insn) +{ + return gfx_col_spSetLights(insn, n_insn, GFX_ID_SPSETLIGHTS1, NUMLIGHTS_1); +} + +int gfx_col_spSetLights2(struct gfx_insn *insn, int n_insn) +{ + return gfx_col_spSetLights(insn, n_insn, GFX_ID_SPSETLIGHTS2, NUMLIGHTS_2); +} + +int gfx_col_spSetLights3(struct gfx_insn *insn, int n_insn) +{ + return gfx_col_spSetLights(insn, n_insn, GFX_ID_SPSETLIGHTS3, NUMLIGHTS_3); +} + +int gfx_col_spSetLights4(struct gfx_insn *insn, int n_insn) +{ + return gfx_col_spSetLights(insn, n_insn, GFX_ID_SPSETLIGHTS4, NUMLIGHTS_4); +} + +int gfx_col_spSetLights5(struct gfx_insn *insn, int n_insn) +{ + return gfx_col_spSetLights(insn, n_insn, GFX_ID_SPSETLIGHTS5, NUMLIGHTS_5); +} + +int gfx_col_spSetLights6(struct gfx_insn *insn, int n_insn) +{ + return gfx_col_spSetLights(insn, n_insn, GFX_ID_SPSETLIGHTS6, NUMLIGHTS_6); +} + +int gfx_col_spSetLights7(struct gfx_insn *insn, int n_insn) +{ + return gfx_col_spSetLights(insn, n_insn, GFX_ID_SPSETLIGHTS7, NUMLIGHTS_7); +} + +#if defined(F3D_GBI) || defined(F3DEX_GBI) +int gfx_dis_spNumLights(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_SPNUMLIGHTS; + insn->n_gfx = 1; + insn->arg[0] = (lo - 0x80000000) / 32 - 1; + _Bool err = 0; + if (lo < 0x80000040 || lo % 32 != 0) { + insn->strarg[0] = strarg_invd; + err = 1; + } + return err; +} +#elif defined(F3DEX_GBI_2) +int gfx_dis_spNumLights(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_SPNUMLIGHTS; + insn->n_gfx = 1; + insn->arg[0] = lo / 24; + _Bool err = 0; + if (lo < 24 || lo % 24 != 0) { + insn->strarg[0] = strarg_invd; + err = 1; + } + return err; +} +#endif + +#if defined(F3D_GBI) || defined(F3DEX_GBI) +int gfx_dis_spLight(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_SPLIGHT; + insn->n_gfx = 1; + insn->arg[0] = lo; + insn->arg[1] = (getfield(hi, 8, 16) - G_MV_L0) / 2 + 1; + insn->strarg[0] = strarg_x32; + return 0; +} +#elif defined(F3DEX_GBI_2) +int gfx_dis_spLight(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_SPLIGHT; + insn->n_gfx = 1; + insn->arg[0] = lo; + insn->arg[1] = (getfield(hi, 8, 8) * 8 / 24) - 1; + insn->strarg[0] = strarg_x32; + return 0; +} +#endif + +int gfx_col_spLightColor(struct gfx_insn *insn, int n_insn) +{ + if (n_insn < 2) + return 0; + if (insn[0].def != GFX_ID_MOVEWD || insn[0].arg[0] != G_MW_LIGHTCOL || + insn[0].arg[1] % 0x18 != 0 || insn[0].arg[1] > G_MWO_aLIGHT_8) + { + return 0; + } + uint16_t offset = insn[0].arg[1]; + uint32_t packedcolor = insn[0].arg[2]; + if (insn[1].def != GFX_ID_MOVEWD || insn[1].arg[0] != G_MW_LIGHTCOL || + insn[1].arg[1] != offset + 4 || insn[1].arg[2] != packedcolor) + { + return 0; + } + memmove(&insn[1], &insn[2], sizeof(*insn) * (n_insn - 2)); + memset(insn, 0, sizeof(*insn)); + insn->def = GFX_ID_SPLIGHTCOLOR; + insn->n_gfx = 2; + insn->arg[0] = offset / 0x18 + 1; + insn->arg[1] = packedcolor; + insn->strarg[0] = strarg_light; + insn->strarg[1] = strarg_x32; + return 1; +} + +int gfx_dis_spTexture(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_SPTEXTURE; + insn->n_gfx = 1; + insn->arg[0] = getfield(lo, 16, 16); + insn->arg[1] = getfield(lo, 16, 0); + insn->arg[2] = getfield(hi, 3, 11); + insn->arg[3] = getfield(hi, 3, 8); +#if defined(F3D_GBI) || defined(F3DEX_GBI) + insn->arg[4] = getfield(hi, 8, 0); +#elif defined(F3DEX_GBI_2) + insn->arg[4] = getfield(hi, 7, 1); +#endif + insn->strarg[0] = strarg_qu016; + insn->strarg[1] = strarg_qu016; + insn->strarg[3] = strarg_tile; + insn->strarg[4] = strarg_switch; + return 0; +} + +int gfx_col_spTextureRectangle(struct gfx_insn *insn, int n_insn) +{ + if (n_insn < 3) + return 0; + if (insn[0].def != GFX_ID_TEXRECT) + return 0; + qu102_t ulx = insn[0].arg[0]; + qu102_t uly = insn[0].arg[1]; + qu102_t lrx = insn[0].arg[2]; + qu102_t lry = insn[0].arg[3]; + int tile = insn[0].arg[4]; + if (insn[1].def != GFX_ID_DPHALF1) + return 0; + qs105_t s = sx(getfield(insn[1].arg[0], 16, 16), 16); + qs105_t t = sx(getfield(insn[1].arg[0], 16, 0), 16); + if (insn[2].def != GFX_ID_DPHALF2) + return 0; + qs510_t dsdx = sx(getfield(insn[2].arg[0], 16, 16), 16); + qs510_t dtdy = sx(getfield(insn[2].arg[0], 16, 0), 16); + memmove(&insn[1], &insn[3], sizeof(*insn) * (n_insn - 3)); + memset(insn, 0, sizeof(*insn)); + insn->def = GFX_ID_SPTEXTURERECTANGLE; + insn->n_gfx = 3; + insn->arg[0] = ulx; + insn->arg[1] = uly; + insn->arg[2] = lrx; + insn->arg[3] = lry; + insn->arg[4] = tile; + insn->arg[5] = s; + insn->arg[6] = t; + insn->arg[7] = dsdx; + insn->arg[8] = dtdy; + insn->strarg[0] = strarg_qu102; + insn->strarg[1] = strarg_qu102; + insn->strarg[2] = strarg_qu102; + insn->strarg[3] = strarg_qu102; + insn->strarg[4] = strarg_tile; + insn->strarg[5] = strarg_qs105; + insn->strarg[6] = strarg_qs105; + insn->strarg[7] = strarg_qs510; + insn->strarg[8] = strarg_qs510; + return 2; +} + +int gfx_col_spTextureRectangleFlip(struct gfx_insn *insn, int n_insn) +{ + if (n_insn < 3) + return 0; + if (insn[0].def != GFX_ID_TEXRECTFLIP) + return 0; + qu102_t ulx = insn[0].arg[0]; + qu102_t uly = insn[0].arg[1]; + qu102_t lrx = insn[0].arg[2]; + qu102_t lry = insn[0].arg[3]; + int tile = insn[0].arg[4]; + if (insn[1].def != GFX_ID_DPHALF1) + return 0; + qs105_t s = sx(getfield(insn[1].arg[0], 16, 16), 16); + qs105_t t = sx(getfield(insn[1].arg[0], 16, 0), 16); + if (insn[2].def != GFX_ID_DPHALF2) + return 0; + qs510_t dsdx = sx(getfield(insn[2].arg[0], 16, 16), 16); + qs510_t dtdy = sx(getfield(insn[2].arg[0], 16, 0), 16); + memmove(&insn[1], &insn[3], sizeof(*insn) * (n_insn - 3)); + memset(insn, 0, sizeof(*insn)); + insn->def = GFX_ID_SPTEXTURERECTANGLEFLIP; + insn->n_gfx = 3; + insn->arg[0] = ulx; + insn->arg[1] = uly; + insn->arg[2] = lrx; + insn->arg[3] = lry; + insn->arg[4] = tile; + insn->arg[5] = s; + insn->arg[6] = t; + insn->arg[7] = dsdx; + insn->arg[8] = dtdy; + insn->strarg[0] = strarg_qu102; + insn->strarg[1] = strarg_qu102; + insn->strarg[2] = strarg_qu102; + insn->strarg[3] = strarg_qu102; + insn->strarg[4] = strarg_tile; + insn->strarg[5] = strarg_qs105; + insn->strarg[6] = strarg_qs105; + insn->strarg[7] = strarg_qs510; + insn->strarg[8] = strarg_qs510; + return 2; +} + +#if defined(F3D_GBI) +int gfx_dis_spVertex(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_SPVERTEX; + insn->n_gfx = 1; + int n = getfield(hi, 4, 20) + 1; + int v0 = getfield(hi, 4, 16); + int size = getfield(hi, 16, 0); + insn->arg[0] = lo; + insn->arg[1] = n; + insn->arg[2] = v0; + insn->strarg[0] = strarg_x32; + _Bool err = 0; + if (size != sizeof(Vtx) * n) { + insn->strarg[1] = strarg_invd; + err = 1; + } + return err; +} +#elif defined(F3DEX_GBI) +int gfx_dis_spVertex(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_SPVERTEX; + insn->n_gfx = 1; + int n = getfield(hi, 6, 10); + int v0 = getfield(hi, 8, 16); + int size = getfield(hi, 10, 0); + insn->arg[0] = lo; + insn->arg[1] = n; + insn->arg[2] = v0 / 2; + insn->strarg[0] = strarg_x32; + _Bool err = 0; + if (size != sizeof(Vtx) * n - 1) { + insn->strarg[1] = strarg_invd; + err = 1; + } + if (v0 % 2 != 0) { + insn->strarg[2] = strarg_invd; + err = 1; + } + return err; +} +#elif defined(F3DEX_GBI_2) +int gfx_dis_spVertex(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_SPVERTEX; + insn->n_gfx = 1; + int n = getfield(hi, 8, 12); + int v0 = getfield(hi, 7, 1) - n; + insn->arg[0] = lo; + insn->arg[1] = n; + insn->arg[2] = v0; + insn->strarg[0] = strarg_x32; + return 0; +} +#endif + +int gfx_dis_spViewport(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_SPVIEWPORT; + insn->n_gfx = 1; + insn->arg[0] = lo; + insn->strarg[0] = strarg_x32; + return 0; +} + +int gfx_dis_dpLoadTLUTCmd(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_DPLOADTLUTCMD; + insn->n_gfx = 1; + insn->arg[0] = getfield(lo, 3, 24); + insn->arg[1] = getfield(lo, 10, 14); + insn->strarg[0] = strarg_tile; + return 0; +} + +int gfx_col_dpLoadTLUT(struct gfx_insn *insn, int n_insn) +{ + if (n_insn < 6) + return 0; + if (insn[0].def != GFX_ID_DPSETTEXTUREIMAGE || + insn[0].arg[0] != G_IM_FMT_RGBA || insn[0].arg[1] != G_IM_SIZ_16b || + insn[0].arg[2] != 1) + { + return 0; + } + uint32_t dram = insn[0].arg[3]; + if (insn[1].def != GFX_ID_DPTILESYNC) + return 0; + if (insn[2].def != GFX_ID_DPSETTILE || + insn[2].arg[0] != 0 || insn[2].arg[1] != 0 || insn[2].arg[2] != 0 || + insn[2].arg[4] != G_TX_LOADTILE || insn[2].arg[5] != 0 || + insn[2].arg[6] != 0 || insn[2].arg[7] != 0 || insn[2].arg[8] != 0 || + insn[2].arg[9] != 0 || insn[2].arg[10] != 0 || insn[2].arg[11] != 0) + { + return 0; + } + uint32_t tmem = insn[2].arg[3]; + if (insn[3].def != GFX_ID_DPLOADSYNC) + return 0; + if (insn[4].def != GFX_ID_DPLOADTLUTCMD || insn[4].arg[0] != G_TX_LOADTILE) + return 0; + int count = insn[4].arg[1] + 1; + if (insn[5].def != GFX_ID_DPPIPESYNC) + return 0; + memmove(&insn[1], &insn[6], sizeof(*insn) * (n_insn - 6)); + memset(insn, 0, sizeof(*insn)); + insn->def = GFX_ID_DPLOADTLUT; + insn->n_gfx = 6; + insn->arg[0] = count; + insn->arg[1] = tmem; + insn->arg[2] = dram; + insn->strarg[1] = strarg_x16; + insn->strarg[2] = strarg_x32; + return 5; +} + +#if defined(F3DEX_GBI) || defined(F3DEX_GBI_2) +int gfx_dis_BranchZ(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + union + { + uint32_t u32; + float f; + } reint_f; + insn->def = GFX_ID_BRANCHZ; + insn->n_gfx = 1; + int na = getfield(hi, 12, 12); + int nb = getfield(hi, 12, 0); + insn->arg[0] = nb / 2; + reint_f.f = 1.f / (1.f - (int32_t)lo / (65536.f * 1023.f)); + insn->arg[1] = reint_f.u32; + reint_f.f = 1; + insn->arg[2] = reint_f.u32; + reint_f.f = 1023; + insn->arg[3] = reint_f.u32; + insn->arg[4] = G_BZ_PERSP; + insn->arg[5] = 0; + insn->arg[6] = 1023; + insn->strarg[1] = strarg_f; + insn->strarg[2] = strarg_f; + insn->strarg[3] = strarg_f; + insn->strarg[4] = strarg_bz; + _Bool err = 0; + if (nb % 2 != 0 || na / 5 != nb / 2) { + insn->strarg[0] = strarg_invd; + err = 1; + } + if (na % 5 != 0) + err = 1; + return err; +} +#endif + +int gfx_dis_DisplayList(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + int branch = getfield(hi, 8, 16); + if (branch == 0) + return gfx_dis_spDisplayList(insn, hi, lo); + else if (branch == 1) + return gfx_dis_spBranchList(insn, hi, lo); + else { + insn->def = GFX_ID_DISPLAYLIST; + insn->n_gfx = 1; + insn->arg[0] = lo; + insn->arg[1] = branch; + insn->strarg[0] = strarg_x32; + return 1; + } +} + +int gfx_dis_dpHalf1(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_DPHALF1; + insn->n_gfx = 1; + insn->arg[0] = lo; + insn->strarg[0] = strarg_x32; + return 0; +} + +int gfx_dis_dpHalf2(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_DPHALF2; + insn->n_gfx = 1; + insn->arg[0] = lo; + insn->strarg[0] = strarg_x32; + return 0; +} + +int gfx_dis_dpLoadTile(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_DPLOADTILE; + insn->n_gfx = 1; + insn->arg[0] = getfield(lo, 3, 24); + insn->arg[1] = getfield(hi, 12, 12); + insn->arg[2] = getfield(hi, 12, 0); + insn->arg[3] = getfield(lo, 12, 12); + insn->arg[4] = getfield(lo, 12, 0); + insn->strarg[0] = strarg_tile; + insn->strarg[1] = strarg_qu102; + insn->strarg[2] = strarg_qu102; + insn->strarg[3] = strarg_qu102; + insn->strarg[4] = strarg_qu102; + return 0; +} + +#if defined(F3DEX_GBI_2) +int gfx_dis_spGeometryMode(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + uint32_t clearbits = getfield(~hi, 24, 0); + uint32_t setbits = lo; + if (clearbits == 0 && setbits != 0) + return gfx_dis_spSetGeometryMode(insn, hi, lo); + else if (clearbits != 0 && setbits == 0) + return gfx_dis_spClearGeometryMode(insn, hi, lo); + else if (clearbits == 0x00FFFFFF) + return gfx_dis_spLoadGeometryMode(insn, hi, lo); + else { + insn->def = GFX_ID_SPGEOMETRYMODE; + insn->n_gfx = 1; + insn->arg[0] = clearbits; + insn->arg[1] = setbits; + insn->strarg[0] = strarg_gm; + insn->strarg[1] = strarg_gm; + return 0; + } +} +#endif + +int gfx_dis_spSetOtherModeLo(struct gfx_insn *insn, 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 gfx_dis_dpSetAlphaCompare(insn, hi, lo); + else if (shift == G_MDSFT_ZSRCSEL && length == G_MDSIZ_ZSRCSEL) + return gfx_dis_dpSetDepthSource(insn, hi, lo); + else if (shift == G_MDSFT_RENDERMODE && length == G_MDSIZ_RENDERMODE) + return gfx_dis_dpSetRenderMode(insn, hi, lo); + else { + insn->def = GFX_ID_SPSETOTHERMODELO; + insn->n_gfx = 1; + insn->arg[0] = shift; + insn->arg[1] = length; + insn->arg[2] = lo; + insn->strarg[0] = strarg_sftlo; + insn->strarg[2] = strarg_othermodelo; + return 1; + } +} + +int gfx_dis_spSetOtherModeHi(struct gfx_insn *insn, 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 gfx_dis_dpSetAlphaDither(insn, hi, lo); + else if (shift == G_MDSFT_RGBDITHER && length == G_MDSIZ_RGBDITHER) + return gfx_dis_dpSetColorDither(insn, hi, lo); + else if (shift == G_MDSFT_COMBKEY && length == G_MDSIZ_COMBKEY) + return gfx_dis_dpSetCombineKey(insn, hi, lo); + else if (shift == G_MDSFT_TEXTCONV && length == G_MDSIZ_TEXTCONV) + return gfx_dis_dpSetTextureConvert(insn, hi, lo); + else if (shift == G_MDSFT_TEXTFILT && length == G_MDSIZ_TEXTFILT) + return gfx_dis_dpSetTextureFilter(insn, hi, lo); + else if (shift == G_MDSFT_TEXTLUT && length == G_MDSIZ_TEXTLUT) + return gfx_dis_dpSetTextureLUT(insn, hi, lo); + else if (shift == G_MDSFT_TEXTLOD && length == G_MDSIZ_TEXTLOD) + return gfx_dis_dpSetTextureLOD(insn, hi, lo); + else if (shift == G_MDSFT_TEXTDETAIL && length == G_MDSIZ_TEXTDETAIL) + return gfx_dis_dpSetTextureDetail(insn, hi, lo); + else if (shift == G_MDSFT_TEXTPERSP && length == G_MDSIZ_TEXTPERSP) + return gfx_dis_dpSetTexturePersp(insn, hi, lo); + else if (shift == G_MDSFT_CYCLETYPE && length == G_MDSIZ_CYCLETYPE) + return gfx_dis_dpSetCycleType(insn, hi, lo); + else if (shift == G_MDSFT_PIPELINE && length == G_MDSIZ_PIPELINE) + return gfx_dis_dpPipelineMode(insn, hi, lo); + else { + insn->def = GFX_ID_SPSETOTHERMODEHI; + insn->n_gfx = 1; + insn->arg[0] = shift; + insn->arg[1] = length; + insn->arg[2] = lo; + insn->strarg[0] = strarg_sfthi; + insn->strarg[2] = strarg_othermodehi; + return 1; + } + return 0; +} + +int gfx_dis_dpSetOtherMode(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_DPSETOTHERMODE; + insn->n_gfx = 1; + insn->arg[0] = getfield(hi, 24, 0); + insn->arg[1] = lo; + insn->strarg[0] = strarg_othermodehi; + insn->strarg[1] = strarg_othermodelo; + return 0; +} + +int gfx_dis_MoveWd(struct gfx_insn *insn, 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 gfx_dis_spFogPosition(insn, hi, lo); +#if !(defined(F3D_BETA) && (defined(F3D_GBI) || defined(F3DEX_GBI))) + else if (index == G_MW_PERSPNORM && offset == 0) + return gfx_dis_spPerspNormalize(insn, hi, lo); +#endif + else if (index == G_MW_SEGMENT) + return gfx_dis_spSegment(insn, hi, lo); + else if (index == G_MW_NUMLIGHT && offset == G_MWO_NUMLIGHT) + return gfx_dis_spNumLights(insn, hi, lo); +#if defined(F3D_GBI) + else if (index == G_MW_POINTS) + return gfx_dis_spModifyVertex(insn, hi, lo); +#endif +#if defined(F3D_GBI) || defined(F3DEX_GBI) + else if (index == G_MW_MATRIX) + return gfx_dis_spInsertMatrix(insn, hi, lo); +#endif + else { + insn->def = GFX_ID_MOVEWD; + insn->n_gfx = 1; + insn->arg[0] = index; + insn->arg[1] = offset; + insn->arg[2] = lo; + insn->strarg[0] = strarg_mw; + if (index == G_MW_MATRIX) + insn->strarg[1] = strarg_mwo_matrix; + else if (index == G_MW_CLIP) + insn->strarg[1] = strarg_mwo_clip; + else if (index == G_MW_LIGHTCOL) + insn->strarg[1] = strarg_mwo_lightcol; + else + insn->strarg[1] = strarg_x16; + insn->strarg[2] = strarg_x32; + } + return 0; +} + +#if defined(F3D_GBI) || defined(F3DEX_GBI) +int gfx_dis_MoveMem(struct gfx_insn *insn, 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 gfx_dis_spLight(insn, hi, lo); + } + else if (size == sizeof(Light) && index == G_MV_LOOKATX) + return gfx_dis_spLookAtX(insn, hi, lo); + else if (size == sizeof(Light) && index == G_MV_LOOKATY) + return gfx_dis_spLookAtY(insn, hi, lo); + else if (size == sizeof(Vp) && index == G_MV_VIEWPORT) + return gfx_dis_spViewport(insn, hi, lo); + else { + insn->def = GFX_ID_MOVEMEM; + insn->n_gfx = 1; + insn->arg[0] = size; + insn->arg[1] = index; + insn->arg[2] = lo; + insn->strarg[0] = strarg_x8; + insn->strarg[1] = strarg_mv; + insn->strarg[2] = strarg_x32; + return 0; + } +} +#elif defined(F3DEX_GBI_2) +int gfx_dis_MoveMem(struct gfx_insn *insn, 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 gfx_dis_spLight(insn, hi, lo); + } + else if (size == sizeof(Light) && index == G_MV_LIGHT && + offset == G_MVO_LOOKATX) + { + return gfx_dis_spLookAtX(insn, hi, lo); + } + else if (size == sizeof(Light) && index == G_MV_LIGHT && + offset == G_MVO_LOOKATY) + { + return gfx_dis_spLookAtY(insn, hi, lo); + } + else if (size == sizeof(Vp) && index == G_MV_VIEWPORT && offset == 0) + return gfx_dis_spViewport(insn, hi, lo); + else { + insn->def = GFX_ID_MOVEMEM; + insn->n_gfx = 1; + insn->arg[0] = size; + insn->arg[1] = index; + insn->arg[2] = offset; + insn->arg[3] = lo; + insn->strarg[0] = strarg_x8; + insn->strarg[1] = strarg_mv; + insn->strarg[2] = strarg_x16; + insn->strarg[3] = strarg_x32; + return 0; + } +} +#endif + +#if defined(F3DEX_GBI_2) +int gfx_dis_spDma_io(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + int flag = getfield(hi, 1, 23); + if (flag == 0) + return gfx_dis_spDmaRead(insn, hi, lo); + else if (flag == 1) + return gfx_dis_spDmaWrite(insn, hi, lo); + else { + insn->def = GFX_ID_SPDMA_IO; + insn->n_gfx = 1; + insn->arg[0] = flag; + insn->arg[1] = getfield(hi, 10, 13) * 8; + insn->arg[2] = lo; + insn->arg[3] = getfield(hi, 12, 10) + 1; + insn->strarg[1] = strarg_x16; + insn->strarg[2] = strarg_x32; + insn->strarg[3] = strarg_x16; + return 1; + } +} + +int gfx_dis_spDmaRead(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_SPDMAREAD; + insn->n_gfx = 1; + insn->arg[0] = getfield(hi, 10, 13) * 8; + insn->arg[1] = lo; + insn->arg[2] = getfield(hi, 12, 10) + 1; + insn->strarg[0] = strarg_x16; + insn->strarg[1] = strarg_x32; + insn->strarg[2] = strarg_x16; + return 0; +} + +int gfx_dis_spDmaWrite(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_SPDMAWRITE; + insn->n_gfx = 1; + insn->arg[0] = getfield(hi, 10, 13) * 8; + insn->arg[1] = lo; + insn->arg[2] = getfield(hi, 12, 10) + 1; + insn->strarg[0] = strarg_x16; + insn->strarg[1] = strarg_x32; + insn->strarg[2] = strarg_x16; + return 0; +} +#endif + +#if defined(F3DEX_GBI) || defined(F3DEX_GBI_2) +int gfx_dis_LoadUcode(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_LOADUCODE; + insn->n_gfx = 1; + insn->arg[0] = lo; + insn->arg[1] = getfield(hi, 16, 0) + 1; + insn->strarg[0] = strarg_x32; + insn->strarg[1] = strarg_x16; + return 0; +} + +int gfx_col_spLoadUcodeEx(struct gfx_insn *insn, int n_insn) +{ + if (n_insn < 2) + return 0; + if (insn[0].def != GFX_ID_DPHALF1) + return 0; + uint32_t uc_dstart = insn[0].arg[0]; + if (insn[1].def != GFX_ID_LOADUCODE) + return 0; + uint32_t uc_start = insn[1].arg[0]; + uint32_t uc_dsize = insn[1].arg[1]; + memmove(&insn[1], &insn[2], sizeof(*insn) * (n_insn - 2)); + memset(insn, 0, sizeof(*insn)); + insn->def = GFX_ID_SPLOADUCODEEX; + insn->n_gfx = 2; + insn->arg[0] = uc_start; + insn->arg[1] = uc_dstart; + insn->arg[2] = uc_dsize; + insn->strarg[0] = strarg_x32; + insn->strarg[1] = strarg_x32; + insn->strarg[2] = strarg_x16; + return 1; +} +#endif + +int gfx_dis_TexRect(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_TEXRECT; + insn->n_gfx = 1; + insn->arg[0] = getfield(lo, 12, 12); + insn->arg[1] = getfield(lo, 12, 0); + insn->arg[2] = getfield(hi, 12, 12); + insn->arg[3] = getfield(hi, 12, 0); + insn->arg[4] = getfield(lo, 3, 24); + insn->strarg[0] = strarg_qu102; + insn->strarg[1] = strarg_qu102; + insn->strarg[2] = strarg_qu102; + insn->strarg[3] = strarg_qu102; + insn->strarg[4] = strarg_tile; + return 0; +} + +int gfx_dis_TexRectFlip(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_TEXRECTFLIP; + insn->n_gfx = 1; + insn->arg[0] = getfield(lo, 12, 12); + insn->arg[1] = getfield(lo, 12, 0); + insn->arg[2] = getfield(hi, 12, 12); + insn->arg[3] = getfield(hi, 12, 0); + insn->arg[4] = getfield(lo, 3, 24); + insn->strarg[0] = strarg_qu102; + insn->strarg[1] = strarg_qu102; + insn->strarg[2] = strarg_qu102; + insn->strarg[3] = strarg_qu102; + insn->strarg[4] = strarg_tile; + return 0; +} + +int gfx_dis_spNoOp(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_SPNOOP; + insn->n_gfx = 1; + return 0; +} + +#if defined(F3DEX_GBI_2) +int gfx_dis_Special3(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_SPECIAL3; + insn->n_gfx = 1; + insn->arg[0] = hi; + insn->arg[1] = lo; + insn->strarg[0] = strarg_x32; + insn->strarg[1] = strarg_x32; + return 0; +} + +int gfx_dis_Special2(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_SPECIAL2; + insn->n_gfx = 1; + insn->arg[0] = hi; + insn->arg[1] = lo; + insn->strarg[0] = strarg_x32; + insn->strarg[1] = strarg_x32; + return 0; +} + +int gfx_dis_Special1(struct gfx_insn *insn, uint32_t hi, uint32_t lo) +{ + insn->def = GFX_ID_SPECIAL1; + insn->n_gfx = 1; + insn->arg[0] = hi; + insn->arg[1] = lo; + insn->strarg[0] = strarg_x32; + insn->strarg[1] = strarg_x32; + return 0; +} +#endif + +struct gfx_insn_info gfx_insn_info[] = +{ + { + "Gfx", + GFX_ID_INVD, + GFX_IT_MACRO, -1, + 2, gfx_dis_invd, + }, + { + "gsDPFillRectangle", + GFX_ID_DPFILLRECTANGLE, + GFX_IT_OP, G_FILLRECT, + 4, gfx_dis_dpFillRectangle, + }, + { + "gsDPFullSync", + GFX_ID_DPFULLSYNC, + GFX_IT_OP, G_RDPFULLSYNC, + 0, gfx_dis_dpFullSync, + }, + { + "gsDPLoadSync", + GFX_ID_DPLOADSYNC, + GFX_IT_OP, G_RDPLOADSYNC, + 0, gfx_dis_dpLoadSync, + }, + { + "gsDPTileSync", + GFX_ID_DPTILESYNC, + GFX_IT_OP, G_RDPTILESYNC, + 0, gfx_dis_dpTileSync, + }, + { + "gsDPPipeSync", + GFX_ID_DPPIPESYNC, + GFX_IT_OP, G_RDPPIPESYNC, + 0, gfx_dis_dpPipeSync, + }, + { + "gsDPLoadTLUT_pal16", + GFX_ID_DPLOADTLUT_PAL16, + GFX_IT_MULTIMACRO, G_SETTIMG, + 2, gfx_col_dpLoadTLUT_pal16, + }, + { + "gsDPLoadTLUT_pal256", + GFX_ID_DPLOADTLUT_PAL256, + GFX_IT_MULTIMACRO, G_SETTIMG, + 1, gfx_col_dpLoadTLUT_pal256, + }, + { + "gsDPLoadMultiBlockYuvS", + GFX_ID_DPLOADMULTIBLOCKYUVS, + GFX_IT_MULTIMACRO, G_SETTIMG, + 14, gfx_col_dpLoadMultiBlockYuvS, + }, + { + "gsDPLoadMultiBlockYuv", + GFX_ID_DPLOADMULTIBLOCKYUV, + GFX_IT_MULTIMACRO, G_SETTIMG, + 14, gfx_col_dpLoadMultiBlockYuv, + }, + { + "gsDPLoadMultiBlock_4bS", + GFX_ID_DPLOADMULTIBLOCK_4BS, + GFX_IT_MULTIMACRO, G_SETTIMG, + 13, gfx_col_dpLoadMultiBlock_4bS, + }, + { + "gsDPLoadMultiBlock_4b", + GFX_ID_DPLOADMULTIBLOCK_4B, + GFX_IT_MULTIMACRO, G_SETTIMG, + 13, gfx_col_dpLoadMultiBlock_4b, + }, + { + "gsDPLoadMultiBlockS", + GFX_ID_DPLOADMULTIBLOCKS, + GFX_IT_MULTIMACRO, G_SETTIMG, + 14, gfx_col_dpLoadMultiBlockS, + }, + { + "gsDPLoadMultiBlock", + GFX_ID_DPLOADMULTIBLOCK, + GFX_IT_MULTIMACRO, G_SETTIMG, + 14, gfx_col_dpLoadMultiBlock, + }, + { + "_gsDPLoadTextureBlockYuvS", + GFX_ID__DPLOADTEXTUREBLOCKYUVS, + GFX_IT_MULTIMACRO, G_SETTIMG, + 13, gfx_col__dpLoadTextureBlockYuvS, + }, + { + "_gsDPLoadTextureBlockYuv", + GFX_ID__DPLOADTEXTUREBLOCKYUV, + GFX_IT_MULTIMACRO, G_SETTIMG, + 13, gfx_col__dpLoadTextureBlockYuv, + }, + { + "_gsDPLoadTextureBlock_4bS", + GFX_ID__DPLOADTEXTUREBLOCK_4BS, + GFX_IT_MULTIMACRO, G_SETTIMG, + 12, gfx_col__dpLoadTextureBlock_4bS, + }, + { + "_gsDPLoadTextureBlock_4b", + GFX_ID__DPLOADTEXTUREBLOCK_4B, + GFX_IT_MULTIMACRO, G_SETTIMG, + 12, gfx_col__dpLoadTextureBlock_4b, + }, + { + "_gsDPLoadTextureBlockS", + GFX_ID__DPLOADTEXTUREBLOCKS, + GFX_IT_MULTIMACRO, G_SETTIMG, + 13, gfx_col__dpLoadTextureBlockS, + }, + { + "_gsDPLoadTextureBlock", + GFX_ID__DPLOADTEXTUREBLOCK, + GFX_IT_MULTIMACRO, G_SETTIMG, + 13, gfx_col__dpLoadTextureBlock, + }, + { + "gsDPLoadTextureBlockYuvS", + GFX_ID_DPLOADTEXTUREBLOCKYUVS, + GFX_IT_MULTIMACRO, G_SETTIMG, + 12, gfx_col_dpLoadTextureBlockYuvS, + }, + { + "gsDPLoadTextureBlockYuv", + GFX_ID_DPLOADTEXTUREBLOCKYUV, + GFX_IT_MULTIMACRO, G_SETTIMG, + 12, gfx_col_dpLoadTextureBlockYuv, + }, + { + "gsDPLoadTextureBlock_4bS", + GFX_ID_DPLOADTEXTUREBLOCK_4BS, + GFX_IT_MULTIMACRO, G_SETTIMG, + 11, gfx_col_dpLoadTextureBlock_4bS, + }, + { + "gsDPLoadTextureBlock_4b", + GFX_ID_DPLOADTEXTUREBLOCK_4B, + GFX_IT_MULTIMACRO, G_SETTIMG, + 11, gfx_col_dpLoadTextureBlock_4b, + }, + { + "gsDPLoadTextureBlockS", + GFX_ID_DPLOADTEXTUREBLOCKS, + GFX_IT_MULTIMACRO, G_SETTIMG, + 12, gfx_col_dpLoadTextureBlockS, + }, + { + "gsDPLoadTextureBlock", + GFX_ID_DPLOADTEXTUREBLOCK, + GFX_IT_MULTIMACRO, G_SETTIMG, + 12, gfx_col_dpLoadTextureBlock, + }, + { + "gsDPLoadMultiTileYuv", + GFX_ID_DPLOADMULTITILEYUV, + GFX_IT_MULTIMACRO, G_SETTIMG, + 18, gfx_col_dpLoadMultiTileYuv, + }, + { + "gsDPLoadMultiTile_4b", + GFX_ID_DPLOADMULTITILE_4B, + GFX_IT_MULTIMACRO, G_SETTIMG, + 17, gfx_col_dpLoadMultiTile_4b, + }, + { + "gsDPLoadMultiTile", + GFX_ID_DPLOADMULTITILE, + GFX_IT_MULTIMACRO, G_SETTIMG, + 18, gfx_col_dpLoadMultiTile, + }, + { + "_gsDPLoadTextureTileYuv", + GFX_ID__DPLOADTEXTURETILEYUV, + GFX_IT_MULTIMACRO, G_SETTIMG, + 17, gfx_col__dpLoadTextureTileYuv, + }, + { + "_gsDPLoadTextureTile_4b", + GFX_ID__DPLOADTEXTURETILE_4B, + GFX_IT_MULTIMACRO, G_SETTIMG, + 16, gfx_col__dpLoadTextureTile_4b, + }, + { + "_gsDPLoadTextureTile", + GFX_ID__DPLOADTEXTURETILE, + GFX_IT_MULTIMACRO, G_SETTIMG, + 17, gfx_col__dpLoadTextureTile, + }, + { + "gsDPLoadTextureTileYuv", + GFX_ID_DPLOADTEXTURETILEYUV, + GFX_IT_MULTIMACRO, G_SETTIMG, + 16, gfx_col_dpLoadTextureTileYuv, + }, + { + "gsDPLoadTextureTile_4b", + GFX_ID_DPLOADTEXTURETILE_4B, + GFX_IT_MULTIMACRO, G_SETTIMG, + 15, gfx_col_dpLoadTextureTile_4b, + }, + { + "gsDPLoadTextureTile", + GFX_ID_DPLOADTEXTURETILE, + GFX_IT_MULTIMACRO, G_SETTIMG, + 16, gfx_col_dpLoadTextureTile, + }, + { + "gsDPLoadBlock", + GFX_ID_DPLOADBLOCK, + GFX_IT_OP, G_LOADBLOCK, + 5, gfx_dis_dpLoadBlock, + }, + { + "gsDPNoOp", + GFX_ID_DPNOOP, + GFX_IT_MACRO, G_NOOP, + 0, gfx_dis_dpNoOp, + }, + { + "gsDPNoOpTag", + GFX_ID_DPNOOPTAG, + GFX_IT_OP, G_NOOP, + 1, gfx_dis_dpNoOpTag, + }, + { + "gsDPPipelineMode", + GFX_ID_DPPIPELINEMODE, + GFX_IT_MACRO, G_SETOTHERMODE_H, + 1, gfx_dis_dpPipelineMode, + }, + { + "gsDPSetBlendColor", + GFX_ID_DPSETBLENDCOLOR, + GFX_IT_OP, G_SETBLENDCOLOR, + 4, gfx_dis_dpSetBlendColor, + }, + { + "gsDPSetEnvColor", + GFX_ID_DPSETENVCOLOR, + GFX_IT_OP, G_SETENVCOLOR, + 4, gfx_dis_dpSetEnvColor, + }, + { + "gsDPSetFillColor", + GFX_ID_DPSETFILLCOLOR, + GFX_IT_OP, G_SETFILLCOLOR, + 1, gfx_dis_dpSetFillColor, + }, + { + "gsDPSetFogColor", + GFX_ID_DPSETFOGCOLOR, + GFX_IT_OP, G_SETFOGCOLOR, + 4, gfx_dis_dpSetFogColor, + }, + { + "gsDPSetPrimColor", + GFX_ID_DPSETPRIMCOLOR, + GFX_IT_OP, G_SETPRIMCOLOR, + 6, gfx_dis_dpSetPrimColor, + }, + { + "gsDPSetColorImage", + GFX_ID_DPSETCOLORIMAGE, + GFX_IT_OP, G_SETCIMG, + 4, gfx_dis_dpSetColorImage, + }, + { + "gsDPSetDepthImage", + GFX_ID_DPSETDEPTHIMAGE, + GFX_IT_OP, G_SETZIMG, + 1, gfx_dis_dpSetDepthImage, + }, + { + "gsDPSetTextureImage", + GFX_ID_DPSETTEXTUREIMAGE, + GFX_IT_OP, G_SETTIMG, + 4, gfx_dis_dpSetTextureImage, + }, + { + "gsDPSetAlphaCompare", + GFX_ID_DPSETALPHACOMPARE, + GFX_IT_MACRO, G_SETOTHERMODE_L, + 1, gfx_dis_dpSetAlphaCompare, + }, + { + "gsDPSetAlphaDither", + GFX_ID_DPSETALPHADITHER, + GFX_IT_MACRO, G_SETOTHERMODE_H, + 1, gfx_dis_dpSetAlphaDither, + }, + { + "gsDPSetColorDither", + GFX_ID_DPSETCOLORDITHER, + GFX_IT_MACRO, G_SETOTHERMODE_H, + 1, gfx_dis_dpSetColorDither, + }, + { + "gsDPSetCombineMode", + GFX_ID_DPSETCOMBINEMODE, + GFX_IT_MACRO, G_SETCOMBINE, + 2, gfx_dis_dpSetCombineMode, + }, + { + "gsDPSetCombineLERP", + GFX_ID_DPSETCOMBINELERP, + GFX_IT_OP, G_SETCOMBINE, + 16, gfx_dis_dpSetCombineLERP, + }, + { + "gsDPSetConvert", + GFX_ID_DPSETCONVERT, + GFX_IT_OP, G_SETCONVERT, + 6, gfx_dis_dpSetConvert, + }, + { + "gsDPSetTextureConvert", + GFX_ID_DPSETTEXTURECONVERT, + GFX_IT_MACRO, G_SETOTHERMODE_H, + 1, gfx_dis_dpSetTextureConvert, + }, + { + "gsDPSetCycleType", + GFX_ID_DPSETCYCLETYPE, + GFX_IT_MACRO, G_SETOTHERMODE_H, + 1, gfx_dis_dpSetCycleType, + }, + { + "gsDPSetDepthSource", + GFX_ID_DPSETDEPTHSOURCE, + GFX_IT_MACRO, G_SETOTHERMODE_L, + 1, gfx_dis_dpSetDepthSource, + }, + { + "gsDPSetCombineKey", + GFX_ID_DPSETCOMBINEKEY, + GFX_IT_MACRO, G_SETOTHERMODE_H, + 1, gfx_dis_dpSetCombineKey, + }, + { + "gsDPSetKeyGB", + GFX_ID_DPSETKEYGB, + GFX_IT_OP, G_SETKEYGB, + 6, gfx_dis_dpSetKeyGB, + }, + { + "gsDPSetKeyR", + GFX_ID_DPSETKEYR, + GFX_IT_OP, G_SETKEYR, + 3, gfx_dis_dpSetKeyR, + }, + { + "gsDPSetPrimDepth", + GFX_ID_DPSETPRIMDEPTH, + GFX_IT_OP, G_SETPRIMDEPTH, + 2, gfx_dis_dpSetPrimDepth, + }, + { + "gsDPSetRenderMode", + GFX_ID_DPSETRENDERMODE, + GFX_IT_MACRO, G_SETOTHERMODE_L, + 2, gfx_dis_dpSetRenderMode, + }, + { + "gsDPSetScissor", + GFX_ID_DPSETSCISSOR, + GFX_IT_MACRO, G_SETSCISSOR, + 5, gfx_dis_dpSetScissor, + }, + { + "gsDPSetScissorFrac", + GFX_ID_DPSETSCISSORFRAC, + GFX_IT_OP, G_SETSCISSOR, + 5, gfx_dis_dpSetScissorFrac, + }, + { + "gsDPSetTextureDetail", + GFX_ID_DPSETTEXTUREDETAIL, + GFX_IT_MACRO, G_SETOTHERMODE_H, + 1, gfx_dis_dpSetTextureDetail, + }, + { + "gsDPSetTextureFilter", + GFX_ID_DPSETTEXTUREFILTER, + GFX_IT_MACRO, G_SETOTHERMODE_H, + 1, gfx_dis_dpSetTextureFilter, + }, + { + "gsDPSetTextureLOD", + GFX_ID_DPSETTEXTURELOD, + GFX_IT_MACRO, G_SETOTHERMODE_H, + 1, gfx_dis_dpSetTextureLOD, + }, + { + "gsDPSetTextureLUT", + GFX_ID_DPSETTEXTURELUT, + GFX_IT_MACRO, G_SETOTHERMODE_H, + 1, gfx_dis_dpSetTextureLUT, + }, + { + "gsDPSetTexturePersp", + GFX_ID_DPSETTEXTUREPERSP, + GFX_IT_MACRO, G_SETOTHERMODE_H, + 1, gfx_dis_dpSetTexturePersp, + }, + { + "gsDPSetTile", + GFX_ID_DPSETTILE, + GFX_IT_OP, G_SETTILE, + 12, gfx_dis_dpSetTile, + }, + { + "gsDPSetTileSize", + GFX_ID_DPSETTILESIZE, + GFX_IT_OP, G_SETTILESIZE, + 5, gfx_dis_dpSetTileSize, + }, + { + "gsSP1Triangle", + GFX_ID_SP1TRIANGLE, + GFX_IT_OP, G_TRI1, + 4, gfx_dis_sp1Triangle, + }, +#if defined(F3DEX_GBI) || defined(F3DEX_GBI_2) + { + "gsSP2Triangles", + GFX_ID_SP2TRIANGLES, + GFX_IT_OP, G_TRI2, + 8, gfx_dis_sp2Triangles, + }, +#endif +#if defined(F3DEX_GBI) + { + "gsSP1Quadrangle", + GFX_ID_SP1QUADRANGLE, + GFX_IT_MACRO, G_TRI2, + 5, gfx_dis_sp1Quadrangle, + }, +#elif defined(F3DEX_GBI_2) + { + "gsSP1Quadrangle", + GFX_ID_SP1QUADRANGLE, + GFX_IT_OP, G_QUAD, + 5, gfx_dis_sp1Quadrangle, + }, +#endif +#if defined(F3D_BETA) && defined(F3DEX_GBI) + { + "gsSPBranchLessZ", + GFX_ID_SPBRANCHLESSZ, + GFX_IT_MULTIMACRO, G_RDPHALF_2, + 6, gfx_col_spBranchLessZ, + }, + { + "gsSPBranchLessZrg", + GFX_ID_SPBRANCHLESSZRG, + GFX_IT_MULTIMACRO, G_RDPHALF_2, + 8, gfx_col_spBranchLessZrg, + }, +#elif defined(F3DEX_GBI) || defined(F3DEX_GBI_2) + { + "gsSPBranchLessZ", + GFX_ID_SPBRANCHLESSZ, + GFX_IT_MULTIMACRO, G_RDPHALF_1, + 6, gfx_col_spBranchLessZ, + }, + { + "gsSPBranchLessZrg", + GFX_ID_SPBRANCHLESSZRG, + GFX_IT_MULTIMACRO, G_RDPHALF_1, + 8, gfx_col_spBranchLessZrg, + }, +#endif + { + "gsSPBranchList", + GFX_ID_SPBRANCHLIST, + GFX_IT_MACRO, G_DL, + 1, gfx_dis_spBranchList, + }, + { + "gsSPClipRatio", + GFX_ID_SPCLIPRATIO, + GFX_IT_MULTIMACRO, G_MOVEWORD, + 1, gfx_col_spClipRatio, + }, + { + "gsSPCullDisplayList", + GFX_ID_SPCULLDISPLAYLIST, + GFX_IT_OP, G_CULLDL, + 2, gfx_dis_spCullDisplayList, + }, + { + "gsSPDisplayList", + GFX_ID_SPDISPLAYLIST, + GFX_IT_MACRO, G_DL, + 1, gfx_dis_spDisplayList, + }, + { + "gsSPEndDisplayList", + GFX_ID_SPENDDISPLAYLIST, + GFX_IT_OP, G_ENDDL, + 0, gfx_dis_spEndDisplayList, + }, + { + "gsSPFogPosition", + GFX_ID_SPFOGPOSITION, + GFX_IT_MACRO, G_MOVEWORD, + 2, gfx_dis_spFogPosition, + }, + { + "gsSPForceMatrix", + GFX_ID_SPFORCEMATRIX, + GFX_IT_MULTIMACRO, G_MOVEMEM, + 1, gfx_col_spForceMatrix, + }, +#if defined(F3D_GBI) || defined(F3DEX_GBI) + { + "gsSPSetGeometryMode", + GFX_ID_SPSETGEOMETRYMODE, + GFX_IT_OP, G_SETGEOMETRYMODE, + 1, gfx_dis_spSetGeometryMode, + }, + { + "gsSPClearGeometryMode", + GFX_ID_SPCLEARGEOMETRYMODE, + GFX_IT_OP, G_CLEARGEOMETRYMODE, + 1, gfx_dis_spClearGeometryMode, + }, + { + "gsSPLoadGeometryMode", + GFX_ID_SPLOADGEOMETRYMODE, + GFX_IT_MULTIMACRO, G_CLEARGEOMETRYMODE, + 1, gfx_col_spLoadGeometryMode, + }, +#elif defined(F3DEX_GBI_2) + { + "gsSPSetGeometryMode", + GFX_ID_SPSETGEOMETRYMODE, + GFX_IT_MACRO, G_GEOMETRYMODE, + 1, gfx_dis_spSetGeometryMode, + }, + { + "gsSPClearGeometryMode", + GFX_ID_SPCLEARGEOMETRYMODE, + GFX_IT_MACRO, G_GEOMETRYMODE, + 1, gfx_dis_spClearGeometryMode, + }, + { + "gsSPLoadGeometryMode", + GFX_ID_SPLOADGEOMETRYMODE, + GFX_IT_MACRO, G_GEOMETRYMODE, + 1, gfx_dis_spLoadGeometryMode, + }, +#endif +#if defined(F3D_GBI) || defined(F3DEX_GBI) + { + "gsSPInsertMatrix", + GFX_ID_SPINSERTMATRIX, + GFX_IT_MACRO, G_MOVEWORD, + 2, gfx_dis_spInsertMatrix, + }, +#endif + { + "gsSPLine3D", + GFX_ID_SPLINE3D, + GFX_IT_MACRO, G_LINE3D, + 3, gfx_dis_spLine3D, + }, + { + "gsSPLineW3D", + GFX_ID_SPLINEW3D, + GFX_IT_OP, G_LINE3D, + 4, gfx_dis_spLineW3D, + }, +#if defined(F3D_BETA) && defined(F3DEX_GBI) + { + "gsSPLoadUcode", + GFX_ID_SPLOADUCODE, + GFX_IT_MULTIMACRO, G_RDPHALF_2, + 2, gfx_col_spLoadUcode, + }, +#elif defined(F3DEX_GBI) || defined(F3DEX_GBI_2) + { + "gsSPLoadUcode", + GFX_ID_SPLOADUCODE, + GFX_IT_MULTIMACRO, G_RDPHALF_1, + 2, gfx_col_spLoadUcode, + }, +#endif + { + "gsSPLookAtX", + GFX_ID_SPLOOKATX, + GFX_IT_MACRO, G_MOVEMEM, + 1, gfx_dis_spLookAtY, + }, + { + "gsSPLookAtY", + GFX_ID_SPLOOKATY, + GFX_IT_MACRO, G_MOVEMEM, + 1, gfx_dis_spLookAtX, + }, + { + "gsSPLookAt", + GFX_ID_SPLOOKAT, + GFX_IT_MULTIMACRO, G_MOVEMEM, + 1, gfx_col_spLookAt, + }, + { + "gsSPMatrix", + GFX_ID_SPMATRIX, + GFX_IT_OP, G_MTX, + 2, gfx_dis_spMatrix, + }, +#if defined(F3D_GBI) + { + "gsSPModifyVertex", + GFX_ID_SPMODIFYVERTEX, + GFX_IT_MACRO, G_MOVEWORD, + 3, gfx_dis_spModifyVertex, + }, +#elif defined(F3DEX_GBI) || defined(F3DEX_GBI_2) + { + "gsSPModifyVertex", + GFX_ID_SPMODIFYVERTEX, + GFX_IT_OP, G_MODIFYVTX, + 3, gfx_dis_spModifyVertex, + }, +#endif +#if defined(F3D_BETA) && (defined(F3D_GBI) || defined(F3DEX_GBI)) + { + "gsSPPerspNormalize", + GFX_ID_SPPERSPNORMALIZE, + GFX_IT_OP, G_PERSPNORM, + 1, gfx_dis_spPerspNormalize, + }, +#else + { + "gsSPPerspNormalize", + GFX_ID_SPPERSPNORMALIZE, + GFX_IT_MACRO, G_MOVEWORD, + 1, gfx_dis_spPerspNormalize, + }, +#endif +#if defined(F3D_GBI) || defined(F3DEX_GBI) + { + "gsSPPopMatrix", + GFX_ID_SPPOPMATRIX, + GFX_IT_OP, G_POPMTX, + 1, gfx_dis_spPopMatrix, + }, +#elif defined(F3DEX_GBI_2) + { + "gsSPPopMatrix", + GFX_ID_SPPOPMATRIX, + GFX_IT_MACRO, G_POPMTX, + 1, gfx_dis_spPopMatrix, + }, + { + "gsSPPopMatrixN", + GFX_ID_SPPOPMATRIXN, + GFX_IT_OP, G_POPMTX, + 2, gfx_dis_spPopMatrixN, + }, +#endif + { + "gsSPSegment", + GFX_ID_SPSEGMENT, + GFX_IT_MACRO, G_MOVEWORD, + 2, gfx_dis_spSegment, + }, + { + "gsSPSetLights1", + GFX_ID_SPSETLIGHTS1, + GFX_IT_MULTIMACRO, G_MOVEWORD, + 1, gfx_col_spSetLights1, + }, + { + "gsSPSetLights2", + GFX_ID_SPSETLIGHTS2, + GFX_IT_MULTIMACRO, G_MOVEWORD, + 1, gfx_col_spSetLights2, + }, + { + "gsSPSetLights3", + GFX_ID_SPSETLIGHTS3, + GFX_IT_MULTIMACRO, G_MOVEWORD, + 1, gfx_col_spSetLights3, + }, + { + "gsSPSetLights4", + GFX_ID_SPSETLIGHTS4, + GFX_IT_MULTIMACRO, G_MOVEWORD, + 1, gfx_col_spSetLights4, + }, + { + "gsSPSetLights5", + GFX_ID_SPSETLIGHTS5, + GFX_IT_MULTIMACRO, G_MOVEWORD, + 1, gfx_col_spSetLights5, + }, + { + "gsSPSetLights6", + GFX_ID_SPSETLIGHTS6, + GFX_IT_MULTIMACRO, G_MOVEWORD, + 1, gfx_col_spSetLights6, + }, + { + "gsSPSetLights7", + GFX_ID_SPSETLIGHTS7, + GFX_IT_MULTIMACRO, G_MOVEWORD, + 1, gfx_col_spSetLights7, + }, + { + "gsSPNumLights", + GFX_ID_SPNUMLIGHTS, + GFX_IT_MACRO, G_MOVEWORD, + 1, gfx_dis_spNumLights, + }, + { + "gsSPLight", + GFX_ID_SPLIGHT, + GFX_IT_MACRO, G_MOVEMEM, + 2, gfx_dis_spLight, + }, + { + "gsSPLightColor", + GFX_ID_SPLIGHTCOLOR, + GFX_IT_MULTIMACRO, G_MOVEWORD, + 2, gfx_col_spLightColor, + }, + { + "gsSPTexture", + GFX_ID_SPTEXTURE, + GFX_IT_OP, G_TEXTURE, + 5, gfx_dis_spTexture, + }, + { + "gsSPTextureRectangle", + GFX_ID_SPTEXTURERECTANGLE, + GFX_IT_MULTIMACRO, G_TEXRECT, + 9, gfx_col_spTextureRectangle, + }, + { + "gsSPTextureRectangleFlip", + GFX_ID_SPTEXTURERECTANGLEFLIP, + GFX_IT_MULTIMACRO, G_TEXRECTFLIP, + 9, gfx_col_spTextureRectangleFlip, + }, + { + "gsSPVertex", + GFX_ID_SPVERTEX, + GFX_IT_OP, G_VTX, + 3, gfx_dis_spVertex, + }, + { + "gsSPViewport", + GFX_ID_SPVIEWPORT, + GFX_IT_MACRO, G_MOVEMEM, + 1, gfx_dis_spViewport, + }, + { + "gsDPLoadTLUTCmd", + GFX_ID_DPLOADTLUTCMD, + GFX_IT_OP, G_LOADTLUT, + 2, gfx_dis_dpLoadTLUTCmd, + }, + { + "gsDPLoadTLUT", + GFX_ID_DPLOADTLUT, + GFX_IT_MULTIMACRO, G_SETTIMG, + 3, gfx_col_dpLoadTLUT, + }, +#if defined(F3DEX_GBI) || defined(F3DEX_GBI_2) + { + "gsBranchZ", + GFX_ID_BRANCHZ, + GFX_IT_OP, G_BRANCH_Z, + 7, gfx_dis_BranchZ, + }, +#endif + { + "gsDisplayList", + GFX_ID_DISPLAYLIST, + GFX_IT_OP, G_DL, + 2, gfx_dis_DisplayList, + }, +#if defined(F3D_BETA) && (defined(F3D_GBI) || defined(F3DEX_GBI)) + { + "gsDPHalf1", + GFX_ID_DPHALF1, + GFX_IT_OP, G_RDPHALF_2, + 1, gfx_dis_dpHalf1, + }, + { + "gsDPHalf2", + GFX_ID_DPHALF2, + GFX_IT_OP, G_RDPHALF_CONT, + 1, gfx_dis_dpHalf2, + }, +#else + { + "gsDPHalf1", + GFX_ID_DPHALF1, + GFX_IT_OP, G_RDPHALF_1, + 1, gfx_dis_dpHalf1, + }, + { + "gsDPHalf2", + GFX_ID_DPHALF2, + GFX_IT_OP, G_RDPHALF_2, + 1, gfx_dis_dpHalf2, + }, +#endif + { + "gsDPLoadTile", + GFX_ID_DPLOADTILE, + GFX_IT_OP, G_LOADTILE, + 5, gfx_dis_dpLoadTile, + }, +#if defined(F3DEX_GBI_2) + { + "gsSPGeometryMode", + GFX_ID_SPGEOMETRYMODE, + GFX_IT_OP, G_GEOMETRYMODE, + 2, gfx_dis_spGeometryMode, + }, +#endif + { + "gsSPSetOtherModeLo", + GFX_ID_SPSETOTHERMODELO, + GFX_IT_OP, G_SETOTHERMODE_L, + 3, gfx_dis_spSetOtherModeLo, + }, + { + "gsSPSetOtherModeHi", + GFX_ID_SPSETOTHERMODEHI, + GFX_IT_OP, G_SETOTHERMODE_H, + 3, gfx_dis_spSetOtherModeHi, + }, + { + "gsDPSetOtherMode", + GFX_ID_DPSETOTHERMODE, + GFX_IT_OP, G_RDPSETOTHERMODE, + 2, gfx_dis_dpSetOtherMode, + }, + { + "gsMoveWd", + GFX_ID_MOVEWD, + GFX_IT_OP, G_MOVEWORD, + 3, gfx_dis_MoveWd, + }, +#if defined(F3D_GBI) || defined(F3DEX_GBI) + { + "gsMoveMem", + GFX_ID_MOVEMEM, + GFX_IT_OP, G_MOVEMEM, + 3, gfx_dis_MoveMem, + }, +#elif defined(F3DEX_GBI_2) + { + "gsMoveMem", + GFX_ID_MOVEMEM, + GFX_IT_OP, G_MOVEMEM, + 4, gfx_dis_MoveMem, + }, +#endif +#if defined(F3DEX_GBI_2) + { + "gsSPDma_io", + GFX_ID_SPDMA_IO, + GFX_IT_OP, G_DMA_IO, + 4, gfx_dis_spDma_io, + }, + { + "gsSPDmaRead", + GFX_ID_SPDMAREAD, + GFX_IT_MACRO, G_DMA_IO, + 3, gfx_dis_spDmaRead, + }, + { + "gsSPDmaWrite", + GFX_ID_SPDMAWRITE, + GFX_IT_MACRO, G_DMA_IO, + 3, gfx_dis_spDmaWrite, + }, +#endif +#if defined(F3DEX_GBI) || defined(F3DEX_GBI_2) + { + "gsLoadUcode", + GFX_ID_LOADUCODE, + GFX_IT_OP, G_LOAD_UCODE, + 2, gfx_dis_LoadUcode, + }, +#endif +#if defined(F3D_BETA) && defined(F3DEX_GBI) + { + "gsSPLoadUcodeEx", + GFX_ID_SPLOADUCODEEX, + GFX_IT_MULTIMACRO, G_RDPHALF_2, + 3, gfx_col_spLoadUcodeEx, + }, +#elif defined(F3DEX_GBI) || defined(F3DEX_GBI_2) + { + "gsSPLoadUcodeEx", + GFX_ID_SPLOADUCODEEX, + GFX_IT_MULTIMACRO, G_RDPHALF_1, + 3, gfx_col_spLoadUcodeEx, + }, +#endif + { + "gsTexRect", + GFX_ID_TEXRECT, + GFX_IT_OP, G_TEXRECT, + 5, gfx_dis_TexRect, + }, + { + "gsTexRectFlip", + GFX_ID_TEXRECTFLIP, + GFX_IT_OP, G_TEXRECTFLIP, + 5, gfx_dis_TexRectFlip, + }, + { + "gsSPNoOp", + GFX_ID_SPNOOP, + GFX_IT_OP, G_SPNOOP, + 0, gfx_dis_spNoOp, + }, +#if defined(F3DEX_GBI_2) + { + "gsSpecial3", + GFX_ID_SPECIAL3, + GFX_IT_OP, G_SPECIAL_3, + 2, gfx_dis_Special3, + }, + { + "gsSpecial2", + GFX_ID_SPECIAL2, + GFX_IT_OP, G_SPECIAL_2, + 2, gfx_dis_Special2, + }, + { + "gsSpecial1", + GFX_ID_SPECIAL1, + GFX_IT_OP, G_SPECIAL_1, + 2, gfx_dis_Special1, + }, +#endif +}; diff --git a/tools/gfxdis/gfxdis.f3dex2 b/tools/gfxdis/gfxdis.f3dex2 new file mode 100755 index 00000000..af73b523 Binary files /dev/null and b/tools/gfxdis/gfxdis.f3dex2 differ diff --git a/tools/gfxdis/gfxdis.h b/tools/gfxdis/gfxdis.h new file mode 100644 index 00000000..8d6cf364 --- /dev/null +++ b/tools/gfxdis/gfxdis.h @@ -0,0 +1,373 @@ +#ifndef GFXDIS_H +#define GFXDIS_H +#include +#include +#include + +struct gfx_insn; + +typedef int (*gfx_insn_dis_t)(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +typedef int (*gfx_insn_col_t)(struct gfx_insn *insn, int n_insn); +typedef int (*gfx_insn_strarg_t)(char *buf, uint32_t arg); + +enum gfx_insn_def +{ + GFX_ID_INVD, + GFX_ID_DPFILLRECTANGLE, + GFX_ID_DPFULLSYNC, + GFX_ID_DPLOADSYNC, + GFX_ID_DPTILESYNC, + GFX_ID_DPPIPESYNC, + GFX_ID_DPLOADTLUT_PAL16, + GFX_ID_DPLOADTLUT_PAL256, + GFX_ID_DPLOADMULTIBLOCKYUVS, + GFX_ID_DPLOADMULTIBLOCKYUV, + GFX_ID_DPLOADMULTIBLOCK_4BS, + GFX_ID_DPLOADMULTIBLOCK_4B, + GFX_ID_DPLOADMULTIBLOCKS, + GFX_ID_DPLOADMULTIBLOCK, + GFX_ID__DPLOADTEXTUREBLOCKYUVS, + GFX_ID__DPLOADTEXTUREBLOCKYUV, + GFX_ID__DPLOADTEXTUREBLOCK_4BS, + GFX_ID__DPLOADTEXTUREBLOCK_4B, + GFX_ID__DPLOADTEXTUREBLOCKS, + GFX_ID__DPLOADTEXTUREBLOCK, + GFX_ID_DPLOADTEXTUREBLOCKYUVS, + GFX_ID_DPLOADTEXTUREBLOCKYUV, + GFX_ID_DPLOADTEXTUREBLOCK_4BS, + GFX_ID_DPLOADTEXTUREBLOCK_4B, + GFX_ID_DPLOADTEXTUREBLOCKS, + GFX_ID_DPLOADTEXTUREBLOCK, + GFX_ID_DPLOADMULTITILEYUV, + GFX_ID_DPLOADMULTITILE_4B, + GFX_ID_DPLOADMULTITILE, + GFX_ID__DPLOADTEXTURETILEYUV, + GFX_ID__DPLOADTEXTURETILE_4B, + GFX_ID__DPLOADTEXTURETILE, + GFX_ID_DPLOADTEXTURETILEYUV, + GFX_ID_DPLOADTEXTURETILE_4B, + GFX_ID_DPLOADTEXTURETILE, + GFX_ID_DPLOADBLOCK, + GFX_ID_DPNOOP, + GFX_ID_DPNOOPTAG, + GFX_ID_DPPIPELINEMODE, + GFX_ID_DPSETBLENDCOLOR, + GFX_ID_DPSETENVCOLOR, + GFX_ID_DPSETFILLCOLOR, + GFX_ID_DPSETFOGCOLOR, + GFX_ID_DPSETPRIMCOLOR, + GFX_ID_DPSETCOLORIMAGE, + GFX_ID_DPSETDEPTHIMAGE, + GFX_ID_DPSETTEXTUREIMAGE, + GFX_ID_DPSETALPHACOMPARE, + GFX_ID_DPSETALPHADITHER, + GFX_ID_DPSETCOLORDITHER, + GFX_ID_DPSETCOMBINEMODE, + GFX_ID_DPSETCOMBINELERP, + GFX_ID_DPSETCONVERT, + GFX_ID_DPSETTEXTURECONVERT, + GFX_ID_DPSETCYCLETYPE, + GFX_ID_DPSETDEPTHSOURCE, + GFX_ID_DPSETCOMBINEKEY, + GFX_ID_DPSETKEYGB, + GFX_ID_DPSETKEYR, + GFX_ID_DPSETPRIMDEPTH, + GFX_ID_DPSETRENDERMODE, + GFX_ID_DPSETSCISSOR, + GFX_ID_DPSETSCISSORFRAC, + GFX_ID_DPSETTEXTUREDETAIL, + GFX_ID_DPSETTEXTUREFILTER, + GFX_ID_DPSETTEXTURELOD, + GFX_ID_DPSETTEXTURELUT, + GFX_ID_DPSETTEXTUREPERSP, + GFX_ID_DPSETTILE, + GFX_ID_DPSETTILESIZE, + GFX_ID_SP1TRIANGLE, +#if defined(F3DEX_GBI) || defined(F3DEX_GBI_2) + GFX_ID_SP2TRIANGLES, + GFX_ID_SP1QUADRANGLE, + GFX_ID_SPBRANCHLESSZ, + GFX_ID_SPBRANCHLESSZRG, +#endif + GFX_ID_SPBRANCHLIST, + GFX_ID_SPCLIPRATIO, + GFX_ID_SPCULLDISPLAYLIST, + GFX_ID_SPDISPLAYLIST, + GFX_ID_SPENDDISPLAYLIST, + GFX_ID_SPFOGPOSITION, + GFX_ID_SPFORCEMATRIX, + GFX_ID_SPSETGEOMETRYMODE, + GFX_ID_SPCLEARGEOMETRYMODE, + GFX_ID_SPLOADGEOMETRYMODE, +#if defined(F3D_GBI) || defined(F3DB_GBI) || defined(F3DEX_GBI) + GFX_ID_SPINSERTMATRIX, +#endif + GFX_ID_SPLINE3D, + GFX_ID_SPLINEW3D, +#if defined(F3DEX_GBI) || defined(F3DEX_GBI_2) + GFX_ID_SPLOADUCODE, +#endif + GFX_ID_SPLOOKATX, + GFX_ID_SPLOOKATY, + GFX_ID_SPLOOKAT, + GFX_ID_SPMATRIX, + GFX_ID_SPMODIFYVERTEX, + GFX_ID_SPPERSPNORMALIZE, + GFX_ID_SPPOPMATRIX, +#if defined(F3DEX_GBI_2) + GFX_ID_SPPOPMATRIXN, +#endif + GFX_ID_SPSEGMENT, + GFX_ID_SPSETLIGHTS1, + GFX_ID_SPSETLIGHTS2, + GFX_ID_SPSETLIGHTS3, + GFX_ID_SPSETLIGHTS4, + GFX_ID_SPSETLIGHTS5, + GFX_ID_SPSETLIGHTS6, + GFX_ID_SPSETLIGHTS7, + GFX_ID_SPNUMLIGHTS, + GFX_ID_SPLIGHT, + GFX_ID_SPLIGHTCOLOR, + GFX_ID_SPTEXTURE, + GFX_ID_SPTEXTURERECTANGLE, + GFX_ID_SPTEXTURERECTANGLEFLIP, + GFX_ID_SPVERTEX, + GFX_ID_SPVIEWPORT, + GFX_ID_DPLOADTLUTCMD, + GFX_ID_DPLOADTLUT, +#if defined(F3DEX_GBI) || defined(F3DEX_GBI_2) + GFX_ID_BRANCHZ, +#endif + GFX_ID_DISPLAYLIST, + GFX_ID_DPHALF1, + GFX_ID_DPHALF2, + GFX_ID_DPLOADTILE, +#if defined(F3DEX_GBI_2) + GFX_ID_SPGEOMETRYMODE, +#endif + GFX_ID_SPSETOTHERMODELO, + GFX_ID_SPSETOTHERMODEHI, + GFX_ID_DPSETOTHERMODE, + GFX_ID_MOVEWD, + GFX_ID_MOVEMEM, +#if defined(F3DEX_GBI_2) + GFX_ID_SPDMA_IO, + GFX_ID_SPDMAREAD, + GFX_ID_SPDMAWRITE, +#endif +#if defined(F3DEX_GBI) || defined(F3DEX_GBI_2) + GFX_ID_LOADUCODE, + GFX_ID_SPLOADUCODEEX, +#endif + GFX_ID_TEXRECT, + GFX_ID_TEXRECTFLIP, + GFX_ID_SPNOOP, +#if defined(F3DEX_GBI_2) + GFX_ID_SPECIAL3, + GFX_ID_SPECIAL2, + GFX_ID_SPECIAL1, +#endif + GFX_ID_MAX, +}; + +enum gfx_insn_type +{ + GFX_IT_OP, + GFX_IT_MACRO, + GFX_IT_MULTIMACRO, +}; + +struct gfx_insn_info +{ + const char *name; + enum gfx_insn_def def; + enum gfx_insn_type type; + int opcode; + int n_args; + void *handler; +}; + +struct gfx_insn +{ + enum gfx_insn_def def; + int n_gfx; + uint32_t arg[18]; + gfx_insn_strarg_t strarg[18]; +}; + +struct gfxdis_cfg +{ + _Bool dis_invd; + _Bool use_q; + _Bool dec_color; +}; + +int gfx_insn_dis(struct gfx_insn *insn, Gfx *gfx); +int gfx_insn_col(struct gfx_insn *insn, int n_insn); +char *gfx_insn_str(struct gfx_insn *insn, char *buf); +char *gfx_insn_str_dyn(struct gfx_insn *insn, const char *arg, char *buf); +int gfx_dis(struct vector *insn_vect, Gfx *gfx, int max); + +int gfx_dis_invd(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_dpFillRectangle(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_dpFullSync(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_dpLoadSync(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_dpTileSync(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_dpPipeSync(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_col_dpLoadTLUT_pal16(struct gfx_insn *insn, int n_insn); +int gfx_col_dpLoadTLUT_pal256(struct gfx_insn *insn, int n_insn); +int gfx_col_dpLoadMultiBlockYuvS(struct gfx_insn *insn, int n_insn); +int gfx_col_dpLoadMultiBlockYuv(struct gfx_insn *insn, int n_insn); +int gfx_col_dpLoadMultiBlock_4bS(struct gfx_insn *insn, int n_insn); +int gfx_col_dpLoadMultiBlock_4b(struct gfx_insn *insn, int n_insn); +int gfx_col_dpLoadMultiBlockS(struct gfx_insn *insn, int n_insn); +int gfx_col_dpLoadMultiBlock(struct gfx_insn *insn, int n_insn); +int gfx_col__dpLoadTextureBlockYuvS(struct gfx_insn *insn, int n_insn); +int gfx_col__dpLoadTextureBlockYuv(struct gfx_insn *insn, int n_insn); +int gfx_col__dpLoadTextureBlock_4bS(struct gfx_insn *insn, int n_insn); +int gfx_col__dpLoadTextureBlock_4b(struct gfx_insn *insn, int n_insn); +int gfx_col__dpLoadTextureBlockS(struct gfx_insn *insn, int n_insn); +int gfx_col__dpLoadTextureBlock(struct gfx_insn *insn, int n_insn); +int gfx_col_dpLoadTextureBlockYuvS(struct gfx_insn *insn, int n_insn); +int gfx_col_dpLoadTextureBlockYuv(struct gfx_insn *insn, int n_insn); +int gfx_col_dpLoadTextureBlock_4bS(struct gfx_insn *insn, int n_insn); +int gfx_col_dpLoadTextureBlock_4b(struct gfx_insn *insn, int n_insn); +int gfx_col_dpLoadTextureBlockS(struct gfx_insn *insn, int n_insn); +int gfx_col_dpLoadTextureBlock(struct gfx_insn *insn, int n_insn); +int gfx_col_dpLoadMultiTileYuv(struct gfx_insn *insn, int n_insn); +int gfx_col_dpLoadMultiTile_4b(struct gfx_insn *insn, int n_insn); +int gfx_col_dpLoadMultiTile(struct gfx_insn *insn, int n_insn); +int gfx_col__dpLoadTextureTileYuv(struct gfx_insn *insn, int n_insn); +int gfx_col__dpLoadTextureTile_4b(struct gfx_insn *insn, int n_insn); +int gfx_col__dpLoadTextureTile(struct gfx_insn *insn, int n_insn); +int gfx_col_dpLoadTextureTileYuv(struct gfx_insn *insn, int n_insn); +int gfx_col_dpLoadTextureTile_4b(struct gfx_insn *insn, int n_insn); +int gfx_col_dpLoadTextureTile(struct gfx_insn *insn, int n_insn); +int gfx_dis_dpLoadBlock(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_dpNoOp(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_dpNoOpTag(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_dpPipelineMode(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_dpSetBlendColor(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_dpSetEnvColor(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_dpSetFillColor(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_dpSetFogColor(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_dpSetPrimColor(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_dpSetColorImage(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_dpSetDepthImage(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_dpSetTextureImage(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_dpSetAlphaCompare(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_dpSetAlphaDither(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_dpSetColorDither(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_dpSetCombineMode(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_dpSetCombineLERP(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_dpSetConvert(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_dpSetTextureConvert(struct gfx_insn *insn, + uint32_t hi, uint32_t lo); +int gfx_dis_dpSetCycleType(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_dpSetDepthSource(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_dpSetCombineKey(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_dpSetKeyGB(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_dpSetKeyR(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_dpSetPrimDepth(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_dpSetRenderMode(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_dpSetScissor(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_dpSetScissorFrac(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_dpSetTextureDetail(struct gfx_insn *insn, + uint32_t hi, uint32_t lo); +int gfx_dis_dpSetTextureFilter(struct gfx_insn *insn, + uint32_t hi, uint32_t lo); +int gfx_dis_dpSetTextureLOD(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_dpSetTextureLUT(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_dpSetTexturePersp(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_dpSetTile(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_dpSetTileSize(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_sp1Triangle(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +#if defined(F3DEX_GBI) || defined(F3DEX_GBI_2) +int gfx_dis_sp2Triangles(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_sp1Quadrangle(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_col_spBranchLessZ(struct gfx_insn *insn, int n_insn); +int gfx_col_spBranchLessZrg(struct gfx_insn *insn, int n_insn); +#endif +int gfx_dis_spBranchList(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_col_spClipRatio(struct gfx_insn *insn, int n_insn); +int gfx_dis_spCullDisplayList(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_spDisplayList(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_spEndDisplayList(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_spFogPosition(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_col_spForceMatrix(struct gfx_insn *insn, int n_insn); +int gfx_dis_spSetGeometryMode(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_spClearGeometryMode(struct gfx_insn *insn, + uint32_t hi, uint32_t lo); +int gfx_dis_spLoadGeometryMode(struct gfx_insn *insn, + uint32_t hi, uint32_t lo); +#if defined(F3D_GBI) || defined(F3DB_GBI) || defined(F3DEX_GBI) +int gfx_dis_spInsertMatrix(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +#endif +int gfx_dis_spLine3D(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_spLineW3D(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +#if defined(F3DEX_GBI) || defined(F3DEX_GBI_2) +int gfx_col_spLoadUcode(struct gfx_insn *insn, int n_insn); +#endif +int gfx_dis_spLookAtX(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_spLookAtY(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_col_spLookAt(struct gfx_insn *insn, int n_insn); +int gfx_dis_spMatrix(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_spModifyVertex(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_spPerspNormalize(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_spPopMatrix(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +#if defined(F3DEX_GBI_2) +int gfx_dis_spPopMatrixN(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +#endif +int gfx_dis_spSegment(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_col_spSetLights1(struct gfx_insn *insn, int n_insn); +int gfx_col_spSetLights2(struct gfx_insn *insn, int n_insn); +int gfx_col_spSetLights3(struct gfx_insn *insn, int n_insn); +int gfx_col_spSetLights4(struct gfx_insn *insn, int n_insn); +int gfx_col_spSetLights5(struct gfx_insn *insn, int n_insn); +int gfx_col_spSetLights6(struct gfx_insn *insn, int n_insn); +int gfx_col_spSetLights7(struct gfx_insn *insn, int n_insn); +int gfx_dis_spNumLights(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_spLight(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_col_spLightColor(struct gfx_insn *insn, int n_insn); +int gfx_dis_spTexture(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_col_spTextureRectangle(struct gfx_insn *insn, int n_insn); +int gfx_col_spTextureRectangleFlip(struct gfx_insn *insn, int n_insn); +int gfx_dis_spVertex(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_spViewport(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_dpLoadTLUTCmd(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_col_dpLoadTLUT(struct gfx_insn *insn, int n_insn); +#if defined(F3DEX_GBI) || defined(F3DEX_GBI_2) +int gfx_dis_BranchZ(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +#endif +int gfx_dis_DisplayList(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_dpHalf1(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_dpHalf2(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_dpLoadTile(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_spGeometryMode(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_spSetOtherModeLo(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_spSetOtherModeHi(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_dpSetOtherMode(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_MoveWd(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_MoveMem(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +#if defined(F3DEX_GBI_2) +int gfx_dis_spDma_io(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_spDmaRead(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_spDmaWrite(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +#endif +#if defined(F3DEX_GBI) || defined(F3DEX_GBI_2) +int gfx_dis_LoadUcode(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_col_spLoadUcodeEx(struct gfx_insn *insn, int n_insn); +#endif +int gfx_dis_TexRect(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_TexRectFlip(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_spNoOp(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +#if defined(F3DEX_GBI_2) +int gfx_dis_Special3(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_Special2(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +int gfx_dis_Special1(struct gfx_insn *insn, uint32_t hi, uint32_t lo); +#endif + +extern struct gfx_insn_info gfx_insn_info[]; +extern struct gfxdis_cfg gfxdis_cfg; + +#endif diff --git a/tools/gfxdis/include/grc.c b/tools/gfxdis/include/grc.c new file mode 100644 index 00000000..ff3ecd1b --- /dev/null +++ b/tools/gfxdis/include/grc.c @@ -0,0 +1,34 @@ +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +typedef struct +{ + const char *name; + void *data; + size_t size; +} grc_t; + +extern grc_t __RESOURCE_LIST__[]; +extern grc_t __RESOURCE_END__[]; + +int grc_resource_get(const char *res_name, void **data, size_t *size) +{ + for (grc_t *r = __RESOURCE_LIST__; r < __RESOURCE_END__; ++r) + if (strcmp(res_name, r->name) == 0) { + if (data) + *data = r->data; + if (size) + *size = r->size; + return 1; + } + return 0; +} + +#ifdef __cplusplus +} +#endif diff --git a/tools/gfxdis/include/grc.h b/tools/gfxdis/include/grc.h new file mode 100644 index 00000000..fea28c5f --- /dev/null +++ b/tools/gfxdis/include/grc.h @@ -0,0 +1,32 @@ +#ifndef N64_GRC_H +#define N64_GRC_H +#include +#include +#include "n64.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +struct grc_texture +{ + g_ifmt_t im_fmt; + g_isiz_t im_siz; + uint16_t image_width; + uint16_t image_height; + uint16_t tile_width; + uint16_t tile_height; + uint16_t tiles_x; + uint16_t tiles_y; + uint16_t pad; + char texture_data[]; +}; + +int grc_resource_get(const char *res_name, void **data, size_t *size); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/tools/gfxdis/include/list/list.c b/tools/gfxdis/include/list/list.c new file mode 100644 index 00000000..67c7001c --- /dev/null +++ b/tools/gfxdis/include/list/list.c @@ -0,0 +1,264 @@ +/* list.c + * -glank + */ + +#include +#include +#include +#include "list.h" + +struct list_element_header +{ + struct list_element_header *prev, *next; +}; + +#define MAX_ALIGN(N) (((N) + _Alignof(max_align_t) - 1) & \ + ~(_Alignof(max_align_t) - 1)) +#define ELEMENT_HEADER_SIZE (MAX_ALIGN(sizeof(struct list_element_header))) + + +#ifdef __cplusplus +extern "C" +{ +#endif + +void list_init(struct list *list, size_t element_size) +{ + list->element_size = element_size; + list->size = 0; + list->first = NULL; + list->last = NULL; +} + +void *list_prev(const void *element) +{ + const struct list_element_header *header = + (const struct list_element_header*)((const char*)element - + ELEMENT_HEADER_SIZE); + if (header->prev) + return (char*)header->prev + ELEMENT_HEADER_SIZE; + else + return NULL; +} + +void *list_next(const void *element) +{ + const struct list_element_header *header = + (const struct list_element_header*)((const char*)element - + ELEMENT_HEADER_SIZE); + if (header->next) + return (char*)header->next + ELEMENT_HEADER_SIZE; + else + return NULL; +} + +void *list_prev_in(const struct list *list, const void *element) +{ + if (!element) + return list->last; + return list_prev(element); +} + +void *list_next_in(const struct list *list, const void *element) +{ + if (!element) + return list->first; + return list_next(element); +} + +void *list_at(const struct list *list, size_t position) +{ + if (list->size == 0) + return NULL; + struct list_element_header *header = (struct list_element_header*) + ((char*)list->first - + ELEMENT_HEADER_SIZE); + for (size_t i = 0; i < position; ++i) { + if (header->next) + header = header->next; + else + return NULL; + } + return (char*)header + ELEMENT_HEADER_SIZE; +} + +void *list_insert_size(struct list *list, void *element, size_t size, + const void *data) +{ + struct list_element_header *new_header = (struct list_element_header*) + malloc(ELEMENT_HEADER_SIZE + size); + if (!new_header) + return NULL; + void *new_data = (char*)new_header + ELEMENT_HEADER_SIZE; + if (data) + memcpy(new_data, data, size); + if (element) { + struct list_element_header *header = (struct list_element_header*) + ((char*)element - + ELEMENT_HEADER_SIZE); + new_header->prev = header->prev; + new_header->next = header; + if (header->prev) + header->prev->next = new_header; + header->prev = new_header; + if (element == list->first) + list->first = new_data; + } + else { + if (list->size == 0) { + new_header->prev = NULL; + list->first = new_data; + } + else { + new_header->prev = (struct list_element_header*)((char*)list->last - + ELEMENT_HEADER_SIZE); + new_header->prev->next = new_header; + } + new_header->next = NULL; + list->last = new_data; + } + ++list->size; + return new_data; +} + +void list_transfer(struct list *dest, void *position, + struct list *src, void *element) +{ + struct list_element_header *e_header = (struct list_element_header*) + ((char*)element - + ELEMENT_HEADER_SIZE); + if (element == src->first) { + if (e_header->next) + src->first = (void*)((char*)e_header->next + ELEMENT_HEADER_SIZE); + else + src->first = NULL; + } + if (element == src->last) { + if (e_header->prev) + src->last = (void*)((char*)e_header->prev + ELEMENT_HEADER_SIZE); + else + src->last = NULL; + } + if (e_header->prev) + e_header->prev->next = e_header->next; + if (e_header->next) + e_header->next->prev = e_header->prev; + if (position) { + struct list_element_header *p_header = (struct list_element_header*) + ((char*)position - + ELEMENT_HEADER_SIZE); + e_header->prev = p_header->prev; + e_header->next = p_header; + if (p_header->prev) + p_header->prev->next = e_header; + p_header->prev = e_header; + if (position == dest->first) + dest->first = element; + } + else { + if (dest->size == 0) { + e_header->prev = NULL; + dest->first = element; + } + else { + e_header->prev = (struct list_element_header*)((char*)dest->last - + ELEMENT_HEADER_SIZE); + e_header->prev->next = e_header; + } + e_header->next = NULL; + dest->last = element; + } + --src->size; + ++dest->size; +} + +void list_splice(struct list *dest, struct list *src) +{ + if (!src->first) + return; + dest->size += src->size; + if (dest->last) { + struct list_element_header *f_header = (struct list_element_header*) + ((char*)src->first - + ELEMENT_HEADER_SIZE); + struct list_element_header *l_header = (struct list_element_header*) + ((char*)dest->last - + ELEMENT_HEADER_SIZE); + f_header->prev = l_header; + l_header->next = f_header; + } + else + dest->first = src->first; + dest->last = src->last; + src->first = NULL; + src->last = NULL; + src->size = 0; +} + +void *list_insert(struct list *list, void *element, const void *data) +{ + return list_insert_size(list, element, list->element_size, data); +} + +void *list_insert_after_size(struct list *list, void *element, size_t size, + const void *data) +{ + return list_insert_size(list, list_next_in(list, element), size, data); +} + +void *list_insert_after(struct list *list, void *element, const void *data) +{ + return list_insert_size(list, list_next_in(list, element), + list->element_size, data); +} + +void *list_push_back_size(struct list *list, size_t size, const void *data) +{ + return list_insert_size(list, NULL, size, data); +} + +void *list_push_back(struct list *list, const void *data) +{ + return list_insert_size(list, NULL, list->element_size, data); +} + +void list_erase(struct list *list, void *element) +{ + struct list_element_header *header = (struct list_element_header*) + ((char*)element - ELEMENT_HEADER_SIZE); + if (element == list->first) { + if (header->next) + list->first = (void*)((char*)header->next + ELEMENT_HEADER_SIZE); + else + list->first = NULL; + } + if (element == list->last) { + if (header->prev) + list->last = (void*)((char*)header->prev + ELEMENT_HEADER_SIZE); + else + list->last = NULL; + } + if (header->prev) + header->prev->next = header->next; + if (header->next) + header->next->prev = header->prev; + free(header); + --list->size; +} + +void list_destroy(struct list *list) +{ + struct list_element_header *header = NULL; + if (list->first) + header = (struct list_element_header*)((char*)list->first - + ELEMENT_HEADER_SIZE); + while (header) { + struct list_element_header *next_header = header->next; + free(header); + header = next_header; + } +} + +#ifdef __cplusplus +} +#endif diff --git a/tools/gfxdis/include/list/list.h b/tools/gfxdis/include/list/list.h new file mode 100644 index 00000000..f345781b --- /dev/null +++ b/tools/gfxdis/include/list/list.h @@ -0,0 +1,44 @@ +/* list.h + * -glank + */ + +#ifndef LIST_H +#define LIST_H +#include + +struct list +{ + size_t element_size, size; + void *first, *last; +}; + +#ifdef __cplusplus +extern "C" +{ +#endif + +void list_init(struct list *list, size_t element_size); +void *list_prev(const void *element); +void *list_next(const void *element); +void *list_prev_in(const struct list *list, const void *element); +void *list_next_in(const struct list *list, const void *element); +void *list_at(const struct list *list, size_t position); +void *list_insert_size(struct list *list, void *element, size_t size, + const void *data); +void list_transfer(struct list *dest, void *position, + struct list *src, void *element); +void list_splice(struct list *dest, struct list *src); +void *list_insert(struct list *list, void *element, const void *data); +void *list_insert_after_size(struct list *list, void *element, size_t size, + const void *data); +void *list_insert_after(struct list *list, void *element, const void *data); +void *list_push_back_size(struct list *list, size_t size, const void *data); +void *list_push_back(struct list *list, const void *data); +void list_erase(struct list *list, void *element); +void list_destroy(struct list *list); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/tools/gfxdis/include/memory/memory.c b/tools/gfxdis/include/memory/memory.c new file mode 100644 index 00000000..eb7b7333 --- /dev/null +++ b/tools/gfxdis/include/memory/memory.c @@ -0,0 +1,214 @@ +/* memory.c + * -glank + */ + +#include +#include +#include +#include "memory.h" + +#ifndef MALLOC_PRINTF +#include +#define MALLOC_PRINTF printf +#endif + +#ifndef MALLOC_ARENA_SIZE +#define MALLOC_ARENA_SIZE (1024 * 1024 * 1) +#endif + +#define MAX_ALIGN(N) (((N) + _Alignof(max_align_t) - 1) & \ + ~(_Alignof(max_align_t) - 1)) +#define BLOCK_HEADER_SIZE (MAX_ALIGN(sizeof(struct block_header))) + +struct block_header +{ + int free; + size_t size; + struct block_header *prev_block, *next_block; +}; + +static int malloc_ready = 0; +static int malloc_debug_level = 0; +#ifdef MALLOC_STATIC_ARENA +_Alignas(max_align_t) static char arena[MALLOC_ARENA_SIZE]; +#else +static char *arena = 0; +#endif +static struct block_header *first_free_block; + + +#ifdef __cplusplus +extern "C" +{ +#endif + +void malloc_init() +{ +#ifndef MALLOC_STATIC_ARENA + if (!arena) + arena = (char*)sbrk(MALLOC_ARENA_SIZE); +#endif + first_free_block = (struct block_header*)arena; + first_free_block->free = 1; + first_free_block->size = MALLOC_ARENA_SIZE - BLOCK_HEADER_SIZE; + first_free_block->prev_block = 0; + first_free_block->next_block = 0; +} + +void malloc_set_debug(int debug_level) +{ + malloc_debug_level = debug_level; +} + +int malloc_get_debug() +{ + return malloc_debug_level; +} + +void malloc_print_debug() +{ + struct block_header *block_ptr, *prev_block = 0; + int i; + MALLOC_PRINTF("malloc debug:\n"); + for (i = 0, block_ptr = (struct block_header*)arena; block_ptr; + ++i, block_ptr = block_ptr->next_block) + { + MALLOC_PRINTF(" block no. %i%s:\n", i, + block_ptr == first_free_block ? " (first free)" : ""); + MALLOC_PRINTF(" address: 0x%08" PRIx32 "\n", (uint32_t)block_ptr); + MALLOC_PRINTF(" free: %i\n", block_ptr->free); + MALLOC_PRINTF(" size: %i\n", block_ptr->size); + MALLOC_PRINTF(" prev_block: 0x%08" PRIx32 "\n", + (uint32_t)block_ptr->prev_block); + MALLOC_PRINTF(" next_block: 0x%08" PRIx32 "\n", + (uint32_t)block_ptr->next_block); + if (block_ptr->prev_block != prev_block) + MALLOC_PRINTF("malloc inconsistency!\n"); + prev_block = block_ptr; + } +} + +void *malloc(size_t size) +{ + size = MAX_ALIGN(size); + + if (!malloc_ready) { + malloc_init(); + malloc_ready = 1; + } + + if (malloc_debug_level >= MALLOC_DEBUG_SIMPLE) { + MALLOC_PRINTF("malloc(%u)\n", size); + if (malloc_debug_level >= MALLOC_DEBUG_VERBOSE) + malloc_print_debug(); + } + + struct block_header *block_ptr, *next_free_block; + + for (block_ptr = first_free_block; block_ptr; + block_ptr = block_ptr->next_block) + { + if (block_ptr->free && block_ptr->size >= size) { + if (block_ptr->size - size >= (BLOCK_HEADER_SIZE + MAX_ALIGN(1))) { + next_free_block = (struct block_header*)((char*)block_ptr + + BLOCK_HEADER_SIZE + size); + next_free_block->free = 1; + next_free_block->size = block_ptr->size - size - BLOCK_HEADER_SIZE; + next_free_block->prev_block = block_ptr; + next_free_block->next_block = block_ptr->next_block; + if (block_ptr->next_block) + block_ptr->next_block->prev_block = next_free_block; + block_ptr->next_block = next_free_block; + block_ptr->size = size; + } + block_ptr->free = 0; + if (block_ptr == first_free_block) { + for (next_free_block = block_ptr->next_block; next_free_block; + next_free_block = next_free_block->next_block) + { + if (next_free_block->free) + break; + } + first_free_block = next_free_block; + } + if (malloc_debug_level >= MALLOC_DEBUG_VERBOSE) + malloc_print_debug(); + return (char*)block_ptr + BLOCK_HEADER_SIZE; + } + } + + if (malloc_debug_level >= MALLOC_DEBUG_SIMPLE) + MALLOC_PRINTF(" allocation failed\n"); + + return 0; +} + +void free(void *ptr) +{ + struct block_header *block_ptr = (struct block_header*)((char*)ptr - + BLOCK_HEADER_SIZE); + + if (malloc_debug_level >= MALLOC_DEBUG_SIMPLE) { + MALLOC_PRINTF("free(0x%08" PRIx32 ")\n", (uint32_t)block_ptr); + if (malloc_debug_level >= MALLOC_DEBUG_VERBOSE) + malloc_print_debug(); + } + + if (block_ptr->next_block && block_ptr->next_block->free) { + block_ptr->size = ((char*)block_ptr->next_block + + block_ptr->next_block->size) - (char*)block_ptr; + if (block_ptr->next_block->next_block) + block_ptr->next_block->next_block->prev_block = block_ptr; + block_ptr->next_block = block_ptr->next_block->next_block; + } + if (block_ptr->prev_block && block_ptr->prev_block->free) { + block_ptr->prev_block->size = ((char*)block_ptr + block_ptr->size) - + (char*)block_ptr->prev_block; + block_ptr->prev_block->next_block = block_ptr->next_block; + if (block_ptr->next_block) + block_ptr->next_block->prev_block = block_ptr->prev_block; + block_ptr = block_ptr->prev_block; + } + else + block_ptr->free = 1; + if (first_free_block > block_ptr) + first_free_block = block_ptr; + + if (malloc_debug_level >= MALLOC_DEBUG_VERBOSE) + malloc_print_debug(); +} + + +void *memcpy(void *dest, const void *src, size_t size) +{ + if (size == 0 || (char*)dest == (char*)src) + return dest; + char *c_dest = (char*)dest; + const char *c_src = (const char*)src; + while (size--) + *c_dest++ = *c_src++; + return dest; +} + +static void *memcpy_reverse(void *dest, const void *src, size_t size) +{ + if (size == 0 || (char*)dest == (char*)src) + return dest; + char *c_dest = (char*)dest + size; + const char *c_src = (const char*)src + size; + while (size--) + *--c_dest = *--c_src; + return dest; +} + +void *memmove(void *dest, const void* src, size_t size) +{ + if ((char*)dest < (char*)src) + return memcpy(dest, src, size); + else + return memcpy_reverse(dest, src, size); +} + +#ifdef __cplusplus +} +#endif diff --git a/tools/gfxdis/include/memory/memory.h b/tools/gfxdis/include/memory/memory.h new file mode 100644 index 00000000..1c1e5d87 --- /dev/null +++ b/tools/gfxdis/include/memory/memory.h @@ -0,0 +1,33 @@ +/* memory.h + * -glank + */ + +#ifndef MEMORY_H +#define MEMORY_H +#include + +#define MALLOC_DEBUG_NONE 0 +#define MALLOC_DEBUG_SIMPLE 1 +#define MALLOC_DEBUG_VERBOSE 2 + +#ifdef __cplusplus +extern "C" +{ +#endif + +void malloc_init(); +void malloc_set_debug(int debug_level); +int malloc_get_debug(); +void malloc_print_debug(); + +void *malloc(size_t size); +void free(void *ptr); + +void *memcpy(void *dest, const void *src, size_t size); +void *memmove(void *dest, const void *src, size_t size); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/tools/gfxdis/include/mips.h b/tools/gfxdis/include/mips.h new file mode 100644 index 00000000..12511c39 --- /dev/null +++ b/tools/gfxdis/include/mips.h @@ -0,0 +1,591 @@ +/** + * mips.h version 0.1rc8 + * nec vr4300, mips iii + * note: providing arguments with side-effects to these macros should + * be considered unsafe in general, as they may be evaluated more than once + * -glank +**/ + +#ifndef MIPS_H +#define MIPS_H + +#include + +/** + * mips general +**/ + +/* field manipulation macros */ +#define MIPS_GET_FIELD(f,x) ((MIPS_I_(x)&f##MASK)>>f##SHIFT) +#define MIPS_MAKE_FIELD(f,x) ((MIPS_I_(x)<=MIPS_KUSEG_BASE && \ + MIPS_I_(x)=MIPS_KSEG0_BASE && \ + MIPS_I_(x)=MIPS_KSEG1_BASE && \ + MIPS_I_(x)=MIPS_KSEG0_BASE && \ + MIPS_I_(x)=MIPS_KSSEG_BASE && \ + MIPS_I_(x)=MIPS_KSEG3_BASE) +#define MIPS_IS_SUSEG MIPS_IS_KUSEG +#define MIPS_IS_SSEG MIPS_IS_KSSEG +#define MIPS_IS_USEG MIPS_IS_KUSEG + +/* status register */ +#define MIPS_STATUS_CU3 MIPS_I_(0x80000000) +#define MIPS_STATUS_CU2 MIPS_I_(0x40000000) +#define MIPS_STATUS_CU1 MIPS_I_(0x20000000) +#define MIPS_STATUS_CU0 MIPS_I_(0x10000000) +#define MIPS_STATUS_RP MIPS_I_(0x08000000) +#define MIPS_STATUS_FR MIPS_I_(0x04000000) +#define MIPS_STATUS_RE MIPS_I_(0x02000000) +#define MIPS_STATUS_ITS MIPS_I_(0x01000000) +#define MIPS_STATUS_BEV MIPS_I_(0x00400000) +#define MIPS_STATUS_TS MIPS_I_(0x00200000) +#define MIPS_STATUS_SR MIPS_I_(0x00100000) +#define MIPS_STATUS_CH MIPS_I_(0x00040000) +#define MIPS_STATUS_CE MIPS_I_(0x00020000) +#define MIPS_STATUS_DE MIPS_I_(0x00010000) +#define MIPS_STATUS_IM7 MIPS_I_(0x00008000) +#define MIPS_STATUS_IM6 MIPS_I_(0x00004000) +#define MIPS_STATUS_IM5 MIPS_I_(0x00002000) +#define MIPS_STATUS_IM4 MIPS_I_(0x00001000) +#define MIPS_STATUS_IM3 MIPS_I_(0x00000800) +#define MIPS_STATUS_IM2 MIPS_I_(0x00000400) +#define MIPS_STATUS_IM1 MIPS_I_(0x00000200) +#define MIPS_STATUS_IM0 MIPS_I_(0x00000100) +#define MIPS_STATUS_KX MIPS_I_(0x00000080) +#define MIPS_STATUS_SX MIPS_I_(0x00000040) +#define MIPS_STATUS_UX MIPS_I_(0x00000020) +#define MIPS_STATUS_KSUMASK MIPS_I_(0x00000018) +#define MIPS_STATUS_KSUSHIFT 3 +#define MIPS_STATUS_KSU_U 2 +#define MIPS_STATUS_KSU_S 1 +#define MIPS_STATUS_KSU_K 0 +#define MIPS_STATUS_ERL MIPS_I_(0x00000004) +#define MIPS_STATUS_EXL MIPS_I_(0x00000002) +#define MIPS_STATUS_IE MIPS_I_(0x00000001) + +/* cause register */ +#define MIPS_CAUSE_BD MIPS_I_(0x80000000) +#define MIPS_CAUSE_CEMASK MIPS_I_(0x30000000) +#define MIPS_CAUSE_CESHIFT 28 +#define MIPS_CAUSE_IP7 MIPS_I_(0x00008000) +#define MIPS_CAUSE_IP6 MIPS_I_(0x00004000) +#define MIPS_CAUSE_IP5 MIPS_I_(0x00002000) +#define MIPS_CAUSE_IP4 MIPS_I_(0x00001000) +#define MIPS_CAUSE_IP3 MIPS_I_(0x00000800) +#define MIPS_CAUSE_IP2 MIPS_I_(0x00000400) +#define MIPS_CAUSE_IP1 MIPS_I_(0x00000200) +#define MIPS_CAUSE_IP0 MIPS_I_(0x00000100) +#define MIPS_CAUSE_EXCMASK MIPS_I_(0x0000007C) +#define MIPS_CAUSE_EXCSHIFT 2 + +/* exception codes */ +#define MIPS_EXC_INT 0 +#define MIPS_EXC_MOD 1 +#define MIPS_EXC_TLBL 2 +#define MIPS_EXC_TLBS 3 +#define MIPS_EXC_ADEL 4 +#define MIPS_EXC_ADES 5 +#define MIPS_EXC_IBE 6 +#define MIPS_EXC_DBE 7 +#define MIPS_EXC_SYS 8 +#define MIPS_EXC_BP 9 +#define MIPS_EXC_RI 10 +#define MIPS_EXC_CPU 11 +#define MIPS_EXC_OV 12 +#define MIPS_EXC_TR 13 +#define MIPS_EXC_FPE 15 +#define MIPS_EXC_WATCH 23 + +/* prid */ +#define MIPS_PRID_IMPMASK MIPS_I_(0xFF00) +#define MIPS_PRID_IMPSHIFT 8 +#define MIPS_PRID_REVMASK MIPS_I_(0x00FF) +#define MIPS_PRID_REVSHIFT 0 + +/* cache targets */ +#define MIPS_CACHEMASK MIPS_I_(0x03) +#define MIPS_CACHESHIFT 0 +#define MIPS_CACHE_I 0 +#define MIPS_CACHE_D 1 + +/* cache operations */ +#define MIPS_CACHEOP(c,o) (MIPS_MAKE_FIELD(MIPS_CACHE,c)| \ + MIPS_MAKE_FIELD(MIPS_CACHEOP,o)) +#define MIPS_CACHEOPMASK MIPS_I_(0x1C) +#define MIPS_CACHEOPSHIFT 2 +#define MIPS_CACHEOP_II 0 +#define MIPS_CACHEOP_IWBI 0 +#define MIPS_CACHEOP_ILT 1 +#define MIPS_CACHEOP_IST 2 +#define MIPS_CACHEOP_CDE 3 +#define MIPS_CACHEOP_HI 4 +#define MIPS_CACHEOP_HWBI 5 +#define MIPS_CACHEOP_F 5 +#define MIPS_CACHEOP_HWB 6 + +/* config register */ +#define MIPS_CONFIG_ECMASK MIPS_I_(0x70000000) +#define MIPS_CONFIG_ECSHIFT 28 +#define MIPS_CONFIG_EC_1_1 6 +#define MIPS_CONFIG_EC_3_2 7 +#define MIPS_CONFIG_EC_2_1 0 +#define MIPS_CONFIG_EC_3_1 1 +#define MIPS_CONFIG_EPMASK MIPS_I_(0x0F000000) +#define MIPS_CONFIG_EPSHIFT 24 +#define MIPS_CONFIG_EP_D 0 +#define MIPS_CONFIG_EP_DXXDXX 6 +#define MIPS_CONFIG_BE MIPS_I_(0x00008000) +#define MIPS_CONFIG_K0MASK MIPS_I_(0x00000007) +#define MIPS_CONFIG_K0SHIFT 0 +#define MIPS_CONFIG_K0_NC 2 +#define MIPS_CONFIG_K0_C 3 + +/* taglo register */ +#define MIPS_TAGLO_PTLMASK MIPS_I_(0x0FFFFF00) +#define MIPS_TAGLO_PTLSHIFT 8 +#define MIPS_TAGLO_PSMASK MIPS_I_(0x000000C0) +#define MIPS_TAGLO_PSSHIFT 6 +#define MIPS_TAGLO_PS_INVD 0 +#define MIPS_TAGLO_PS_DIRTY 3 + +/* memory breakpoints */ +#define MIPS_WATCHLO_PAMASK MIPS_I_(0xFFFFFFF8) +#define MIPS_WATCHLO_PASHIFT 3 +#define MIPS_WATCHLO_R MIPS_I_(0x00000002) +#define MIPS_WATCHLO_W MIPS_I_(0x00000001) + +/* cp0 registers */ +#define MIPS_CP0_INDEX 0 +#define MIPS_CP0_RANDOM 1 +#define MIPS_CP0_ENTRYLO0 2 +#define MIPS_CP0_ENTRYLO1 3 +#define MIPS_CP0_CONTEXT 4 +#define MIPS_CP0_PAGEMASK 5 +#define MIPS_CP0_WIRED 6 +#define MIPS_CP0_BADVADDR 8 +#define MIPS_CP0_COUNT 9 +#define MIPS_CP0_ENTRYHI 10 +#define MIPS_CP0_COMPARE 11 +#define MIPS_CP0_SR 12 +#define MIPS_CP0_CAUSE 13 +#define MIPS_CP0_EPC 14 +#define MIPS_CP0_PRID 15 +#define MIPS_CP0_CONFIG 16 +#define MIPS_CP0_LLADDR 17 +#define MIPS_CP0_WATCHLO 18 +#define MIPS_CP0_WATCHHI 19 +#define MIPS_CP0_XCONTEXT 20 +#define MIPS_CP0_PERR 26 +#define MIPS_CP0_CACHEERR 27 +#define MIPS_CP0_TAGLO 28 +#define MIPS_CP0_TAGHI 29 +#define MIPS_CP0_ERREPC 30 + +/* floating point control registers */ +#define MIPS_FCR_IR 0 +#define MIPS_FCR_CS 31 + +/* floating point control and status register */ +#define MIPS_FCSR_FS MIPS_I_(0x01000000) +#define MIPS_FCSR_C MIPS_I_(0x00800000) +#define MIPS_FCSR_CE MIPS_I_(0x00020000) +#define MIPS_FCSR_CV MIPS_I_(0x00010000) +#define MIPS_FCSR_CZ MIPS_I_(0x00008000) +#define MIPS_FCSR_CO MIPS_I_(0x00004000) +#define MIPS_FCSR_CU MIPS_I_(0x00002000) +#define MIPS_FCSR_CI MIPS_I_(0x00001000) +#define MIPS_FCSR_EV MIPS_I_(0x00000800) +#define MIPS_FCSR_EZ MIPS_I_(0x00000400) +#define MIPS_FCSR_EO MIPS_I_(0x00000200) +#define MIPS_FCSR_EU MIPS_I_(0x00000100) +#define MIPS_FCSR_EI MIPS_I_(0x00000080) +#define MIPS_FCSR_FV MIPS_I_(0x00000040) +#define MIPS_FCSR_FZ MIPS_I_(0x00000020) +#define MIPS_FCSR_FO MIPS_I_(0x00000010) +#define MIPS_FCSR_FU MIPS_I_(0x00000008) +#define MIPS_FCSR_FI MIPS_I_(0x00000004) +#define MIPS_FCSR_RMMASK MIPS_I_(0x00000003) +#define MIPS_FCSR_RMSHIFT 0 +#define MIPS_FCSR_RM_RN 0 +#define MIPS_FCSR_RM_RZ 1 +#define MIPS_FCSR_RM_RP 2 +#define MIPS_FCSR_RM_RM 3 + +/** + * inline assembly macros +**/ + +/* general purpose registers */ +#define MIPS_R0 0 +#define MIPS_AT 1 +#define MIPS_V0 2 +#define MIPS_V1 3 +#define MIPS_A0 4 +#define MIPS_A1 5 +#define MIPS_A2 6 +#define MIPS_A3 7 +#define MIPS_T0 8 +#define MIPS_T1 9 +#define MIPS_T2 10 +#define MIPS_T3 11 +#define MIPS_T4 12 +#define MIPS_T5 13 +#define MIPS_T6 14 +#define MIPS_T7 15 +#define MIPS_S0 16 +#define MIPS_S1 17 +#define MIPS_S2 18 +#define MIPS_S3 19 +#define MIPS_S4 20 +#define MIPS_S5 21 +#define MIPS_S6 22 +#define MIPS_S7 23 +#define MIPS_T8 24 +#define MIPS_T9 25 +#define MIPS_K0 26 +#define MIPS_K1 27 +#define MIPS_GP 28 +#define MIPS_SP 29 +#define MIPS_FP 30 +#define MIPS_RA 31 + +/* floating point registers */ +#define MIPS_F0 0 +#define MIPS_F1 1 +#define MIPS_F2 2 +#define MIPS_F3 3 +#define MIPS_F4 4 +#define MIPS_F5 5 +#define MIPS_F6 6 +#define MIPS_F7 7 +#define MIPS_F8 8 +#define MIPS_F9 9 +#define MIPS_F10 10 +#define MIPS_F11 11 +#define MIPS_F12 12 +#define MIPS_F13 13 +#define MIPS_F14 14 +#define MIPS_F15 15 +#define MIPS_F16 16 +#define MIPS_F17 17 +#define MIPS_F18 18 +#define MIPS_F19 19 +#define MIPS_F20 20 +#define MIPS_F21 21 +#define MIPS_F22 22 +#define MIPS_F23 23 +#define MIPS_F24 24 +#define MIPS_F25 25 +#define MIPS_F26 26 +#define MIPS_F27 27 +#define MIPS_F28 28 +#define MIPS_F29 29 +#define MIPS_F30 30 +#define MIPS_F31 31 + +/* loads and stores */ +#define MIPS_LB(rt,of,rs) MIPS_INI_(0x20,rs,rt,of) +#define MIPS_LBU(rt,of,rs) MIPS_INI_(0x24,rs,rt,of) +#define MIPS_LD(rt,of,rs) MIPS_INI_(0x37,rs,rt,of) +#define MIPS_LDL(rt,of,rs) MIPS_INI_(0x1A,rs,rt,of) +#define MIPS_LDR(rt,of,rs) MIPS_INI_(0x1B,rs,rt,of) +#define MIPS_LH(rt,of,rs) MIPS_INI_(0x21,rs,rt,of) +#define MIPS_LHU(rt,of,rs) MIPS_INI_(0x25,rs,rt,of) +#define MIPS_LL(rt,of,rs) MIPS_INI_(0x30,rs,rt,of) +#define MIPS_LLD(rt,of,rs) MIPS_INI_(0x34,rs,rt,of) +#define MIPS_LW(rt,of,rs) MIPS_INI_(0x23,rs,rt,of) +#define MIPS_LWL(rt,of,rs) MIPS_INI_(0x22,rs,rt,of) +#define MIPS_LWR(rt,of,rs) MIPS_INI_(0x26,rs,rt,of) +#define MIPS_LWU(rt,of,rs) MIPS_INI_(0x27,rs,rt,of) +#define MIPS_SB(rt,of,rs) MIPS_INI_(0x28,rs,rt,of) +#define MIPS_SC(rt,of,rs) MIPS_INI_(0x38,rs,rt,of) +#define MIPS_SCD(rt,of,rs) MIPS_INI_(0x3C,rs,rt,of) +#define MIPS_SD(rt,of,rs) MIPS_INI_(0x3F,rs,rt,of) +#define MIPS_SDL(rt,of,rs) MIPS_INI_(0x2C,rs,rt,of) +#define MIPS_SDR(rt,of,rs) MIPS_INI_(0x2D,rs,rt,of) +#define MIPS_SH(rt,of,rs) MIPS_INI_(0x29,rs,rt,of) +#define MIPS_SW(rt,of,rs) MIPS_INI_(0x2B,rs,rt,of) +#define MIPS_SWL(rt,of,rs) MIPS_INI_(0x2A,rs,rt,of) +#define MIPS_SWR(rt,of,rs) MIPS_INI_(0x2E,rs,rt,of) +#define MIPS_SYNC() MIPS_INR_(0x0F,0,0,0) + +/* integer operations */ +#define MIPS_ADD(rd,rs,rt) MIPS_INR_(0x20,rs,rt,rd) +#define MIPS_ADDI(rt,rs,im) MIPS_INI_(0x08,rs,rt,im) +#define MIPS_ADDIU(rt,rs,im) MIPS_INI_(0x09,rs,rt,im) +#define MIPS_ADDU(rd,rs,rt) MIPS_INR_(0x21,rs,rt,rd) +#define MIPS_AND(rd,rs,rt) MIPS_INR_(0x24,rs,rt,rd) +#define MIPS_ANDI(rt,rs,im) MIPS_INI_(0x0C,rs,rt,im) +#define MIPS_DADD(rd,rs,rt) MIPS_INR_(0x2C,rs,rt,rd) +#define MIPS_DADDI(rt,rs,im) MIPS_INI_(0x18,rs,rt,im) +#define MIPS_DADDIU(rt,rs,im) MIPS_INI_(0x19,rs,rt,im) +#define MIPS_DADDU(rd,rs,rt) MIPS_INR_(0x2D,rs,rt,rd) +#define MIPS_DDIV(rs,rt) MIPS_INR_(0x1E,rs,rt,0) +#define MIPS_DDIVU(rs,rt) MIPS_INR_(0x1F,rs,rt,0) +#define MIPS_DIV(rs,rt) MIPS_INR_(0x1A,rs,rt,0) +#define MIPS_DIVU(rs,rt) MIPS_INR_(0x1B,rs,rt,0) +#define MIPS_DMULT(rs,rt) MIPS_INR_(0x1C,rs,rt,0) +#define MIPS_DMULTU(rs,rt) MIPS_INR_(0x1D,rs,rt,0) +#define MIPS_DSLL(rd,rt,sa) MIPS_INS_(0x38,0,rt,rd,sa) +#define MIPS_DSLL32(rd,rt,sa) MIPS_INS_(0x3C,0,rt,rd,sa) +#define MIPS_DSLLV(rd,rt,rs) MIPS_INR_(0x14,rs,rt,rd) +#define MIPS_DSRA(rd,rt,sa) MIPS_INS_(0x3B,0,rt,rd,sa) +#define MIPS_DSRA32(rd,rt,sa) MIPS_INS_(0x3F,0,rt,rd,sa) +#define MIPS_DSRAV(rd,rt,rs) MIPS_INR_(0x17,rs,rt,rd) +#define MIPS_DSRL(rd,rt,sa) MIPS_INS_(0x3A,0,rt,rd,sa) +#define MIPS_DSRL32(rd,rt,sa) MIPS_INS_(0x3E,0,rt,rd,sa) +#define MIPS_DSRLV(rd,rt,rs) MIPS_INR_(0x16,rs,rt,rd) +#define MIPS_DSUB(rd,rs,rt) MIPS_INR_(0x2E,rs,rt,rd) +#define MIPS_DSUBU(rd,rs,rt) MIPS_INR_(0x2F,rs,rt,rd) +#define MIPS_LUI(rt,im) MIPS_INI_(0x0F,0,rt,im) +#define MIPS_MFHI(rd) MIPS_INR_(0x10,0,0,rd) +#define MIPS_MFLO(rd) MIPS_INR_(0x12,0,0,rd) +#define MIPS_MTHI(rs) MIPS_INR_(0x11,rs,0,0) +#define MIPS_MTLO(rs) MIPS_INR_(0x13,rs,0,0) +#define MIPS_MULT(rs,rt) MIPS_INR_(0x18,rs,rt,0) +#define MIPS_MULTU(rs,rt) MIPS_INR_(0x19,rs,rt,0) +#define MIPS_NOR(rd,rs,rt) MIPS_INR_(0x27,rs,rt,rd) +#define MIPS_OR(rd,rs,rt) MIPS_INR_(0x25,rs,rt,rd) +#define MIPS_ORI(rt,rs,im) MIPS_INI_(0x0D,rs,rt,im) +#define MIPS_SLL(rd,rt,sa) MIPS_INS_(0x00,0,rt,rd,sa) +#define MIPS_SLLV(rd,rt,rs) MIPS_INR_(0x04,rs,rt,rd) +#define MIPS_SLT(rd,rs,rt) MIPS_INR_(0x2A,rs,rt,rd) +#define MIPS_SLTI(rt,rs,im) MIPS_INI_(0x0A,rs,rt,im) +#define MIPS_SLTIU(rt,rs,im) MIPS_INI_(0x0B,rs,rt,im) +#define MIPS_SLTU(rd,rs,rt) MIPS_INR_(0x2B,rs,rt,rd) +#define MIPS_SRA(rd,rt,sa) MIPS_INS_(0x03,0,rt,rd,sa) +#define MIPS_SRAV(rd,rt,rs) MIPS_INR_(0x07,rs,rt,rd) +#define MIPS_SRL(rd,rt,sa) MIPS_INS_(0x02,0,rt,rd,sa) +#define MIPS_SRLV(rd,rt,rs) MIPS_INR_(0x06,rs,rt,rd) +#define MIPS_SUB(rd,rs,rt) MIPS_INR_(0x22,rs,rt,rd) +#define MIPS_SUBU(rd,rs,rt) MIPS_INR_(0x23,rs,rt,rd) +#define MIPS_XOR(rd,rs,rt) MIPS_INR_(0x26,rs,rt,rd) +#define MIPS_XORI(rt,rs,im) MIPS_INI_(0x0E,rs,rt,im) + +/* branching */ +#define MIPS_BEQ(rs,rt,of) MIPS_INB_(0x04,rs,rt,of) +#define MIPS_BEQL(rs,rt,of) MIPS_INB_(0x14,rs,rt,of) +#define MIPS_BGEZ(rs,of) MIPS_INB_(0x01,rs,0x01,of) +#define MIPS_BGEZAL(rs,of) MIPS_INB_(0x01,rs,0x11,of) +#define MIPS_BGEZALL(rs,of) MIPS_INB_(0x01,rs,0x13,of) +#define MIPS_BGEZL(rs,of) MIPS_INB_(0x01,rs,0x03,of) +#define MIPS_BGTZ(rs,of) MIPS_INB_(0x07,rs,0x00,of) +#define MIPS_BGTZL(rs,of) MIPS_INB_(0x17,rs,0x00,of) +#define MIPS_BLEZ(rs,of) MIPS_INB_(0x06,rs,0x00,of) +#define MIPS_BLEZL(rs,of) MIPS_INB_(0x16,rs,0x00,of) +#define MIPS_BLTZ(rs,of) MIPS_INB_(0x01,rs,0x00,of) +#define MIPS_BLTZAL(rs,of) MIPS_INB_(0x01,rs,0x10,of) +#define MIPS_BLTZALL(rs,of) MIPS_INB_(0x01,rs,0x12,of) +#define MIPS_BLTZL(rs,of) MIPS_INB_(0x01,rs,0x02,of) +#define MIPS_BNE(rs,rt,of) MIPS_INB_(0x05,rs,rt,of) +#define MIPS_BNEL(rs,rt,of) MIPS_INB_(0x15,rs,rt,of) +#define MIPS_J(ad) MIPS_INJ_(0x02,ad) +#define MIPS_JAL(ad) MIPS_INJ_(0x03,ad) +#define MIPS_JALR(rd,rs) MIPS_INR_(0x09,rs,0,rd) +#define MIPS_JR(rs) MIPS_INR_(0x08,rs,0,0) + +/* exceptions */ +#define MIPS_BREAK(ec) MIPS_INE_(0x0D,ec) +#define MIPS_SYSCALL(ec) MIPS_INE_(0x0C,ec) +#define MIPS_TEQ(rs,rt,tc) MIPS_INT_(0x34,rs,rt,tc) +#define MIPS_TEQI(rs,im) MIPS_INI_(0x01,rs,0x0C,im) +#define MIPS_TGE(rs,rt,tc) MIPS_INT_(0x30,rs,rt,tc) +#define MIPS_TGEI(rs,im) MIPS_INI_(0x01,rs,0x08,im) +#define MIPS_TGEIU(rs,im) MIPS_INI_(0x01,rs,0x09,im) +#define MIPS_TGEU(rs,rt,tc) MIPS_INT_(0x31,rs,rt,tc) +#define MIPS_TLT(rs,rt,tc) MIPS_INT_(0x32,rs,rt,tc) +#define MIPS_TLTI(rs,im) MIPS_INI_(0x01,rs,0x0A,im) +#define MIPS_TLTIU(rs,im) MIPS_INI_(0x01,rs,0x0B,im) +#define MIPS_TLTU(rs,rt,tc) MIPS_INT_(0x33,rs,rt,tc) +#define MIPS_TNE(rs,rt,tc) MIPS_INT_(0x36,rs,rt,tc) +#define MIPS_TNEI(rs,im) MIPS_INI_(0x01,rs,0x0E,im) + +/* system control */ +#define MIPS_CACHE(op,of,rs) MIPS_INI_(0x2F,rs,op,of) +#define MIPS_ERET() MIPS_INC_(0x18,0x10,0,0) +#define MIPS_MFC0(rt,fs) MIPS_INC_(0x00,0x00,rt,fs) +#define MIPS_MTC0(rt,fs) MIPS_INC_(0x00,0x04,rt,fs) +#define MIPS_TLBP() MIPS_INC_(0x08,0x10,0,0) +#define MIPS_TLBR() MIPS_INC_(0x01,0x10,0,0) +#define MIPS_TLBWI() MIPS_INC_(0x02,0x10,0,0) +#define MIPS_TLBWR() MIPS_INC_(0x06,0x10,0,0) + +/* floating point operations */ +#define MIPS_ABSD(fd,fs) MIPS_INF_(0x05,MIPS_FMD_,0,fs,fd) +#define MIPS_ABSS(fd,fs) MIPS_INF_(0x05,MIPS_FMS_,0,fs,fd) +#define MIPS_ADDD(fd,fs,ft) MIPS_INF_(0x00,MIPS_FMD_,ft,fs,fd) +#define MIPS_ADDS(fd,fs,ft) MIPS_INF_(0x00,MIPS_FMS_,ft,fs,fd) +#define MIPS_BC1F(of) MIPS_INFB_(0x00,of) +#define MIPS_BC1FL(of) MIPS_INFB_(0x02,of) +#define MIPS_BC1T(of) MIPS_INFB_(0x01,of) +#define MIPS_BC1TL(of) MIPS_INFB_(0x03,of) +#define MIPS_CEILLD(fd,fs) MIPS_INF_(0x0A,MIPS_FMD_,0,fs,fd) +#define MIPS_CEILLS(fd,fs) MIPS_INF_(0x0A,MIPS_FMS_,0,fs,fd) +#define MIPS_CEILWD(fd,fs) MIPS_INF_(0x0E,MIPS_FMD_,0,fs,fd) +#define MIPS_CEILWS(fd,fs) MIPS_INF_(0x0E,MIPS_FMS_,0,fs,fd) +#define MIPS_CEQD(fs,ft) MIPS_INF_(0x32,MIPS_FMD_,ft,fs,0) +#define MIPS_CEQS(fs,ft) MIPS_INF_(0x32,MIPS_FMS_,ft,fs,0) +#define MIPS_CFC1(rt,fs) MIPS_INF_(0x00,0x02,rt,fs,0) +#define MIPS_CFD(fs,ft) MIPS_INF_(0x30,MIPS_FMD_,ft,fs,0) +#define MIPS_CFS(fs,ft) MIPS_INF_(0x30,MIPS_FMS_,ft,fs,0) +#define MIPS_CLED(fs,ft) MIPS_INF_(0x3E,MIPS_FMD_,ft,fs,0) +#define MIPS_CLES(fs,ft) MIPS_INF_(0x3E,MIPS_FMS_,ft,fs,0) +#define MIPS_CLTD(fs,ft) MIPS_INF_(0x3C,MIPS_FMD_,ft,fs,0) +#define MIPS_CLTS(fs,ft) MIPS_INF_(0x3C,MIPS_FMS_,ft,fs,0) +#define MIPS_CNGED(fs,ft) MIPS_INF_(0x3D,MIPS_FMD_,ft,fs,0) +#define MIPS_CNGES(fs,ft) MIPS_INF_(0x3D,MIPS_FMS_,ft,fs,0) +#define MIPS_CNGLD(fs,ft) MIPS_INF_(0x3B,MIPS_FMD_,ft,fs,0) +#define MIPS_CNGLED(fs,ft) MIPS_INF_(0x39,MIPS_FMD_,ft,fs,0) +#define MIPS_CNGLES(fs,ft) MIPS_INF_(0x39,MIPS_FMS_,ft,fs,0) +#define MIPS_CNGLS(fs,ft) MIPS_INF_(0x3B,MIPS_FMS_,ft,fs,0) +#define MIPS_CNGTD(fs,ft) MIPS_INF_(0x3F,MIPS_FMD_,ft,fs,0) +#define MIPS_CNGTS(fs,ft) MIPS_INF_(0x3F,MIPS_FMS_,ft,fs,0) +#define MIPS_COLED(fs,ft) MIPS_INF_(0x36,MIPS_FMD_,ft,fs,0) +#define MIPS_COLES(fs,ft) MIPS_INF_(0x36,MIPS_FMS_,ft,fs,0) +#define MIPS_COLTD(fs,ft) MIPS_INF_(0x34,MIPS_FMD_,ft,fs,0) +#define MIPS_COLTS(fs,ft) MIPS_INF_(0x34,MIPS_FMS_,ft,fs,0) +#define MIPS_CSEQD(fs,ft) MIPS_INF_(0x3A,MIPS_FMD_,ft,fs,0) +#define MIPS_CSEQS(fs,ft) MIPS_INF_(0x3A,MIPS_FMS_,ft,fs,0) +#define MIPS_CSFD(fs,ft) MIPS_INF_(0x38,MIPS_FMD_,ft,fs,0) +#define MIPS_CSFS(fs,ft) MIPS_INF_(0x38,MIPS_FMS_,ft,fs,0) +#define MIPS_CTC1(rt,fs) MIPS_INF_(0x00,0x06,rt,fs,0) +#define MIPS_CUEQD(fs,ft) MIPS_INF_(0x33,MIPS_FMD_,ft,fs,0) +#define MIPS_CUEQS(fs,ft) MIPS_INF_(0x33,MIPS_FMS_,ft,fs,0) +#define MIPS_CULED(fs,ft) MIPS_INF_(0x37,MIPS_FMD_,ft,fs,0) +#define MIPS_CULES(fs,ft) MIPS_INF_(0x37,MIPS_FMS_,ft,fs,0) +#define MIPS_CULTD(fs,ft) MIPS_INF_(0x35,MIPS_FMD_,ft,fs,0) +#define MIPS_CULTS(fs,ft) MIPS_INF_(0x35,MIPS_FMS_,ft,fs,0) +#define MIPS_CUND(fs,ft) MIPS_INF_(0x31,MIPS_FMD_,ft,fs,0) +#define MIPS_CUNS(fs,ft) MIPS_INF_(0x31,MIPS_FMS_,ft,fs,0) +#define MIPS_CVTDL(fd,fs) MIPS_INF_(0x21,MIPS_FML_,0,fs,fd) +#define MIPS_CVTDS(fd,fs) MIPS_INF_(0x21,MIPS_FMS_,0,fs,fd) +#define MIPS_CVTDW(fd,fs) MIPS_INF_(0x21,MIPS_FMW_,0,fs,fd) +#define MIPS_CVTLD(fd,fs) MIPS_INF_(0x25,MIPS_FMD_,0,fs,fd) +#define MIPS_CVTLS(fd,fs) MIPS_INF_(0x25,MIPS_FMS_,0,fs,fd) +#define MIPS_CVTSD(fd,fs) MIPS_INF_(0x20,MIPS_FMD_,0,fs,fd) +#define MIPS_CVTSL(fd,fs) MIPS_INF_(0x20,MIPS_FML_,0,fs,fd) +#define MIPS_CVTSW(fd,fs) MIPS_INF_(0x20,MIPS_FMW_,0,fs,fd) +#define MIPS_CVTWD(fd,fs) MIPS_INF_(0x24,MIPS_FMD_,0,fs,fd) +#define MIPS_CVTWS(fd,fs) MIPS_INF_(0x24,MIPS_FMS_,0,fs,fd) +#define MIPS_DIVD(fd,fs,ft) MIPS_INF_(0x03,MIPS_FMD_,ft,fs,fd) +#define MIPS_DIVS(fd,fs,ft) MIPS_INF_(0x03,MIPS_FMS_,ft,fs,fd) +#define MIPS_DMFC1(rt,fs) MIPS_INF_(0x00,0x01,rt,fs,0) +#define MIPS_DMTC1(rt,fs) MIPS_INF_(0x00,0x05,rt,fs,0) +#define MIPS_FLOORLD(fd,fs) MIPS_INF_(0x0B,MIPS_FMD_,0,fs,fd) +#define MIPS_FLOORLS(fd,fs) MIPS_INF_(0x0B,MIPS_FMS_,0,fs,fd) +#define MIPS_FLOORWD(fd,fs) MIPS_INF_(0x0F,MIPS_FMD_,0,fs,fd) +#define MIPS_FLOORWS(fd,fs) MIPS_INF_(0x0F,MIPS_FMS_,0,fs,fd) +#define MIPS_LDC1(ft,of,rs) MIPS_INI_(0x35,rs,ft,of) +#define MIPS_LWC1(ft,of,rs) MIPS_INI_(0x31,rs,ft,of) +#define MIPS_MFC1(rt,fs) MIPS_INF_(0x00,0x00,rt,fs,0) +#define MIPS_MTC1(rt,fs) MIPS_INF_(0x00,0x04,rt,fs,0) +#define MIPS_MOVD(fd,fs) MIPS_INF_(0x06,MIPS_FMD_,0,fs,fd) +#define MIPS_MOVS(fd,fs) MIPS_INF_(0x06,MIPS_FMS_,0,fs,fd) +#define MIPS_MULD(fd,fs,ft) MIPS_INF_(0x02,MIPS_FMD_,ft,fs,fd) +#define MIPS_MULS(fd,fs,ft) MIPS_INF_(0x02,MIPS_FMS_,ft,fs,fd) +#define MIPS_NEGD(fd,fs) MIPS_INF_(0x07,MIPS_FMD_,0,fs,fd) +#define MIPS_NEGS(fd,fs) MIPS_INF_(0x07,MIPS_FMS_,0,fs,fd) +#define MIPS_ROUNDLD(fd,fs) MIPS_INF_(0x08,MIPS_FMD_,0,fs,fd) +#define MIPS_ROUNDLS(fd,fs) MIPS_INF_(0x08,MIPS_FMS_,0,fs,fd) +#define MIPS_ROUNDWD(fd,fs) MIPS_INF_(0x0C,MIPS_FMD_,0,fs,fd) +#define MIPS_ROUNDWS(fd,fs) MIPS_INF_(0x0C,MIPS_FMS_,0,fs,fd) +#define MIPS_SDC1(ft,of,rs) MIPS_INI_(0x3D,rs,ft,of) +#define MIPS_SQRTD(fd,fs) MIPS_INF_(0x04,MIPS_FMD_,0,fs,fd) +#define MIPS_SQRTS(fd,fs) MIPS_INF_(0x04,MIPS_FMS_,0,fs,fd) +#define MIPS_SUBD(fd,fs,ft) MIPS_INF_(0x01,MIPS_FMD_,ft,fs,fd) +#define MIPS_SUBS(fd,fs,ft) MIPS_INF_(0x01,MIPS_FMS_,ft,fs,fd) +#define MIPS_SWC1(ft,of,rs) MIPS_INI_(0x39,rs,ft,of) +#define MIPS_TRUNCLD(fd,fs) MIPS_INF_(0x09,MIPS_FMD_,0,fs,fd) +#define MIPS_TRUNCLS(fd,fs) MIPS_INF_(0x09,MIPS_FMS_,0,fs,fd) +#define MIPS_TRUNCWD(fd,fs) MIPS_INF_(0x0D,MIPS_FMD_,0,fs,fd) +#define MIPS_TRUNCWS(fd,fs) MIPS_INF_(0x0D,MIPS_FMS_,0,fs,fd) + +/* pseudo-instructions */ +#define MIPS_NOP() MIPS_SLL(MIPS_R0,MIPS_R0,0) + +/** + * private helper macros +**/ + +#define MIPS_I_(x) ((uint32_t)(x)) +#define MIPS_OP_(x) ((MIPS_I_(x)&0x3F)<<26) +#define MIPS_RS_(x) ((MIPS_I_(x)&0x1F)<<21) +#define MIPS_RT_(x) ((MIPS_I_(x)&0x1F)<<16) +#define MIPS_RD_(x) ((MIPS_I_(x)&0x1F)<<11) +#define MIPS_SA_(x) ((MIPS_I_(x)&0x1F)<<6) +#define MIPS_EC_(x) ((MIPS_I_(x)&0xFFFFF)<<6) +#define MIPS_TC_(x) ((MIPS_I_(x)&0x3FF)<<6) +#define MIPS_FN_(x) (MIPS_I_(x)&0x3F) +#define MIPS_IM_(x) (MIPS_I_(x)&0xFFFF) +#define MIPS_AD_(x) ((MIPS_I_(x)&0xFFFFFFF)>>2) +#define MIPS_OF_(x) ((MIPS_I_(x)>>2)&0xFFFF) +#define MIPS_INI_(op,rs,rt,im) (MIPS_OP_(op)|MIPS_RS_(rs)| \ + MIPS_RT_(rt)|MIPS_IM_(im)) +#define MIPS_INB_(op,rs,rt,of) (MIPS_OP_(op)|MIPS_RS_(rs)| \ + MIPS_RT_(rt)|MIPS_OF_(of)) +#define MIPS_INS_(fn,rs,rt,rd,sa) (MIPS_RS_(rs)|MIPS_RT_(rt)| \ + MIPS_RD_(rd)|MIPS_SA_(sa)| \ + MIPS_FN_(fn)) +#define MIPS_INR_(fn,rs,rt,rd) MIPS_INS_(fn,rs,rt,rd,0) +#define MIPS_INJ_(op,ad) (MIPS_OP_(op)|MIPS_AD_(ad)) +#define MIPS_INC_(fn,fm,rt,fs) (MIPS_OP_(0x10)|MIPS_RS_(fm)| \ + MIPS_RT_(rt)|MIPS_RD_(fs)| \ + MIPS_FN_(fn)) +#define MIPS_INF_(fn,fm,ft,fs,fd) (MIPS_OP_(0x11)|MIPS_RS_(fm)| \ + MIPS_RT_(ft)|MIPS_RD_(fs)| \ + MIPS_SA_(fd)|MIPS_FN_(fn)) +#define MIPS_INE_(fn,ec) (MIPS_EC_(ec)|MIPS_FN_(fn)) +#define MIPS_INT_(fn,rs,rt,tc) (MIPS_RS_(rs)|MIPS_RT_(rt)| \ + MIPS_TC_(tc)|MIPS_FN_(fn)) +#define MIPS_INFB_(nt,of) MIPS_INB_(0x11,0x08,nt,of) +#define MIPS_FMS_ 0x10 +#define MIPS_FMD_ 0x11 +#define MIPS_FMW_ 0x14 +#define MIPS_FML_ 0x15 + +#endif diff --git a/tools/gfxdis/include/n64.h b/tools/gfxdis/include/n64.h new file mode 100644 index 00000000..798085ec --- /dev/null +++ b/tools/gfxdis/include/n64.h @@ -0,0 +1,15 @@ +/* n64.h + * -glank + */ + +#ifndef N64_H +#define N64_H + +#include "n64/gbi.h" +#include "n64/message.h" +#include "n64/pi.h" +#include "n64/task.h" +#include "n64/thread.h" +#include "n64/vr4300.h" + +#endif diff --git a/tools/gfxdis/include/n64/gbi.h b/tools/gfxdis/include/n64/gbi.h new file mode 100644 index 00000000..265e105c --- /dev/null +++ b/tools/gfxdis/include/n64/gbi.h @@ -0,0 +1,2871 @@ +/** + * gbi.h version 0.2rev2 + * n64 graphics microcode interface library + * compatible with fast3d, f3dex, f3dex2, s2dex, and s2dex2 + * + * select a microcode with one of these preprocessor definitions; + * #define F3D_GBI + * for fast3d (selected automatically by default), or + * #define F3DEX_GBI + * for f3dex/s2dex, or + * #define F3DEX_GBI_2 + * for f3dex2/s2dex2 + * + * for early versions of fast3d and f3dex, also define the following; + * #define F3D_BETA +**/ + +#ifndef N64_GBI_H +#define N64_GBI_H + +#include +#include + +/* use fast3d by default */ +#if !defined(F3D_GBI) && !defined(F3DEX_GBI) && !defined(F3DEX_GBI_2) +# define F3D_GBI +#endif + +/* commands for fast3d and f3dex */ +#if defined(F3D_GBI) || defined(F3DEX_GBI) +# define G_SPNOOP 0x00 +# define G_MTX 0x01 +# define G_MOVEMEM 0x03 +# define G_VTX 0x04 +# define G_DL 0x06 +# define G_RDPHALF_CONT 0xB2 +# define G_RDPHALF_2 0xB3 +# if defined(F3D_BETA) +# define G_PERSPNORM 0xB4 +# else +# define G_RDPHALF_1 0xB4 +# endif +# define G_LINE3D 0xB5 +# define G_CLEARGEOMETRYMODE 0xB6 +# define G_SETGEOMETRYMODE 0xB7 +# define G_ENDDL 0xB8 +# define G_SETOTHERMODE_L 0xB9 +# define G_SETOTHERMODE_H 0xBA +# define G_TEXTURE 0xBB +# define G_MOVEWORD 0xBC +# define G_POPMTX 0xBD +# define G_CULLDL 0xBE +# define G_TRI1 0xBF +# define G_NOOP 0xC0 +#endif + +/* commands for f3dex */ +#if defined(F3DEX_GBI) +# define G_LOAD_UCODE 0xAF +# define G_BRANCH_Z 0xB0 +# define G_TRI2 0xB1 +# define G_MODIFYVTX 0xB2 +#endif + +/* commands for f3dex2 */ +#if defined(F3DEX_GBI_2) +# define G_NOOP 0x00 +# define G_VTX 0x01 +# define G_MODIFYVTX 0x02 +# define G_CULLDL 0x03 +# define G_BRANCH_Z 0x04 +# define G_TRI1 0x05 +# define G_TRI2 0x06 +# define G_QUAD 0x07 +# define G_LINE3D 0x08 +# define G_SPECIAL_3 0xD3 +# define G_SPECIAL_2 0xD4 +# define G_SPECIAL_1 0xD5 +# define G_DMA_IO 0xD6 +# define G_TEXTURE 0xD7 +# define G_POPMTX 0xD8 +# define G_GEOMETRYMODE 0xD9 +# define G_MTX 0xDA +# define G_MOVEWORD 0xDB +# define G_MOVEMEM 0xDC +# define G_LOAD_UCODE 0xDD +# define G_DL 0xDE +# define G_ENDDL 0xDF +# define G_SPNOOP 0xE0 +# define G_RDPHALF_1 0xE1 +# define G_SETOTHERMODE_L 0xE2 +# define G_SETOTHERMODE_H 0xE3 +# define G_RDPHALF_2 0xF1 +#endif + +/* rdp commands */ +#define G_TEXRECT 0xE4 +#define G_TEXRECTFLIP 0xE5 +#define G_RDPLOADSYNC 0xE6 +#define G_RDPPIPESYNC 0xE7 +#define G_RDPTILESYNC 0xE8 +#define G_RDPFULLSYNC 0xE9 +#define G_SETKEYGB 0xEA +#define G_SETKEYR 0xEB +#define G_SETCONVERT 0xEC +#define G_SETSCISSOR 0xED +#define G_SETPRIMDEPTH 0xEE +#define G_RDPSETOTHERMODE 0xEF +#define G_LOADTLUT 0xF0 +#define G_SETTILESIZE 0xF2 +#define G_LOADBLOCK 0xF3 +#define G_LOADTILE 0xF4 +#define G_SETTILE 0xF5 +#define G_FILLRECT 0xF6 +#define G_SETFILLCOLOR 0xF7 +#define G_SETFOGCOLOR 0xF8 +#define G_SETBLENDCOLOR 0xF9 +#define G_SETPRIMCOLOR 0xFA +#define G_SETENVCOLOR 0xFB +#define G_SETCOMBINE 0xFC +#define G_SETTIMG 0xFD +#define G_SETZIMG 0xFE +#define G_SETCIMG 0xFF + +/* commands for s2dex */ +#if defined(F3DEX_GBI) +# define G_BG_1CYC 0x01 +# define G_BG_COPY 0x02 +# define G_OBJ_RECTANGLE 0x03 +# define G_OBJ_SPRITE 0x04 +# define G_OBJ_MOVEMEM 0x05 +# define G_SELECT_DL 0xB0 +# define G_OBJ_RENDERMODE 0xB1 +# define G_OBJ_RECTANGLE_R 0xB2 +# define G_OBJ_LOADTXTR 0xC1 +# define G_OBJ_LDTX_SPRITE 0xC2 +# define G_OBJ_LDTX_RECT 0xC3 +# define G_OBJ_LDTX_RECT_R 0xC4 +#endif + +/* commands for s2dex2 */ +#if defined(F3DEX_GBI_2) +# define G_OBJ_RECTANGLE 0x01 +# define G_OBJ_SPRITE 0x02 +# define G_SELECT_DL 0x04 +# define G_OBJ_LOADTXTR 0x05 +# define G_OBJ_LDTX_SPRITE 0x06 +# define G_OBJ_LDTX_RECT 0x07 +# define G_OBJ_LDTX_RECT_R 0x08 +# define G_BG_1CYC 0x09 +# define G_BG_COPY 0x0A +# define G_OBJ_RENDERMODE 0x0B +# define G_OBJ_RECTANGLE_R 0xDA +# define G_OBJ_MOVEMEM 0xDC +#endif + +/* commands for s2dex and s2dex2 */ +#if defined(F3DEX_GBI) || defined(F3DEX_GBI_2) +# define G_RDPHALF_0 0xE4 +#endif + +/* image formats */ +#define G_IM_FMT_RGBA 0 +#define G_IM_FMT_YUV 1 +#define G_IM_FMT_CI 2 +#define G_IM_FMT_IA 3 +#define G_IM_FMT_I 4 +#define G_IM_SIZ_4b 0 +#define G_IM_SIZ_8b 1 +#define G_IM_SIZ_16b 2 +#define G_IM_SIZ_32b 3 + +/* texture settings */ +#define G_TX_NOMIRROR (gI_(0b0)<<0) +#define G_TX_MIRROR (gI_(0b1)<<0) +#define G_TX_WRAP (gI_(0b0)<<1) +#define G_TX_CLAMP (gI_(0b1)<<1) +#define G_TX_NOMASK gI_(0) +#define G_TX_NOLOD gI_(0) +#define G_OFF gI_(0) +#define G_ON gI_(1) + +/* tile indices */ +#define G_TX_LOADTILE 7 +#define G_TX_RENDERTILE 0 + +/* geometry mode */ +#define G_ZBUFFER (gI_(0b1)<<0) +#define G_SHADE (gI_(0b1)<<2) +#define G_CULL_BOTH (G_CULL_FRONT|G_CULL_BACK) +#define G_FOG (gI_(0b1)<<16) +#define G_LIGHTING (gI_(0b1)<<17) +#define G_TEXTURE_GEN (gI_(0b1)<<18) +#define G_TEXTURE_GEN_LINEAR (gI_(0b1)<<19) +#define G_LOD (gI_(0b1)<<20) + +/* geometry mode for fast3d */ +#if defined(F3D_GBI) +# define G_CLIPPING (gI_(0b0)<<0) +#endif + +/* geometry mode for fast3d and f3dex */ +#if defined(F3D_GBI) || defined(F3DEX_GBI) +# define G_TEXTURE_ENABLE (gI_(0b1)<<1) +# define G_SHADING_SMOOTH (gI_(0b1)<<9) +# define G_CULL_FRONT (gI_(0b1)<<12) +# define G_CULL_BACK (gI_(0b1)<<13) +#endif + +/* geometry mode for f3dex and f3dex2 */ +#if defined(F3DEX_GBI) || defined(F3DEX_GBI_2) +# define G_CLIPPING (gI_(0b1)<<23) +#endif + +/* geometry mode for f3dex2 */ +#if defined(F3DEX_GBI_2) +# define G_TEXTURE_ENABLE (gI_(0b0)<<0) +# define G_CULL_FRONT (gI_(0b1)<<9) +# define G_CULL_BACK (gI_(0b1)<<10) +# define G_SHADING_SMOOTH (gI_(0b1)<<21) +#endif + +/* othermode lo */ +#define G_MDSFT_ALPHACOMPARE 0 +#define G_MDSFT_ZSRCSEL 2 +#define G_MDSFT_RENDERMODE 3 +#define G_MDSIZ_ALPHACOMPARE 2 +#define G_MDSIZ_ZSRCSEL 1 +#define G_MDSIZ_RENDERMODE 29 + +#define G_AC_NONE (gI_(0b00)<>16)&0x00007FFF, \ + (qs1516(xy)>>16)&0x00007FFF, \ + (qs1516(xz)>>16)&0x00007FFF, \ + (qs1516(xw)>>16)&0x00007FFF, \ + (qs1516(yx)>>16)&0x00007FFF, \ + (qs1516(yy)>>16)&0x00007FFF, \ + (qs1516(yz)>>16)&0x00007FFF, \ + (qs1516(yw)>>16)&0x00007FFF, \ + (qs1516(zx)>>16)&0x00007FFF, \ + (qs1516(zy)>>16)&0x00007FFF, \ + (qs1516(zz)>>16)&0x00007FFF, \ + (qs1516(zw)>>16)&0x00007FFF, \ + (qs1516(wx)>>16)&0x00007FFF, \ + (qs1516(wy)>>16)&0x00007FFF, \ + (qs1516(wz)>>16)&0x00007FFF, \ + (qs1516(ww)>>16)&0x00007FFF}, \ + .f={qs1516(xx)&0x0000FFFF, \ + qs1516(xy)&0x0000FFFF, \ + qs1516(xz)&0x0000FFFF, \ + qs1516(xw)&0x0000FFFF, \ + qs1516(yx)&0x0000FFFF, \ + qs1516(yy)&0x0000FFFF, \ + qs1516(yz)&0x0000FFFF, \ + qs1516(yw)&0x0000FFFF, \ + qs1516(zx)&0x0000FFFF, \ + qs1516(zy)&0x0000FFFF, \ + qs1516(zz)&0x0000FFFF, \ + qs1516(zw)&0x0000FFFF, \ + qs1516(wx)&0x0000FFFF, \ + qs1516(wy)&0x0000FFFF, \ + qs1516(wz)&0x0000FFFF, \ + qs1516(ww)&0x0000FFFF}}) +#define gdSPDefLookAt(rx,ry,rz, \ + ux,uy,uz) ((LookAt) \ + {{{{{0,0,0},0,{0,0,0},0, \ + {rx,ry,rz},0}}, \ + {{{0,0x80,0},0,{0,0x80,0},0, \ + {ux,uy,uz},0}}}}) +#define gdSPDefLights0(ar,ag,ab) ((Lights0) \ + {{{{ar,ag,ab},0,{ar,ag,ab},0}}, \ + {{{{0,0,0},0,{0,0,0},0,{0,0,0},0}}}}) +#define \ +gdSPDefLights1(ar,ag,ab, \ + r1,g1,b1,x1,y1,z1) ((Lights1) \ + {{{{ar,ag,ab},0,{ar,ag,ab},0}}, \ + {{{{r1,g1,b1},0,{r1,g1,b1},0, \ + {x1,y1,z1},0}}}}) +#define \ +gdSPDefLights2(ar,ag,ab, \ + r1,g1,b1,x1,y1,z1, \ + r2,g2,b2,x2,y2,z2) ((Lights2) \ + {{{{ar,ag,ab},0,{ar,ag,ab},0}}, \ + {{{{r1,g1,b1},0,{r1,g1,b1},0, \ + {x1,y1,z1},0}}, \ + {{{r2,g2,b2},0,{r2,g2,b2},0, \ + {x2,y2,z2},0}}}}) +#define \ +gdSPDefLights3(ar,ag,ab, \ + r1,g1,b1,x1,y1,z1, \ + r2,g2,b2,x2,y2,z2, \ + r3,g3,b3,x3,y3,z3) ((Lights3) \ + {{{{ar,ag,ab},0,{ar,ag,ab},0}}, \ + {{{{r1,g1,b1},0,{r1,g1,b1},0, \ + {x1,y1,z1},0}}, \ + {{{r2,g2,b2},0,{r2,g2,b2},0, \ + {x2,y2,z2},0}}, \ + {{{r3,g3,b3},0,{r3,g3,b3},0, \ + {x3,y3,z3},0}}}}) +#define \ +gdSPDefLights4(ar,ag,ab, \ + r1,g1,b1,x1,y1,z1, \ + r2,g2,b2,x2,y2,z2, \ + r3,g3,b3,x3,y3,z3, \ + r4,g4,b4,x4,y4,z4) ((Lights4) \ + {{{{ar,ag,ab},0,{ar,ag,ab},0}}, \ + {{{{r1,g1,b1},0,{r1,g1,b1},0, \ + {x1,y1,z1},0}}, \ + {{{r2,g2,b2},0,{r2,g2,b2},0, \ + {x2,y2,z2},0}}, \ + {{{r3,g3,b3},0,{r3,g3,b3},0, \ + {x3,y3,z3},0}}, \ + {{{r4,g4,b4},0,{r4,g4,b4},0, \ + {x4,y4,z4},0}}}}) +#define \ +gdSPDefLights5(ar,ag,ab, \ + r1,g1,b1,x1,y1,z1, \ + r2,g2,b2,x2,y2,z2, \ + r3,g3,b3,x3,y3,z3, \ + r4,g4,b4,x4,y4,z4, \ + r5,g5,b5,x5,y5,z5) ((Lights5) \ + {{{{ar,ag,ab},0,{ar,ag,ab},0}}, \ + {{{{r1,g1,b1},0,{r1,g1,b1},0, \ + {x1,y1,z1},0}}, \ + {{{r2,g2,b2},0,{r2,g2,b2},0, \ + {x2,y2,z2},0}}, \ + {{{r3,g3,b3},0,{r3,g3,b3},0, \ + {x3,y3,z3},0}}, \ + {{{r4,g4,b4},0,{r4,g4,b4},0, \ + {x4,y4,z4},0}}, \ + {{{r5,g5,b5},0,{r5,g5,b5},0, \ + {x5,y5,z5},0}}}}) +#define \ +gdSPDefLights6(ar,ag,ab, \ + r1,g1,b1,x1,y1,z1, \ + r2,g2,b2,x2,y2,z2, \ + r3,g3,b3,x3,y3,z3, \ + r4,g4,b4,x4,y4,z4, \ + r5,g5,b5,x5,y5,z5, \ + r6,g6,b6,x6,y6,z6) ((Lights6) \ + {{{{ar,ag,ab},0,{ar,ag,ab},0}}, \ + {{{{r1,g1,b1},0,{r1,g1,b1},0, \ + {x1,y1,z1},0}}, \ + {{{r2,g2,b2},0,{r2,g2,b2},0, \ + {x2,y2,z2},0}}, \ + {{{r3,g3,b3},0,{r3,g3,b3},0, \ + {x3,y3,z3},0}}, \ + {{{r4,g4,b4},0,{r4,g4,b4},0, \ + {x4,y4,z4},0}}, \ + {{{r5,g5,b5},0,{r5,g5,b5},0, \ + {x5,y5,z5},0}}, \ + {{{r6,g6,b6},0,{r6,g6,b6},0, \ + {x6,y6,z6},0}}}}) +#define \ +gdSPDefLights7(ar,ag,ab, \ + r1,g1,b1,x1,y1,z1, \ + r2,g2,b2,x2,y2,z2, \ + r3,g3,b3,x3,y3,z3, \ + r4,g4,b4,x4,y4,z4, \ + r5,g5,b5,x5,y5,z5, \ + r6,g6,b6,x6,y6,z6, \ + r7,g7,b7,x7,y7,z7) ((Lights7) \ + {{{{ar,ag,ab},0,{ar,ag,ab},0}}, \ + {{{{r1,g1,b1},0,{r1,g1,b1},0, \ + {x1,y1,z1},0}}, \ + {{{r2,g2,b2},0,{r2,g2,b2},0, \ + {x2,y2,z2},0}}, \ + {{{r3,g3,b3},0,{r3,g3,b3},0, \ + {x3,y3,z3},0}}, \ + {{{r4,g4,b4},0,{r4,g4,b4},0, \ + {x4,y4,z4},0}}, \ + {{{r5,g5,b5},0,{r5,g5,b5},0, \ + {x5,y5,z5},0}}, \ + {{{r6,g6,b6},0,{r6,g6,b6},0, \ + {x6,y6,z6},0}}, \ + {{{r7,g7,b7},0,{r7,g7,b7},0, \ + {x7,y7,z7},0}}}}) +#define gdSPDefVtx(x,y,z,s,t) ((Vtx) \ + {.v={{x,y,z},0,{qs105(s),qs105(t)}}}) +#define gdSPDefVtxC(x,y,z,s,t, \ + r,g,b,a) ((Vtx) \ + {.v={{x,y,z},0,{qs105(s),qs105(t)}, \ + {r,g,b,a}}}) +#define gdSPDefVtxN(x,y,z,s,t, \ + nx,ny,nz,a) ((Vtx) \ + {.n={{x,y,z},0,{qs105(s),qs105(t)}, \ + {nx,ny,nz},a}}) + +/* instruction macros */ +#define \ +gsDPFillRectangle(ulx,uly,lrx,lry) gO_(G_FILLRECT, \ + gF_(lrx,10,14)|gF_(lry,10,2), \ + gF_(ulx,10,14)|gF_(uly,10,2)) +#define \ +gsDPScisFillRectangle(ulx,uly,lrx, \ + lry) gsDPFillRectangle((ulx)<0?0:(ulx), \ + (uly)<0?0:(uly), \ + (lrx)<0?0:(lrx), \ + (lry)<0?0:(lry)) +#define gsDPFullSync() gO_(G_RDPFULLSYNC,0,0) +#define gsDPLoadSync() gO_(G_RDPLOADSYNC,0,0) +#define gsDPTileSync() gO_(G_RDPTILESYNC,0,0) +#define gsDPPipeSync() gO_(G_RDPPIPESYNC,0,0) +#define gsDPLoadTLUT_pal16(pal,dram) gsDPLoadTLUT(16,256+(gI_(pal)&0xF)*16, \ + dram) +#define gsDPLoadTLUT_pal256(dram) gsDPLoadTLUT(256,256,dram) +#define \ +gLTB_(timg,fmt,siz,width,height,pal,\ + cms,cmt,masks,maskt, \ + shifts,shiftt,dxt,tmem,rt,line) gsDPSetTextureImage(fmt, \ + G_SIZ_LDSIZ(siz), \ + 1,timg), \ + gsDPSetTile(fmt,G_SIZ_LDSIZ(siz),0, \ + tmem,G_TX_LOADTILE,0, \ + cmt,maskt,shiftt, \ + cms,masks,shifts), \ + gsDPLoadSync(), \ + gsDPLoadBlock(G_TX_LOADTILE,0,0, \ + (((width)*(height)+1)* \ + G_SIZ_BITS(siz)-1)/ \ + G_SIZ_BITS( \ + G_SIZ_LDSIZ(siz))-1, \ + dxt), \ + gsDPPipeSync(), \ + gsDPSetTile(fmt,siz,line,tmem,rt,pal, \ + cmt,maskt,shiftt, \ + cms,masks,shifts), \ + gsDPSetTileSize(rt,0,0, \ + qu102((width)-1), \ + qu102((height)-1)) +#define \ +gsDPLoadTextureBlock(timg,fmt,siz, \ + width,height, \ + pal,cms,cmt, \ + masks,maskt, \ + shifts,shiftt) gLTB_(timg,fmt,siz,width,height,pal, \ + cms,cmt,masks,maskt,shifts,shiftt,\ + G_DXT(siz,width),0x0, \ + G_TX_RENDERTILE, \ + ((width)*G_SIZ_LDBITS(siz)+63)/64) +#define \ +gsDPLoadTextureBlockS(timg,fmt,siz, \ + width,height, \ + pal,cms,cmt, \ + masks,maskt, \ + shifts,shiftt) gLTB_(timg,fmt,siz,width,height,pal, \ + cms,cmt,masks,maskt,shifts,shiftt,\ + 0,0x0,G_TX_RENDERTILE, \ + ((width)*G_SIZ_LDBITS(siz)+63)/64) +#define \ +gsDPLoadTextureBlock_4b(timg,fmt, \ + width, \ + height,pal, \ + cms,cmt, \ + masks, \ + maskt, \ + shifts, \ + shiftt) gLTB_(timg,fmt,G_IM_SIZ_4b, \ + width,height,pal, \ + cms,cmt,masks,maskt,shifts,shiftt,\ + G_DXT(G_IM_SIZ_4b,width),0x0, \ + G_TX_RENDERTILE,((width)*4+63)/64) +#define \ +gsDPLoadTextureBlock_4bS(timg,fmt, \ + width, \ + height,pal,\ + cms,cmt, \ + masks, \ + maskt, \ + shifts, \ + shiftt) gLTB_(timg,fmt,G_IM_SIZ_4b, \ + width,height,pal, \ + cms,cmt,masks,maskt,shifts,shiftt,\ + 0,0x0,G_TX_RENDERTILE, \ + ((width)*4+63)/64) +#define \ +gsDPLoadTextureBlockYuv(timg,fmt, \ + siz, \ + width, \ + height, \ + pal, \ + cms,cmt, \ + masks, \ + maskt, \ + shifts, \ + shiftt) gLTB_(timg,fmt,siz,width,height,pal, \ + cms,cmt,masks,maskt,shifts,shiftt,\ + G_DXT(siz,width),0x0, \ + G_TX_RENDERTILE,((width)+7)/8) +#define \ +gsDPLoadTextureBlockYuvS(timg,fmt, \ + siz, \ + width, \ + height, \ + pal, \ + cms,cmt, \ + masks, \ + maskt, \ + shifts, \ + shiftt) gLTB_(timg,fmt,siz,width,height,pal, \ + cms,cmt,masks,maskt,shifts,shiftt,\ + 0,0x0,G_TX_RENDERTILE, \ + ((width)+7)/8) +#define \ +_gsDPLoadTextureBlock(timg,tmem, \ + fmt,siz, \ + width,height, \ + pal,cms,cmt, \ + masks,maskt, \ + shifts,shiftt) gLTB_(timg,fmt,siz,width,height,pal, \ + cms,cmt,masks,maskt,shifts,shiftt,\ + G_DXT(siz,width),tmem, \ + G_TX_RENDERTILE, \ + ((width)*G_SIZ_LDBITS(siz)+63)/64) +#define \ +_gsDPLoadTextureBlockS(timg,tmem, \ + fmt,siz, \ + width,height,\ + pal,cms,cmt, \ + masks,maskt, \ + shifts,shiftt) gLTB_(timg,fmt,siz,width,height,pal, \ + cms,cmt,masks,maskt,shifts,shiftt,\ + 0,tmem,G_TX_RENDERTILE, \ + ((width)*G_SIZ_LDBITS(siz)+63)/64) +#define \ +_gsDPLoadTextureBlock_4b(timg,tmem, \ + fmt,width, \ + height,pal,\ + cms,cmt, \ + masks, \ + maskt, \ + shifts, \ + shiftt) gLTB_(timg,fmt,G_IM_SIZ_4b, \ + width,height,pal, \ + cms,cmt,masks,maskt,shifts,shiftt,\ + G_DXT(G_IM_SIZ_4b,width),tmem, \ + G_TX_RENDERTILE,((width)*4+63)/64) +#define \ +_gsDPLoadTextureBlock_4bS(timg,tmem,\ + fmt,width,\ + height, \ + pal,cms, \ + cmt,masks,\ + maskt, \ + shifts, \ + shiftt) gLTB_(timg,fmt,G_IM_SIZ_4b, \ + width,height,pal, \ + cms,cmt,masks,maskt,shifts,shiftt,\ + 0,tmem,G_TX_RENDERTILE, \ + ((width)*4+63)/64) +#define \ +_gsDPLoadTextureBlockYuv(timg,tmem, \ + fmt,siz, \ + width, \ + height,pal,\ + cms,cmt, \ + masks, \ + maskt, \ + shifts, \ + shiftt) gLTB_(timg,fmt,siz,width,height,pal, \ + cms,cmt,masks,maskt,shifts,shiftt,\ + G_DXT(siz,width),tmem, \ + G_TX_RENDERTILE,((width)+7)/8) +#define \ +_gsDPLoadTextureBlockYuvS(timg,tmem,\ + fmt,siz, \ + width, \ + height, \ + pal, \ + cms,cmt, \ + masks, \ + maskt, \ + shifts, \ + shiftt) gLTB_(timg,fmt,siz,width,height,pal, \ + cms,cmt,masks,maskt,shifts,shiftt,\ + 0,tmem,G_TX_RENDERTILE, \ + ((width)+7)/8) +#define \ +gsDPLoadMultiBlock(timg,tmem,rt, \ + fmt,siz, \ + width,height, \ + pal,cms,cmt, \ + masks,maskt, \ + shifts,shiftt) gLTB_(timg,fmt,siz,width,height,pal, \ + cms,cmt,masks,maskt,shifts,shiftt,\ + G_DXT(siz,width),tmem,rt, \ + ((width)*G_SIZ_LDBITS(siz)+63)/64) +#define \ +gsDPLoadMultiBlockS(timg,tmem,rt, \ + fmt,siz, \ + width,height, \ + pal,cms,cmt, \ + masks,maskt, \ + shifts,shiftt) gLTB_(timg,fmt,siz,width,height,pal, \ + cms,cmt,masks,maskt,shifts,shiftt,\ + 0,tmem,rt, \ + ((width)*G_SIZ_LDBITS(siz)+63)/64) +#define \ +gsDPLoadMultiBlock_4b(timg,tmem,rt, \ + fmt, \ + width,height, \ + pal,cms,cmt, \ + masks,maskt, \ + shifts,shiftt) gLTB_(timg,fmt,G_IM_SIZ_4b, \ + width,height,pal, \ + cms,cmt,masks,maskt,shifts,shiftt,\ + G_DXT(G_IM_SIZ_4b,width),tmem,rt, \ + ((width)*4+63)/64) +#define \ +gsDPLoadMultiBlock_4bS(timg,tmem,rt,\ + fmt, \ + width,height,\ + pal,cms,cmt, \ + masks,maskt, \ + shifts,shiftt) gLTB_(timg,fmt,G_IM_SIZ_4b, \ + width,height,pal, \ + cms,cmt,masks,maskt,shifts,shiftt,\ + 0,tmem,rt,((width)*4+63)/64) +#define \ +gsDPLoadMultiBlockYuv(timg,tmem,rt, \ + fmt,siz, \ + width,height, \ + pal,cms,cmt, \ + masks,maskt, \ + shifts,shiftt) gLTB_(timg,fmt,siz,width,height,pal, \ + cms,cmt,masks,maskt,shifts,shiftt,\ + G_DXT(siz,width),tmem,rt, \ + ((width)+7)/8) +#define \ +gsDPLoadMultiBlockYuvS(timg,tmem,rt,\ + fmt,siz, \ + width,height,\ + pal,cms,cmt, \ + masks,maskt, \ + shifts,shiftt) gLTB_(timg,fmt,siz,width,height,pal, \ + cms,cmt,masks,maskt,shifts,shiftt,\ + 0,tmem,rt,((width)+7)/8) +#define \ +gLTT_(timg,fmt,siz,width,height, \ + uls,ult,lrs,lrt,pal,cms,cmt, \ + masks,maskt,shifts,shiftt, \ + tmem,rt,line) gsDPSetTextureImage(fmt,siz,width,timg),\ + gsDPSetTile(fmt,siz,line,tmem, \ + G_TX_LOADTILE,0, \ + cmt,maskt,shiftt, \ + cms,masks,shifts), \ + gsDPLoadSync(), \ + gsDPLoadTile(G_TX_LOADTILE, \ + qu102(uls),qu102(ult), \ + qu102(lrs),qu102(lrt)), \ + gsDPPipeSync(), \ + gsDPSetTile(fmt,siz,line, \ + tmem,rt,pal, \ + cmt,maskt,shiftt, \ + cms,masks,shifts), \ + gsDPSetTileSize(rt, \ + qu102(uls),qu102(ult), \ + qu102(lrs),qu102(lrt)) +#define \ +gLTT4_(timg,fmt,width,height, \ + uls,ult,lrs,lrt,pal,cms,cmt, \ + masks,maskt,shifts,shiftt, \ + tmem,rt) gsDPSetTextureImage(fmt,G_IM_SIZ_8b, \ + (width)/2,timg), \ + gsDPSetTile(fmt,G_IM_SIZ_8b, \ + (((lrs)-(uls)+1)/2+7)/8, \ + tmem,G_TX_LOADTILE,0, \ + cmt,maskt,shiftt, \ + cms,masks,shifts), \ + gsDPLoadSync(), \ + gsDPLoadTile(G_TX_LOADTILE, \ + qu102(uls)/2,qu102(ult), \ + qu102(lrs)/2,qu102(lrt)), \ + gsDPPipeSync(), \ + gsDPSetTile(fmt,G_IM_SIZ_4b, \ + (((lrs)-(uls)+1)/2+7)/8, \ + tmem,rt,pal, \ + cmt,maskt,shiftt, \ + cms,masks,shifts), \ + gsDPSetTileSize(rt, \ + qu102(uls),qu102(ult), \ + qu102(lrs),qu102(lrt)) +#define \ +gsDPLoadTextureTile(timg,fmt,siz, \ + width,height, \ + uls,ult,lrs, \ + lrt,pal,cms, \ + cmt,masks, \ + maskt,shifts, \ + shiftt) gLTT_(timg,fmt,siz,width,height, \ + uls,ult,lrs,lrt,pal,cms,cmt, \ + masks,maskt,shifts,shiftt, \ + 0x0,G_TX_RENDERTILE, \ + (((lrs)-(uls)+1)* \ + G_SIZ_LDBITS(siz)+63)/64) +#define \ +gsDPLoadTextureTile_4b(timg,fmt, \ + width, \ + height,uls, \ + ult,lrs,lrt, \ + pal,cms,cmt, \ + masks,maskt, \ + shifts,shiftt) gLTT4_(timg,fmt,width,height, \ + uls,ult,lrs,lrt,pal,cms,cmt, \ + masks,maskt,shifts,shiftt, \ + 0x0,G_TX_RENDERTILE) +#define \ +gsDPLoadTextureTileYuv(timg,fmt,siz,\ + width,height,\ + uls,ult,lrs, \ + lrt,pal,cms, \ + cmt,masks, \ + maskt,shifts,\ + shiftt) gLTT_(timg,fmt,siz,width,height, \ + uls,ult,lrs,lrt,pal,cms,cmt, \ + masks,maskt,shifts,shiftt, \ + 0x0,G_TX_RENDERTILE, \ + (((lrs)-(uls)+1)+7)/8) +#define \ +_gsDPLoadTextureTile(timg,tmem, \ + fmt,siz, \ + width,height, \ + uls,ult,lrs, \ + lrt,pal,cms, \ + cmt,masks, \ + maskt,shifts, \ + shiftt) gLTT_(timg,fmt,siz,width,height, \ + uls,ult,lrs,lrt,pal,cms,cmt, \ + masks,maskt,shifts,shiftt, \ + tmem,G_TX_RENDERTILE, \ + (((lrs)-(uls)+1)* \ + G_SIZ_LDBITS(siz)+63)/64) +#define \ +_gsDPLoadTextureTile_4b(timg,tmem, \ + fmt,width, \ + height,uls, \ + ult,lrs,lrt,\ + pal,cms,cmt,\ + masks,maskt,\ + shifts, \ + shiftt) gLTT4_(timg,fmt,width,height, \ + uls,ult,lrs,lrt,pal,cms,cmt, \ + masks,maskt,shifts,shiftt, \ + tmem,G_TX_RENDERTILE) +#define \ +_gsDPLoadTextureTileYuv(timg,tmem, \ + fmt,siz, \ + width, \ + height,uls, \ + ult,lrs,lrt,\ + pal,cms,cmt,\ + masks,maskt,\ + shifts, \ + shiftt) gLTT_(timg,fmt,siz,width,height, \ + uls,ult,lrs,lrt,pal,cms,cmt, \ + masks,maskt,shifts,shiftt, \ + tmem,G_TX_RENDERTILE, \ + (((lrs)-(uls)+1)+7)/8) +#define \ +gsDPLoadMultiTile(timg,tmem,rt, \ + fmt,siz, \ + width,height, \ + uls,ult,lrs,lrt, \ + pal,cms,cmt, \ + masks,maskt, \ + shifts,shiftt) gLTT_(timg,fmt,siz,width,height, \ + uls,ult,lrs,lrt,pal,cms,cmt, \ + masks,maskt,shifts,shiftt,tmem,rt,\ + (((lrs)-(uls)+1)* \ + G_SIZ_LDBITS(siz)+63)/64) +#define \ +gsDPLoadMultiTile_4b(timg,tmem,rt, \ + fmt,width, \ + height,uls,ult,\ + lrs,lrt,pal, \ + cms,cmt, \ + masks,maskt, \ + shifts,shiftt) gLTT4_(timg,fmt,width,height, \ + uls,ult,lrs,lrt,pal,cms,cmt, \ + masks,maskt,shifts,shiftt,tmem,rt) +#define \ +gsDPLoadMultiTileYuv(timg,tmem,rt, \ + fmt,siz,width, \ + height,uls,ult,\ + lrs,lrt,pal, \ + cms,cmt, \ + masks,maskt, \ + shifts,shiftt) gLTT_(timg,fmt,siz,width,height, \ + uls,ult,lrs,lrt,pal,cms,cmt, \ + masks,maskt,shifts,shiftt, \ + tmem,rt,(((lrs)-(uls)+1)+7)/8) +#define gsDPLoadBlock(tile,uls,ult, \ + lrs,dxt) gO_(G_LOADBLOCK, \ + gF_(uls,12,12)|gF_(ult,12,0), \ + gF_(tile,3,24)|gF_(lrs,12,12)| \ + gF_(dxt,12,0)) +#define gsDPNoOp() gsDPNoOpTag(0) +#define gsDPNoOpTag(tag) gO_(G_NOOP,0,tag) +#define gsDPPipelineMode(mode) gsSPSetOtherModeHi(G_MDSFT_PIPELINE, \ + G_MDSIZ_PIPELINE, \ + mode) +#define gsDPSetBlendColor(r,g,b,a) gO_(G_SETBLENDCOLOR,0, \ + gF_(r,8,24)|gF_(g,8,16)| \ + gF_(b,8,8)|gF_(a,8,0)) +#define gsDPSetEnvColor(r,g,b,a) gO_(G_SETENVCOLOR,0, \ + gF_(r,8,24)|gF_(g,8,16)| \ + gF_(b,8,8)|gF_(a,8,0)) +#define gsDPSetFillColor(c) gO_(G_SETFILLCOLOR,0,c) +#define gsDPSetFogColor(r,g,b,a) gO_(G_SETFOGCOLOR,0, \ + gF_(r,8,24)|gF_(g,8,16)| \ + gF_(b,8,8)|gF_(a,8,0)) +#define gsDPSetPrimColor(m,l,r,g,b,a) gO_(G_SETPRIMCOLOR, \ + gF_(m,8,8)|gF_(l,8,0), \ + gF_(r,8,24)|gF_(g,8,16)| \ + gF_(b,8,8)|gF_(a,8,0)) +#define \ +gsDPSetColorImage(fmt,siz,width, \ + img) gO_(G_SETCIMG, \ + gF_(fmt,3,21)| \ + gF_(siz,2,19)| \ + gF_((width)-1,12,0), \ + img) +#define gsDPSetDepthImage(img) gO_(G_SETZIMG,0,img) +#define \ +gsDPSetTextureImage(fmt,siz,width, \ + img) gO_(G_SETTIMG, \ + gF_(fmt,3,21)| \ + gF_(siz,2,19)| \ + gF_((width)-1,12,0), \ + img) +#define \ +gsDPSetHilite1Tile(tile,hilite, \ + width,height) gsDPSetTileSize(tile, \ + ((Hilite*)(hilite))-> \ + h.x1&0xFFF, \ + ((Hilite*)(hilite))-> \ + h.y1&0xFFF, \ + (((width)-1)*4+ \ + ((Hilite*)(hilite))-> \ + h.x1)&0xFFF, \ + (((height)-1)*4+ \ + ((Hilite*)(hilite))-> \ + h.y1)&0xFFF) +#define \ +gsDPSetHilite2Tile(tile,hilite, \ + width,height) gsDPSetTileSize(tile, \ + ((Hilite*)(hilite))-> \ + h.x2&0xFFF, \ + ((Hilite*)(hilite))-> \ + h.y2&0xFFF, \ + (((width)-1)*4+ \ + ((Hilite*)(hilite))-> \ + h.x2)&0xFFF, \ + (((height)-1)*4+ \ + ((Hilite*)(hilite))-> \ + h.y2)&0xFFF) +#define gsDPSetAlphaCompare(mode) gsSPSetOtherModeLo(G_MDSFT_ALPHACOMPARE,\ + G_MDSIZ_ALPHACOMPARE,\ + mode) +#define gsDPSetAlphaDither(type) gsSPSetOtherModeHi(G_MDSFT_ALPHADITHER, \ + G_MDSIZ_ALPHADITHER, \ + type) +#define gsDPSetColorDither(type) gsSPSetOtherModeHi(G_MDSFT_RGBDITHER, \ + G_MDSIZ_RGBDITHER, \ + type) +#define gsDPSetCombineMode(mode1, \ + mode2) gsDPSetCombineLERP(mode1,mode2) +#define \ +gsDPSetCombineLERP(a0,b0,c0,d0,Aa0, \ + Ab0,Ac0,Ad0,a1, \ + b1,c1,d1,Aa1, \ + Ab1,Ac1,Ad1) gO_(G_SETCOMBINE, \ + gF_(G_CCMUX_##a0,4,20)| \ + gF_(G_CCMUX_##c0,5,15)| \ + gF_(G_ACMUX_##Aa0,3,12)| \ + gF_(G_ACMUX_##Ac0,3,9)| \ + gF_(G_CCMUX_##a1,4,5)| \ + gF_(G_CCMUX_##c1,5,0), \ + gF_(G_CCMUX_##b0,4,28)| \ + gF_(G_CCMUX_##b1,4,24)| \ + gF_(G_ACMUX_##Aa1,3,21)| \ + gF_(G_ACMUX_##Ac1,3,18)| \ + gF_(G_CCMUX_##d0,3,15)| \ + gF_(G_ACMUX_##Ab0,3,12)| \ + gF_(G_ACMUX_##Ad0,3,9)| \ + gF_(G_CCMUX_##d1,3,6)| \ + gF_(G_ACMUX_##Ab1,3,3)| \ + gF_(G_ACMUX_##Ad1,3,0)) +#define gsDPSetConvert(k0,k1,k2, \ + k3,k4,k5) gO_(G_SETCONVERT, \ + gF_(k0,9,13)|gF_(k1,9,4)| \ + gF_(gI_(k2)>>5,4,0), \ + gF_(k2,5,27)|gF_(k3,9,18)| \ + gF_(k4,9,9)|gF_(k5,9,0)) +#define gsDPSetTextureConvert(type) gsSPSetOtherModeHi(G_MDSFT_TEXTCONV, \ + G_MDSIZ_TEXTCONV, \ + type) +#define gsDPSetCycleType(type) gsSPSetOtherModeHi(G_MDSFT_CYCLETYPE, \ + G_MDSIZ_CYCLETYPE, \ + type) +#define gsDPSetDepthSource(source) gsSPSetOtherModeLo(G_MDSFT_ZSRCSEL, \ + G_MDSIZ_ZSRCSEL, \ + source) +#define gsDPSetCombineKey(type) gsSPSetOtherModeHi(G_MDSFT_COMBKEY, \ + G_MDSIZ_COMBKEY, \ + type) +#define gsDPSetKeyGB(cG,sG,wG, \ + cB,sB,wB) gO_(G_SETKEYGB, \ + gF_(wG,12,12)|gF_(wB,12,0), \ + gF_(cG,8,24)|gF_(sG,8,16)| \ + gF_(cB,8,8)|gF_(sB,8,0)) +#define gsDPSetKeyR(cR,sR,wR) gO_(G_SETKEYR,0, \ + gF_(wR,12,16)|gF_(cR,8,8)| \ + gF_(sR,8,0)) +#define gsDPSetPrimDepth(z,dz) gO_(G_SETPRIMDEPTH,0, \ + gF_(z,16,16)|gF_(dz,16,0)) +#define gsDPSetRenderMode(mode1, \ + mode2) gsSPSetOtherModeLo(G_MDSFT_RENDERMODE, \ + G_MDSIZ_RENDERMODE, \ + gI_(mode1)|gI_(mode2)) +#define gsDPSetScissor(mode,ulx, \ + uly,lrx,lry) gsDPSetScissorFrac(mode, \ + qu102(gI_(ulx)), \ + qu102(gI_(uly)), \ + qu102(gI_(lrx)), \ + qu102(gI_(lry))) +#define \ +gsDPSetScissorFrac(mode, \ + ulx,uly,lrx,lry) gO_(G_SETSCISSOR, \ + gF_(ulx,12,12)|gF_(uly,12,0), \ + gF_(mode,2,24)|gF_(lrx,12,12)| \ + gF_(lry,12,0)) +#define gsDPSetTextureDetail(type) gsSPSetOtherModeHi(G_MDSFT_TEXTDETAIL, \ + G_MDSIZ_TEXTDETAIL, \ + type) +#define gsDPSetTextureFilter(mode) gsSPSetOtherModeHi(G_MDSFT_TEXTFILT, \ + G_MDSIZ_TEXTFILT, \ + mode) +#define gsDPSetTextureLOD(mode) gsSPSetOtherModeHi(G_MDSFT_TEXTLOD, \ + G_MDSIZ_TEXTLOD, \ + mode) +#define gsDPSetTextureLUT(mode) gsSPSetOtherModeHi(G_MDSFT_TEXTLUT, \ + G_MDSIZ_TEXTLUT, \ + mode) +#define gsDPSetTexturePersp(enable) gsSPSetOtherModeHi(G_MDSFT_TEXTPERSP, \ + G_MDSIZ_TEXTPERSP, \ + enable) +#define \ +gsDPSetTile(fmt,siz,line,tmem, \ + tile,palette,cmt, \ + maskt,shiftt,cms,masks, \ + shifts) gO_(G_SETTILE, \ + gF_(fmt,3,21)|gF_(siz,2,19)| \ + gF_(line,9,9)|gF_(tmem,9,0), \ + gF_(tile,3,24)|gF_(palette,4,20)| \ + gF_(cmt,2,18)|gF_(maskt,4,14)| \ + gF_(shiftt,4,10)|gF_(cms,2,8)| \ + gF_(masks,4,4)|gF_(shifts,4,0)) +#define gsDPSetTileSize(tile,uls, \ + ult,lrs,lrt) gO_(G_SETTILESIZE, \ + gF_(uls,12,12)|gF_(ult,12,0), \ + gF_(tile,3,24)|gF_(lrs,12,12)| \ + gF_(lrt,12,0)) +#define gsSPBranchList(dl) gsDisplayList(dl,1) +#define gsSPClipRatio(r) gsMoveWd(G_MW_CLIP,G_MWO_CLIP_RNX, \ + (uint16_t)(r)), \ + gsMoveWd(G_MW_CLIP,G_MWO_CLIP_RNY, \ + (uint16_t)(r)), \ + gsMoveWd(G_MW_CLIP,G_MWO_CLIP_RPX, \ + (uint16_t)-(r)), \ + gsMoveWd(G_MW_CLIP,G_MWO_CLIP_RPY, \ + (uint16_t)-(r)) +#define gsSPDisplayList(dl) gsDisplayList(dl,0) +#define gsSPEndDisplayList() gO_(G_ENDDL,0,0) +#define gsSPFogPosition(min,max) gsMoveWd(G_MW_FOG,G_MWO_FOG, \ + gF_(128000/((max)-(min)), \ + 16,16)| \ + gF_((500-(min))*256/ \ + ((max)-(min)),16,0)) +#define gsSPLine3D(v0,v1,flag) gsSPLineW3D(v0,v1,0,flag) +#define gsSPLookAt(l) gsSPLookAtX(l), \ + gsSPLookAtY(gI_(l)+0x10) +#define gsSPSegment(seg,base) gsMoveWd(G_MW_SEGMENT,(seg)*4,base) +#define gsSPSetLights0(lites) gsSPNumLights(NUMLIGHTS_0), \ + gsSPLight(&(lites).l[0],1), \ + gsSPLight(&(lites).a,2) +#define gsSPSetLights1(lites) gsSPNumLights(NUMLIGHTS_1), \ + gsSPLight(&(lites).l[0],1), \ + gsSPLight(&(lites).a,2) +#define gsSPSetLights2(lites) gsSPNumLights(NUMLIGHTS_2), \ + gsSPLight(&(lites).l[0],1), \ + gsSPLight(&(lites).l[1],2), \ + gsSPLight(&(lites).a,3) +#define gsSPSetLights3(lites) gsSPNumLights(NUMLIGHTS_3), \ + gsSPLight(&(lites).l[0],1), \ + gsSPLight(&(lites).l[1],2), \ + gsSPLight(&(lites).l[2],3), \ + gsSPLight(&(lites).a,4) +#define gsSPSetLights4(lites) gsSPNumLights(NUMLIGHTS_4), \ + gsSPLight(&(lites).l[0],1), \ + gsSPLight(&(lites).l[1],2), \ + gsSPLight(&(lites).l[2],3), \ + gsSPLight(&(lites).l[3],4), \ + gsSPLight(&(lites).a,5) +#define gsSPSetLights5(lites) gsSPNumLights(NUMLIGHTS_5), \ + gsSPLight(&(lites).l[0],1), \ + gsSPLight(&(lites).l[1],2), \ + gsSPLight(&(lites).l[2],3), \ + gsSPLight(&(lites).l[3],4), \ + gsSPLight(&(lites).l[4],5), \ + gsSPLight(&(lites).a,6) +#define gsSPSetLights6(lites) gsSPNumLights(NUMLIGHTS_6), \ + gsSPLight(&(lites).l[0],1), \ + gsSPLight(&(lites).l[1],2), \ + gsSPLight(&(lites).l[2],3), \ + gsSPLight(&(lites).l[3],4), \ + gsSPLight(&(lites).l[4],5), \ + gsSPLight(&(lites).l[5],6), \ + gsSPLight(&(lites).a,7) +#define gsSPSetLights7(lites) gsSPNumLights(NUMLIGHTS_7), \ + gsSPLight(&(lites).l[0],1), \ + gsSPLight(&(lites).l[1],2), \ + gsSPLight(&(lites).l[2],3), \ + gsSPLight(&(lites).l[3],4), \ + gsSPLight(&(lites).l[4],5), \ + gsSPLight(&(lites).l[5],6), \ + gsSPLight(&(lites).l[6],7), \ + gsSPLight(&(lites).a,8) +#define gsSPSetStatus(sid,val) gsMoveWd(G_MW_GENSTAT,sid,val) +#define gsSPNumLights(n) gsMoveWd(G_MW_NUMLIGHT,G_MWO_NUMLIGHT, \ + NUML(n)) +#define gsSPLightColor(Lightnum, \ + packedcolor) gsMoveWd(G_MW_LIGHTCOL, \ + G_MWO_a##Lightnum,packedcolor),\ + gsMoveWd(G_MW_LIGHTCOL, \ + G_MWO_b##Lightnum,packedcolor) +#define \ +gsSPTextureRectangle(ulx,uly,lrx, \ + lry,tile,s,t, \ + dsdx,dtdy) gsTexRect(ulx,uly,lrx,lry,tile), \ + gsDPHalf1(gF_(s,16,16)|gF_(t,16,0)), \ + gsDPHalf2(gF_(dsdx,16,16)|gF_(dtdy,16,0)) +#define \ +gsSPScisTextureRectangle(ulx,uly, \ + lrx,lry, \ + tile,s,t, \ + dsdx,dtdy) gsTexRect((ulx)<0?0:(ulx), \ + (uly)<0?0:(uly), \ + (lrx)<0?0:(lrx), \ + (lry)<0?0:(lry), \ + tile), \ + gsDPHalf1(gF_((s)+(ulx)*(dsdx)* \ + ((ulx)<0)*((dsdx)<0?1:-1)/\ + 0x80,16,16)| \ + gF_((t)+(uly)*(dtdy)* \ + ((uly)<0)*((dtdy)<0?1:-1)/\ + 0x80,16,0)), \ + gsDPHalf2(gF_(dsdx,16,16)|gF_(dtdy,16,0)) +#define \ +gsSPTextureRectangleFlip(ulx,uly, \ + lrx,lry, \ + tile,s,t, \ + dsdx,dtdy) gsTexRectFlip(ulx,uly,lrx,lry,tile), \ + gsDPHalf1(gF_(s,16,16)|gF_(t,16,0)), \ + gsDPHalf2(gF_(dsdx,16,16)|gF_(dtdy,16,0)) +#define \ +gsSPScisTextureRectangleFlip(ulx, \ + uly, \ + lrx, \ + lry, \ + tile, \ + s,t, \ + dsdx, \ + dtdy) gsTexRectFlip((ulx)<0?0:(ulx), \ + (uly)<0?0:(uly), \ + (lrx)<0?0:(lrx), \ + (lry)<0?0:(lry), \ + tile), \ + gsDPHalf1(gF_((s)+(ulx)*(dsdx)* \ + ((ulx)<0)*((dsdx)<0?1:-1)/\ + 0x80,16,16)| \ + gF_((t)+(uly)*(dtdy)* \ + ((uly)<0)*((dtdy)<0?1:-1)/\ + 0x80,16,0)), \ + gsDPHalf2(gF_(dsdx,16,16)|gF_(dtdy,16,0)) +#define gsSPBgRectCopy(bg) gO_(G_BG_COPY,0,bg) +#define gsSPBgRect1Cyc(bg) gO_(G_BG_1CYC,0,bg) +#define gsSPObjRectangle(sp) gO_(G_OBJ_RECTANGLE,0,sp) +#define gsSPObjRectangleR(sp) gO_(G_OBJ_RECTANGLE_R,0,sp) +#define gsSPObjSprite(sp) gO_(G_OBJ_SPRITE,0,sp) +#define gsSPObjMatrix(mtx) gO_(G_OBJ_MOVEMEM, \ + gF_(sizeof(uObjMtx)-1,8,16),mtx) +#define gsSPObjSubMatrix(mtx) gO_(G_OBJ_MOVEMEM, \ + gF_(sizeof(uObjSubMtx)-1,8,16)| \ + gF_(2,16,0),mtx) +#define gsSPObjRenderMode(mode) gO_(G_OBJ_RENDERMODE,0,mode) +#define gsSPObjLoadTxtr(tx) gO_(G_OBJ_LOADTXTR,23,tx) +#define gsSPObjLoadTxRect(txsp) gO_(G_OBJ_LDTX_RECT,47,txsp) +#define gsSPObjLoadTxRectR(txsp) gO_(G_OBJ_LDTX_RECT_R,47,txsp) +#define gsSPObjLoadTxSprite(txsp) gO_(G_OBJ_LDTX_SPRITE,47,txsp) +#define gsSPSelectDL(ldl,sid,flag, \ + mask) gO_(G_RDPHALF_0, \ + gF_(sid,8,16)|gF_(ldl,16,0), \ + flag), \ + gO_(G_SELECT_DL,gF_(0x00,8,16)| \ + gF_(gI_(ldl)>>16,16,0),mask) +#define gsSPSelectBranchDL(bdl,sid, \ + flag,mask) gO_(G_RDPHALF_0, \ + gF_(sid,8,16)|gF_(bdl,16,0), \ + flag), \ + gO_(G_SELECT_DL,gF_(0x01,8,16)| \ + gF_(gI_(bdl)>>16,16,0),mask) + +/* unlisted instructions */ +#define gsDPLoadTLUTCmd(tile,count) gO_(G_LOADTLUT,0,gF_(tile,3,24)| \ + gF_(count,10,14)) +#define gsDPLoadTLUT(count,tmem,dram) gsDPSetTextureImage(G_IM_FMT_RGBA, \ + G_IM_SIZ_16b,1, \ + dram), \ + gsDPTileSync(), \ + gsDPSetTile(0,0,0,tmem,G_TX_LOADTILE,0, \ + 0,0,0,0,0,0), \ + gsDPLoadSync(), \ + gsDPLoadTLUTCmd(G_TX_LOADTILE, \ + (count)-1), \ + gsDPPipeSync() +#define gsDisplayList(dl,branch) gO_(G_DL,gF_(branch,8,16),dl) +#define gsDPLoadTile(tile,uls,ult, \ + lrs,lrt) gO_(G_LOADTILE, \ + gF_(uls,12,12)|gF_(ult,12,0), \ + gF_(tile,3,24)|gF_(lrs,12,12)| \ + gF_(lrt,12,0)) +#define gsDPSetCombine(c) gO_(G_SETCOMBINE, \ + (gL_(c)>>32)&0xFFFFFFFF, \ + (gL_(c)>>0)&0xFFFFFFFF) +#define gsSPSetOtherModeLo(shift, \ + length, \ + data) gsSPSetOtherMode(G_SETOTHERMODE_L, \ + shift,length,data) +#define gsSPSetOtherModeHi(shift, \ + length, \ + data) gsSPSetOtherMode(G_SETOTHERMODE_H, \ + shift,length,data) +#define \ +gsDPSetOtherMode(mode0,mode1) gO_(G_RDPSETOTHERMODE,gF_(mode0,24,0), \ + mode1) +#define \ +gsTexRect(ulx,uly,lrx,lry,tile) gO_(G_TEXRECT, \ + gF_(lrx,12,12)|gF_(lry,12,0), \ + gF_(tile,3,24)|gF_(ulx,12,12)| \ + gF_(uly,12,0)) +#define \ +gsTexRectFlip(ulx,uly,lrx,lry,tile) gO_(G_TEXRECTFLIP, \ + gF_(lrx,12,12)|gF_(lry,12,0), \ + gF_(tile,3,24)|gF_(ulx,12,12)| \ + gF_(uly,12,0)) +#define gsSPNoOp() gO_(G_SPNOOP,0,0) + +/* instruction macros for fast3d */ +#if defined(F3D_GBI) +# define gsSP1Triangle(v0,v1,v2,flag) gO_(G_TRI1,0,gF_(flag,8,24)| \ + gF_(gI_(v0)*10,8,16)| \ + gF_(gI_(v1)*10,8,8)| \ + gF_(gI_(v2)*10,8,0)) +# define gsSPCullDisplayList(v0,vn) gO_(G_CULLDL,((v0)&0xF)*40, \ + (((vn)+1)&0xF)*40) +# define gsSPLineW3D(v0,v1,wd,flag) gO_(G_LINE3D,0,gF_(flag,8,24)| \ + gF_(gI_(v0)*10,8,16)| \ + gF_(gI_(v1)*10,8,8)| \ + gF_(wd,8,0)) +# define gsSPModifyVertex(vtx,where,\ + val) gsMoveWd(G_MW_POINTS,(vtx)*40+(where), \ + val) +# define gsSPVertex(v,n,v0) gO_(G_VTX,gF_((n)-1,4,20)|gF_(v0,4,16)| \ + gF_(sizeof(Vtx)*(n),16,0),v) +#endif + +/* instruction macros for fast3d and f3dex */ +#if defined(F3D_GBI) || defined(F3DEX_GBI) +# define gsSPForceMatrix(mptr) gsMoveMem(16,G_MV_MATRIX_1, \ + (char*)(mptr)), \ + gsMoveMem(16,G_MV_MATRIX_2, \ + (char*)(mptr)+16), \ + gsMoveMem(16,G_MV_MATRIX_3, \ + (char*)(mptr)+32), \ + gsMoveMem(16,G_MV_MATRIX_4, \ + (char*)(mptr)+48) +# define gsSPSetGeometryMode(mode) gO_(G_SETGEOMETRYMODE,0,gI_(mode)) +# define gsSPClearGeometryMode(mode) gO_(G_CLEARGEOMETRYMODE,0,gI_(mode)) +# define gsSPLoadGeometryMode(mode) gsSPClearGeometryMode(~gI_(0)), \ + gsSPSetGeometryMode(mode) +# define gsSPInsertMatrix(where,num) gsMoveWd(G_MW_MATRIX,where,num) +# define gsSPLookAtX(l) gsMoveMem(sizeof(Light),G_MV_LOOKATX,l) +# define gsSPLookAtY(l) gsMoveMem(sizeof(Light),G_MV_LOOKATY,l) +# define gsSPMatrix(matrix,param) gO_(G_MTX,gF_(param,8,16)| \ + gF_(sizeof(Mtx),16,0),matrix) +# define gsSPPopMatrix(param) gO_(G_POPMTX,0,param) +# define gsSPLight(l,n) gsMoveMem(sizeof(Light), \ + G_MV_L0+((n)-1)*2,l) +# define gsSPTexture(sc,tc,level, \ + tile,on) gO_(G_TEXTURE, \ + gF_(level,3,11)|gF_(tile,3,8)| \ + gF_(on,8,0),gF_(sc,16,16)| \ + gF_(tc,16,0)) +# define gsSPViewport(v) gsMoveMem(sizeof(Vp),G_MV_VIEWPORT,v) +# define \ +gsSPSetOtherMode(opc,shift,length, \ + data) gO_(opc,gF_(shift,8,8)|gF_(length,8,0), \ + data) +# define gsMoveWd(index,offset,data) gO_(G_MOVEWORD,gF_(offset,16,8)| \ + gF_(index,8,0),data) +# define gsMoveMem(size,index, \ + address) gO_(G_MOVEMEM,gF_(index,8,16)| \ + gF_(size,16,0),address) +#endif + +/* instruction macros for f3dex */ +#if defined(F3DEX_GBI) +# define \ +gsSP1Quadrangle(v0,v1,v2,v3,flag) gO_(G_TRI2, \ + gF_(((flag)==0?gI_(v0): \ + (flag)==1?gI_(v1): \ + (flag)==2?gI_(v2): \ + gI_(v3))*2,8,16)| \ + gF_(((flag)==0?gI_(v1): \ + (flag)==1?gI_(v2): \ + (flag)==2?gI_(v3): \ + gI_(v0))*2,8,8)| \ + gF_(((flag)==0?gI_(v2): \ + (flag)==1?gI_(v3): \ + (flag)==2?gI_(v0): \ + gI_(v1))*2,8,0), \ + gF_(((flag)==0?gI_(v0): \ + (flag)==1?gI_(v1): \ + (flag)==2?gI_(v2): \ + gI_(v3))*2,8,16)| \ + gF_(((flag)==0?gI_(v2): \ + (flag)==1?gI_(v3): \ + (flag)==2?gI_(v0): \ + gI_(v1))*2,8,8)| \ + gF_(((flag)==0?gI_(v3): \ + (flag)==1?gI_(v0): \ + (flag)==2?gI_(v1): \ + gI_(v2))*2,8,0)) +# define gsSPVertex(v,n,v0) gO_(G_VTX,gF_((v0)*2,8,16)|gF_(n,6,10)| \ + gF_(sizeof(Vtx)*(n)-1,10,0),v) +#endif + +/* instruction macros for f3dex and f3dex2 */ +#if defined(F3DEX_GBI) || defined(F3DEX_GBI_2) +# define gsSP1Triangle(v0,v1,v2,flag) gO_(G_TRI1, \ + gF_(((flag)==0?gI_(v0): \ + (flag)==1?gI_(v1): \ + gI_(v2))*2,8,16)| \ + gF_(((flag)==0?gI_(v1): \ + (flag)==1?gI_(v2): \ + gI_(v0))*2,8,8)| \ + gF_(((flag)==0?gI_(v2): \ + (flag)==1?gI_(v0): \ + gI_(v1))*2,8,0),0) +# define \ +gsSP2Triangles(v00,v01,v02,flag0, \ + v10,v11,v12,flag1) gO_(G_TRI2, \ + gF_(((flag0)==0?gI_(v00): \ + (flag0)==1?gI_(v01): \ + gI_(v02))*2,8,16)| \ + gF_(((flag0)==0?gI_(v01): \ + (flag0)==1?gI_(v02): \ + gI_(v00))*2,8,8)| \ + gF_(((flag0)==0?gI_(v02): \ + (flag0)==1?gI_(v00): \ + gI_(v01))*2,8,0), \ + gF_(((flag1)==0?gI_(v10): \ + (flag1)==1?gI_(v11): \ + gI_(v12))*2,8,16)| \ + gF_(((flag1)==0?gI_(v11): \ + (flag1)==1?gI_(v12): \ + gI_(v10))*2,8,8)| \ + gF_(((flag1)==0?gI_(v12): \ + (flag1)==1?gI_(v10): \ + gI_(v11))*2,8,0)) +# define \ +gsSPBranchLessZ(branchdl,vtx,zval, \ + near,far,flag) gsSPBranchLessZrg(branchdl,vtx,zval, \ + near,far,flag,0,0x3FF) +# define \ +gsSPBranchLessZrg(branchdl,vtx, \ + zval,near,far, \ + flag,zmin,zmax) gsDPHalf1(branchdl), \ + gsBranchZ(vtx,zval,near,far,flag, \ + zmin,zmax) +# define gsSPCullDisplayList(v0,vn) gO_(G_CULLDL,gF_((v0)*2,16,0), \ + gF_((vn)*2,16,0)) +# define gsSPLineW3D(v0,v1,wd,flag) gO_(G_LINE3D, \ + gF_(((flag)==0?gI_(v0): \ + gI_(v1))*2,8,16)| \ + gF_(((flag)==0?gI_(v1): \ + gI_(v0))*2,8,8)| \ + gF_(wd,8,0),0) +# define gsSPLoadUcode(uc_start, \ + uc_dstart) gsSPLoadUcodeEx(uc_start,uc_dstart,0x800) +# define gsSPModifyVertex(vtx,where,\ + val) gO_(G_MODIFYVTX,gF_(where,8,16)| \ + gF_((vtx)*2,16,0),val) +# define gsBranchZ(vtx,zval, \ + near,far, \ + flag,zmin,zmax) gO_(G_BRANCH_Z,gF_((vtx)*5,12,12)| \ + gF_((vtx)*2,12,0), \ + qs1616((flag)==G_BZ_PERSP? \ + (1.f-(float)(near)/ \ + (float)(zval))/ \ + (1.f-(float)(near)/ \ + (float)(far)): \ + ((float)(zval)- \ + (float)(near))/ \ + ((float)(far)- \ + (float)(near)))* \ + ((int32_t)((zmax)-(zmin))&~1)+ \ + qs1616(zmin)) +# define \ +gsLoadUcode(uc_start,uc_dsize) gO_(G_LOAD_UCODE, \ + gF_((uc_dsize)-1,16,0),uc_start) +# define \ +gsSPLoadUcodeEx(uc_start,uc_dstart, \ + uc_dsize) gsDPHalf1(uc_dstart), \ + gsLoadUcode(uc_start,uc_dsize) +#endif + +/* instruction macros for f3dex2 */ +#if defined(F3DEX_GBI_2) +# define \ +gsSP1Quadrangle(v0,v1,v2,v3,flag) gO_(G_QUAD, \ + gF_(((flag)==0?gI_(v0): \ + (flag)==1?gI_(v1): \ + (flag)==2?gI_(v2): \ + gI_(v3))*2,8,16)| \ + gF_(((flag)==0?gI_(v1): \ + (flag)==1?gI_(v2): \ + (flag)==2?gI_(v3): \ + gI_(v0))*2,8,8)| \ + gF_(((flag)==0?gI_(v2): \ + (flag)==1?gI_(v3): \ + (flag)==2?gI_(v0): \ + gI_(v1))*2,8,0), \ + gF_(((flag)==0?gI_(v0): \ + (flag)==1?gI_(v1): \ + (flag)==2?gI_(v2): \ + gI_(v3))*2,8,16)| \ + gF_(((flag)==0?gI_(v2): \ + (flag)==1?gI_(v3): \ + (flag)==2?gI_(v0): \ + gI_(v1))*2,8,8)| \ + gF_(((flag)==0?gI_(v3): \ + (flag)==1?gI_(v0): \ + (flag)==2?gI_(v1): \ + gI_(v2))*2,8,0)) +# define gsSPForceMatrix(mptr) gsMoveMem(sizeof(Mtx),G_MV_MATRIX,0, \ + mptr), \ + gsMoveWd(G_MW_FORCEMTX,0,0x10000) +# define gsSPSetGeometryMode(mode) gsSPGeometryMode(0,mode) +# define gsSPClearGeometryMode(mode) gsSPGeometryMode(mode,0) +# define gsSPLoadGeometryMode(mode) gsSPGeometryMode(~gI_(0),mode) +# define gsSPLookAtX(l) gsMoveMem(sizeof(Light),G_MV_LIGHT, \ + G_MVO_LOOKATX,l) +# define gsSPLookAtY(l) gsMoveMem(sizeof(Light),G_MV_LIGHT, \ + G_MVO_LOOKATY,l) +# define gsSPMatrix(matrix,param) gO_(G_MTX,gF_((sizeof(Mtx)-1)/8,5,19)| \ + gF_(gI_(param)^G_MTX_PUSH,8,0), \ + matrix) +# define gsSPPopMatrix(param) gsSPPopMatrixN(param,1) +# define gsSPPopMatrixN(param,n) gO_(G_POPMTX, \ + gF_((sizeof(Mtx)-1)/8,5,19)| \ + gF_(2,8,0),sizeof(Mtx)*(n)) +# define gsSPLight(l,n) gsMoveMem(sizeof(Light),G_MV_LIGHT, \ + ((n)+1)*0x18,l) +# define gsSPTexture(sc,tc,level, \ + tile,on) gO_(G_TEXTURE, \ + gF_(level,3,11)|gF_(tile,3,8)| \ + gF_(on,7,1),gF_(sc,16,16)| \ + gF_(tc,16,0)) +# define gsSPVertex(v,n,v0) gO_(G_VTX,gF_(n,8,12)|gF_((v0)+(n),7,1),v) +# define gsSPViewport(v) gsMoveMem(sizeof(Vp),G_MV_VIEWPORT,0,v) +# define gsSPGeometryMode(clearbits,\ + setbits) gO_(G_GEOMETRYMODE, \ + gF_(~gI_(clearbits),24,0),setbits) +# define \ +gsSPSetOtherMode(opc,shift,length, \ + data) gO_(opc, \ + gF_(32-(shift)-(length),8,8)| \ + gF_((length)-1,8,0),data) +# define gsMoveWd(index,offset,data) gO_(G_MOVEWORD,gF_(index,8,16)| \ + gF_(offset,16,0),data) +# define gsMoveMem(size,index, \ + offset,address) gO_(G_MOVEMEM,gF_((size-1)/8,5,19)| \ + gF_((offset)/8,8,8)| \ + gF_(index,8,0),address) +# define \ +gsSPDma_io(flag,dmem,dram,size) gO_(G_DMA_IO,gF_(flag,1,23)| \ + gF_((dmem)/8,10,13)| \ + gF_((size)-1,12,0),dram) +# define gsSPDmaRead(dmem,dram,size) gsSPDma_io(0,dmem,dram,size) +# define gsSPDmaWrite(dmem,dram,size) gsSPDma_io(1,dmem,dram,size) +# define gsSpecial3(hi,lo) gO_(G_SPECIAL_3,hi,lo) +# define gsSpecial2(hi,lo) gO_(G_SPECIAL_2,hi,lo) +# define gsSpecial1(hi,lo) gO_(G_SPECIAL_1,hi,lo) +#endif + +/* instruction macros for beta fast3d and f3dex */ +#if defined(F3D_BETA) && (defined(F3D_GBI) || defined(F3DEX_GBI)) +# define gsSPPerspNormalize(scale) gO_(G_PERSPNORM,0,scale) +# define gsDPHalf1(wordhi) gO_(G_RDPHALF_2,0,wordhi) +# define gsDPHalf2(wordlo) gO_(G_RDPHALF_CONT,0,wordlo) +#else +# define gsSPPerspNormalize(scale) gsMoveWd(G_MW_PERSPNORM,0,scale) +# define gsDPHalf1(wordhi) gO_(G_RDPHALF_1,0,wordhi) +# define gsDPHalf2(wordlo) gO_(G_RDPHALF_2,0,wordlo) +#endif + +/* dynamic instruction macros */ +#define gDisplayListPut(gdl,...) ({Gfx Gdl__[]={__VA_ARGS__}; \ + for(size_t Gi__=0;Gi__ +#include "thread.h" + +#define OS_NUM_EVENTS 15 + +#define OS_EVENT_SW1 0 +#define OS_EVENT_SW2 1 +#define OS_EVENT_CART 2 +#define OS_EVENT_COUNTER 3 +#define OS_EVENT_SP 4 +#define OS_EVENT_SI 5 +#define OS_EVENT_AI 6 +#define OS_EVENT_VI 7 +#define OS_EVENT_PI 8 +#define OS_EVENT_DP 9 +#define OS_EVENT_CPU_BREAK 10 +#define OS_EVENT_SP_BREAK 11 +#define OS_EVENT_FAULT 12 +#define OS_EVENT_THREADSTATUS 13 +#define OS_EVENT_PRENMI 14 + +#define OS_MESG_NOBLOCK 0 +#define OS_MESG_BLOCK 1 + +#define MQ_GET_COUNT(mq) ((mq)->validCount) +#define MQ_IS_EMPTY(mq) (MQ_GET_COUNT(mq)==0) +#define MQ_IS_FULL(mq) (MQ_GET_COUNT(mq)>=(mq)->msgCount) + +typedef uint32_t OSEvent; +typedef void *OSMesg; + +typedef struct +{ + OSThread *mtqueue; /* 0x0000 */ + OSThread *fullqueue; /* 0x0004 */ + int32_t validCount; /* 0x0008 */ + int32_t first; /* 0x000C */ + int32_t msgCount; /* 0x0010 */ + OSMesg *msg; /* 0x0014 */ + /* 0x0018 */ +} OSMesgQueue; + +typedef void (*osCreateMesgQueue_t)(OSMesgQueue*, OSMesg*, int32_t); +typedef int32_t (*osSendMesg_t) (OSMesgQueue*, OSMesg, int32_t); +typedef int32_t (*osJamMesg_t) (OSMesgQueue*, OSMesg, int32_t); +typedef int32_t (*osRecvMesg_t) (OSMesgQueue*, OSMesg*, int32_t); +typedef void (*osSetEventMesg_t) (OSEvent, OSMesgQueue*, OSMesg); + +#endif diff --git a/tools/gfxdis/include/n64/pi.h b/tools/gfxdis/include/n64/pi.h new file mode 100644 index 00000000..3235773a --- /dev/null +++ b/tools/gfxdis/include/n64/pi.h @@ -0,0 +1,109 @@ +#ifndef N64_PI_H +#define N64_PI_H + +#include + +#define PI_STATUS_DMA_BUSY 0x01 +#define PI_STATUS_IO_BUSY 0x02 +#define PI_STATUS_ERROR 0x04 +#define PI_STATUS_RESET 0x01 +#define PI_STATUS_CLR_INTR 0x02 + +#define DEVICE_TYPE_CART 0 +#define DEVICE_TYPE_BULK 1 +#define DEVICE_TYPE_64DD 2 +#define DEVICE_TYPE_SRAM 3 +#define DEVICE_TYPE_INIT 7 + +#define PI_DOMAIN1 0 +#define PI_DOMAIN2 1 + +#define OS_MESG_TYPE_LOOPBACK 10 +#define OS_MESG_TYPE_DMAREAD 11 +#define OS_MESG_TYPE_DMAWRITE 12 +#define OS_MESG_TYPE_VRETRACE 13 +#define OS_MESG_TYPE_COUNTER 14 +#define OS_MESG_TYPE_EDMAREAD 15 +#define OS_MESG_TYPE_EDMAWRITE 16 + +#define OS_MESG_PRI_NORMAL 0 +#define OS_MESG_PRI_HIGH 1 + +#define OS_READ 0 +#define OS_WRITE 1 +#define OS_OTHERS 2 + +typedef struct +{ + uint32_t dram_addr; /* 0x0000 */ + uint32_t cart_addr; /* 0x0004 */ + uint32_t rd_len; /* 0x0008 */ + uint32_t wr_len; /* 0x000C */ + uint32_t status; /* 0x0010 */ + /* 0x0014 */ +} pi_regs_t; + +typedef struct +{ + uint32_t errStatus; /* 0x0000 */ + void *dramAddr; /* 0x0004 */ + void *C2Addr; /* 0x0008 */ + uint32_t sectorSize; /* 0x000C */ + uint32_t C1ErrNum; /* 0x0010 */ + uint32_t C1ErrSector[4]; /* 0x0014 */ + /* 0x0024 */ +} __OSBlockInfo; + +typedef struct +{ + uint32_t cmdType; /* 0x0000 */ + uint16_t transferMode; /* 0x0004 */ + uint16_t blockNum; /* 0x0006 */ + int32_t sectorNum; /* 0x0008 */ + uint32_t devAddr; /* 0x000C */ + uint32_t bmCtlShadow; /* 0x0010 */ + uint32_t seqCtlShadow; /* 0x0014 */ + __OSBlockInfo block[2]; /* 0x0018 */ + /* 0x0060 */ +} __OSTranxInfo; + +typedef struct OSPiHandle_s OSPiHandle; +struct OSPiHandle_s +{ + OSPiHandle *next; /* 0x0000 */ + uint8_t type; /* 0x0004 */ + uint8_t latency; /* 0x0005 */ + uint8_t pageSize; /* 0x0006 */ + uint8_t relDuration; /* 0x0007 */ + uint8_t pulse; /* 0x0008 */ + uint8_t domain; /* 0x0009 */ + uint32_t baseAddress; /* 0x000C */ + uint32_t speed; /* 0x0010 */ + __OSTranxInfo transferInfo; /* 0x0014 */ + /* 0x0074 */ +}; + +typedef struct +{ + uint16_t type; /* 0x0000 */ + uint8_t pri; /* 0x0002 */ + uint8_t status; /* 0x0003 */ + OSMesgQueue *retQueue; /* 0x0004 */ + /* 0x0008 */ +} OSIoMesgHdr; + +typedef struct +{ + OSIoMesgHdr hdr; /* 0x0000 */ + void *dramAddr; /* 0x0008 */ + uint32_t devAddr; /* 0x000C */ + uint32_t size; /* 0x0010 */ + OSPiHandle *piHandle; /* 0x0014 */ + /* 0x0018 */ +} OSIoMesg; + +typedef int32_t (*osEPiStartDma_t)(OSPiHandle*, OSIoMesg*, int32_t); + +#define pi_regs (*(volatile pi_regs_t*)0xA4600000) + +#endif diff --git a/tools/gfxdis/include/n64/task.h b/tools/gfxdis/include/n64/task.h new file mode 100644 index 00000000..13fb53b3 --- /dev/null +++ b/tools/gfxdis/include/n64/task.h @@ -0,0 +1,43 @@ +#ifndef N64_TASK_H +#define N64_TASK_H + +#include +#include "message.h" + +typedef struct +{ + _Alignas(8) + uint32_t type; /* 0x0000 */ + uint32_t flags; /* 0x0004 */ + uint64_t *ucode_boot; /* 0x0008 */ + uint32_t ucode_boot_size; /* 0x000C */ + uint64_t *ucode; /* 0x0010 */ + uint32_t ucode_size; /* 0x0014 */ + uint64_t *ucode_data; /* 0x0018 */ + uint32_t ucode_data_size; /* 0x001C */ + uint64_t *dram_stack; /* 0x0020 */ + uint32_t dram_stack_size; /* 0x0024 */ + uint64_t *output_buff; /* 0x0028 */ + uint64_t *output_buff_size; /* 0x002C */ + uint64_t *data_ptr; /* 0x0030 */ + uint32_t data_size; /* 0x0034 */ + uint64_t *yield_data_ptr; /* 0x0038 */ + uint32_t yield_data_size; /* 0x003C */ + /* 0x0040 */ +} OSTask; + +typedef struct OSScTask_s OSScTask; + +struct OSScTask_s +{ + OSScTask *next; /* 0x0000 */ + uint32_t state; /* 0x0004 */ + uint32_t flags; /* 0x0008 */ + void *framebuffer; /* 0x000C */ + OSTask list; /* 0x0010 */ + OSMesgQueue *msgQ; /* 0x0050 */ + OSMesg msg; /* 0x0054 */ + /* 0x0058 */ +}; + +#endif diff --git a/tools/gfxdis/include/n64/thread.h b/tools/gfxdis/include/n64/thread.h new file mode 100644 index 00000000..cc039157 --- /dev/null +++ b/tools/gfxdis/include/n64/thread.h @@ -0,0 +1,66 @@ +#ifndef N64_THREAD_H +#define N64_THREAD_H + +#include + +#define OS_STATE_STOPPED 1 +#define OS_STATE_RUNNABLE 2 +#define OS_STATE_RUNNING 4 +#define OS_STATE_WAITING 8 + +#define OS_PRIORITY_IDLE 0 +#define OS_PRIORITY_APPMAX 127 +#define OS_PRIORITY_SIMGR 140 +#define OS_PRIORITY_PIMGR 150 +#define OS_PRIORITY_RMONSPIN 200 +#define OS_PRIORITY_RMON 250 +#define OS_PRIORITY_VIMGR 254 +#define OS_PRIORITY_MAX 255 + +typedef int32_t OSPri; +typedef int32_t OSId; + +typedef struct +{ + uint64_t at, v0, v1, a0, a1, a2, a3, + t0, t1, t2, t3, t4, t5, t6, t7, + s0, s1, s2, s3, s4, s5, s6, s7, + t8, t9, gp, sp, s8, ra, lo, hi; + uint32_t sr, pc, cause, badvaddr, rcp; + uint32_t fpcsr; + union + { + float fp32[32]; + double fp64[16]; + }; + /* 0x01D8 */ +} __OSThreadContext; + +typedef struct OSThread_s OSThread; +struct OSThread_s +{ + OSThread *next; /* 0x0000 */ + OSPri priority; /* 0x0004 */ + OSThread **queue; /* 0x0008 */ + OSThread *tlnext; /* 0x000C */ + uint16_t state; /* 0x0010 */ + uint16_t flags; /* 0x0012 */ + OSId id; /* 0x0014 */ + int32_t fp; /* 0x0018 */ + __OSThreadContext context; /* 0x001C */ + /* 0x01F4 */ +}; + +typedef void (*osCreateThread_t) (OSThread*, OSId, void(*)(void*), + void*, void*, OSPri); +typedef void (*osDestroyThread_t) (OSThread*); +typedef void (*osYieldThread_t) (void); +typedef void (*osStartThread_t) (OSThread*); +typedef void (*osStopThread_t) (OSThread*); +typedef OSId (*osGetThreadId_t) (OSThread*); +typedef void (*osSetThreadPri_t) (OSThread*, OSPri); +typedef OSPri (*osGetThreadPri_t) (OSThread*); +typedef OSThread *(*osGetCurrFaultedThread_t) (void); +typedef OSThread *(*osGetNextFaultedThread_t) (OSThread*); + +#endif diff --git a/tools/gfxdis/include/n64/vr4300.h b/tools/gfxdis/include/n64/vr4300.h new file mode 100644 index 00000000..b81463ed --- /dev/null +++ b/tools/gfxdis/include/n64/vr4300.h @@ -0,0 +1,7 @@ +#ifndef N64_VR4300_H +#define N64_VR4300_H + +#define OS_CLOCK_RATE 62500000 +#define OS_CPU_COUNTER 46875000 + +#endif diff --git a/tools/gfxdis/include/set/set.c b/tools/gfxdis/include/set/set.c new file mode 100644 index 00000000..4304f6a7 --- /dev/null +++ b/tools/gfxdis/include/set/set.c @@ -0,0 +1,154 @@ +/* set.c + * -glank + */ + +#include +#include +#include "set.h" + +#define MAX_ALIGN(N) (((N) + _Alignof(max_align_t) - 1) & \ + ~(_Alignof(max_align_t) - 1)) + +#ifdef __cplusplus +extern "C" +{ +#endif + +static size_t set_locate(const struct set *set, void *value, _Bool *match) +{ + if (set->container.size == 0) { + *match = 0; + return 0; + } + size_t left = 0; + size_t right = set->container.size - 1; + size_t position = 0; + while (left <= right) { + position = (left + right) / 2; + void *element_value = vector_at(&set->container, position); + if (set->comparator(element_value, value)) { + ++position; + left = position; + } + else if (set->comparator(value, element_value)) { + if (position == 0) + break; + right = position - 1; + } + else { + *match = 1; + return position; + } + } + *match = 0; + return position; +} + +void set_init(struct set *set, size_t value_size, + _Bool (*comparator)(void *a, void *b)) +{ + set->comparator = comparator; + vector_init(&set->container, value_size); +} + +void set_destroy(struct set *set) +{ + vector_destroy(&set->container); +} + +void *set_insert(struct set *set, void *value) +{ + _Bool match; + size_t position = set_locate(set, value, &match); + if (match) { + void *old_value = vector_at(&set->container, position); + memcpy(old_value, value, set->container.element_size); + return old_value; + } + return vector_insert(&set->container, position, 1, value); +} + +void *set_put(struct set *set, void *value) +{ + _Bool match; + size_t position = set_locate(set, value, &match); + if (match) + return NULL; + return vector_insert(&set->container, position, 1, value); +} + +void set_erase(struct set *set, void *value) +{ + _Bool match; + size_t position = set_locate(set, value, &match); + if (match) + vector_erase(&set->container, position, 1); +} + +void *set_get(const struct set *set, void *value) +{ + _Bool match; + size_t position = set_locate(set, value, &match); + if (!match) + return NULL; + return vector_at(&set->container, position); +} + +void *set_at(const struct set *set, size_t position) +{ + return vector_at(&set->container, position); +} + +void set_union(struct set *a, const struct set *b) +{ + for (size_t i = 0; i < b->container.size; ++i) { + void *value = vector_at(&b->container, i); + _Bool match; + size_t position = set_locate(a, value, &match); + if (!match) + vector_insert(&a->container, position, 1, value); + } +} + +void set_intersection(struct set *a, const struct set *b) +{ + for (size_t i = 0; i < a->container.size; ) { + void *value = vector_at(&a->container, i); + _Bool match; + set_locate(b, value, &match); + if (!match) + vector_erase(&a->container, i, 1); + else + ++i; + } +} + +void set_difference(struct set *a, const struct set *b) +{ + for (size_t i = 0; i < a->container.size; ) { + void *value = vector_at(&a->container, i); + _Bool match; + set_locate(b, value, &match); + if (match) + vector_erase(&a->container, i, 1); + else + ++i; + } +} + +void set_symmetric_difference(struct set *a, const struct set *b) +{ + for (size_t i = 0; i < b->container.size; ++i) { + void *value = vector_at(&b->container, i); + _Bool match; + size_t position = set_locate(a, value, &match); + if (match) + vector_erase(&a->container, position, 1); + else + vector_insert(&a->container, position, 1, value); + } +} + +#ifdef __cplusplus +} +#endif diff --git a/tools/gfxdis/include/set/set.h b/tools/gfxdis/include/set/set.h new file mode 100644 index 00000000..993fe01e --- /dev/null +++ b/tools/gfxdis/include/set/set.h @@ -0,0 +1,38 @@ +/* set.h + * -glank + */ + +#ifndef SET_H +#define SET_H +#include +#include + +struct set +{ + _Bool (*comparator)(void *a, void *b); + struct vector container; +}; + +#ifdef __cplusplus +extern "C" +{ +#endif + +void set_init(struct set *set, size_t value_size, + _Bool (*comparator)(void *a, void *b)); +void set_destroy(struct set *set); +void *set_insert(struct set *set, void *value); +void *set_put(struct set *set, void *value); +void set_erase(struct set *set, void *value); +void *set_get(const struct set *set, void *value); +void *set_at(const struct set *set, size_t position); +void set_union(struct set *a, const struct set *b); +void set_intersection(struct set *a, const struct set *b); +void set_difference(struct set *a, const struct set *b); +void set_symmetric_difference(struct set *a, const struct set *b); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/tools/gfxdis/include/startup.c b/tools/gfxdis/include/startup.c new file mode 100644 index 00000000..0bdfbd86 --- /dev/null +++ b/tools/gfxdis/include/startup.c @@ -0,0 +1,59 @@ +/* startup.c + * -glank + */ + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +#ifndef NO_STARTUP_LISTS +static __attribute__((section(".ctor_i"), used)) int32_t ctor_i = -1; +static __attribute__((section(".ctor_n"), used)) int32_t ctor_n = 0; +static __attribute__((section(".dtor_i"), used)) int32_t dtor_i = -1; +static __attribute__((section(".dtor_n"), used)) int32_t dtor_n = 0; +#endif + +extern __attribute__((section(".bss"))) void *__bss_end; +extern __attribute__((section(".bss"))) void *__bss_start; + +extern void (*__CTOR_LIST__[])(void); +extern void (*__DTOR_LIST__[])(void); + +void clear_bss(void) +{ + char *p = (char*)&__bss_start; + char *e = (char*)&__bss_end; + while (p < e) + *p++ = 0; +} + +void do_global_ctors(void) +{ + static _Bool global_ctors_done; + if (global_ctors_done) + return; + int32_t i = (int32_t)__CTOR_LIST__[0]; + if (i == -1) + for (i = 0; __CTOR_LIST__[i + 1]; ++i) + ; + while (i > 0) + __CTOR_LIST__[i--](); + global_ctors_done = 1; +} + +void do_global_dtors(void) +{ + static _Bool global_dtors_done; + if (global_dtors_done) + return; + for (void (**dtor)(void) = &__DTOR_LIST__[1]; *dtor; ++dtor) + (*dtor)(); + global_dtors_done = 1; +} + +#ifdef __cplusplus +} +#endif diff --git a/tools/gfxdis/include/startup.h b/tools/gfxdis/include/startup.h new file mode 100644 index 00000000..c808d7e3 --- /dev/null +++ b/tools/gfxdis/include/startup.h @@ -0,0 +1,34 @@ +/* startup.h + * -glank + */ + +#ifndef STARTUP_H +#define STARTUP_H + +#ifdef __cplusplus +#define ENTRY extern "C" __attribute__((section(".text.startup"))) +#define HOOK extern "C" __attribute__((section(".text.hook"), used)) +extern "C" +{ +#else +#define ENTRY __attribute__((section(".text.startup"))) +#define HOOK __attribute__((section(".text.hook"), used)) +#endif + +void clear_bss(void); +void do_global_ctors(void); +void do_global_dtors(void); + +#ifdef __cplusplus +} +#endif + +static inline void init_gp(void) +{ + __asm__ volatile("la $gp, _gp;"); +} + +#define CTOR __attribute__((constructor)) +#define DTOR __attribute__((destructor)) + +#endif diff --git a/tools/gfxdis/include/vector/vector.c b/tools/gfxdis/include/vector/vector.c new file mode 100644 index 00000000..7085afd8 --- /dev/null +++ b/tools/gfxdis/include/vector/vector.c @@ -0,0 +1,155 @@ +/* vector.c + * -glank + */ + +#include +#include +#include "vector.h" + + +#ifdef __cplusplus +extern "C" +{ +#endif + +void vector_init(struct vector *vector, size_t element_size) +{ + vector->element_size = element_size; + vector->size = 0; + vector->capacity = 0; + vector->begin = 0; + vector->end = 0; + vector->rbegin = 0; + vector->rend = 0; +} + +void *vector_at(const struct vector *vector, size_t position) +{ + if (!vector->begin || position >= vector->size) + return 0; + return (char*)vector->begin + vector->element_size * position; +} + +int vector_reserve(struct vector *vector, size_t num) +{ + size_t new_cap = vector->size + num; + if (new_cap <= vector->capacity) + return 1; + char *new_data = (char*)realloc(vector->begin, vector->element_size * new_cap); + if (!new_data) + return 0; + vector->begin = new_data; + vector->rend = new_data - vector->element_size; + vector->end = (char*)vector->begin + vector->element_size * vector->size; + vector->rbegin = (char*)vector->end - vector->element_size; + vector->capacity = new_cap; + return 1; +} + +void *vector_insert(struct vector *vector, size_t position, size_t num, + const void *data) +{ + if (num == 0) { + if (vector->begin) + return vector->begin; + else + return (void*)1; + } + if (position > vector->size) + return 0; + size_t new_cap = vector->capacity; + if (new_cap == 0) + new_cap = num; + else { + if (new_cap < vector->size + num) + new_cap *= 2; + if (new_cap < vector->size + num) + new_cap = vector->size + num; + } + if (new_cap != vector->capacity) { + char *new_data = (char*)realloc(vector->begin, + vector->element_size * new_cap); + if (!new_data) + return 0; + vector->begin = new_data; + vector->rend = new_data - vector->element_size; + vector->capacity = new_cap; + } + memmove((char*)vector->begin + vector->element_size * (position + num), + (char*)vector->begin + vector->element_size * position, + vector->element_size * (vector->size - position)); + if (data) + memcpy((char*)vector->begin + vector->element_size * position, data, + vector->element_size * num); + vector->size += num; + vector->end = (char*)vector->begin + vector->element_size * vector->size; + vector->rbegin = (char*)vector->end - vector->element_size; + return (char*)vector->begin + vector->element_size * position; +} + +void *vector_push_back(struct vector *vector, size_t num, const void *data) +{ + return vector_insert(vector, vector->size, num, data); +} + +int vector_erase(struct vector *vector, size_t position, size_t num) +{ + if (!vector->begin || num > vector->size || position >= vector->size) + return 0; + if (num == vector->size) { + vector_clear(vector); + return 1; + } + memmove((char*)vector->begin + vector->element_size * position, + (char*)vector->begin + vector->element_size * (position + num), + vector->element_size * (vector->size - position - num)); + vector->size -= num; + vector->end = (char*)vector->begin + vector->element_size * vector->size; + vector->rbegin = (char*)vector->end - vector->element_size; + return 1; +} + +int vector_shrink_to_fit(struct vector *vector) +{ + size_t new_cap = vector->size; + char *new_data = (char*)realloc(vector->begin, + vector->element_size * new_cap); + if (new_cap > 0 && !new_data) + return 0; + vector->begin = new_data; + vector->rend = new_data - vector->element_size; + vector->end = (char*)vector->begin + vector->element_size * vector->size; + vector->rbegin = (char*)vector->end - vector->element_size; + vector->capacity = new_cap; + return 1; +} + +void *vector_release(struct vector *vector) +{ + void *data = vector->begin; + vector->size = 0; + vector->capacity = 0; + vector->begin = 0; + vector->end = 0; + vector->rbegin = 0; + vector->rend = 0; + return data; +} + +void vector_clear(struct vector *vector) +{ + vector->size = 0; + vector->end = vector->begin; + vector->rbegin = vector->begin; + vector->rend = vector->begin; +} + +void vector_destroy(struct vector *vector) +{ + if (vector->begin) + free(vector->begin); +} + +#ifdef __cplusplus +} +#endif diff --git a/tools/gfxdis/include/vector/vector.h b/tools/gfxdis/include/vector/vector.h new file mode 100644 index 00000000..1ff674e0 --- /dev/null +++ b/tools/gfxdis/include/vector/vector.h @@ -0,0 +1,37 @@ +/* vector.h + * -glank + */ + +#ifndef VECTOR_H +#define VECTOR_H +#include + +struct vector +{ + size_t element_size, size, capacity; + void *begin, *end; + void *rbegin, *rend; +}; + +#ifdef __cplusplus +extern "C" +{ +#endif + +void vector_init(struct vector *vector, size_t element_size); +void *vector_at(const struct vector *vector, size_t position); +int vector_reserve(struct vector *vector, size_t num); +void *vector_insert(struct vector *vector, size_t position, size_t num, + const void *data); +void *vector_push_back(struct vector *vector, size_t num, const void *data); +int vector_erase(struct vector *vector, size_t position, size_t num); +int vector_shrink_to_fit(struct vector *vector); +void *vector_release(struct vector *vector); +void vector_clear(struct vector *vector); +void vector_destroy(struct vector *vector); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/tools/gfxdis/include/vr4300.c b/tools/gfxdis/include/vr4300.c new file mode 100644 index 00000000..2b619a78 --- /dev/null +++ b/tools/gfxdis/include/vr4300.c @@ -0,0 +1,1043 @@ +#include +#include +#include +#include "vr4300.h" + +const char *vr4300_reg_mnem[] = +{ + "$r0", + "$at", + "$v0", + "$v1", + "$a0", + "$a1", + "$a2", + "$a3", + "$t0", + "$t1", + "$t2", + "$t3", + "$t4", + "$t5", + "$t6", + "$t7", + "$s0", + "$s1", + "$s2", + "$s3", + "$s4", + "$s5", + "$s6", + "$s7", + "$t8", + "$t9", + "$k0", + "$k1", + "$gp", + "$sp", + "$s8", + "$ra", + "$index", + "$random", + "$entrylo0", + "$entrylo1", + "$context", + "$pagemask", + "$wired", + "$7", + "$badvaddr", + "$count", + "$entryhi", + "$compare", + "$sr", + "$cause", + "$epc", + "$prid", + "$config", + "$lladdr", + "$watchlo", + "$watchhi", + "$xcontext", + "$21", + "$22", + "$23", + "$24", + "$25", + "$ecc", + "$cacheerr", + "$taglo", + "$taghi", + "$errorepc", + "$31", + "$f0", + "$f1", + "$f2", + "$f3", + "$f4", + "$f5", + "$f6", + "$f7", + "$f8", + "$f9", + "$f10", + "$f11", + "$f12", + "$f13", + "$f14", + "$f15", + "$f16", + "$f17", + "$f18", + "$f19", + "$f20", + "$f21", + "$f22", + "$f23", + "$f24", + "$f25", + "$f26", + "$f27", + "$f28", + "$f29", + "$f30", + "$f31", + "$fcr0", + "$fcr1", + "$fcr2", + "$fcr3", + "$fcr4", + "$fcr5", + "$fcr6", + "$fcr7", + "$fcr8", + "$fcr9", + "$fcr10", + "$fcr11", + "$fcr12", + "$fcr13", + "$fcr14", + "$fcr15", + "$fcr16", + "$fcr17", + "$fcr18", + "$fcr19", + "$fcr20", + "$fcr21", + "$fcr22", + "$fcr23", + "$fcr24", + "$fcr25", + "$fcr26", + "$fcr27", + "$fcr28", + "$fcr29", + "$fcr30", + "$fcr31", + "$lo", + "$hi", + "$cc", +}; + +const char *vr4300_op_mnem[] = +{ + "abs.d", + "abs.s", + "add", + "add.d", + "addi", + "addiu", + "add.s", + "addu", + "and", + "andi", + "bc1f", + "bc1fl", + "bc1t", + "bc1tl", + "beq", + "beql", + "bgez", + "bgezal", + "bgezall", + "bgezl", + "bgtz", + "bgtzl", + "blez", + "blezl", + "bltz", + "bltzal", + "bltzall", + "bltzl", + "bne", + "bnel", + "break", + "cache", + "ceil.l.d", + "ceil.l.s", + "ceil.w.d", + "ceil.w.s", + "c.eq.d", + "c.eq.s", + "cfc1", + "c.f.d", + "c.f.s", + "c.le.d", + "c.le.s", + "c.lt.d", + "c.lt.s", + "c.nge.d", + "c.nge.s", + "c.ngl.d", + "c.ngle.d", + "c.ngle.s", + "c.ngl.s", + "c.ngt.d", + "c.ngt.s", + "c.ole.d", + "c.ole.s", + "c.olt.d", + "c.olt.s", + "c.seq.d", + "c.seq.s", + "c.sf.d", + "c.sf.s", + "ctc1", + "c.ueq.d", + "c.ueq.s", + "c.ule.d", + "c.ule.s", + "c.ult.d", + "c.ult.s", + "c.un.d", + "c.un.s", + "cvt.d.l", + "cvt.d.s", + "cvt.d.w", + "cvt.l.d", + "cvt.l.s", + "cvt.s.d", + "cvt.s.l", + "cvt.s.w", + "cvt.w.d", + "cvt.w.s", + "dadd", + "daddi", + "daddiu", + "daddu", + "ddiv", + "ddivu", + "div", + "div.d", + "div.s", + "divu", + "dmfc1", + "dmtc1", + "dmult", + "dmultu", + "dsll", + "dsll32", + "dsllv", + "dsra", + "dsra32", + "dsrav", + "dsrl", + "dsrl32", + "dsrlv", + "dsub", + "dsubu", + "eret", + "floor.l.d", + "floor.l.s", + "floor.w.d", + "floor.w.s", + "j", + "jal", + "jalr", + "jr", + "lb", + "lbu", + "ld", + "ldc1", + "ldl", + "ldr", + "lh", + "lhu", + "ll", + "lld", + "lui", + "lw", + "lwc1", + "lwl", + "lwr", + "lwu", + "mfc0", + "mfc1", + "mfhi", + "mflo", + "mov.d", + "mov.s", + "mtc0", + "mtc1", + "mthi", + "mtlo", + "mul.d", + "mul.s", + "mult", + "multu", + "neg.d", + "neg.s", + "nor", + "or", + "ori", + "round.l.d", + "round.l.s", + "round.w.d", + "round.w.s", + "sb", + "sc", + "scd", + "sd", + "sdc1", + "sdl", + "sdr", + "sh", + "sll", + "sllv", + "slt", + "slti", + "sltiu", + "sltu", + "sqrt.d", + "sqrt.s", + "sra", + "srav", + "srl", + "srlv", + "sub", + "sub.d", + "sub.s", + "subu", + "sw", + "swc1", + "swl", + "swr", + "sync", + "syscall", + "teq", + "teqi", + "tge", + "tgei", + "tgeiu", + "tgeu", + "tlbp", + "tlbr", + "tlbwi", + "tlbwr", + "tlt", + "tlti", + "tltiu", + "tltu", + "tne", + "tnei", + "trunc.l.d", + "trunc.l.s", + "trunc.w.d", + "trunc.w.s", + "xor", + "xori", +}; + +static int32_t sx_imm(uint32_t code) +{ + int32_t imm = ((code >> 0) & 0b1111111111111111); + if (imm >= 0b1000000000000000) + imm = -0b10000000000000000 + imm; + return imm; +} + +static _Bool decode_i_so(enum vr4300_op opcode, uint32_t code, + struct vr4300_insn *insn) +{ + insn->opcode = opcode; + insn->opnd_type[0] = VR4300_OPND_CPU; + insn->opnd_type[1] = VR4300_OPND_BRANCH; + insn->opnd_type[2] = VR4300_OPND_NULL; + insn->opnd_value[0] = VR4300_REG_CPU_FIRST + ((code >> 21) & 0b11111); + insn->opnd_value[1] = sx_imm(code) * 4; + return 1; +} + +static _Bool decode_i_si(enum vr4300_op opcode, uint32_t code, + struct vr4300_insn *insn) +{ + insn->opcode = opcode; + insn->opnd_type[0] = VR4300_OPND_CPU; + insn->opnd_type[1] = VR4300_OPND_IMMEDIATE; + insn->opnd_type[2] = VR4300_OPND_NULL; + insn->opnd_value[0] = VR4300_REG_CPU_FIRST + ((code >> 21) & 0b11111); + insn->opnd_value[1] = sx_imm(code); + return 1; +} + +static _Bool decode_i_o(enum vr4300_op opcode, uint32_t code, + struct vr4300_insn *insn) +{ + insn->opcode = opcode; + insn->opnd_type[0] = VR4300_OPND_BRANCH; + insn->opnd_type[1] = VR4300_OPND_NULL; + insn->opnd_type[2] = VR4300_OPND_NULL; + insn->opnd_value[0] = sx_imm(code) * 4; + return 1; +} + +static _Bool decode_i_sto(enum vr4300_op opcode, uint32_t code, + struct vr4300_insn *insn) +{ + insn->opcode = opcode; + insn->opnd_type[0] = VR4300_OPND_CPU; + insn->opnd_type[1] = VR4300_OPND_CPU; + insn->opnd_type[2] = VR4300_OPND_BRANCH; + insn->opnd_value[0] = VR4300_REG_CPU_FIRST + ((code >> 21) & 0b11111); + insn->opnd_value[1] = VR4300_REG_CPU_FIRST + ((code >> 16) & 0b11111); + insn->opnd_value[2] = sx_imm(code) * 4; + return 1; +} + +static _Bool decode_i_tsi(enum vr4300_op opcode, uint32_t code, + struct vr4300_insn *insn) +{ + insn->opcode = opcode; + insn->opnd_type[0] = VR4300_OPND_CPU; + insn->opnd_type[1] = VR4300_OPND_CPU; + insn->opnd_type[2] = VR4300_OPND_IMMEDIATE; + insn->opnd_value[0] = VR4300_REG_CPU_FIRST + ((code >> 16) & 0b11111); + insn->opnd_value[1] = VR4300_REG_CPU_FIRST + ((code >> 21) & 0b11111); + insn->opnd_value[2] = sx_imm(code); + return 1; +} + +static _Bool decode_i_ti(enum vr4300_op opcode, uint32_t code, + struct vr4300_insn *insn) +{ + insn->opcode = opcode; + insn->opnd_type[0] = VR4300_OPND_CPU; + insn->opnd_type[1] = VR4300_OPND_IMMEDIATE; + insn->opnd_type[2] = VR4300_OPND_NULL; + insn->opnd_value[0] = VR4300_REG_CPU_FIRST + ((code >> 16) & 0b11111); + insn->opnd_value[1] = ((code >> 0) & 0b1111111111111111); + return 1; +} + +static _Bool decode_i_tob(enum vr4300_op opcode, uint32_t code, + struct vr4300_insn *insn) +{ + insn->opcode = opcode; + insn->opnd_type[0] = VR4300_OPND_CPU; + insn->opnd_type[1] = VR4300_OPND_OFFSET; + insn->opnd_type[2] = VR4300_OPND_CPU; + insn->opnd_value[0] = VR4300_REG_CPU_FIRST + ((code >> 16) & 0b11111); + insn->opnd_value[1] = sx_imm(code); + insn->opnd_value[2] = VR4300_REG_CPU_FIRST + ((code >> 21) & 0b11111); + return 1; +} + +static _Bool decode_i_oob(enum vr4300_op opcode, uint32_t code, + struct vr4300_insn *insn) +{ + insn->opcode = opcode; + insn->opnd_type[0] = VR4300_OPND_CACHE; + insn->opnd_type[1] = VR4300_OPND_OFFSET; + insn->opnd_type[2] = VR4300_OPND_CPU; + insn->opnd_value[0] = ((code >> 16) & 0b11111); + insn->opnd_value[1] = sx_imm(code); + insn->opnd_value[2] = VR4300_REG_CPU_FIRST + ((code >> 21) & 0b11111); + return 1; +} + +static _Bool decode_i_t1ob(enum vr4300_op opcode, uint32_t code, + struct vr4300_insn *insn) +{ + insn->opcode = opcode; + insn->opnd_type[0] = VR4300_OPND_CP1; + insn->opnd_type[1] = VR4300_OPND_OFFSET; + insn->opnd_type[2] = VR4300_OPND_CPU; + insn->opnd_value[0] = VR4300_REG_CP1_FIRST + ((code >> 16) & 0b11111); + insn->opnd_value[1] = sx_imm(code); + insn->opnd_value[2] = VR4300_REG_CPU_FIRST + ((code >> 21) & 0b11111); + return 1; +} + +static _Bool decode_j(enum vr4300_op opcode, uint32_t code, + struct vr4300_insn *insn) +{ + insn->opcode = opcode; + insn->opnd_type[0] = VR4300_OPND_JUMP; + insn->opnd_type[1] = VR4300_OPND_NULL; + insn->opnd_type[2] = VR4300_OPND_NULL; + insn->opnd_value[0] = (((code >> 0) & 0b11111111111111111111111111) << 2); + return 1; +} + +static _Bool decode_r_dta(enum vr4300_op opcode, uint32_t code, + struct vr4300_insn *insn) +{ + insn->opcode = opcode; + insn->opnd_type[0] = VR4300_OPND_CPU; + insn->opnd_type[1] = VR4300_OPND_CPU; + insn->opnd_type[2] = VR4300_OPND_IMMEDIATE; + insn->opnd_value[0] = VR4300_REG_CPU_FIRST + ((code >> 11) & 0b11111); + insn->opnd_value[1] = VR4300_REG_CPU_FIRST + ((code >> 16) & 0b11111); + insn->opnd_value[2] = ((code >> 6) & 0b11111); + return 1; +} + +static _Bool decode_r_dts(enum vr4300_op opcode, uint32_t code, + struct vr4300_insn *insn) +{ + insn->opcode = opcode; + insn->opnd_type[0] = VR4300_OPND_CPU; + insn->opnd_type[1] = VR4300_OPND_CPU; + insn->opnd_type[2] = VR4300_OPND_CPU; + insn->opnd_value[0] = VR4300_REG_CPU_FIRST + ((code >> 11) & 0b11111); + insn->opnd_value[1] = VR4300_REG_CPU_FIRST + ((code >> 16) & 0b11111); + insn->opnd_value[2] = VR4300_REG_CPU_FIRST + ((code >> 21) & 0b11111); + return 1; +} + +static _Bool decode_r_s(enum vr4300_op opcode, uint32_t code, + struct vr4300_insn *insn) +{ + insn->opcode = opcode; + insn->opnd_type[0] = VR4300_OPND_CPU; + insn->opnd_type[1] = VR4300_OPND_NULL; + insn->opnd_type[2] = VR4300_OPND_NULL; + insn->opnd_value[0] = VR4300_REG_CPU_FIRST + ((code >> 21) & 0b11111); + return 1; +} + +static _Bool decode_r_ds(enum vr4300_op opcode, uint32_t code, + struct vr4300_insn *insn) +{ + insn->opcode = opcode; + insn->opnd_type[0] = VR4300_OPND_CPU; + insn->opnd_type[1] = VR4300_OPND_CPU; + insn->opnd_type[2] = VR4300_OPND_NULL; + insn->opnd_value[0] = VR4300_REG_CPU_FIRST + ((code >> 11) & 0b11111); + insn->opnd_value[1] = VR4300_REG_CPU_FIRST + ((code >> 21) & 0b11111); + return 1; +} + +static _Bool decode_r_c(enum vr4300_op opcode, uint32_t code, + struct vr4300_insn *insn) +{ + insn->opcode = opcode; + insn->opnd_type[0] = VR4300_OPND_IMMEDIATE; + insn->opnd_type[1] = VR4300_OPND_NULL; + insn->opnd_type[2] = VR4300_OPND_NULL; + insn->opnd_value[0] = ((code >> 6) & 0b11111111111111111111); + return 1; +} + +static _Bool decode_r(enum vr4300_op opcode, uint32_t code, + struct vr4300_insn *insn) +{ + insn->opcode = opcode; + insn->opnd_type[0] = VR4300_OPND_NULL; + insn->opnd_type[1] = VR4300_OPND_NULL; + insn->opnd_type[2] = VR4300_OPND_NULL; + return 1; +} + +static _Bool decode_r_d(enum vr4300_op opcode, uint32_t code, + struct vr4300_insn *insn) +{ + insn->opcode = opcode; + insn->opnd_type[0] = VR4300_OPND_CPU; + insn->opnd_type[1] = VR4300_OPND_NULL; + insn->opnd_type[2] = VR4300_OPND_NULL; + insn->opnd_value[0] = VR4300_REG_CPU_FIRST + ((code >> 11) & 0b11111); + return 1; +} + +static _Bool decode_r_st(enum vr4300_op opcode, uint32_t code, + struct vr4300_insn *insn) +{ + insn->opcode = opcode; + insn->opnd_type[0] = VR4300_OPND_CPU; + insn->opnd_type[1] = VR4300_OPND_CPU; + insn->opnd_type[2] = VR4300_OPND_NULL; + insn->opnd_value[0] = VR4300_REG_CPU_FIRST + ((code >> 21) & 0b11111); + insn->opnd_value[1] = VR4300_REG_CPU_FIRST + ((code >> 16) & 0b11111); + return 1; +} + +static _Bool decode_r_dst(enum vr4300_op opcode, uint32_t code, + struct vr4300_insn *insn) +{ + insn->opcode = opcode; + insn->opnd_type[0] = VR4300_OPND_CPU; + insn->opnd_type[1] = VR4300_OPND_CPU; + insn->opnd_type[2] = VR4300_OPND_CPU; + insn->opnd_value[0] = VR4300_REG_CPU_FIRST + ((code >> 11) & 0b11111); + insn->opnd_value[1] = VR4300_REG_CPU_FIRST + ((code >> 21) & 0b11111); + insn->opnd_value[2] = VR4300_REG_CPU_FIRST + ((code >> 16) & 0b11111); + return 1; +} + +static _Bool decode_r_stc(enum vr4300_op opcode, uint32_t code, + struct vr4300_insn *insn) +{ + insn->opcode = opcode; + insn->opnd_type[0] = VR4300_OPND_CPU; + insn->opnd_type[1] = VR4300_OPND_CPU; + insn->opnd_type[2] = VR4300_OPND_IMMEDIATE; + insn->opnd_value[0] = VR4300_REG_CPU_FIRST + ((code >> 21) & 0b11111); + insn->opnd_value[1] = VR4300_REG_CPU_FIRST + ((code >> 16) & 0b11111); + insn->opnd_value[2] = ((code >> 6) & 0b1111111111); + return 1; +} + +static _Bool decode_r_td0(enum vr4300_op opcode, uint32_t code, + struct vr4300_insn *insn) +{ + insn->opcode = opcode; + insn->opnd_type[0] = VR4300_OPND_CPU; + insn->opnd_type[1] = VR4300_OPND_CP0; + insn->opnd_type[2] = VR4300_OPND_NULL; + insn->opnd_value[0] = VR4300_REG_CPU_FIRST + ((code >> 16) & 0b11111); + insn->opnd_value[1] = VR4300_REG_CP0_FIRST + ((code >> 11) & 0b11111); + return 1; +} + +static _Bool decode_r_d1s1t1(enum vr4300_op opcode, uint32_t code, + struct vr4300_insn *insn) +{ + insn->opcode = opcode; + insn->opnd_type[0] = VR4300_OPND_CP1; + insn->opnd_type[1] = VR4300_OPND_CP1; + insn->opnd_type[2] = VR4300_OPND_CP1; + insn->opnd_value[0] = VR4300_REG_CP1_FIRST + ((code >> 6) & 0b11111); + insn->opnd_value[1] = VR4300_REG_CP1_FIRST + ((code >> 11) & 0b11111); + insn->opnd_value[2] = VR4300_REG_CP1_FIRST + ((code >> 16) & 0b11111); + return 1; +} + +static _Bool decode_r_d1s1(enum vr4300_op opcode, uint32_t code, + struct vr4300_insn *insn) +{ + insn->opcode = opcode; + insn->opnd_type[0] = VR4300_OPND_CP1; + insn->opnd_type[1] = VR4300_OPND_CP1; + insn->opnd_type[2] = VR4300_OPND_NULL; + insn->opnd_value[0] = VR4300_REG_CP1_FIRST + ((code >> 6) & 0b11111); + insn->opnd_value[1] = VR4300_REG_CP1_FIRST + ((code >> 11) & 0b11111); + return 1; +} + +static _Bool decode_r_s1t1(enum vr4300_op opcode, uint32_t code, + struct vr4300_insn *insn) +{ + insn->opcode = opcode; + insn->opnd_type[0] = VR4300_OPND_CP1; + insn->opnd_type[1] = VR4300_OPND_CP1; + insn->opnd_type[2] = VR4300_OPND_NULL; + insn->opnd_value[0] = VR4300_REG_CP1_FIRST + ((code >> 11) & 0b11111); + insn->opnd_value[1] = VR4300_REG_CP1_FIRST + ((code >> 16) & 0b11111); + return 1; +} + +static _Bool decode_r_ts1(enum vr4300_op opcode, uint32_t code, + struct vr4300_insn *insn) +{ + insn->opcode = opcode; + insn->opnd_type[0] = VR4300_OPND_CPU; + insn->opnd_type[1] = VR4300_OPND_CP1; + insn->opnd_type[2] = VR4300_OPND_NULL; + insn->opnd_value[0] = VR4300_REG_CPU_FIRST + ((code >> 16) & 0b11111); + insn->opnd_value[1] = VR4300_REG_CP1_FIRST + ((code >> 11) & 0b11111); + return 1; +} + +static _Bool decode_r_ts1c(enum vr4300_op opcode, uint32_t code, + struct vr4300_insn *insn) +{ + insn->opcode = opcode; + insn->opnd_type[0] = VR4300_OPND_CPU; + insn->opnd_type[1] = VR4300_OPND_FCR; + insn->opnd_type[2] = VR4300_OPND_NULL; + insn->opnd_value[0] = VR4300_REG_CPU_FIRST + ((code >> 16) & 0b11111); + insn->opnd_value[1] = VR4300_REG_FCR_FIRST + ((code >> 11) & 0b11111); + return 1; +} + +static _Bool decode_special(uint32_t code, struct vr4300_insn *insn) +{ + uint8_t funct = ((code >> 0) & 0b111111); + switch (funct) { + case 0b000000: return decode_r_dta(VR4300_OP_SLL, code, insn); + case 0b000010: return decode_r_dta(VR4300_OP_SRL, code, insn); + case 0b000011: return decode_r_dta(VR4300_OP_SRA, code, insn); + case 0b000100: return decode_r_dts(VR4300_OP_SLLV, code, insn); + case 0b000110: return decode_r_dts(VR4300_OP_SRLV, code, insn); + case 0b000111: return decode_r_dts(VR4300_OP_SRAV, code, insn); + case 0b001000: return decode_r_s(VR4300_OP_JR, code, insn); + case 0b001001: return decode_r_ds(VR4300_OP_JALR, code, insn); + case 0b001100: return decode_r_c(VR4300_OP_SYSCALL, code, insn); + case 0b001101: return decode_r_c(VR4300_OP_BREAK, code, insn); + case 0b001111: return decode_r(VR4300_OP_SYNC, code, insn); + case 0b010000: return decode_r_d(VR4300_OP_MFHI, code, insn); + case 0b010001: return decode_r_s(VR4300_OP_MTHI, code, insn); + case 0b010010: return decode_r_d(VR4300_OP_MFLO, code, insn); + case 0b010011: return decode_r_s(VR4300_OP_MTLO, code, insn); + case 0b010100: return decode_r_dts(VR4300_OP_DSLLV, code, insn); + case 0b010110: return decode_r_dts(VR4300_OP_DSRLV, code, insn); + case 0b010111: return decode_r_dts(VR4300_OP_DSRAV, code, insn); + case 0b011000: return decode_r_st(VR4300_OP_MULT, code, insn); + case 0b011001: return decode_r_st(VR4300_OP_MULTU, code, insn); + case 0b011010: return decode_r_st(VR4300_OP_DIV, code, insn); + case 0b011011: return decode_r_st(VR4300_OP_DIVU, code, insn); + case 0b011100: return decode_r_st(VR4300_OP_DMULT, code, insn); + case 0b011101: return decode_r_st(VR4300_OP_DMULTU, code, insn); + case 0b011110: return decode_r_st(VR4300_OP_DDIV, code, insn); + case 0b011111: return decode_r_st(VR4300_OP_DDIVU, code, insn); + case 0b100000: return decode_r_dst(VR4300_OP_ADD, code, insn); + case 0b100001: return decode_r_dst(VR4300_OP_ADDU, code, insn); + case 0b100010: return decode_r_dst(VR4300_OP_SUB, code, insn); + case 0b100011: return decode_r_dst(VR4300_OP_SUBU, code, insn); + case 0b100100: return decode_r_dst(VR4300_OP_AND, code, insn); + case 0b100101: return decode_r_dst(VR4300_OP_OR, code, insn); + case 0b100110: return decode_r_dst(VR4300_OP_XOR, code, insn); + case 0b100111: return decode_r_dst(VR4300_OP_NOR, code, insn); + case 0b101010: return decode_r_dst(VR4300_OP_SLT, code, insn); + case 0b101011: return decode_r_dst(VR4300_OP_SLTU, code, insn); + case 0b101100: return decode_r_dst(VR4300_OP_DADD, code, insn); + case 0b101101: return decode_r_dst(VR4300_OP_DADDU, code, insn); + case 0b101110: return decode_r_dst(VR4300_OP_DSUB, code, insn); + case 0b101111: return decode_r_dst(VR4300_OP_DSUBU, code, insn); + case 0b110000: return decode_r_stc(VR4300_OP_TGE, code, insn); + case 0b110001: return decode_r_stc(VR4300_OP_TGEU, code, insn); + case 0b110010: return decode_r_stc(VR4300_OP_TLT, code, insn); + case 0b110011: return decode_r_stc(VR4300_OP_TLTU, code, insn); + case 0b110100: return decode_r_stc(VR4300_OP_TEQ, code, insn); + case 0b110110: return decode_r_stc(VR4300_OP_TNE, code, insn); + case 0b111000: return decode_r_dta(VR4300_OP_DSLL, code, insn); + case 0b111010: return decode_r_dta(VR4300_OP_DSRL, code, insn); + case 0b111011: return decode_r_dta(VR4300_OP_DSRA, code, insn); + case 0b111100: return decode_r_dta(VR4300_OP_DSLL32, code, insn); + case 0b111110: return decode_r_dta(VR4300_OP_DSRL32, code, insn); + case 0b111111: return decode_r_dta(VR4300_OP_DSRA32, code, insn); + default : return 0; + } +} + +static _Bool decode_regimm(uint32_t code, struct vr4300_insn *insn) +{ + uint8_t rt = ((code >> 16) & 0b11111); + switch (rt) { + case 0b00000: return decode_i_so(VR4300_OP_BLTZ, code, insn); + case 0b00001: return decode_i_so(VR4300_OP_BGEZ, code, insn); + case 0b00010: return decode_i_so(VR4300_OP_BLTZL, code, insn); + case 0b00011: return decode_i_so(VR4300_OP_BGEZL, code, insn); + case 0b01000: return decode_i_si(VR4300_OP_TGEI, code, insn); + case 0b01001: return decode_i_si(VR4300_OP_TGEIU, code, insn); + case 0b01010: return decode_i_si(VR4300_OP_TLTI, code, insn); + case 0b01011: return decode_i_si(VR4300_OP_TLTIU, code, insn); + case 0b01100: return decode_i_si(VR4300_OP_TEQI, code, insn); + case 0b01110: return decode_i_si(VR4300_OP_TNEI, code, insn); + case 0b10000: return decode_i_so(VR4300_OP_BLTZAL, code, insn); + case 0b10001: return decode_i_so(VR4300_OP_BGEZAL, code, insn); + case 0b10010: return decode_i_so(VR4300_OP_BLTZALL, code, insn); + case 0b10011: return decode_i_so(VR4300_OP_BGEZALL, code, insn); + default : return 0; + } +} + +static _Bool decode_cop0_co(uint32_t code, struct vr4300_insn *insn) +{ + uint8_t funct = ((code >> 0) & 0b111111); + switch (funct) { + case 0b000001: return decode_r(VR4300_OP_TLBR, code, insn); + case 0b000010: return decode_r(VR4300_OP_TLBWI, code, insn); + case 0b000110: return decode_r(VR4300_OP_TLBWR, code, insn); + case 0b001000: return decode_r(VR4300_OP_TLBP, code, insn); + case 0b011000: return decode_r(VR4300_OP_ERET, code, insn); + default : return 0; + } +} + +static _Bool decode_cop0(uint32_t code, struct vr4300_insn *insn) +{ + uint8_t rs = ((code >> 21) & 0b11111); + switch (rs) { + case 0b00000: return decode_r_td0(VR4300_OP_MFC0, code, insn); + case 0b00100: return decode_r_td0(VR4300_OP_MTC0, code, insn); + case 0b10000: + case 0b10001: + case 0b10010: + case 0b10011: + case 0b10100: + case 0b10101: + case 0b10110: + case 0b10111: + case 0b11000: + case 0b11001: + case 0b11010: + case 0b11011: + case 0b11100: + case 0b11101: + case 0b11110: + case 0b11111: return decode_cop0_co(code, insn); + default : return 0; + } +} + +static _Bool decode_cop1_bc1(uint32_t code, struct vr4300_insn *insn) +{ + uint8_t rt = ((code >> 16) & 0b11111); + switch (rt) { + case 0b00000: return decode_i_o(VR4300_OP_BC1F, code, insn); + case 0b00001: return decode_i_o(VR4300_OP_BC1T, code, insn); + case 0b00010: return decode_i_o(VR4300_OP_BC1FL, code, insn); + case 0b00011: return decode_i_o(VR4300_OP_BC1TL, code, insn); + default : return 0; + } +} + +static _Bool decode_cop1_s(uint32_t code, struct vr4300_insn *insn) +{ + uint8_t funct = ((code >> 0) & 0b111111); + switch (funct) { + case 0b000000: return decode_r_d1s1t1(VR4300_OP_ADDS, code, insn); + case 0b000001: return decode_r_d1s1t1(VR4300_OP_SUBS, code, insn); + case 0b000010: return decode_r_d1s1t1(VR4300_OP_MULS, code, insn); + case 0b000011: return decode_r_d1s1t1(VR4300_OP_DIVS, code, insn); + case 0b000100: return decode_r_d1s1(VR4300_OP_SQRTS, code, insn); + case 0b000101: return decode_r_d1s1(VR4300_OP_ABSS, code, insn); + case 0b000110: return decode_r_d1s1(VR4300_OP_MOVS, code, insn); + case 0b000111: return decode_r_d1s1(VR4300_OP_NEGS, code, insn); + case 0b001000: return decode_r_d1s1(VR4300_OP_ROUNDLS, code, insn); + case 0b001001: return decode_r_d1s1(VR4300_OP_TRUNCLS, code, insn); + case 0b001010: return decode_r_d1s1(VR4300_OP_CEILLS, code, insn); + case 0b001011: return decode_r_d1s1(VR4300_OP_FLOORLS, code, insn); + case 0b001100: return decode_r_d1s1(VR4300_OP_ROUNDWS, code, insn); + case 0b001101: return decode_r_d1s1(VR4300_OP_TRUNCWS, code, insn); + case 0b001110: return decode_r_d1s1(VR4300_OP_CEILWS, code, insn); + case 0b001111: return decode_r_d1s1(VR4300_OP_FLOORWS, code, insn); + case 0b100001: return decode_r_d1s1(VR4300_OP_CVTDS, code, insn); + case 0b100100: return decode_r_d1s1(VR4300_OP_CVTWS, code, insn); + case 0b100101: return decode_r_d1s1(VR4300_OP_CVTLS, code, insn); + case 0b110000: return decode_r_s1t1(VR4300_OP_CFS, code, insn); + case 0b110001: return decode_r_s1t1(VR4300_OP_CUNS, code, insn); + case 0b110010: return decode_r_s1t1(VR4300_OP_CEQS, code, insn); + case 0b110011: return decode_r_s1t1(VR4300_OP_CUEQS, code, insn); + case 0b110100: return decode_r_s1t1(VR4300_OP_COLTS, code, insn); + case 0b110101: return decode_r_s1t1(VR4300_OP_CULTS, code, insn); + case 0b110110: return decode_r_s1t1(VR4300_OP_COLES, code, insn); + case 0b110111: return decode_r_s1t1(VR4300_OP_CULES, code, insn); + case 0b111000: return decode_r_s1t1(VR4300_OP_CSFS, code, insn); + case 0b111001: return decode_r_s1t1(VR4300_OP_CNGLES, code, insn); + case 0b111010: return decode_r_s1t1(VR4300_OP_CSEQS, code, insn); + case 0b111011: return decode_r_s1t1(VR4300_OP_CNGLS, code, insn); + case 0b111100: return decode_r_s1t1(VR4300_OP_CLTS, code, insn); + case 0b111101: return decode_r_s1t1(VR4300_OP_CNGES, code, insn); + case 0b111110: return decode_r_s1t1(VR4300_OP_CLES, code, insn); + case 0b111111: return decode_r_s1t1(VR4300_OP_CNGTS, code, insn); + default : return 0; + } +} + +static _Bool decode_cop1_d(uint32_t code, struct vr4300_insn *insn) +{ + uint8_t funct = ((code >> 0) & 0b111111); + switch (funct) { + case 0b000000: return decode_r_d1s1t1(VR4300_OP_ADDD, code, insn); + case 0b000001: return decode_r_d1s1t1(VR4300_OP_SUBD, code, insn); + case 0b000010: return decode_r_d1s1t1(VR4300_OP_MULD, code, insn); + case 0b000011: return decode_r_d1s1t1(VR4300_OP_DIVD, code, insn); + case 0b000100: return decode_r_d1s1(VR4300_OP_SQRTD, code, insn); + case 0b000101: return decode_r_d1s1(VR4300_OP_ABSD, code, insn); + case 0b000110: return decode_r_d1s1(VR4300_OP_MOVD, code, insn); + case 0b000111: return decode_r_d1s1(VR4300_OP_NEGD, code, insn); + case 0b001000: return decode_r_d1s1(VR4300_OP_ROUNDLD, code, insn); + case 0b001001: return decode_r_d1s1(VR4300_OP_TRUNCLD, code, insn); + case 0b001010: return decode_r_d1s1(VR4300_OP_CEILLD, code, insn); + case 0b001011: return decode_r_d1s1(VR4300_OP_FLOORLD, code, insn); + case 0b001100: return decode_r_d1s1(VR4300_OP_ROUNDWD, code, insn); + case 0b001101: return decode_r_d1s1(VR4300_OP_TRUNCWD, code, insn); + case 0b001110: return decode_r_d1s1(VR4300_OP_CEILWD, code, insn); + case 0b001111: return decode_r_d1s1(VR4300_OP_FLOORWD, code, insn); + case 0b100000: return decode_r_d1s1(VR4300_OP_CVTSD, code, insn); + case 0b100100: return decode_r_d1s1(VR4300_OP_CVTWD, code, insn); + case 0b100101: return decode_r_d1s1(VR4300_OP_CVTLD, code, insn); + case 0b110000: return decode_r_s1t1(VR4300_OP_CFD, code, insn); + case 0b110001: return decode_r_s1t1(VR4300_OP_CUND, code, insn); + case 0b110010: return decode_r_s1t1(VR4300_OP_CEQD, code, insn); + case 0b110011: return decode_r_s1t1(VR4300_OP_CUEQD, code, insn); + case 0b110100: return decode_r_s1t1(VR4300_OP_COLTD, code, insn); + case 0b110101: return decode_r_s1t1(VR4300_OP_CULTD, code, insn); + case 0b110110: return decode_r_s1t1(VR4300_OP_COLED, code, insn); + case 0b110111: return decode_r_s1t1(VR4300_OP_CULED, code, insn); + case 0b111000: return decode_r_s1t1(VR4300_OP_CSFD, code, insn); + case 0b111001: return decode_r_s1t1(VR4300_OP_CNGLED, code, insn); + case 0b111010: return decode_r_s1t1(VR4300_OP_CSEQD, code, insn); + case 0b111011: return decode_r_s1t1(VR4300_OP_CNGLD, code, insn); + case 0b111100: return decode_r_s1t1(VR4300_OP_CLTD, code, insn); + case 0b111101: return decode_r_s1t1(VR4300_OP_CNGED, code, insn); + case 0b111110: return decode_r_s1t1(VR4300_OP_CLED, code, insn); + case 0b111111: return decode_r_s1t1(VR4300_OP_CNGTD, code, insn); + default : return 0; + } +} + +static _Bool decode_cop1_w(uint32_t code, struct vr4300_insn *insn) +{ + uint8_t funct = ((code >> 0) & 0b111111); + switch (funct) { + case 0b100000: return decode_r_d1s1(VR4300_OP_CVTSW, code, insn); + case 0b100001: return decode_r_d1s1(VR4300_OP_CVTDW, code, insn); + default : return 0; + } +} + +static _Bool decode_cop1_l(uint32_t code, struct vr4300_insn *insn) +{ + uint8_t funct = ((code >> 0) & 0b111111); + switch (funct) { + case 0b100000: return decode_r_d1s1(VR4300_OP_CVTSL, code, insn); + case 0b100001: return decode_r_d1s1(VR4300_OP_CVTDL, code, insn); + default : return 0; + } +} + +static _Bool decode_cop1(uint32_t code, struct vr4300_insn *insn) +{ + uint8_t rs = ((code >> 21) & 0b11111); + switch (rs) { + case 0b00000: return decode_r_ts1(VR4300_OP_MFC1, code, insn); + case 0b00001: return decode_r_ts1(VR4300_OP_DMFC1, code, insn); + case 0b00010: return decode_r_ts1c(VR4300_OP_CFC1, code, insn); + case 0b00100: return decode_r_ts1(VR4300_OP_MTC1, code, insn); + case 0b00101: return decode_r_ts1(VR4300_OP_DMTC1, code, insn); + case 0b00110: return decode_r_ts1c(VR4300_OP_CTC1, code, insn); + case 0b01000: return decode_cop1_bc1(code, insn); + case 0b10000: return decode_cop1_s(code, insn); + case 0b10001: return decode_cop1_d(code, insn); + case 0b10100: return decode_cop1_w(code, insn); + case 0b10101: return decode_cop1_l(code, insn); + default : return 0; + } +} + +_Bool vr4300_decode_insn(uint32_t code, struct vr4300_insn *insn) +{ + uint8_t op = ((code >> 26) & 0b111111); + switch (op) { + case 0b000000: return decode_special(code, insn); + case 0b000001: return decode_regimm(code, insn); + case 0b000010: return decode_j(VR4300_OP_J, code, insn); + case 0b000011: return decode_j(VR4300_OP_JAL, code, insn); + case 0b000100: return decode_i_sto(VR4300_OP_BEQ, code, insn); + case 0b000101: return decode_i_sto(VR4300_OP_BNE, code, insn); + case 0b000110: return decode_i_so(VR4300_OP_BLEZ, code, insn); + case 0b000111: return decode_i_so(VR4300_OP_BGTZ, code, insn); + case 0b001000: return decode_i_tsi(VR4300_OP_ADDI, code, insn); + case 0b001001: return decode_i_tsi(VR4300_OP_ADDIU, code, insn); + case 0b001010: return decode_i_tsi(VR4300_OP_SLTI, code, insn); + case 0b001011: return decode_i_tsi(VR4300_OP_SLTIU, code, insn); + case 0b001100: return decode_i_tsi(VR4300_OP_ANDI, code, insn); + case 0b001101: return decode_i_tsi(VR4300_OP_ORI, code, insn); + case 0b001110: return decode_i_tsi(VR4300_OP_XORI, code, insn); + case 0b001111: return decode_i_ti(VR4300_OP_LUI, code, insn); + case 0b010000: return decode_cop0(code, insn); + case 0b010001: return decode_cop1(code, insn); + case 0b010100: return decode_i_sto(VR4300_OP_BEQL, code, insn); + case 0b010101: return decode_i_sto(VR4300_OP_BNEL, code, insn); + case 0b010110: return decode_i_so(VR4300_OP_BLEZL, code, insn); + case 0b010111: return decode_i_so(VR4300_OP_BGTZL, code, insn); + case 0b011000: return decode_i_tsi(VR4300_OP_DADDI, code, insn); + case 0b011001: return decode_i_tsi(VR4300_OP_DADDIU, code, insn); + case 0b011010: return decode_i_tob(VR4300_OP_LDL, code, insn); + case 0b011011: return decode_i_tob(VR4300_OP_LDR, code, insn); + case 0b100000: return decode_i_tob(VR4300_OP_LB, code, insn); + case 0b100001: return decode_i_tob(VR4300_OP_LH, code, insn); + case 0b100010: return decode_i_tob(VR4300_OP_LWL, code, insn); + case 0b100011: return decode_i_tob(VR4300_OP_LW, code, insn); + case 0b100100: return decode_i_tob(VR4300_OP_LBU, code, insn); + case 0b100101: return decode_i_tob(VR4300_OP_LHU, code, insn); + case 0b100110: return decode_i_tob(VR4300_OP_LWR, code, insn); + case 0b100111: return decode_i_tob(VR4300_OP_LWU, code, insn); + case 0b101000: return decode_i_tob(VR4300_OP_SB, code, insn); + case 0b101001: return decode_i_tob(VR4300_OP_SH, code, insn); + case 0b101010: return decode_i_tob(VR4300_OP_SWL, code, insn); + case 0b101011: return decode_i_tob(VR4300_OP_SW, code, insn); + case 0b101100: return decode_i_tob(VR4300_OP_SDL, code, insn); + case 0b101101: return decode_i_tob(VR4300_OP_SDR, code, insn); + case 0b101110: return decode_i_tob(VR4300_OP_SWR, code, insn); + case 0b101111: return decode_i_oob(VR4300_OP_CACHE, code, insn); + case 0b110000: return decode_i_tob(VR4300_OP_LL, code, insn); + case 0b110001: return decode_i_t1ob(VR4300_OP_LWC1, code, insn); + case 0b110100: return decode_i_tob(VR4300_OP_LLD, code, insn); + case 0b110101: return decode_i_t1ob(VR4300_OP_LDC1, code, insn); + case 0b110111: return decode_i_tob(VR4300_OP_LD, code, insn); + case 0b111000: return decode_i_tob(VR4300_OP_SC, code, insn); + case 0b111001: return decode_i_t1ob(VR4300_OP_SWC1, code, insn); + case 0b111100: return decode_i_tob(VR4300_OP_SCD, code, insn); + case 0b111101: return decode_i_t1ob(VR4300_OP_SDC1, code, insn); + case 0b111111: return decode_i_tob(VR4300_OP_SD, code, insn); + default : return 0; + } +} + +void vr4300_print_insn(struct vr4300_insn *insn, uint32_t addr, FILE *f) +{ + if (insn->opcode == VR4300_OP_SLL && + insn->opnd_value[0] == VR4300_REG_R0 && + insn->opnd_value[1] == VR4300_REG_R0 && + insn->opnd_value[2] == 0) + { + fprintf(f, "nop"); + return; + } + fprintf(f, "%s", vr4300_op_mnem[insn->opcode]); + _Bool base = 0; + for (int i = 0; i < 3; ++i) { + switch (insn->opnd_type[i]) { + case VR4300_OPND_NULL: + break; + case VR4300_OPND_CPU: + if (base) { + fprintf(f, "(%s)", vr4300_reg_mnem[insn->opnd_value[i]]); + base = 0; + break; + } + case VR4300_OPND_CP0: + case VR4300_OPND_CP1: + case VR4300_OPND_FCR: + if (i > 0) + fputc(',', f); + fprintf(f, " %s", vr4300_reg_mnem[insn->opnd_value[i]]); + break; + case VR4300_OPND_JUMP: + if (i > 0) + fputc(',', f); + fprintf(f, " 0x%08" PRIx32, + (addr & 0xF0000000) | insn->opnd_value[i]); + break; + case VR4300_OPND_BRANCH: + if (i > 0) + fputc(',', f); + fprintf(f, " 0x%08" PRIx32, addr + 4 + insn->opnd_value[i]); + break; + case VR4300_OPND_OFFSET: + base = 1; + case VR4300_OPND_IMMEDIATE: + if (i > 0) + fputc(',', f); + fprintf(f, " %" PRIi32, insn->opnd_value[i]); + break; + case VR4300_OPND_CACHE: + fprintf(f, " %04" PRIx32, insn->opnd_value[i]); + break; + } + } +} diff --git a/tools/gfxdis/include/vr4300.h b/tools/gfxdis/include/vr4300.h new file mode 100644 index 00000000..bb941d0a --- /dev/null +++ b/tools/gfxdis/include/vr4300.h @@ -0,0 +1,392 @@ +#ifndef VR4300_H +#define VR4300_H +#include +#include + +#define VR4300_REG_CPU_FIRST VR4300_REG_R0 +#define VR4300_REG_CPU_LAST VR4300_REG_RA +#define VR4300_REG_CP0_FIRST VR4300_REG_INDEX +#define VR4300_REG_CP0_LAST VR4300_REG_INVD6 +#define VR4300_REG_CP1_FIRST VR4300_REG_F0 +#define VR4300_REG_CP1_LAST VR4300_REG_F31 +#define VR4300_REG_FCR_FIRST VR4300_REG_FCR0 +#define VR4300_REG_FCR_LAST VR4300_REG_FCR31 + +enum vr4300_reg +{ + /* cpu regs */ + VR4300_REG_R0, + VR4300_REG_AT, + VR4300_REG_V0, + VR4300_REG_V1, + VR4300_REG_A0, + VR4300_REG_A1, + VR4300_REG_A2, + VR4300_REG_A3, + VR4300_REG_T0, + VR4300_REG_T1, + VR4300_REG_T2, + VR4300_REG_T3, + VR4300_REG_T4, + VR4300_REG_T5, + VR4300_REG_T6, + VR4300_REG_T7, + VR4300_REG_S0, + VR4300_REG_S1, + VR4300_REG_S2, + VR4300_REG_S3, + VR4300_REG_S4, + VR4300_REG_S5, + VR4300_REG_S6, + VR4300_REG_S7, + VR4300_REG_T8, + VR4300_REG_T9, + VR4300_REG_K0, + VR4300_REG_K1, + VR4300_REG_GP, + VR4300_REG_SP, + VR4300_REG_S8, + VR4300_REG_RA, + /* cop0 regs */ + VR4300_REG_INDEX, + VR4300_REG_RANDOM, + VR4300_REG_ENTRYLO0, + VR4300_REG_ENTRYLO1, + VR4300_REG_CONTEXT, + VR4300_REG_PAGEMASK, + VR4300_REG_WIRED, + VR4300_REG_INVD0, + VR4300_REG_BADVADDR, + VR4300_REG_COUNT, + VR4300_REG_ENTRYHI, + VR4300_REG_COMPARE, + VR4300_REG_STATUS, + VR4300_REG_CAUSE, + VR4300_REG_EPC, + VR4300_REG_PRID, + VR4300_REG_CONFIG, + VR4300_REG_LLADDR, + VR4300_REG_WATCHLO, + VR4300_REG_WATCHHI, + VR4300_REG_XCONTEXT, + VR4300_REG_INVD1, + VR4300_REG_INVD2, + VR4300_REG_INVD3, + VR4300_REG_INVD4, + VR4300_REG_INVD5, + VR4300_REG_PERR, + VR4300_REG_CACHEERR, + VR4300_REG_TAGLO, + VR4300_REG_TAGHI, + VR4300_REG_ERROREPC, + VR4300_REG_INVD6, + /* cop1 regs */ + VR4300_REG_F0, + VR4300_REG_F1, + VR4300_REG_F2, + VR4300_REG_F3, + VR4300_REG_F4, + VR4300_REG_F5, + VR4300_REG_F6, + VR4300_REG_F7, + VR4300_REG_F8, + VR4300_REG_F9, + VR4300_REG_F10, + VR4300_REG_F11, + VR4300_REG_F12, + VR4300_REG_F13, + VR4300_REG_F14, + VR4300_REG_F15, + VR4300_REG_F16, + VR4300_REG_F17, + VR4300_REG_F18, + VR4300_REG_F19, + VR4300_REG_F20, + VR4300_REG_F21, + VR4300_REG_F22, + VR4300_REG_F23, + VR4300_REG_F24, + VR4300_REG_F25, + VR4300_REG_F26, + VR4300_REG_F27, + VR4300_REG_F28, + VR4300_REG_F29, + VR4300_REG_F30, + VR4300_REG_F31, + /* cop1 control regs */ + VR4300_REG_FCR0, + VR4300_REG_FCR1, + VR4300_REG_FCR2, + VR4300_REG_FCR3, + VR4300_REG_FCR4, + VR4300_REG_FCR5, + VR4300_REG_FCR6, + VR4300_REG_FCR7, + VR4300_REG_FCR8, + VR4300_REG_FCR9, + VR4300_REG_FCR10, + VR4300_REG_FCR11, + VR4300_REG_FCR12, + VR4300_REG_FCR13, + VR4300_REG_FCR14, + VR4300_REG_FCR15, + VR4300_REG_FCR16, + VR4300_REG_FCR17, + VR4300_REG_FCR18, + VR4300_REG_FCR19, + VR4300_REG_FCR20, + VR4300_REG_FCR21, + VR4300_REG_FCR22, + VR4300_REG_FCR23, + VR4300_REG_FCR24, + VR4300_REG_FCR25, + VR4300_REG_FCR26, + VR4300_REG_FCR27, + VR4300_REG_FCR28, + VR4300_REG_FCR29, + VR4300_REG_FCR30, + VR4300_REG_FCR31, + /* pseudo-registers */ + VR4300_REG_LO, + VR4300_REG_HI, + VR4300_REG_CC, + VR4300_REG_MAX, +}; + +enum vr4300_op +{ + VR4300_OP_ABSD, + VR4300_OP_ABSS, + VR4300_OP_ADD, + VR4300_OP_ADDD, + VR4300_OP_ADDI, + VR4300_OP_ADDIU, + VR4300_OP_ADDS, + VR4300_OP_ADDU, + VR4300_OP_AND, + VR4300_OP_ANDI, + VR4300_OP_BC1F, + VR4300_OP_BC1FL, + VR4300_OP_BC1T, + VR4300_OP_BC1TL, + VR4300_OP_BEQ, + VR4300_OP_BEQL, + VR4300_OP_BGEZ, + VR4300_OP_BGEZAL, + VR4300_OP_BGEZALL, + VR4300_OP_BGEZL, + VR4300_OP_BGTZ, + VR4300_OP_BGTZL, + VR4300_OP_BLEZ, + VR4300_OP_BLEZL, + VR4300_OP_BLTZ, + VR4300_OP_BLTZAL, + VR4300_OP_BLTZALL, + VR4300_OP_BLTZL, + VR4300_OP_BNE, + VR4300_OP_BNEL, + VR4300_OP_BREAK, + VR4300_OP_CACHE, + VR4300_OP_CEILLD, + VR4300_OP_CEILLS, + VR4300_OP_CEILWD, + VR4300_OP_CEILWS, + VR4300_OP_CEQD, + VR4300_OP_CEQS, + VR4300_OP_CFC1, + VR4300_OP_CFD, + VR4300_OP_CFS, + VR4300_OP_CLED, + VR4300_OP_CLES, + VR4300_OP_CLTD, + VR4300_OP_CLTS, + VR4300_OP_CNGED, + VR4300_OP_CNGES, + VR4300_OP_CNGLD, + VR4300_OP_CNGLED, + VR4300_OP_CNGLES, + VR4300_OP_CNGLS, + VR4300_OP_CNGTD, + VR4300_OP_CNGTS, + VR4300_OP_COLED, + VR4300_OP_COLES, + VR4300_OP_COLTD, + VR4300_OP_COLTS, + VR4300_OP_CSEQD, + VR4300_OP_CSEQS, + VR4300_OP_CSFD, + VR4300_OP_CSFS, + VR4300_OP_CTC1, + VR4300_OP_CUEQD, + VR4300_OP_CUEQS, + VR4300_OP_CULED, + VR4300_OP_CULES, + VR4300_OP_CULTD, + VR4300_OP_CULTS, + VR4300_OP_CUND, + VR4300_OP_CUNS, + VR4300_OP_CVTDL, + VR4300_OP_CVTDS, + VR4300_OP_CVTDW, + VR4300_OP_CVTLD, + VR4300_OP_CVTLS, + VR4300_OP_CVTSD, + VR4300_OP_CVTSL, + VR4300_OP_CVTSW, + VR4300_OP_CVTWD, + VR4300_OP_CVTWS, + VR4300_OP_DADD, + VR4300_OP_DADDI, + VR4300_OP_DADDIU, + VR4300_OP_DADDU, + VR4300_OP_DDIV, + VR4300_OP_DDIVU, + VR4300_OP_DIV, + VR4300_OP_DIVD, + VR4300_OP_DIVS, + VR4300_OP_DIVU, + VR4300_OP_DMFC1, + VR4300_OP_DMTC1, + VR4300_OP_DMULT, + VR4300_OP_DMULTU, + VR4300_OP_DSLL, + VR4300_OP_DSLL32, + VR4300_OP_DSLLV, + VR4300_OP_DSRA, + VR4300_OP_DSRA32, + VR4300_OP_DSRAV, + VR4300_OP_DSRL, + VR4300_OP_DSRL32, + VR4300_OP_DSRLV, + VR4300_OP_DSUB, + VR4300_OP_DSUBU, + VR4300_OP_ERET, + VR4300_OP_FLOORLD, + VR4300_OP_FLOORLS, + VR4300_OP_FLOORWD, + VR4300_OP_FLOORWS, + VR4300_OP_J, + VR4300_OP_JAL, + VR4300_OP_JALR, + VR4300_OP_JR, + VR4300_OP_LB, + VR4300_OP_LBU, + VR4300_OP_LD, + VR4300_OP_LDC1, + VR4300_OP_LDL, + VR4300_OP_LDR, + VR4300_OP_LH, + VR4300_OP_LHU, + VR4300_OP_LL, + VR4300_OP_LLD, + VR4300_OP_LUI, + VR4300_OP_LW, + VR4300_OP_LWC1, + VR4300_OP_LWL, + VR4300_OP_LWR, + VR4300_OP_LWU, + VR4300_OP_MFC0, + VR4300_OP_MFC1, + VR4300_OP_MFHI, + VR4300_OP_MFLO, + VR4300_OP_MOVD, + VR4300_OP_MOVS, + VR4300_OP_MTC0, + VR4300_OP_MTC1, + VR4300_OP_MTHI, + VR4300_OP_MTLO, + VR4300_OP_MULD, + VR4300_OP_MULS, + VR4300_OP_MULT, + VR4300_OP_MULTU, + VR4300_OP_NEGD, + VR4300_OP_NEGS, + VR4300_OP_NOR, + VR4300_OP_OR, + VR4300_OP_ORI, + VR4300_OP_ROUNDLD, + VR4300_OP_ROUNDLS, + VR4300_OP_ROUNDWD, + VR4300_OP_ROUNDWS, + VR4300_OP_SB, + VR4300_OP_SC, + VR4300_OP_SCD, + VR4300_OP_SD, + VR4300_OP_SDC1, + VR4300_OP_SDL, + VR4300_OP_SDR, + VR4300_OP_SH, + VR4300_OP_SLL, + VR4300_OP_SLLV, + VR4300_OP_SLT, + VR4300_OP_SLTI, + VR4300_OP_SLTIU, + VR4300_OP_SLTU, + VR4300_OP_SQRTD, + VR4300_OP_SQRTS, + VR4300_OP_SRA, + VR4300_OP_SRAV, + VR4300_OP_SRL, + VR4300_OP_SRLV, + VR4300_OP_SUB, + VR4300_OP_SUBD, + VR4300_OP_SUBS, + VR4300_OP_SUBU, + VR4300_OP_SW, + VR4300_OP_SWC1, + VR4300_OP_SWL, + VR4300_OP_SWR, + VR4300_OP_SYNC, + VR4300_OP_SYSCALL, + VR4300_OP_TEQ, + VR4300_OP_TEQI, + VR4300_OP_TGE, + VR4300_OP_TGEI, + VR4300_OP_TGEIU, + VR4300_OP_TGEU, + VR4300_OP_TLBP, + VR4300_OP_TLBR, + VR4300_OP_TLBWI, + VR4300_OP_TLBWR, + VR4300_OP_TLT, + VR4300_OP_TLTI, + VR4300_OP_TLTIU, + VR4300_OP_TLTU, + VR4300_OP_TNE, + VR4300_OP_TNEI, + VR4300_OP_TRUNCLD, + VR4300_OP_TRUNCLS, + VR4300_OP_TRUNCWD, + VR4300_OP_TRUNCWS, + VR4300_OP_XOR, + VR4300_OP_XORI, +}; + +enum vr4300_opnd_type +{ + VR4300_OPND_NULL, + VR4300_OPND_CPU, + VR4300_OPND_CP0, + VR4300_OPND_CP1, + VR4300_OPND_FCR, + VR4300_OPND_JUMP, + VR4300_OPND_BRANCH, + VR4300_OPND_OFFSET, + VR4300_OPND_IMMEDIATE, + VR4300_OPND_CACHE, +}; + +struct vr4300_insn +{ + enum vr4300_op opcode; + enum vr4300_opnd_type opnd_type[3]; + int32_t opnd_value[3]; +}; + +_Bool vr4300_decode_insn(uint32_t code, struct vr4300_insn *insn); +void vr4300_print_insn(struct vr4300_insn *insn, uint32_t addr, FILE *f); + +extern const char *vr4300_reg_mnem[]; +extern const char *vr4300_op_mnem[]; + +#endif diff --git a/tools/gfxdis/main.c b/tools/gfxdis/main.c new file mode 100644 index 00000000..191b0b83 --- /dev/null +++ b/tools/gfxdis/main.c @@ -0,0 +1,406 @@ +#include +#include +#include +#include +#include +#include +#include +#include "gfxdis.h" +#include + +#ifdef _WIN32 +# include +# include +#endif + +#if defined(F3D_GBI) +# if defined(F3D_BETA) +static const char *prog_name = "gfxdis.f3db"; +# else +static const char *prog_name = "gfxdis.f3d"; +# endif +#elif defined(F3DEX_GBI) +# if defined(F3D_BETA) +static const char *prog_name = "gfxdis.f3dexb"; +# else +static const char *prog_name = "gfxdis.f3dex"; +# endif +#elif defined(F3DEX_GBI_2) +static const char *prog_name = "gfxdis.f3dex2"; +#endif + +static int usage(void) +{ + fprintf(stderr, + "gfxdis-0.6: display list disassembler\n" + "written by: glank\n" + "build date: " __TIME__ ", " __DATE__ "\n" + "usage:\n" + " %s [-x] [-i] [-dc] [-p] [-r] [-g ] [-n ] [-a ] " + "{ -f | -d }\n" + "options:\n" + " -x do not use fixed-point conversion macros\n" + " -i do not stop at unrecognized or malformed " + "instructions\n" + " -dc use decimal numbers for color components\n" + " -p print offsets\n" + " -r print raw data\n" + " -g generate dynamic macros with as the first " + "argument\n" + " -n disassemble at most instructions\n" + " -a start disassembling at \n" + " -f disassemble , '-' for stdin\n" + " -d disassemble hexadecimal byte codes from the " + "command line\n", + prog_name); + return -1; +} + +static int parse_number(const char *str, int base, int *num) +{ + int sign = 1; + if (base < 0) { + if (str[0] == '+') + ++str; + else if (str[0] == '-') { + sign = -1; + ++str; + } + base = -base; + } + if (base <= 1) { + if (strncmp(str, "0x", 2) == 0 || strncmp(str, "0X", 2) == 0) { + base = 16; + str += 2; + } + else if (strncmp(str, "0b", 2) == 0 || strncmp(str, "0B", 2) == 0) { + base = 2; + str += 2; + } + else if (str[0] == '0' && str[1] != 0) { + base = 8; + ++str; + } + else + base = 10; + } + int v = 0; + do { + int c = *str++; + if (c >= '0' && c <= '9') + c = c - '0'; + else if (c >= 'a' && c <= 'f') + c = c - 'a' + 10; + else if (c >= 'A' && c <= 'F') + c = c - 'A' + 10; + else + return -1; + if (c >= base) + return -1; + v = v * base + c; + } while (*str); + v = v * sign; + *num = v; + return 0; +} + +static int gfx_v_num(struct vector *gfx_v) +{ + return gfx_v->size * gfx_v->element_size / sizeof(Gfx); +} + +static _Bool gfx_v_ate(struct vector *gfx_v, int max) +{ + return max >= 0 && gfx_v_num(gfx_v) >= max; +} + +static int from_file(struct vector *gfx_v, const char *filename, int max, + int offset) +{ + int result = 0; +#ifdef _WIN32 + int mode = _O_TEXT; +#endif + + FILE *f = NULL; + if (strcmp(filename, "-") == 0) { + filename = "stdin"; +#ifdef _WIN32 + mode = _setmode(_fileno(stdin), _O_BINARY); + if (mode == -1) { + fprintf(stderr, "%s: %s: %s\n", prog_name, strerror(errno), filename); + goto err; + } +#endif + f = stdin; + } + else { + f = fopen(filename, "rb"); + if (!f) { + fprintf(stderr, "%s: %s: %s\n", prog_name, strerror(errno), filename); + goto err; + } + } + + if (offset != 0 && fseek(f, offset, SEEK_SET)) { + for (int i = 0; i < offset; ++i) { + if (fgetc(f) == EOF) { + if (ferror(f)) { + fprintf(stderr, "%s: %s: %s\n", prog_name, strerror(errno), + filename); + goto err; + } + else + break; + } + } + } + + while (!gfx_v_ate(gfx_v, max)) { + Gfx gfx; + if (fread(&gfx, sizeof(gfx), 1, f) != 1) { + if (ferror(f)) { + fprintf(stderr, "%s: %s: %s\n", prog_name, strerror(errno), filename); + goto err; + } + else + break; + } + int n = sizeof(gfx) / gfx_v->element_size; + if (!vector_push_back(gfx_v, n, &gfx)) { + fprintf(stderr, "%s: out of memory\n", prog_name); + goto err; + } + } + + goto exit; + +err: + result = -1; + +exit: + if (f) { + if (f == stdin) { +#ifdef _WIN32 + _setmode(_fileno(f), mode); +#endif + } + else + fclose(f); + } + + return result; +} + +static int from_line(struct vector *gfx_v, int argc, char *argv[], int argp, + int max, int offset) +{ + int result = 0; + + int pos = 0; + while (argp < argc) { + char *p = argv[argp++]; + while (*p) { + unsigned char byte = 0; + for (int i = 0; i < 2 && *p; ++i) { + int c = *p++; + if (c >= '0' && c <= '9') + c = c - '0'; + else if (c >= 'a' && c <= 'f') + c = c - 'a' + 10; + else if (c >= 'A' && c <= 'F') + c = c - 'A' + 10; + else { + fprintf(stderr, "%s: invalid input data: %c\n", prog_name, c); + goto err; + } + byte = byte * 16 + c; + } + if (pos++ >= offset && !gfx_v_ate(gfx_v, max)) { + int n = gfx_v->element_size / sizeof(byte); + if (!vector_push_back(gfx_v, n, &byte)) { + fprintf(stderr, "%s: out of memory\n", prog_name); + goto err; + } + } + } + } + + goto exit; + +err: + result = -1; + +exit: + return result; +} + +int main(int argc, char *argv[]) +{ + int result = 0; + + struct vector gfx_v; + vector_init(&gfx_v, sizeof(unsigned char)); + + if (argc == 1) { + result = usage(); + goto exit; + } + + int argp = 1; + const char *opt_x = NULL; + const char *opt_i = NULL; + const char *opt_dc = NULL; + const char *opt_p = NULL; + const char *opt_r = NULL; + const char *opt_g = NULL; + const char *opt_n = NULL; + const char *opt_a = NULL; + const char *opt_f = NULL; + const char *opt_d = NULL; + while (argp < argc) { + _Bool param = 0; + const char **p_opt; + if (strcmp(argv[argp], "-x") == 0) + p_opt = &opt_x; + else if (strcmp(argv[argp], "-i") == 0) + p_opt = &opt_i; + else if (strcmp(argv[argp], "-dc") == 0) + p_opt = &opt_dc; + else if (strcmp(argv[argp], "-p") == 0) + p_opt = &opt_p; + else if (strcmp(argv[argp], "-r") == 0) + p_opt = &opt_r; + else if (strcmp(argv[argp], "-g") == 0) { + param = 1; + p_opt = &opt_g; + } + else if (strcmp(argv[argp], "-n") == 0) { + param = 1; + p_opt = &opt_n; + } + else if (strcmp(argv[argp], "-a") == 0) { + param = 1; + p_opt = &opt_a; + } + else if (strcmp(argv[argp], "-f") == 0) { + param = 1; + p_opt = &opt_f; + } + else if (strcmp(argv[argp], "-d") == 0) + p_opt = &opt_d; + else + break; + if (param) { + ++argp; + if (argp >= argc) { + fprintf(stderr, "%s: option requires a parameter: %s\n", prog_name, + argv[argp - 1]); + goto err; + } + } + *p_opt = argv[argp++]; + } + + if (opt_f && argp != argc) { + fprintf(stderr, "%s: unrecognized option: %s\n", prog_name, argv[argp]); + goto err; + } + + if ((opt_d != NULL) == (opt_f != NULL)) { + fprintf(stderr, "%s: specify either -f or -d\n", prog_name); + goto err; + } + + int max = -1; + if (opt_n && parse_number(opt_n, 1, &max)) { + fprintf(stderr, "%s: bad number given for -n: %s\n", prog_name, opt_n); + goto err; + } + + int offset = 0; + if (opt_a && parse_number(opt_a, 1, &offset)) { + fprintf(stderr, "%s: bad number given for -a: %s\n", prog_name, opt_a); + goto err; + } + + if (opt_f) + result = from_file(&gfx_v, opt_f, max, offset); + else if (opt_d) + result = from_line(&gfx_v, argc, argv, argp, max, offset); + if (result) + goto exit; + + gfxdis_cfg.dis_invd = (opt_i != NULL); + gfxdis_cfg.use_q = (opt_x == NULL); + gfxdis_cfg.dec_color = (opt_dc != NULL); + + { + Gfx *raw = gfx_v.begin; + int raw_p = 0; + struct vector insn_vect; + result = gfx_dis(&insn_vect, raw, gfx_v_num(&gfx_v)); + if (opt_g == NULL) + printf("{\n"); + for (int i = 0; i < insn_vect.size; ++i) { + char s[1024]; + struct gfx_insn *insn = vector_at(&insn_vect, i); + if (opt_g == NULL) + gfx_insn_str(insn, s); + else + gfx_insn_str_dyn(insn, opt_g, s); + if (opt_p || opt_r) { + int n = opt_r ? insn->n_gfx : 1; + for (int j = 0; j < n; ++j) { + if (opt_g == NULL) + printf(" /*"); + else + printf("/*"); + if (opt_p) { + uint32_t addr = offset + (raw_p + j) * sizeof(Gfx); + printf(" %08" PRIX32 ":", addr); + } + if (opt_r) { + uint32_t hi = btoh32(raw[raw_p + j].hi); + uint32_t lo = btoh32(raw[raw_p + j].lo); + printf(" %08" PRIX32 " %08" PRIX32, hi, lo); + } + if (j == 0) { + if (opt_g == NULL) + printf(" */ %s,\n", s); + else + printf(" */ %s;\n", s); + } + else + printf(" */\n"); + } + } + else { + if (opt_g == NULL) + printf(" %s,\n", s); + else + printf("%s;\n", s); + } + raw_p += insn->n_gfx; + } + vector_destroy(&insn_vect); + if (opt_g == NULL) + printf("}\n"); + if (result == -1) + fprintf(stderr, "%s: out of memory\n", prog_name); + } + + goto exit; + +err: + result = -1; + +exit: + vector_destroy(&gfx_v); + + return result; +} + +#include + + diff --git a/tools/gfxdis/swap.h b/tools/gfxdis/swap.h new file mode 100644 index 00000000..f3b6c881 --- /dev/null +++ b/tools/gfxdis/swap.h @@ -0,0 +1,82 @@ +#ifndef SWAP_H +#define SWAP_H +// #include +#include + +static inline uint32_t htob32(uint32_t v) +{ +#ifndef WORDS_BIGENDIAN + return ((v & 0xFF000000) >> 24) | ((v & 0x00FF0000) >> 8) | + ((v & 0x0000FF00) << 8) | ((v & 0x000000FF) << 24); +#else + return v; +#endif +} + +static inline uint32_t btoh32(uint32_t v) +{ +#ifndef WORDS_BIGENDIAN + return ((v & 0xFF000000) >> 24) | ((v & 0x00FF0000) >> 8) | + ((v & 0x0000FF00) << 8) | ((v & 0x000000FF) << 24); +#else + return v; +#endif +} + +static inline uint16_t htob16(uint16_t v) +{ +#ifndef WORDS_BIGENDIAN + return ((v & 0xFF00) >> 8) | ((v & 0x00FF) << 8); +#else + return v; +#endif +} + +static inline uint16_t btoh16(uint16_t v) +{ +#ifndef WORDS_BIGENDIAN + return ((v & 0xFF00) >> 8) | ((v & 0x00FF) << 8); +#else + return v; +#endif +} + +static inline uint32_t htol32(uint32_t v) +{ +#ifdef WORDS_BIGENDIAN + return ((v & 0xFF000000) >> 24) | ((v & 0x00FF0000) >> 8) | + ((v & 0x0000FF00) << 8) | ((v & 0x000000FF) << 24); +#else + return v; +#endif +} + +static inline uint32_t ltoh32(uint32_t v) +{ +#ifdef WORDS_BIGENDIAN + return ((v & 0xFF000000) >> 24) | ((v & 0x00FF0000) >> 8) | + ((v & 0x0000FF00) << 8) | ((v & 0x000000FF) << 24); +#else + return v; +#endif +} + +static inline uint16_t htol16(uint16_t v) +{ +#ifdef WORDS_BIGENDIAN + return ((v & 0xFF00) >> 8) | ((v & 0x00FF) << 8); +#else + return v; +#endif +} + +static inline uint16_t ltoh16(uint16_t v) +{ +#ifdef WORDS_BIGENDIAN + return ((v & 0xFF00) >> 8) | ((v & 0x00FF) << 8); +#else + return v; +#endif +} + +#endif diff --git a/tools/gfxdis/vector/vector.c b/tools/gfxdis/vector/vector.c new file mode 100644 index 00000000..7085afd8 --- /dev/null +++ b/tools/gfxdis/vector/vector.c @@ -0,0 +1,155 @@ +/* vector.c + * -glank + */ + +#include +#include +#include "vector.h" + + +#ifdef __cplusplus +extern "C" +{ +#endif + +void vector_init(struct vector *vector, size_t element_size) +{ + vector->element_size = element_size; + vector->size = 0; + vector->capacity = 0; + vector->begin = 0; + vector->end = 0; + vector->rbegin = 0; + vector->rend = 0; +} + +void *vector_at(const struct vector *vector, size_t position) +{ + if (!vector->begin || position >= vector->size) + return 0; + return (char*)vector->begin + vector->element_size * position; +} + +int vector_reserve(struct vector *vector, size_t num) +{ + size_t new_cap = vector->size + num; + if (new_cap <= vector->capacity) + return 1; + char *new_data = (char*)realloc(vector->begin, vector->element_size * new_cap); + if (!new_data) + return 0; + vector->begin = new_data; + vector->rend = new_data - vector->element_size; + vector->end = (char*)vector->begin + vector->element_size * vector->size; + vector->rbegin = (char*)vector->end - vector->element_size; + vector->capacity = new_cap; + return 1; +} + +void *vector_insert(struct vector *vector, size_t position, size_t num, + const void *data) +{ + if (num == 0) { + if (vector->begin) + return vector->begin; + else + return (void*)1; + } + if (position > vector->size) + return 0; + size_t new_cap = vector->capacity; + if (new_cap == 0) + new_cap = num; + else { + if (new_cap < vector->size + num) + new_cap *= 2; + if (new_cap < vector->size + num) + new_cap = vector->size + num; + } + if (new_cap != vector->capacity) { + char *new_data = (char*)realloc(vector->begin, + vector->element_size * new_cap); + if (!new_data) + return 0; + vector->begin = new_data; + vector->rend = new_data - vector->element_size; + vector->capacity = new_cap; + } + memmove((char*)vector->begin + vector->element_size * (position + num), + (char*)vector->begin + vector->element_size * position, + vector->element_size * (vector->size - position)); + if (data) + memcpy((char*)vector->begin + vector->element_size * position, data, + vector->element_size * num); + vector->size += num; + vector->end = (char*)vector->begin + vector->element_size * vector->size; + vector->rbegin = (char*)vector->end - vector->element_size; + return (char*)vector->begin + vector->element_size * position; +} + +void *vector_push_back(struct vector *vector, size_t num, const void *data) +{ + return vector_insert(vector, vector->size, num, data); +} + +int vector_erase(struct vector *vector, size_t position, size_t num) +{ + if (!vector->begin || num > vector->size || position >= vector->size) + return 0; + if (num == vector->size) { + vector_clear(vector); + return 1; + } + memmove((char*)vector->begin + vector->element_size * position, + (char*)vector->begin + vector->element_size * (position + num), + vector->element_size * (vector->size - position - num)); + vector->size -= num; + vector->end = (char*)vector->begin + vector->element_size * vector->size; + vector->rbegin = (char*)vector->end - vector->element_size; + return 1; +} + +int vector_shrink_to_fit(struct vector *vector) +{ + size_t new_cap = vector->size; + char *new_data = (char*)realloc(vector->begin, + vector->element_size * new_cap); + if (new_cap > 0 && !new_data) + return 0; + vector->begin = new_data; + vector->rend = new_data - vector->element_size; + vector->end = (char*)vector->begin + vector->element_size * vector->size; + vector->rbegin = (char*)vector->end - vector->element_size; + vector->capacity = new_cap; + return 1; +} + +void *vector_release(struct vector *vector) +{ + void *data = vector->begin; + vector->size = 0; + vector->capacity = 0; + vector->begin = 0; + vector->end = 0; + vector->rbegin = 0; + vector->rend = 0; + return data; +} + +void vector_clear(struct vector *vector) +{ + vector->size = 0; + vector->end = vector->begin; + vector->rbegin = vector->begin; + vector->rend = vector->begin; +} + +void vector_destroy(struct vector *vector) +{ + if (vector->begin) + free(vector->begin); +} + +#ifdef __cplusplus +} +#endif diff --git a/tools/gfxdis/vector/vector.h b/tools/gfxdis/vector/vector.h new file mode 100644 index 00000000..1ff674e0 --- /dev/null +++ b/tools/gfxdis/vector/vector.h @@ -0,0 +1,37 @@ +/* vector.h + * -glank + */ + +#ifndef VECTOR_H +#define VECTOR_H +#include + +struct vector +{ + size_t element_size, size, capacity; + void *begin, *end; + void *rbegin, *rend; +}; + +#ifdef __cplusplus +extern "C" +{ +#endif + +void vector_init(struct vector *vector, size_t element_size); +void *vector_at(const struct vector *vector, size_t position); +int vector_reserve(struct vector *vector, size_t num); +void *vector_insert(struct vector *vector, size_t position, size_t num, + const void *data); +void *vector_push_back(struct vector *vector, size_t num, const void *data); +int vector_erase(struct vector *vector, size_t position, size_t num); +int vector_shrink_to_fit(struct vector *vector); +void *vector_release(struct vector *vector); +void vector_clear(struct vector *vector); +void vector_destroy(struct vector *vector); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/tools/gfxdis_f3dex2 b/tools/gfxdis_f3dex2 new file mode 100755 index 00000000..0bd58bb0 Binary files /dev/null and b/tools/gfxdis_f3dex2 differ diff --git a/tools/scut/GeoFromBin.py b/tools/scut/GeoFromBin.py new file mode 100644 index 00000000..429f581a --- /dev/null +++ b/tools/scut/GeoFromBin.py @@ -0,0 +1,840 @@ +import struct +import math +from KirbyCSdatatypes import * + +globBank = 0 +globIndex = 0 + +symbols = {} + +#------------------------------------------------------------------------------- +#Geo Block Functions + +def SegPtrList(start,rom): + i=0 + arr = [] + while(True): + ar = struct.unpack(">L",rom[start+i:start+i+4]) + arr.append(ar) + if ar[0] == 0: + break + i+=4 + return arr + +def GetGeoHeader(rom,start): + header = [] + for s in Geo_Header.keys(): + v = struct.unpack(">L",rom[start+s:start+s+4]) + header.append([Geo_Header[s],v]) + return header + +def GetGeoVertRefs(rom,start,GH): + start = start+(GH[4][1][0]&0xFFFFFF) + symbols[start | 0x04000000] = "bank_%d_index_%d_vert_load_refs_%08X" % (globBank, globIndex, start | 0x04000000) + refs = SegPtrList(start,rom) + return refs + +def GetGeoImgRefs(rom,start,GH): + start = start+(GH[3][1][0]&0xFFFFFF) + symbols[start | 0x04000000] = "bank_%d_index_%d_tex_img_refs_%08X" % (globBank, globIndex, start | 0x04000000) + refs = SegPtrList(start,rom) + return refs + +def GetLayout(rom,start,GH,end): + start = start+(GH[0][1][0]&0xFFFFFF) + layout = [] + end = end+(GH[0][1][0]&0xFFFFFF) + len = end-start + i=0 + env = [] + Envfx = False + symbols[start | 0x04000000] = "bank_%d_index_%d_layout_%08X" % (globBank, globIndex, start | 0x04000000) + while(True): + v = [] + for s in Layout.keys(): + q = struct.unpack(Layout.get(s)[0],rom[start+s+i:i+start+s+Layout.get(s)[2]]) + if s == 4: + q2 = struct.unpack(Layout.get(s)[0],rom[start+s+i:i+start+s+Layout.get(s)[2]])[0] + if q2 != 0: + symbols[q2] = "bank_%d_index_%d_entry_point_%08X" % (globBank, globIndex, q2) + v.append([Layout.get(s)[1],q]) + if Envfx: + env.append(v) + else: + layout.append(v) + if v[1][1][0] == 0x12 and (v[2][1][0]&0x80000000==0x80000000): + Envfx = True + elif v[1][1][0] == 0x12: + break + elif (Envfx == True and (v[0][1][0]&0x8000)==0x8000) or i>(len-48): + break + i+=44 + return [layout,env] + +def GetEntryPoints(rom,start,Layout,DLmembers): + entry = [] + starts = [] + for L in Layout: + #Only get ones in bank 4. + if L[2][1][0]&0xFF000000 !=0x04000000: + continue + Estart = start+(L[2][1][0]&0xFFFFFF) + starts.append(L[2][1][0]) + i=0 + E = [] + while(True): + DLm = DLmembers+1 + v = struct.unpack(">%dL"%DLm,rom[Estart+i:Estart+i+DLm*4]) + E.append(v) + if v[0] == 4: + break + i+=DLm*4 + entry.append(E) + return [entry,starts] + +def GetEntryPoints14(rom,start,ptr): + entry = [] + starts = [] + Estart = start+(ptr&0xFFFFFF) + starts.append(ptr) + i=0 + E = [] + while(True): + v = struct.unpack(">2L",rom[Estart+i:Estart+i+8]) + E.append(v) + if v[0] == 4: + break + i+=8 + entry.append(E) + return [entry,starts] + +def GetEntryPoints1B(rom,start,Layout): + entry = [] + starts = [] + for L in Layout: + #Only get ones in bank 4. + if L[2][1][0]&0xFF000000 !=0x04000000: + continue + Estart = start+(L[2][1][0]&0xFFFFFF) + starts.append(L[2][1][0]) + i=0 + E = [] + v = struct.unpack(">L",rom[Estart+i:Estart+i+4])[0] + q = struct.unpack(">L",rom[Estart+i+4:Estart+i+8])[0] + #This is a bit idiotic but I do this so I don't have to + #create if statements for each specific render mode. + E.append([0,v]) + E.append([0,q]) + entry.append(E) + entry.append([[4,0]]) + return [entry,starts] + +def GetGroups(rom,start,Layout): + group = [] + starts = [] + for L in Layout: + if L[2][1][0]&0xFF000000 !=0x04000000: + continue + group.append([0,(L[2][1][0])]) + starts.append(L[2][1][0]) + group.append([4,0]) + return [[group],starts] + +def GetMicrocode(rom,start,EP,end,DLmembers): + f3d = [] + starts = [] + jumps = [] + jumped = 0 + for p in EP: + for s in p: + if s[0] == 4: + continue + #an entry point can have any number of DL members in it theoretically + for j in range(1,DLmembers+1,1): + ex2 = [] + #I dynamically create new entry points to deal with jumps. + #This should deal with that error + if j>=len(s): + continue + if s[j]==0: + continue + Fstart = start + (s[j]&0xFFFFFF) + starts.append(s[j]) + if Fstart>end: + break + endDL = 0xDF00000000000000 + JumpEnd = 0xDE01000000000000 + JUMP = 0xDE00000000000000 + BZ = 0xE100000000000000 + i=0 + while(True): + f = struct.unpack(">Q",rom[Fstart+i:Fstart+i+8]) + if f[0] >> 56 == 0x01: + symbols[f[0] & 0xFFFFFFFF] = "bank_%d_index_%d_vtx_%08X" % (globBank, globIndex, f[0] & 0xFFFFFFFF) + ex2.append(f) + if ((f[0] & 0xFF00000000000000)==JUMP) or ((f[0] & 0xFFFFFFFF00000000)==BZ): + if f[0]&0xFF000000==0x04000000: + newEP = (0x1,f[0]&0xFFFFFFFF) + if newEP not in jumps: + p.append(newEP) + jumps.append(newEP) + jumped = newEP + if f[0] == endDL or f[0]&0xFFFFFFFF00000000 == JumpEnd: + break + if Fstart+i>end: + break + i+=8 + f3d.extend([ex2]) + for p in EP: + for a in jumps: + if a in p: + p.remove(a) + return [f3d,starts] + +#switched to dumping verts raw and have gotten better results. Easier to parse too. +def GetGeoVerticesOld(rom,start,VR): + Verts = [] + starts = [] + Vbufs = [] + ranges = [] + for ref in VR: + if ref[0] == 0: + break + Vstart = start + (ref[0]&0xFFFFFF) + G_VTX = struct.unpack(">2L",rom[Vstart:Vstart+8]) + num = (G_VTX[0]&0x000FF000)>>12 + VLoad = (G_VTX[1]&0x00FFFFFF)+start + #remove duplicate verts and clip buffers + if G_VTX[1] in starts: + #low hanging fruit + continue + skip=0 + for v in Vbufs: + #skips + if VLoad<(v[0]+v[1]*16) and VLoad>v[0]: + skip=1 + break + if not skip: + Vbufs.append([VLoad,num]) + starts.append(G_VTX[1]) + #Now I must sort the lists + starts.sort() + Vbufs.sort(key=lambda x: x[0]) + for ref in Vbufs: + VB = [] + for i in range(ref[1]): + Vert = [] + for q in Geo_Vert.keys(): + Vert.append([Geo_Vert.get(q)[1],struct.unpack(Geo_Vert.get(q)[0],rom[i*16+ref[0]+q:i*16+ref[0]+q+Geo_Vert.get(q)[2]])]) + VB.append(Vert) + Verts.append(VB) + return [Verts,starts] + +def GetGeoVertices(rom,start,starts): + startGV =start + 0x20 + if not starts: + return None + q = starts.copy() + q.sort() + end = q[0] + GV = [] + for i in range(startGV,(end&0xFFFFFF)+start,16): + V = [] + for q in Geo_Vert.keys(): + V.append([Geo_Vert.get(q)[1],struct.unpack(Geo_Vert.get(q)[0],rom[i+q:i+q+Geo_Vert.get(q)[2]])]) + GV.append(V) + return GV + +def GetTextureScrolls(rom,start,GH): + TS = GH[1][1][0] + ts = [] + Unk = GH[6][1][0] + l = Unk-TS + if TS and Unk: + Hstart = start+(TS&0x00FFFFFF) + symbols[Hstart | 0x04000000] = "bank_%d_index_%d_texscroll_header_%08X" % (globBank, globIndex, Hstart | 0x04000000) + h = [] + ptrs = [] + i=0 + k=0 + while(True): + word = struct.unpack(">L",rom[Hstart+i*4:i*4+4+Hstart]) + if word[0]==0x99999999: + h.append(word) + k=i*4+4 + break + elif word[0]: + symbols[word[0]] = "bank_%d_index_%d_texture_scroll_subheader_%08X" % (globBank, globIndex, word[0]) + ptrs.append(word) + h.append(word) + else: + h.append(word) + i+=1 + Dptrs = [] + Header2 = [] + for p in ptrs: + Pstart = start+(p[0]&0x00FFFFFF) + i=0 + L = [] + while(True): + word = struct.unpack(">L",rom[Pstart+i*4:i*4+4+Pstart]) + if word[0]==0x99999999: + L.append(word) + break + elif word[0]: + symbols[word[0]] = "bank_%d_index_%d_texture_scroll_%08X" % (globBank, globIndex, word[0]) + Dptrs.append(word) + L.append(word) + else: + L.append(word) + i+=1 + Header2.append([L,p[0]]) + #Now Dptrs is a list of pointers to my 0x78 byte structs. + #Header 2 is a list of all the ptr headers that was inside the main header. + #The texture scroll order should be TSheader,padding,structs,Secondary Headers. + #I will check for padding, but seeing the address of the first thing inside Dptrs, and seeing if + #it matches with the end of the main header, aka variable k. + StructStart = start+(Dptrs[0][0]&0x00FFFFFF) + PadStart = Hstart+k + pad = [] + padLen = StructStart-PadStart + for p in range(padLen)[::4]: + pad.append(struct.unpack(">L",rom[PadStart+p:PadStart+p+4])) + tHs = [*h] + tPad = [*pad] + #Now dumping TS structs. + prev = StructStart + TUnk = [] + for D in Dptrs: + Dstart = start+(D[0]&0x00FFFFFF) + if (Dstart-prev)>0x78: + R = (Dstart-prev-0x78)//4 + TUnk.append(struct.unpack(">%dL"%R,rom[prev+0x78:prev+0x78+R*4])) + else: + TUnk.append(()) + prev = Dstart + scroll = [] + for o,t in TextureScrollStruct.items(): + scroll.append(struct.unpack(t[0],rom[Dstart+o:Dstart+o+t[2]])) + ts.append([scroll,D[0]]) + return [tHs,ts,Header2,tPad,TUnk] + else: + return [None,None,None,None,None] + +def GetUnknown2(rom,start,GH): + Unk = GH[6][1][0] + num = GH[5][1][0] + u = [] + if Unk: + start = start+(Unk&0x00FFFFFF) + symbols[start | 0x04000000] = "bank_%d_index_%d_anims_%08X" % (globBank, globIndex, start | 0x04000000) + for b in range(num): + u.append(struct.unpack(">L",rom[start+4*b:start+4*b+4])) + return u + else: + return [] + +dlists = [] + +def GetGeoBlockData(rom,start,end): + GH = GetGeoHeader(rom,start) + [THS,TS,H2,tPad,tUnk] = GetTextureScrolls(rom,start,GH) + VR = GetGeoVertRefs(rom,start,GH) + IR = GetGeoImgRefs(rom,start,GH) + #Depending on whether the layout is 0x17 or 0x18 the seg ptrs are different + #In 5-4-7 and 5-4-8 a render mode of 0x1C is used which I have no idea about. + if GH[2][1][0] == 0x17: + [L,env] = GetLayout(rom,start,GH,end) + [SP,SPstart] = GetGroups(rom,start,L) + [f3d,starts] = GetMicrocode(rom,start,SP,end,1) #I get the end ptr here for while loop safety + SP = [] + elif GH[2][1][0] == 0x18: + [L,env] = GetLayout(rom,start,GH,end) + [SP,SPstart] = GetEntryPoints(rom,start,L,1) + [f3d,starts] = GetMicrocode(rom,start,SP,end,1) #I get the end ptr here for while loop safety + elif GH[2][1][0] == 0x1C: + [L,env] = GetLayout(rom,start,GH,end) + #basically the same as 0x18, but entry points have two DL members. + [SP,SPstart] = GetEntryPoints(rom,start,L,2) + [f3d,starts] = GetMicrocode(rom,start,SP,end,2) #I get the end ptr here for while loop safety + elif GH[2][1][0] == 0x14: + L = [] + env = [] + [SP,SPstart] = GetEntryPoints14(rom,start,GH[0][1][0]) + [f3d,starts] = GetMicrocode(rom,start,SP,end,1) #I get the end ptr here for while loop safety + elif GH[2][1][0] == 0x13: + L = [] + env = [] + SP = [[[0,GH[0][1][0]],[4,0]]] + SPstart = [GH[0][1][0]] + [f3d,starts] = GetMicrocode(rom,start,SP,end,1) #I get the end ptr here for while loop safety + elif GH[2][1][0] == 0x1B: + [L,env] = GetLayout(rom,start,GH,end) + [SP,SPstart] = GetEntryPoints1B(rom,start,L) + [f3d,starts] = GetMicrocode(rom,start,SP,end,1) #I get the end ptr here for while loop safety + else: + f3d = [] + SP = [] + starts = [] + SPstart = [] + L = [] + env = [] + for i in starts: + symbols[i] = "bank_%d_index_%d_dl_%08X" % (globBank, globIndex, i) + GV = GetGeoVertices(rom,start,starts) + #old cringe method which I'm now retiring. Caused me to parse entire DL + #too many times. + images = [] + unk = GetUnknown2(rom,start,GH) + VBs = [] #old code + return [GH,GV,f3d,IR,VR,SP,L,TS,images,starts,SPstart,VBs,unk,env,THS,H2,tPad,tUnk] + +def WriteGeoBlock(file,GeoBlock,rom): + RM = GeoBlock[0][2][1][0] + file.write( + "#include \n" + "#include \"geo_block_header.h\"\n" + "#include \"stages.h\"\n\n" + ) + + for ket in symbols: + if "subheader" in symbols[ket]: + file.write("extern struct TextureScroll *%s[];\n" % symbols[ket]) + if "_dl_" in symbols[ket]: + file.write("extern Gfx %s[];\n" % symbols[ket]) + + file.write("\n") + + WriteGeoHeader(file,GeoBlock[0]) + WriteGeoVerts(file,GeoBlock[1],GeoBlock[11]) + WriteGeoF3d2(file,GeoBlock[2],GeoBlock[9]) + WriteImgRefs(file,GeoBlock[3]) + WriteVertRefs(file,GeoBlock[4]) + #deal with entry points to display lists differently + #depending on render mode. + if RM==0x18 or RM==0x17 or RM==0x14: + WriteEntryPoints(file,GeoBlock[5],GeoBlock[10]) + elif RM==0x1B: + WriteDLPairs(file,GeoBlock[5],GeoBlock[10]) + elif RM==0x1C: + WriteEntryPoints1C(file,GeoBlock[5],GeoBlock[10]) + if RM!=0x13: + WriteLayout(file,GeoBlock[6],GeoBlock[13],GeoBlock[0]) + else: + file.write("\n// No entry points in render mode 0x13\n") + file.write("\n// No layout in render mode 0x13\n") + WriteTS(file,GeoBlock[0],GeoBlock[7],GeoBlock[14],GeoBlock[15],GeoBlock[16],GeoBlock[17]) + WriteUnk2(file,GeoBlock[0],GeoBlock[12]) + file.close() + del file + +def WriteGeoHeader(file,GH): + global globBank, globIndex + buf = "" + buf += "\nstruct GeoBlockHeader bank_%d_index_%d_geo_block_header = {\n" % (globBank, globIndex) + for h in zip(GH,Geo_Header.keys()): + if h[1] == 0x1c: + buf += " /*0x%02X*/ 0x%X,\n};\n\n"%(h[1],h[0][1][0]) + elif h[1] == 0: + if h[0][1][0] == 0: + buf += " /*0x%02X*/ NULL,\n"%(h[1],h[0][1][0]) + else: + file.write("extern struct Layout %s[];\n" % symbols[h[0][1][0]]) + # buf += " /*0x%02X*/ (struct Layout *) 0x%08X,\n"%(h[1],h[0][1][0]) + buf += " /*0x%02X*/ %s,\n"%(h[1],symbols[h[0][1][0]]) + elif h[1] == 4: + if h[0][1][0] == 0: + buf += " /*0x%02X*/ NULL,\n"%(h[1]) + else: + file.write("extern struct TextureScroll **%s[];\n" % symbols[h[0][1][0]]) + # buf += " /*0x%02X*/ (struct TextureScroll **) 0x%08X,\n"%(h[1],h[0][1][0]) + buf += " /*0x%02X*/ %s,\n"%(h[1],symbols[h[0][1][0]]) + elif h[1] == 0xC: + if h[0][1][0] == 0: + buf += " /*0x%02X*/ NULL,\n"%(h[1]) + else: + file.write("extern Gfx *%s[];\n" % symbols[h[0][1][0]]) + buf += " /*0x%02X*/ %s,\n"%(h[1],symbols[h[0][1][0]]) + elif h[1] == 16: + if h[0][1][0] == 0: + buf += " /*0x%02X*/ NULL,\n"%(h[1]) + else: + file.write("extern Gfx *%s[];\n" % symbols[h[0][1][0]]) + buf += " /*0x%02X*/ %s,\n"%(h[1],symbols[h[0][1][0]]) + elif h[1] == 0x18: + if h[0][1][0] == 0: + buf += " /*0x%02X*/ NULL,\n"%(h[1]) + else: + file.write("extern u32 %s[];\n" % symbols[h[0][1][0]]) + buf += " /*0x%02X*/ %s,\n"%(h[1],symbols[h[0][1][0]]) + else: + buf += " /*0x%02X*/ 0x%X,\n"%(h[1],h[0][1][0]) + file.write(buf) + +def tc(a): + return struct.unpack('>h', bytes.fromhex(str(a)))[0] + +import binascii +def WriteGeoVerts(file,GV,VBs): + global globBank, globIndex + if not GV: + return + # file.write("%s\n"%Geo_Vertices_Comment) + segAddr = 0x04000020 + hits = 0 + for j,v in enumerate(GV): + if segAddr in symbols: + if hits == 0: + file.write("Vtx bank_%d_index_%d_vtx_04000020[] = {\n" % (globBank, globIndex)) + else: + file.write("};\n\nVtx bank_%d_index_%d_vtx_%08X[] = {\n" % (globBank, globIndex, segAddr)) + hits+=1 + file.write(" {{{"+"{:>6}, {:>7}, {:>7}".format( + v[0][1][0], + v[0][1][1], + v[0][1][2], + ) + "}, " + "{}, ".format(v[1][1][0])+"{"+"{:>6}, {:>7}".format( + v[2][1][0], + v[2][1][1], + ) + "}, {"+"0x{:02x}, 0x{:02x}, 0x{:02x}, 0x{:02x}".format( + int(v[3][1][0]), + int(v[3][1][1]), + int(v[3][1][2]), + int(v[3][1][3]), + )+"}}},\n" + ) + segAddr += 16 + file.write("};\n\n") + +import subprocess +def WriteGeoF3d(file,f3d,starts): + global globBank, globIndex + + n=0 + #Sorting stuff when writing so its in the same order it is in the ROM + NewStarts = [[i,s] for i,s in enumerate(starts)] + NewStarts.sort(key= lambda x: x[1]) + NewF3D = [f3d[i[0]] for i in NewStarts] + for j,l in enumerate(NewF3D): + file.write("Gfx bank_%d_index_%d_dl_%08X[] = {\n"%(globBank, globIndex, NewStarts[n][1])) + n+=1 + for k,cmd in enumerate(l): + #idk why I built this to work off hex strings but now it + #fucks my ass and I have to do this dumb method. + hs = "%016X"%cmd[0] + # print(hs) + proc = subprocess.Popen( + "tools/gfxdis.f3dex2 -x -d " + str(hs) + , + shell=True, + stdout=subprocess.PIPE, + ) + toReturn = proc.communicate()[0].decode("ascii") + + toReturn = toReturn.split("\n")[1] + if "gsSPVertex" in toReturn: + tr2 = toReturn.replace(",", " ").replace("(", " ").replace(")"," ").split() + ad = int(tr2[1], 16) + if ad in symbols: + tr2[1] = "bank_%d_index_%d_vtx_%08X" % (globBank, globIndex, ad) + toReturn = " gsSPVertex(%s, %s, %s)," % (tr2[1], tr2[2], tr2[3]) + if "gsSPDisplayList" in toReturn: + tr2 = toReturn.replace(",", " ").replace("(", " ").replace(")"," ").split() + ad = int(tr2[1], 16) + if ad in symbols: + tr2[1] = "bank_%d_index_%d_dl_%08X" % (globBank, globIndex, ad) + toReturn = " gsSPDisplayList(%s)," % (tr2[1]) + + file.write(str(toReturn) + "\n") + file.write("};\n\n") +# file.write("#DL map is nothing in the original game, its here for me\n") +# file.write("DLmap = [\n") +# for j,s in enumerate(NewStarts): +# file.write("%d,"%s[1]) +# file.write("\n]\n") + +def WriteGeoF3d2(file,f3d,starts): + global globBank, globIndex + + n=0 + #Sorting stuff when writing so its in the same order it is in the ROM + NewStarts = [[i,s] for i,s in enumerate(starts)] + NewStarts.sort(key= lambda x: x[1]) + NewF3D = [f3d[i[0]] for i in NewStarts] + for j,l in enumerate(NewF3D): + file.write("Gfx bank_%d_index_%d_dl_%08X[] = {\n"%(globBank, globIndex, NewStarts[n][1])) + n+=1 + + dl_str = "" + for k,cmd in enumerate(l): + #idk why I built this to work off hex strings but now it + #fucks my ass and I have to do this dumb method. + dl_str += "%016X"%cmd[0] + # print(hs) + proc = subprocess.Popen( + "tools/gfxdis.f3dex2 -x -d " + str(dl_str) + , + shell=True, + stdout=subprocess.PIPE, + ) + toReturn = proc.communicate()[0].decode("ascii") + + tr = toReturn.split("\n")[1:-2] + for i in range(len(tr)): + tmp_line = tr[i] + if "gsSPVertex" in tmp_line: + tr2 = tmp_line.replace(",", " ").replace("(", " ").replace(")"," ").split() + ad = int(tr2[1], 16) + if ad in symbols: + tr2[1] = "bank_%d_index_%d_vtx_%08X" % (globBank, globIndex, ad) + tmp_line = " gsSPVertex(%s, %s, %s)," % (tr2[1], tr2[2], tr2[3]) + if "gsSPDisplayList" in tmp_line: + tr2 = tmp_line.replace(",", " ").replace("(", " ").replace(")"," ").split() + ad = int(tr2[1], 16) + if ad in symbols: + tr2[1] = "bank_%d_index_%d_dl_%08X" % (globBank, globIndex, ad) + tmp_line = " gsSPDisplayList(%s)," % (tr2[1]) + if "gsSPBranchLessZ" in tmp_line: + tr2 = tmp_line.replace(",", " ").replace("(", " ").replace(")"," ").split() + print(tr2) + ad = int(tr2[1], 16) + if ad in symbols: + tr2[1] = "bank_%d_index_%d_dl_%08X" % (globBank, globIndex, ad) + tmp_line = " gsSPBranchLessZ(%s, %s, %s, %s, %s, %s)," % (tr2[1], tr2[2], tr2[3], tr2[4], tr2[5], tr2[6]) + tr[i] = tmp_line + + file.write('\n'.join(tr) + "\n") + file.write("};\n\n") + +def WriteLayout(file,L,env,GH): + global globBank, globIndex + if GH[2][1][0]==0x14: + file.write("// No layout in render mode 0x14\n") + return + # file.write("\n// Layouts Start at 0x%X\n"%GH[0][1][0]) + file.write("\nstruct Layout bank_%d_index_%d_layout_%08X[] = {\n"%(globBank, globIndex, GH[0][1][0])) + for i,l in enumerate(L): + file.write(" {\n") + for h in zip(l,Layout.keys()): + if h[1] == 0x20: + file.write(" /*0x%02X*/ {%s},\n },\n"%(h[1],str(h[0][1])[1:-1])) + elif h[1]==4: + if h[0][1][0] == 0: + file.write(" /*0x%02X*/ NULL,\n"%h[1]) + else: + if h[0][1][0] in symbols: + file.write(" /*0x%02X*/ %s,\n"%(h[1],symbols[h[0][1][0]])) + else: + file.write(" /*0x%02X*/ (struct EntryPoint *) 0x%08X,\n"%(h[1],h[0][1][0])) + elif h[1]<8: + file.write(" /*0x%02X*/ 0x%X,\n"%(h[1],h[0][1][0])) + else: + file.write(" /*0x%02X*/ {%s},\n"%(h[1],str(h[0][1])[1:-1])) + file.write("};\n") + #repeat for envfx, could do this smarter but I don't feel like it. + for i,e in enumerate(env): + file.write("\nEnvfx_%d = {\n"%i) + for h in zip(e,Layout.keys()): + if h[1] == 0x20: + file.write(" /*0x%02X*/ %s\n}\n"%(h[1],str(h[0][1]))) + elif h[1]<8: + file.write(" /*0x%02X*/ 0x%X,\n"%(h[1],h[0][1][0])) + else: + file.write(" /*0x%02X*/ %s,\n"%(h[1],str(h[0][1]))) + +def getOffset(segAddr): + tmp = 0 + fd = sorted([i for i in symbols]) + for i in fd: + if segAddr < i: + break + tmp = i + return ("bank_%d_index_%d_dl_%08X" % (globBank, globIndex,tmp), int((segAddr - tmp) / 8)) + +def WriteImgRefs(file,IR): + global globBank, globIndex + file.write("\n// Img Load F3DEX2 cmd refs\nGfx *%s[] = {\n" % [symbols[i] for i in symbols if "img_refs" in symbols[i]][0]) + for i,im in enumerate(IR): + if im[0] == 0: + file.write(" NULL,\n") + else: + file.write(" %s + 0x%X,\n"%getOffset(im[0])) + file.write("};\n") + +def WriteVertRefs(file,VR): + global globBank, globIndex + file.write("\n// Vert Load F3DEX2 cmd refs\nGfx *%s[] = {\n" % [symbols[i] for i in symbols if "load_refs" in symbols[i]][0]) + for i,v in enumerate(VR): + if v[0] == 0: + file.write(" NULL,\n") + else: + file.write(" %s + 0x%X,\n"%getOffset(v[0])) + file.write("};\n") + +def WriteDLPairs(file,SP,starts): + for i,ep in enumerate(zip(SP,starts)): + file.write("\nGfx *bank_%d_index_%d_dl_pair_%08X[] = {\n"%(globBank, globIndex, ep[1])) + symbols[ep[1]] = "bank_%d_index_%d_dl_pair_%08X" % (globBank, globIndex, ep[1]) + for p in ep[0]: + if p[1] in symbols: + file.write(" %s,\n"%symbols[p[1]]) + else: + if p[1] == 0: + file.write(" NULL,\n") + else: + file.write(" 0x%08X,\n"%p[1]) + file.write("};\n") + +def WriteEntryPoints(file,SP,starts): + if len(SP) == 0: + file.write("// No Entry Points\n") + return + for i,ep in enumerate(zip(SP,starts)): + file.write("\nstruct EntryPoint bank_%d_index_%d_entry_point_%08X[] = {\n"%(globBank, globIndex, ep[1])) + for p in ep[0]: + if p[1] == 0: + file.write(" {0x%X, NULL},\n"%p[0]) + else: + if p[1] in symbols: + file.write(" {0x%X, %s},\n"%(p[0],symbols[p[1]])) + else: + file.write(" {0x%X, (Gfx *) 0x%08X},\n"%(p[0],p[1])) + file.write("};\n") + +def WriteEntryPoints1C(file,SP,starts): + global globBank, globIndex + #this is doodoo brain but don't want to rewrite all stuff + if len(SP) == 0: + file.write("// No Entry Points\n") + return + for i,ep in enumerate(zip(SP,starts)): + file.write("\n// Entry Point at 0x%X\nstruct EntryPoint bank_%d_index_%d_entry_point_%d[] = {\n"%(ep[1],globBank, globIndex,i)) + for p in ep[0]: + if p[0] == 4: + file.write("{0x%X,0x%X,0x%X}"%(p[0],p[1],p[2])) + else: + file.write("{0x%X,0x%X,0x%X},"%(p[0],p[1],p[2])) + file.write("\n};\n") + +def WriteUnk2(file,GH,unk): + if unk: + file.write("\nu32 bank_%d_index_%d_anims_%08X[] = {\n"%(globBank, globIndex, GH[6][1][0])) + for i,u in enumerate(unk): + # if i+1==len(unk): + # file.write(" 0x%X"%u + "\n") + # else: + file.write(" BANK_INDEX(%d, %d)"%(u[0] >> 16, u[0] & 0xFFFF) + ",\n") + file.write("};\n") + else: + file.write("\n// No Animations\n") + return + +def WriteTS(file,GH,TS,THS,H2,tPad,tUnk): + global globBank, globIndex + if TS: + #Write Main TS Header + # file.write(TSComment) + ga = GH[1][1][0] + file.write("\nstruct TextureScroll **bank_%d_index_%d_texscroll_header_%08X[] = {\n"%(globBank, globIndex, GH[1][1][0])) + for j,v in enumerate(THS): + if v[0]==0: + file.write(" NULL,\n") + else: + if v[0] in symbols: + file.write(" %s"%symbols[v[0]] + ",\n") + else: + file.write(" (struct TextureScroll **) 0x%08X"%v + ",\n") + ga += 4 + file.write("};\n") + #write padding + symbols[ga] = "bank_%d_index_%d_texture_ptr_%08X" % (globBank, globIndex, ga) + file.write("\n\nu32 bank_%d_index_%d_texture_ptr_%08X[] = {\n" % (globBank, globIndex, ga)) + for j,v in enumerate(tPad): + # else: + if v[0] == 0x99999999: + file.write(" 0x%X"%v + ",\n") + if j + 1 != len(tPad): + file.write("u32 bank_%d_index_%d_texscroll_padding_%08X[] = {\n" % (globBank, globIndex, ga + 4)) + symbols[ga + 4] = "bank_%d_index_%d_texscroll_padding_%08X" % (globBank, globIndex, ga + 4) + else: + if v[0] == 0: + file.write(" 0,\n") + else: + file.write(" BANK_INDEX(%d, %d)"%(v[0] >> 16, v[0] & 0xFFFF) + ",\n") + if j+1==len(tPad): + file.write("};\n\n") + ga += 4 + # file.write("};\n\n") + #Write TS structs + for i,[t,u] in enumerate(zip(TS,tUnk)): + if u: + file.write("u32 bank_%d_index_%d_texture_ptr_%08X[] = {\n "%(globBank, globIndex, (t[1]-len(u)*4))) + symbols[t[1]-len(u)*4] = "bank_%d_index_%d_texture_ptr_%08X"%(globBank, globIndex,t[1]-len(u)*4) + for p in u: + if p == 0x99999999: + file.write(" 0x%08X,\n"%p) + elif p == 0: + file.write(" 0,\n") + else: + file.write(" BANK_INDEX(%d, %d),\n"%(p >> 16, p & 65535)) + file.write("};\n\n") + if t[0]: + file.write("struct TextureScroll bank_%d_index_%d_texture_scroll_%08X = {\n"%(globBank, globIndex,t[1])) + for j,[v,[k,type]] in enumerate(zip(t[0],TextureScrollStruct.items())): + #why yes, I did learn code exclusively on w3schools + if type[0]==">f": + file.write(" /*0x%02X*/ "%k+"%f"%v + ",\n") + elif j == 0x3: + if v[0] == 0: + file.write(" /*0x%02X*/ "%k+"NULL,\n") + else: + file.write(" /*0x%02X*/ %s,\n" % (k, symbols[v[0]])) + # file.write(" /*0x%02X*/ "%k+"(u32 *) 0x%08X"%v + ",\n") + elif type[0]==">4B": + file.write(" /*0x%02X*/ {"%k+str(v)[1:-1] + "},\n") + elif j+1==len(t[0]): + file.write(" /*0x%02X*/ "%k+"0x%X"%v) + else: + file.write(" /*0x%02X*/ "%k+"0x%X"%v + ",\n") + file.write("\n};\n\n") + #Write subheaders + for j,v in enumerate(H2): + file.write("\nstruct TextureScroll *bank_%d_index_%d_texture_scroll_subheader_%08X[] = {\n"%(globBank, globIndex, v[1])) + for k,h in enumerate(v[0]): + if h[0] == 0: + file.write(" NULL" + ",\n") + else: + if h[0] in symbols: + file.write(" &%s,\n" % symbols[h[0]]) + else: + file.write(" (struct TextureScroll *) 0x%08X"%h[0] + ",\n") + file.write("};\n") + else: + file.write("\n// No Texture Scroll section\n\n") + return + +def GeometryBlock(stage,Kirb,start,end): + #Now Testing Formatting Geo Blocks + GB = GetGeoBlockData(Kirb,start,end) + WriteGeoBlock(stage,GB,Kirb) + return GB + + +import sys +def SingleGeo(Bank,Index): + global globBank, globIndex + globBank = Bank + globIndex = Index + #[start,end] = GetPointers(Bank,Index,"Geo_Block",Kirb) + name = ("Bank_%d_Index_%d_Geo"%(Bank,Index)) + stage = open(sys.argv[2],'w') + Kirb=open(sys.argv[1],'rb') + Kirb=Kirb.read() + stage.write("// Bank " + str(Bank) + " ID " + str(Index) + "\n") + GeometryBlock(stage,Kirb,0,len(Kirb)) + +if __name__=='__main__': + toks = sys.argv[1].split("/") + b = int(toks[2].split("_")[1]) + i = int(toks[3]) + SingleGeo(b,i) \ No newline at end of file diff --git a/tools/scut/KirbyCSdatatypes.py b/tools/scut/KirbyCSdatatypes.py new file mode 100644 index 00000000..031b4286 --- /dev/null +++ b/tools/scut/KirbyCSdatatypes.py @@ -0,0 +1,1108 @@ +import struct +#------------------------------------------------------------------------------- +#Functions + +def GetPointers(bank,id,type,Kirb): + UPW = (lambda x: struct.unpack(">L",x)[0]) + BP = 0x000783D4 + BPs = UPW(Kirb[BP+bank*4:BP+bank*4+4])-HS + types = { + "Geo_Block": 0, + "Image":2, + "Anim":4, + "Misc":6 + } + off= types[type]*4 + if type=="Geo_Block": + scale=2 + else: + scale=1 + Table = UPW(Kirb[BPs+off:BPs+off+4])-HS + Offset = UPW(Kirb[BPs+off+4:BPs+off+8]) + if Offset==0xFFFFFFFF: + Offset = 0 + Start = UPW(Kirb[Table+id*4*scale:Table+id*4*scale+4])+Offset + End = UPW(Kirb[Table+4+id*4*scale:Table+id*4*scale+8])+Offset + return [Start,End] + +def GetMidi(id,Kirb,Table): + UPW = (lambda x: struct.unpack(">L",x)[0]) + start = UPW(Kirb[id*8+Table:id*8+Table+4]) + len = UPW(Kirb[id*8+Table+4:id*8+Table+8]) + return [start,len] + +#------------------------------------------------------------------------------- +#Level Data/Structs + +MainStageStruct={ + 0x00:['geo_block_a','>2H',4], + 0x04:['geo_block_b','>2H',4], + 0x08:['skybox_id','>H',2], + 0x0A:['color','>H',2], + 0x0C:['music_id','>L',4], + 0x10:['level_block','>2H',4], + 0x14:['Death Cutscene','>H',2], + 0x16:['Cutsecene related','>H',2], + 0x18:['dust_block','>2H',4], + 0x1C:['dust_img','>2H',4], + 0x20:['area_name','>L',4], +} + +HS = 0x80057DB0 + +Stages = { + 1:[0x783F4,0x784CC,0x785EC,0x78778], + 2:[0x787C0,0x788BC,0x789DC,0x78B44,0x78CAC], + 3:[0x78CF4,0x78E14,0x78F34,0x79078,0x79198], + 4:[0x791E0,0x79300,0x79444,0x79540,0x79684], + 5:[0x796CC,0x797EC,0x7990C,0x79A74,0x79BB8], + 6:[0x79C00,0x79CB4,0x79DD4,0x79FA8], + 7:[0x79FF0,0x7A080,0x7A0EC,0x7A134] +} + +# Legacy +# addr = { + # 0:0x04F3290, + # 1:0x7BACA0, + # 2:0x964660, + # 3:0xBD6DB0, + # 7:0x1D28720 +# } +# table = { + # 0:0x6CA0C, + # 1:0x6FA64, + # 2:0x712D0, + # 3:0x730C4, + # 7:0x77F30 +# } +# tableGS = { + # 0:0x6C8F0, + # 1:0x6CA44, + # 2:0x6FA94, + # 3:0x71300, + # 7:0x76490 #Level geometry +# } + +# TSaddr=0x1CE5A30 + +# TStable=0x77cd0 + +# Images are stored individually +# ImgAddr = { + # 1:0x5B5360, + # 3:0x9D8CB0, + # 5:0x11291B0, + # 7:0x1BD5C80 +# } +# ImgTable = { + # 1:0x6D1E4, + # 3:0xD9268, + # 5:0x74A0C, + # 7:0x76B28 +# } + +#------------------------------------------------------------------------------- +#Level Settings Structs/data + +CollisionHeader={ + 0x0: 'Triangles', + 0x4: 'Number of Triangles', + 0x8: 'Vertices', + 0xC: 'Number of Vertices', + 0x10: 'Triangle Normals', + 0x14: 'Number of Norms', + 0x18: 'Triangle Cells', + 0x1C: 'Number of Triangle Groups', + 0x20: 'Triangle Norm Cells', + 0x24: 'Num Tri Norm Cells', + 0x28: 'Num Tri Norm Cells -1', + 0x2C: 'Destructable Geometry Groups', + 0x30: 'Destructable Geometry Indices', + 0x34: 'Water Data Offset', + 0x38: 'Water Data Len', + 0x3C: 'Water Norms Offset', + 0x40: 'Water Norms Len' +} + +NodeHeader={ + 0x0: 'Num Path Nodes', + 0x4: 'Path Headers', + 0x8: 'Unk Ints', + 0xC: 'Unk Floats' +} + +PathHeader={ + 0x0: ['Camera Node','>L'], + 0x4: ['Path Footer','>L'], + 0x8: ['Node Connector','>L'], + 0xC: ['Num Connections','>H'], + 0xE: ['Self Connected','>H'] +} + +Camera_Node={ + 0x0:(1,'Profile View'), + 0x1:(1,'Unused'), + 0x2:(1,'Lock H pos'), + 0x3:(1,'Lock Y pos'), + 0x4:(1,'Lock Z pos?'), + 0x5:(1,'Unused2'), + 0x6:(1,'Not Camera Pan Phi Above/Below'), + 0x7:(1,'Not Camera Pan Phi Below'), + 0x8:(1,'Camera Pan Theta'), + 0x9:(1,'unused3'), + 0xA:(2,'unused4'), + 0xC:(4,'Focus X pos'), + 0x10:(4,'Focus Y pos'), + 0x14:(4,'Focus Z pos'), + 0x18:(4,'Near Clip Plane'), + 0x1C:(4,'Far Clip Plane'), + 0x20:(8,'Cam R Scale'), + 0x28:(8,'Cam Theta Rot'), + 0x30:(8,'Cam Radius'), + 0x38:(8,'FOV pair'), + 0x40:(8,'Cam Phi Rot'), + 0x48:(8,'Cam X Pos Lock Bounds'), + 0x50:(8,'Cam Y Pos Lock Bounds'), + 0x58:(8,'Cam Z Pos Lock Bounds'), + 0x60:(8,'Cam Yaw Lock Bounds'), + 0x68:(8,'Cam Pitch Lock Bounds'), +} + +Kirby_Settings_Node= { + 0x0:(">H",'unk',2), + 0x2:(">H",'Enter backwards',2), + 0x4:(">4B",'World Warp',4), + 0x8:(">B",'unused',1), + 0x9:(">3B",'Shade_Left',3), + 0xC:(">H",'unk4',2), + 0xE:(">H",'Flags',2), + 0x10:(">H",'opt 1',2), + 0x12:(">H",'opt 2',2), + 0x14:(">f",'opt 3',4), + 0x18:(">f",'opt 4',4), + 0x1C:(">f",'unused',4) +} + +Cam_Size_Enum = { + 4:'>f', + 1:'>B', + 2:'>H', + 8:'>2f' +} + +Path_Footer = { + 0x0: (2,'Flag Check 0x14','>H'), + 0x2: (2,'Number of sections in node','>H'), + 0x4: (4,'unused?','>f'), + 0x8: (4,'offset to nx3 f32 matrix','>L'), + 0xC: (4,'Node_Length','>f'), + 0x10: (4,'offset to Bounds Definition','>L'), + 0x14: (4,'offset to unk','>L') +} + +Water_Quads = { + 0x0: ('>H','Number Normals',2), + 0x2: ('>H','Normals Array Offset',2), + 0x4: ('>B','Water Box Active',1), + 0x5: ('>B','Activate Water Flow',1), + 0x6: ('>B','Water Flow Direction',1), + 0x7: ('>B','Water Flow Speed',1), + 0x8: ('>f','Pos1',4), + 0xC: ('>f','Pos2',4), + 0x10: ('>f','Pos3',4), + 0x14: ('>f','Pos4',4) +} + +EntityStruct = { + 0x00: ('>B','Node Num',1), + 0x01: ('>B','Bank ID',1), + 0x02: ('>B','Entity ID',1), + 0x03: ('>B','Action',1), + 0x04: ('>H','Respawn Flag',2), + 0x06: ('>H','Eeprom',2), + 0x08: ('>3f','Translation Vec3f',12), + 0x14: ('>3f','Rotation Vec3f',12), + 0x20: ('>3f','Scale Vec3f',12) +} + +TextureScrollStruct = { + 0x00:(">H",'field_0x0',2), + 0x02:(">B",'fmt1',1), + 0x03:(">B",'siz1',1), + 0x04:(">L",'* textures',4), + 0x08:(">H",'stretch',2), + 0x0A:(">H",'sharedOffset',2), + 0x0C:(">H",'t0_w',2), + 0x0E:(">H",'t0_h',2), + 0x10:(">L",'halve',4), + 0x14:(">f",'t0_xShift',4), + 0x18:(">f",'t0_yShift',4), + 0x1C:(">f",'xScale',4), + 0x20:(">f",'yScale',4), + 0x24:(">f",'field_0x24',4), + 0x28:(">f",'field_0x28',4), + 0x2C:(">L",'palettes',4), + 0x30:(">H",'flags',2), + 0x32:(">B",'fmt2',1), + 0x33:(">B",'siz2',1), + 0x34:(">H",'w2',2), + 0x36:(">H",'h2',2), + 0x38:(">H",'t1_w',2), + 0x3A:(">H",'t1_h',2), + 0x3C:(">f",'t1_xShift',4), + 0x40:(">f",'t1_yShift',4), + 0x44:(">f",'field_0x44',4), + 0x48:(">f",'field_0x48',4), + 0x4C:(">L",'field_0x4c',4), + 0x50:(">4B",'color prim',4), + 0x54:(">B",'primLODFrac',1), + 0x55:(">B",'field_0x55',1), + 0x56:(">B",'field_0x56',1), + 0x57:(">B",'field_0x57',1), + 0x58:(">4B",'color env',4), + 0x5C:(">4B",'color blend',4), + 0x60:(">4B",'color light1',4), + 0x64:(">4B",'color light2',4), + 0x68:(">L",'field_0x68',4), + 0x6C:(">L",'field_0x6c',4), + 0x70:(">L",'field_0x70',4), + 0x74:(">L",'field_0x74',4) +} + +MHcomment = """# Main Header + # 0x00: u32 Pointer to Collision Header + # 0x04: u32 Pointer to Node Header + # 0x08: u32 Pointer to Entity list + # 0x0C: u32 Padding""" + +Tricomment = """# Tri Struct: + +# ALWAYS BEGINS WITH +# 0000 0001 0002 0003 0004 0005 0006 0007 0008 0009 + # 0x0: u16 Vertex[3] + # 0x6: u16 Number of quad/triangle (I guess used by the tool to import+alignment pad) + # 0x8: u16 collision type (1 forward norm, 2 back norm, 4 no shadow, 8 non solid + # 0xA: u16 Destructable Group Index + # 0xC: u16 Particles when broken (hammer break) + # 0xE: u16 Stop Kirby from going forward + # 0x10: s16 Amount to move kirby while on certain col types/Break Condition + # 0x12: u16 col type 2""" + +CHcomment = """# Collision Header: + # 0x0: Triangles Offset + # 0x4: Number of Triangles + # 0x8: Vertices offset + # 0xC: Number of Vertices + # 0x10: Triangle Normals + # 0x14: Number of Norms + # 0x18: Triangle Groups (cells) Offset + # 0x1C: Number of Triangle Groups + # 0x20: Triangle Norms Cells + # 0x24: Num Tri Norm Cells + # 0x28: Num Tri Norm Cells - 1 + # 0x2C: Destructable Geometry Groups + # 0x30: Destructable Geometry Indices + # 0x34: Water Data + # 0x38: Water Data number + # 0x3C: Water Normals offset + # 0x40: Water Normals number""" + +DesGroupComment = """# Destructable Groups: +# 0x0: u16 Number of times it loops in list +# 0x2: u16 Index inside Dustructable indices list (0x30 in col header) +# 0x4: u16 Layout Index""" + +KirbyNodeComment = """ +# Kiby Settings Node +# 0x0: u8[2] [Node number,padding] +# 0x2: u16 Enter backwards +# 0x4: u8[4] warp destination (world,level,area,direction) +# 0x8: u8 unused +# 0x9: u8[3] Shading +# 0xC: u16 unused //Always zero, maybe old code. +# 0xE: u16 flags (0x1=warp,0x10=read 0x10) +# 0x10: u16 opt 1//Read if flag&0x10 +# 0x12: u16 opt 2//Read if flag&0x10 & opt 1>0 +# 0x14: float optional 3 //only used in 5-5-1 +# 0x18: float optional 4 //only used in 5-5-1 +# 0x1C: unused //unused +""" + +CameraNodeComment = """ +# Camera Node +# 0x0: u16 Profile View //makes cam always at kirby's profile +# 0x1: u16 10 always //I'm pretty sure this does nothing +# 0x2: u8 Lock H pos //follows kirby if not +# 0x3: u8 Lock Y pos //follows if not +# 0x4: u8 Lock Z pos //seemingly does nothing +# 0x5: u8 unused +# 0x6: u8 Not Camera Pan Phi Above/Below +# 0x7: u8 Not Camera Pan Phi Below //doesn't pan up +# 0x8: u8 Camera Pan Theta (from cam to kirby) +# 0x9: u8 unused2 //useless +# 0xA: u16 unk5 (FOV?) //basically useless +# 0xC: f32 Focus X pos (Stays on kirby if 9999) +# 0x10: f32 Focus Y pos (Stays on kirby if 9999) +# 0x14: f32 Focus Z pos (Stays on kirby if 9999) +# 0x18: f32 Near Clip Plane +# 0x1C: f32 Far Clip Plane +# 0x20: f32[2] Cam R scale //for when following kirby +# 0x28: f32[2] Cam Theta Rot (from kirby to camera) //for when following kirby +# 0x30: f32[2] Cam Radius //for when following kirby +# 0x38: f32[2] FOV pair +# 0x40: f32[2] Cam Phi Rot //for when following kirby +# 0x48: f32[2] Cam X Pos Lock Bounds //Locks if -9999,9999, In range of these values it follows kirby, outside it locks at bound +# 0x50: f32[2] Cam Y Pos Lock Bounds //Locks if -9999,9999, In range of these values it follows kirby, outside it locks at bound +# 0x58: f32[2] Cam Z Pos Lock Bounds //Locks if -9999,9999, In range of these values it follows kirby, outside it locks at bound +# 0x60: f32[2] Cam Y Foc Lock Bounds //Locks if -9999,9999, In range of these values it follows kirby, outside it locks at bound +# 0x68: f32[2] Cam X Foc Lock Bounds //Locks if -9999,9999, In range of these values it follows kirby, outside it locks at bound +""" + +NCComment = """ +# Node Connectors format +# 0x0: u8 Stop kirby from going backwards +# 0x1: u8 unused +# 0x2: u8 next node(prev node if second section is present) +# 0x3: u8 unused + +# (optional) +# 0x4: u8 Stop kirby from going forwards +# 0x5: u8 unused +# 0x6: u8 next node +# 0x7: u8 unused +""" + + +SectionSeperatorComment = """#------------------------------------------------------------------------------- + +""" + +PHComment = """ +# PathHeader={ + # 0x0: ['Camera Node','>L'], + # 0x4: ['Path Footer','>L'], + # 0x8: ['Node Connector','>L'], + # 0xC: ['Num Connections','>H'], + # 0xE: ['Self Connected','>H'] +# } +""" + +PNFComment = """ +# Path Node Footer +# 0x0: int Flag Check 0x14 +# 0x2: u16 Number of sections in node +# 0x4: F32 Constant H speed? //used in 3-4-2 only +# 0x8: ptr offset to nx3 f32 matrix +# 0xC: F32 Node Length +# 0x10: ptr offset to Bounds Definition +# 0x14: ptr offset to unk section +""" + +NHComment = """# NodeHeader = { +# 0x0: 'Num Path Nodes', +# 0x4: 'Path Headers', +# 0x8: 'Unk Ints', +# 0xC: 'Unk Floats' +# } +""" + +EntityIDComment = """ +# EntityStruct = { + # 0x00: ('>B','Node Num',1) + # 0x01: ('>B','Bank ID',1) + # 0x02: ('>B','Entity ID',1) + # 0x03: ('>B','Action',1) + # 0x04: ('>H','Respawn Flag',2) + # 0x06: ('>H','Eeprom',2) + # 0x08: ('>3f','Translation Vec3f',12) + # 0x14: ('>3f','Rotation Vec3f',12) + # 0x20: ('>3f','Scale Vec3f',12) +# } +""" + +TSComment = """ +# The texture scrolls section starts with a main header, which is a list of ptrs +# to subheaders. Each subheader is a list of pointers to the following structs. +# Every header is null terminated and ends with 0x99999999. + +# TextureScrollStruct = { +# 0x00:[">H",'field_0x0',2], +# 0x02:[">B",'fmt1',1], +# 0x03:[">B",'siz1',1], +# 0x04:[">L",'* textures',4], +# 0x08:[">H",'stretch',2], +# 0x0A:[">H",'sharedOffset',2], +# 0x0C:[">H",'t0_w',2], +# 0x0E:[">H",'t0_h',2], +# 0x10:[">L",'halve',4], +# 0x14:[">f",'t0_xShift',4], +# 0x18:[">f",'t0_yShift',4], +# 0x1C:[">f",'xScale',4], +# 0x20:[">f",'yScale',4], +# 0x24:[">f",'field_0x24',4], +# 0x28:[">f",'field_0x28',4], +# 0x2C:[">L",'palettes',4], +# 0x30:[">H",'flags',2], +# 0x32:[">B",'fmt2',2], +# 0x33:[">B",'siz2',2], +# 0x34:[">H",'w2',2], +# 0x36:[">H",'h2',2], +# 0x38:[">H",'t1_w',2], +# 0x3A:[">H",'t1_h',2], +# 0x3C:[">f",'t1_xShift',2], +# 0x40:[">f",'t1_yShift',2], +# 0x44:[">f",'field_0x44',2], +# 0x48:[">f",'field_0x48',2], +# 0x4C:[">L",'field_0x4c',2], +# 0x50:[">4B",'color prim',2], +# 0x54:[">B",'primLODFrac',2], +# 0x55:[">B",'field_0x55',2], +# 0x56:[">B",'field_0x56',2], +# 0x57:[">B",'field_0x57',2], +# 0x58:[">4B",'color env',2], +# 0x5C:[">4B",'color blend',2], +# 0x60:[">4B",'color light1',2], +# 0x64:[">4B",'color light2',2], +# 0x68:[">L",'field_0x68',2], +# 0x6C:[">L",'field_0x6c',2], +# 0x70:[">L",'field_0x70',2], +# 0x74:[">L",'field_0x74',2] +# } +""" + +#------------------------------------------------------------------------------- +#Geometry Block Structs/Data + +Geo_Header = { + 0x00:'layout', + 0x04:'tex_scroll', + 0x08:'rendering_mode', + 0x0C:'img_refs', + 0x10:'vtx_refs', + 0x14:'n_unknown2', + 0x18:'unknown2', + 0x1C:'Num Layouts' +} + +Layout = { + 0x00: ('>H','Flag',2), + 0x02: ('>H','Command',2), + 0x04: ('>L','Entry Points',4), + 0x08: ('>3f','Translation Vec3f',12), + 0x14: ('>3f','Rotation Vec3f',12), + 0x20: ('>3f','Scale Vec3f',12) +} + +Geo_Vert = { + 0x00: ('>3H','XYZ',6), + 0x06: ('>H','Padding',2), + 0x08: ('>2H','UV',4), + 0x0C: ('>4B','RGBA',4) +} + +Geo_Vertices_Comment = """ +# Vertex = { + # 0x00: ('>3H','XYZ',6), + # 0x06: ('>H','Padding',2), + # 0x08: ('>2H','UV',4), + # 0x0C: ('>4B','RGBA',4) +# } +""" + +Microcode_Comment = """ + # All G_SETTIMG addresses for level geometry are stored as bank-indeces. + # On load, each bank-index is converted to a virtual address in-place. + # [When reading the addresses, if the resource is not in memory, the game loads it?] + # All G_VTX addresses are segptrs referencing vertices within the block. + + # If texture scroll settings are used, there will be jumps to segment 0x0E (See 8. Texture scroll settings). +""" + +SetImg_Comment = """ + # Zero-terminated list of segptrs, all pointing to microcode beginning with G_SETTIMG (0xFD) commands. + # [Used to fill in the virtual addresses?] + + # If there are no images, there will still be a pointer in the header, but + # the list will just consist of a single 0x00000000. +""" + +EntryPoint_Comment = """ + # Groups display lists together with lists of segptrs to their entry points. + # Each struct is 8 bytes in size: + + # 0x00: int command + # 0x04: segptr entry_point + + # The command field seems to be: + # 00000000: Start group + # 00000001: Continue group + # 00000004: End group (entry_point will be NULL) +""" + +Layout_Comment = """ +# Layout = { + # 0x00: ('>H','Flag',2), + # 0x02: ('>H','Command',2), + # 0x04: ('>L','Entry Points',4), + # 0x08: ('>3f','Translation Vec3f',12), + # 0x14: ('>3f','Rotation Vec3f',12), + # 0x20: ('>3f','Scale Vec3f',12) +# } +""" + +Geo_HeaderComment = """ +# GeoBlock_Header = { + # 0x00:'layout', + # 0x04:'tex_scroll', + # 0x08:'rendering_mode', + # 0x0C:'img_refs', + # 0x10:'vtx_refs', + # 0x14:'Num Anims', + # 0x18:'Anims', + # 0x1C:'Num Layouts' +# } +""" + + + +Main_Stage_Comment=""" +# MainStageStruct={ + # 0x00:['geo_block_a','>2H',4], + # 0x04:['geo_block_b','>2H',4], + # 0x08:['skybox_id','>H',2], + # 0x0A:['color','>H',2], + # 0x0C:['music_id','>L',4], + # 0x10:['level_block','>2H',4], + # 0x14:['Death Cutscene','>H',2], + # 0x16:['Cutsecene related','>H',2], + # 0x18:['dust_block','>2H',4], + # 0x1C:['dust_img','>2H',4], + # 0x20:['area_name','>L',4], +# } + +""" +#------------------------------------------------------------------------------- +#Audio Structs + +ALBankFile={ +0:(lambda x:">H","Revision",lambda x:2), +2:(lambda x:">H","BankCount",lambda x:2), +4:(lambda x:">L","BankArray Offset",lambda x:4) +} + +ALBankFileComment=""" +# ALBankFile={ +# 0:(">H","Revision",2), +# 2:(">H","BankCount",2), +# 4:(">L","BankArray Offset",4) +# } +""" + +ALBank={ +0:(lambda x:">H","Instcount",lambda x:2), +2:(lambda x:">B","Flags",lambda x:1), +3:(lambda x:">B","Pad",lambda x:1), +4:(lambda x:">l","Sample Rate",lambda x:4), +8:(lambda x:">l","Percussion",lambda x:4), +12:(lambda x:">%dl"%x[0][0],"Inst Array Offsets",lambda x:4*x[0][0]) +} + +ALBankComment = """ +# ALBank={ +# 0:(">H","Instcount",2), +# 2:(">B","Flags",1), +# 3:(">B","Pad",1), +# 4:(">l","Sample Rate",4), +# 8:(">l","Percussion",4) +# 12:(">%dl"%Instcount,"Inst Array Offsets",4*Instcount) +# } +""" + +ALInstrument={ +0:(lambda x:">B","Volume",lambda x:1), +1:(lambda x:">B","Pan",lambda x:1), +2:(lambda x:">B","Priority",lambda x:1), +3:(lambda x:">B","Flags",lambda x:1), +4:(lambda x:">B","Trem Type",lambda x:1), +5:(lambda x:">B","Trem Rate",lambda x:1), +6:(lambda x:">B","Trem Depth",lambda x:1), +7:(lambda x:">B","Trem Delay",lambda x:1), +8:(lambda x:">B","Vib Type",lambda x:1), +9:(lambda x:">B","Vib Rate",lambda x:1), +10:(lambda x:">B","Vib Depth",lambda x:1), +11:(lambda x:">B","Vib Delay",lambda x:1), +12:(lambda x:">h","Bend Range",lambda x:2), +14:(lambda x:">h","Sound Count",lambda x:2), +16:(lambda x:">%dl"%x[13][0],"Sound Array Offsets",lambda x:4*x[13][0]), +} + +ALInstrumentComment = """ +# ALInstrument={ +# 0:(">B","Volume",1), +# 1:(">B","Pan",1), +# 2:(">B","Priority",1), +# 3:(">B","Flags",1), +# 4:(">B","Trem Type",1), +# 5:(">B","Trem Rate",1), +# 6:(">B","Trem Depth",1), +# 7:(">B","Trem Delay",1), +# 8:(">B","Vib Type",1), +# 9:(">B","Vib Rate",1), +# 10:(">B","Vib Depth",1), +# 11:(">B","Vib Delay",1), +# 12:(">h","Bend Range",2), +# 14:(">h","Sound_Count",2), +# 16:(">%dl"%Sound_Count,"Sound Array Offsets",4*Sound_Count), +# } +""" + +ALKeyMap={ +0:(lambda x:">B","VelocityMin",lambda x:1), +1:(lambda x:">B","VelocityMax",lambda x:1), +2:(lambda x:">B","Key Min",lambda x:1), +3:(lambda x:">B","Key Max",lambda x:1), +4:(lambda x:">B","Key Base",lambda x:1), +5:(lambda x:">B","Detune",lambda x:1), +} + +AlKeyMapComment = """ +# ALKeyMap={ +# 0:(">B","VelocityMin",1), +# 1:(">B","VelocityMax",1), +# 2:(">B","Key Min",1), +# 3:(">B","Key Max",1), +# 4:(">B","Key Base",1), +# 5:(">B","Detune",1), +# } +""" + +ALSound={ +0:(lambda x:">l","Envelope",lambda x:4), +4:(lambda x:">l","KeyMap",lambda x:4), +8:(lambda x:">l","WaveTable",lambda x:4), +12:(lambda x:">B","SamplePan",lambda x:1), +13:(lambda x:">B","SampleVolume",lambda x:1), +14:(lambda x:">B","Flags",lambda x:1), +} + +AlSoundComment = """ +# ALSound={ +# 0:(">l","Envelope",4), +# 4:(">l","KeyMap",4), +# 8:(">l","WaveTable",4), +# 12:(">B","SamplePan",1), +# 13:(">B","SampleVolume",1), +# 14:(">B","Flags",1), +# } +""" + +ALEnvelope={ +0:(lambda x:">l","Attack Time",lambda x:4), +4:(lambda x:">l","Decay Time",lambda x:4), +8:(lambda x:">l","Release Time",lambda x:4), +12:(lambda x:">h","Attack Volume",lambda x:2), +14:(lambda x:">h","Decay Volume",lambda x:2), +} + +ALEnvelopeComment = """ +# ALEnvelope={ +# 0:(">l","Attack Time",4), +# 4:(">l","Decay Time",4), +# 8:(">l","Release Time",4), +# 12:(">h","Attack Volume",2), +# 14:(">h","Decay Volume",2), +# } +""" + +ALWaveTable={ +0:(lambda x:">l","base",lambda x:4), +4:(lambda x:">l","len",lambda x:4), +8:(lambda x:">B","Type",lambda x:1), +9:(lambda x:">B","Flag",lambda x:1), +10:(lambda x:">H","Padding",lambda x:2), +12:(lambda x:">l","ALADPCMloop Offset",lambda x:4), +16:(lambda x:">l","ALADPCMBook/ALRawLoop Offset",lambda x:4), +} + +ALWaveTableComment = """ +# ALWaveTable={ +# 0:(">l","base",4), +# 4:(">l","len",4), +# 8:(">B","Type",1), +# 9:(">B","Flag",1), +# 10:(">H","Padding",2), +# 12:(">l","ALADPCMloop Offset",4), +# 16:(">l","ALADPCMBook/ALRawLoop Offset",4), +# } +""" + +ALADPCMloop={ +0:(lambda x:">l","start",lambda x:4), +4:(lambda x:">l","end",lambda x:4), +8:(lambda x:">L","count",lambda x:4) +} + +ALADPCMloopComment = """ +# ALADPCMloop={ +# 0:(">l","start",4), +# 4:(">l","end",4), +# 8:(">L","count",4) +# } +""" + +ALADPCMBook={ +0:(lambda x:">l","order",lambda x:4), +4:(lambda x:">l","npredictors",lambda x:4), +8:(lambda x:">%dh"%x[1][0],"book",lambda x:2*x[1][0]) +} + +ALADPCMBookComment = """ +# ALADPCMBook={ +# 0:(">l","order",4), +# 4:(">l","npredictors",4), +# 8:(">%dh"%npredictors,"book",2*npredictors) +# } +""" + +#------------------------------------------------------------------------------- +music_list= { +0x0: ' no change/no music', +0x1: ' Boss', +0x2: ' Battle', +0x3: ' Dance Long', +0x4: ' Dance Short', +0x5: ' Death/Life Lost', +0x6: ' Friends (beta)', +0x7: ' Friends 2 (beta)', +0x8: ' Friends 3 (beta)', +0x9: ' Minigame Victory', +0xA: ' Aqua Star', +0xB: ' Neo Star', +0xC: ' Rock Star', +0xD: ' Pop Star', +0xE: ' Above the Clouds', +0xF: ' Mountain Stream', +0x10: ' Shiver Star', +0x11: ' Inside the Ruins', +0x12: ' Quiet Forest', +0x13: ' Ruins', +0x14: ' Ripple Star Catacombs', +0x15: ' Factory Inspection', +0x16: ' Ripple Star', +0x17: ' Game Over', +0x18: ' Bonus', +0x19: ' Falling Fight', +0x1A: ' Rock Star Select', +0X1B: ' Pop Star Select', +0x1C: ' Aqua Star Select', +0x1D: ' Neo Star Select', +0x1E: ' Shiver Star Select', +0x1F: ' Invincible', +0x20: ' Training', +0x21: ' Talking Battle', +0x22: ' Room Gaurder', +0x23: ' Mini Game Select', +0x24: ' Ripple Star Select', +0x25: ' World Map', +0x26: ' File Select', +0x27: ' Battle Among Friends: Waddle Dee', +0x28: ' Battle Among Friends: Adeline', +0x29: ' Battle Among Friends: King Dedede', +0x2A: ' Opening', +0x2B: ' Your Quest Revealed (one of the beginning cutscenes)', +0x2C: ' What! (one of the beginning cutscenes)', +0x2D: ' Ill Go, Too (one of the beginning cutscenes)', +0x2E: ' Eek! (one of the beginning cutscenes)', +0x2F: ' Mix Me In, Too (one of the beginning cutscenes)', +0x30: ' Whoa!! (one of the beginning cutscenes)', +0x31: ' Ill Come Along With You (one of the cutscenes)', +0x32: ' Alright, On To The Next (one of the cutscenes)', +0x33: ' Im Hungry (one of the cutscenes)', +0x34: ' Beachs Backyard (one of the cutscenes)', +0x35: ' Major Specialization (one of the cutscenes)', +0x36: ' Overnight Detective (one of the cutscenes)', +0x37: ' Final Battle', +0x38: ' Bye-Bye', +0x39: ' The End part 1 (credits?)', +0x3A: ' Nothing?', +0x3B: ' Enemy Card Index', +0x3C: ' Dark Star', +0x3D: ' Miracle Matter', +0x3E: ' Gourmet Race', +0x3F: ' The End part 2 (credits?)', +0x40: ' nothing', +0x41: ' Starts Repeating tracks. Not sure if arrangements/overflow' +} + +Entity_IDS = { + 'N-Z': [0, 0], + 'Rocky': [0, 1], + 'Bronto Burt': [0, 2], + 'Skud': [0, 3], + 'Gordo': [0, 4], + 'Shotzo': [0, 5], + 'Spark-i': [0, 6], + 'Bouncy': [0, 7], + 'Glunk': [0, 8], + '[?? explodes]': [0, 9], + 'Chilly': [0, 10], + 'Propeller': [0, 11], + 'Glom': [0, 12], + 'Mahall': [0, 13], + 'Poppy Bros. Jr.': [0, 14], + 'Bivolt': [0, 15], + 'Splinter': [0, 16], + 'Gobblin': [0, 17], + 'Kany': [0, 18], + 'Bivolt again?': [0, 19], + 'Sirkibble': [0, 20], + 'Gabon': [0, 21], + 'Mariel': [0, 22], + 'Large I3': [0, 23], + 'Snipper': [0, 24], + '[?? explodes again?]': [0, 25], + 'Bonehead': [0, 26], + 'Squibbly': [0, 27], + 'Bobo': [0, 28], + 'Bo': [0, 29], + 'Punc': [0, 30], + 'Mite': [0, 31], + 'Sandman': [0, 32], + 'Flopper': [0, 33], + 'Kapar': [0, 34], + 'Maw': [0, 35], + 'Drop': [0, 36], + 'Pedo': [0, 37], + 'Noo': [0, 38], + 'Tick': [0, 39], + 'Cairn': [0, 40], + '[?? invisible]': [0, 41], + 'Pompey': [0, 42], + 'Hack': [0, 43], + 'Burnis': [0, 44], + 'Fishbone': [0, 45], + 'Frigis': [0, 46], + 'Sawyer': [0, 47], + 'Turbite': [0, 48], + 'Plugg': [0, 49], + 'Ghost knight': [0, 50], + 'Zoos': [0, 51], + 'Kakti': [0, 52], + 'Rockn': [0, 53], + 'Chacha': [0, 54], + 'Galbo': [0, 55], + 'Bumber': [0, 56], + 'Scarfy': [0, 57], + 'Nruff': [0, 58], + 'Emp': [0, 59], + 'Magoo': [0, 60], + 'Yariko': [0, 61], + 'invisible?': [0, 62], + 'Wall Shotzo': [0, 63], + 'Keke': [0, 64], + 'Sparky': [0, 65], + 'Ignus': [0, 66], + 'Flora': [0, 67], + 'Putt': [0, 68], + 'Pteran': [0, 69], + 'Mumbies': [0, 70], + 'Pupa': [0, 71], + 'Mopoo': [0, 72], + 'Zebon': [0, 73], + '[invisible?]': [0, 74], + '[falling rocks sometimes blue]': [0, 75], + '[falling rocks sometimes blue bigger?]': [0, 76], + 'Waddle Dee Boss': [1, 0], + 'Ado Boss': [1, 1], + 'DeeDeeDee Boss': [1, 2], + 'Whispy Woods': [2, 0], + 'Waddle Dee Boss)': [2, 1], + 'Maxim Tomato': [3, 0], + 'Sandwich': [3, 1], + 'Cake': [3, 2], + 'Steak': [3, 3], + 'Ice Cream Bar': [3, 4], + 'Invinsible Candy': [3, 5], + 'Yellow Star': [3, 6], + 'Blue Star': [3, 7], + '[crashes]': [3, 10], + '1up': [3, 9], + 'Flower': [3, 11], + 'School of fish': [3, 12], + 'Butterfly': [3, 13], + 'warps': [5, 0], + 'Door': [5, 31], + 'Door 2': [5, 32], + 'Ado (Gives maxim tomato)': [7, 1], + 'N-Z Boss': [8, 0], + 'Bouncy Boss': [8, 1], + 'Kakti Boss': [8, 2], + 'Fishbones boss': [8, 3], + 'Spark-i Boss': [8, 4], + 'Tick Boss': [8, 5], + 'Kany Boss': [8, 6], + 'Kapar Boss': [8, 7], + 'Blowfish boss': [8, 8], + 'Galbo boss': [8, 9], + 'drop boss?': [8, 10] +} + +Render_Modes = { + "0x00552078": "G_RM_AA_ZB_OPA_SURF", + "0x00112078": "G_RM_AA_ZB_OPA_SURF2", + "0x00552058": "G_RM_AA_ZT_OPA_SURF", + "0x00112058": "G_RM_AA_ZT_OPA_SURF", + "0x00552008": "G_RM_RA_OPA_SURF", + "0x00112008": "G_RM_RA_OPA_SURF2", + "0x00552040": "G_RM_ID_OPA_SURF", + "0x00112040": "G_RM_ID_OPA_SURF2", + "0x00552018": "G_RM_RA_ZT_OPA_SURF", + "0x00112018": "G_RM_RA_ZT_OPA_SURF2", + "0x005049D8": "G_RM_AA_ZB_XLU_SURF", + "0x001049D8": "G_RM_AA_ZB_XLU_SURF2", + "0x005049c8": "G_RM_AA_XLU_SURF", + "0x001049c8": "G_RM_AA_XLU_SURF2", + "0x0C1849D8": "G_RM_AA_ZB_XLU_SURF_REVERSE", + "0x00553008": "G_RM_RA_TEX_EDGE", + "0x00113008": "G_RM_RA_TEX_EDGE2", + "0x00552038": "G_RM_RA_ZB_OPA_SURF", + "0x00112038": "G_RM_RA_ZB_OPA_SURF2", + "0x00553038": "G_RM_RA_ZB_TEX_EDGE", + "0x00113038": "G_RM_RA_ZB_TEX_EDGE2", + "0x00553048": "G_RM_AA_TEX_EDGE", + "0x00113048": "G_RM_AA_TEX_EDGE2", + "0x00552C78": "G_RM_AA_ZB_OPA_DECAL", + "0x00112C78": "G_RM_AA_ZB_OPA_DECAL2", + "0x00553C78": "G_RM_AA_ZB_TEX_EDGE_DECAL", + "0x00113C78": "G_RM_AA_ZB_TEX_EDGE_DECAL2", + "0x00552048": "G_RM_AA_OPA_SURF", + "0x00112048": "G_RM_AA_OPA_SURF2", + "0x00553078": "G_RM_AA_ZB_TEX_EDGE", + "0x00113078": "G_RM_AA_ZB_TEX_EDGE2", + "0x00404B50": "G_RM_ZB_CLD_SURF", + "0x00104B50": "G_RM_ZB_CLD_SURF2", + "0x00404F50": "G_RM_ZB_OVL_SURF", + "0x00104F50": "G_RM_ZB_OVL_SURF2", + '0x00503078':'G_RM_AA_ZB_TEX_TERR', + '0x00103078':'G_RM_AA_ZB_TEX_TERR2', + "0x0C192078": "G_RM_AA_ZB_OPA_INVERT", + "0x0C193078": "G_RM_AA_ZB_TEX_EDGE_INVERT", + "0x0C193038": "G_RM_RA_ZB_TEX_EDGE_INVERT", + "0x0C193048": "G_RM_AA_TEX_EDGE_INVERT", + "0x0C192038": "G_RM_RA_ZB_OPA_INVERT", + "0x0C193C78": "G_RM_RA_ZB_TEX_DECAL_INVERT", + "0x0C192048": "G_RM_AA_OPA_INVERT", + "0x0C192008": "G_RM_RA_OPA_INVERT", + "0x00504DD8": "G_RM_AA_ZB_XLU_DECAL", + "0x0C194DD8": "G_RM_AA_ZB_XLU_DECAL_INVERT", + "0x0C184DD8": "G_RM_AA_ZB_XLU_DECAL_REVERSE", + "0x0C184078": "G_RM_AA_ZB_XLU_SURF_REVERSE", + "0x0C184038": "G_RM_RA_ZB_XLU_SURF_REVERSE", + "0x0C1849c8": "G_RM_AA_XLU_SURF_REVERSE", + "0x0C184008": "G_RM_RA_XLU_SURF_REVERSE", + "0xC8112078": "G_RM_AA_ZB_OPA_SURF_FOG_ALPHA", + "0x00000000": "G_RM_NOOP" +} +Mode_Bits = { +'G_RM_AA_ZB_OPA_SURF': '0x00552078', +'G_RM_AA_ZB_OPA_SURF2': '0x00112078', +'G_RM_AA_ZT_OPA_SURF': '0x00552058', +'G_RM_AA_ZT_OPA_SURF': '0x00112058', +'G_RM_RA_OPA_SURF': '0x00552008', +'G_RM_RA_OPA_SURF2': '0x00112008', +'G_RM_ID_OPA_SURF': '0x00552040', +'G_RM_ID_OPA_SURF2': '0x00112040', +'G_RM_RA_ZT_OPA_SURF': '0x00552018', +'G_RM_RA_ZT_OPA_SURF2': '0x00112018', +'G_RM_AA_ZB_XLU_SURF': '0x005049D8', +'G_RM_AA_ZB_XLU_SURF2': '0x001049D8', +'G_RM_AA_XLU_SURF': '0x005049c8', +'G_RM_AA_XLU_SURF2': '0x001049c8', +'G_RM_AA_ZB_XLU_SURF_REVERSE': '0x0C1849D8', +'G_RM_RA_TEX_EDGE': '0x00553008', +'G_RM_RA_TEX_EDGE2': '0x00113008', +'G_RM_RA_ZB_OPA_SURF': '0x00552038', +'G_RM_RA_ZB_OPA_SURF2': '0x00112038', +'G_RM_RA_ZB_TEX_EDGE': '0x00553038', +'G_RM_RA_ZB_TEX_EDGE2': '0x00113038', +'G_RM_AA_TEX_EDGE': '0x00553048', +'G_RM_AA_TEX_EDGE2': '0x00113048', +'G_RM_AA_ZB_OPA_DECAL': '0x00552C78', +'G_RM_AA_ZB_OPA_DECAL2': '0x00112C78', +'G_RM_AA_ZB_TEX_EDGE_DECAL': '0x00553C78', +'G_RM_AA_ZB_TEX_EDGE_DECAL2': '0x00113C78', +'G_RM_AA_OPA_SURF': '0x00552048', +'G_RM_AA_OPA_SURF2': '0x00112048', +'G_RM_AA_ZB_TEX_EDGE': '0x00553078', +'G_RM_AA_ZB_TEX_EDGE2': '0x00113078', +"G_RM_ZB_CLD_SURF":"0x00404B50", +"G_RM_ZB_CLD_SURF2":"0x00104B50", +"G_RM_ZB_OVL_SURF":"0x00404F50", +"G_RM_ZB_OVL_SURF2":"0x00104F50", +'G_RM_AA_ZB_TEX_TERR': '0x00503078', +'G_RM_AA_ZB_TEX_TERR2': '0x00103078', +'G_RM_AA_ZB_OPA_INVERT': '0x0C192078', +'G_RM_AA_ZB_TEX_EDGE_INVERT': '0x0C193078', +'G_RM_RA_ZB_TEX_EDGE_INVERT': '0x0C193038', +'G_RM_AA_TEX_EDGE_INVERT': '0x0C193048', +'G_RM_RA_ZB_OPA_INVERT': '0x0C192038', +'G_RM_RA_ZB_TEX_DECAL_INVERT': '0x0C193C78', +'G_RM_AA_OPA_INVERT': '0x0C192048', +'G_RM_RA_OPA_INVERT': '0x0C192008', +'G_RM_AA_ZB_XLU_DECAL': '0x00504DD8', +'G_RM_AA_ZB_XLU_DECAL_INVERT': '0x0C194DD8', +'G_RM_AA_ZB_XLU_DECAL_REVERSE': '0x0C184DD8', +'G_RM_AA_ZB_XLU_SURF_REVERSE': '0x0C184078', +'G_RM_RA_ZB_XLU_SURF_REVERSE': '0x0C184038', +'G_RM_AA_XLU_SURF_REVERSE': '0x0C1849c8', +'G_RM_RA_XLU_SURF_REVERSE': '0x0C184008', +'G_RM_AA_ZB_OPA_SURF_FOG_ALPHA': '0xC8112078', +'G_RM_NOOP': '0x00000000' +} + +unk=[ +0x00504FD0, +0x005041C8, +0x005041D8, +0x00504BD0, +0x005049F8, +0x00504A50, +0x00504950, +0x00553c58, +0x00504C78, +0x005049c8, +0x0C192c78, +0x0C193008, +0x0C183008, +0x0C184B50, +0x0C184858, +0x0C1849F8, +0xCC192078, +0xC81049D8, +0x08912078, +0x08912038, +0x00904dd8, +0x00504078, +0xC8112038, +0xC81120F8, +] +#these are listed but given horrible names +BadNames=[ +0x005049c8, +0x001049c8, +0x0C192078, +0x0C193078, +0x0C193038, +0x0C193048, +0x0C192038, +0x0C193C78, +0x0C192048, +0x0C192008, +0x00504DD8, +0x0C194DD8, +0x0C184DD8, +0x0C184078, +0x0C184038, +0x0C1849c8, +0x0C184008, +] \ No newline at end of file diff --git a/tools/scut/__pycache__/KirbyCSdatatypes.cpython-38.pyc b/tools/scut/__pycache__/KirbyCSdatatypes.cpython-38.pyc new file mode 100644 index 00000000..a08e916b Binary files /dev/null and b/tools/scut/__pycache__/KirbyCSdatatypes.cpython-38.pyc differ