summaryrefslogtreecommitdiff
path: root/src/code
diff options
context:
space:
mode:
Diffstat (limited to 'src/code')
-rw-r--r--src/code/ucode_disas.c1077
1 files changed, 1077 insertions, 0 deletions
diff --git a/src/code/ucode_disas.c b/src/code/ucode_disas.c
index 1db6b7e6a..2ba3a5c92 100644
--- a/src/code/ucode_disas.c
+++ b/src/code/ucode_disas.c
@@ -249,6 +249,1082 @@ void UCodeDisas_PrintVertices(UCodeDisas* this, Vtx* vtx, s32 count, s32 start)
}
}
+// Todo: clean this up
+
+typedef struct {
+ s8 cmd;
+ u8 v0;
+ u8 v1;
+ u8 wd;
+ u32 pad;
+} Gline3DFix;
+
+typedef struct {
+ int cmd : 8;
+ u8 pad;
+ u8 prim_min_level;
+ u8 prim_level;
+ u8 r;
+ u8 g;
+ u8 b;
+ u8 a;
+} GsetcolorMod;
+
+typedef struct {
+ u8 cmd;
+ char pad[3];
+ u16 z;
+ u16 d;
+} Gsetprimdepth;
+
+typedef struct {
+ s32 cmd : 8;
+ u32 type : 8;
+ u32 len : 16;
+ union {
+ u32 u32;
+ f32 f32;
+ } value;
+} Gnoop;
+
+typedef struct {
+ u8 cmd;
+ u8 pad[2];
+ u8 params;
+ u32 addr;
+} Gmatrix;
+
+typedef struct {
+ u8 cmd;
+ u32 a : 4;
+ u32 c : 5;
+ u32 z : 3;
+ u32 x : 3;
+ u32 e : 4;
+ u32 g : 5;
+ u32 b : 4;
+ u32 f : 4;
+ u32 v : 3;
+ u32 t : 3;
+ u32 d : 3;
+ u32 y : 3;
+ u32 w : 3;
+ u32 h : 3;
+ u32 u : 3;
+ u32 s : 3;
+} GsetcombineMod;
+
+typedef struct {
+ u32 cmd : 8;
+ u32 pad0 : 8;
+ u32 sft : 8;
+ u32 len : 8;
+ u32 data : 32;
+} GsetothermodeMod;
+
+typedef union {
+ Gwords words;
+ Gnoop noop;
+ Gmatrix matrix;
+ Gdma dma;
+ Gtri tri;
+ Gline3D line;
+ Gpopmtx popmtx;
+ Gsegment segment;
+ GsetothermodeH setothermodeH;
+ GsetothermodeL setothermodeL;
+ GsetothermodeMod setothermode;
+ Gtexture texture;
+ Gperspnorm perspnorm;
+ Gsetimg setimg;
+ GsetcombineMod setcombine;
+ GsetcolorMod setcolor; // mod
+ Gfillrect fillrect; /* use for setscissor also */
+ Gsettile settile;
+ Gloadtile loadtile; /* use for loadblock also, th is dxt */
+ Gsettilesize settilesize;
+ Gloadtlut loadtlut;
+ Gsetprimdepth setprimdepth;
+ long long int force_structure_alignment;
+} GfxMod;
+
+#ifdef NON_EQUIVALENT
+void UCodeDisas_Disassemble(UCodeDisas* this, u32 ptr) {
+ GfxMod* gfx; // 0x394 -> s5
+ u32 exit; // 0x378 -> 0x308
+ u32 addr;
+ s32 i0;
+ u32 rdpHalf; // 0x384 -> 0x2FC
+ u16 linkDlLow;
+ u8 sid;
+ GfxMod curGfx; // 0x370 -> 0x2F0 (pointer to it in s8)
+ u8 cmd; // s1
+
+ gfx = ptr;
+ exit = false;
+
+ while (!exit) {
+ this->dlCnt++;
+
+ gfx = UCodeDisas_TranslateAddr(this, gfx);
+ DISAS_LOG("%08x:", gfx);
+
+ curGfx = *gfx;
+ cmd = curGfx.dma.cmd;
+ addr = UCodeDisas_TranslateAddr(this, curGfx.dma.addr);
+
+ DISAS_LOG("%08x-%08x:", curGfx.words.w0, curGfx.words.w1);
+
+ for (i0 = 0; i0 < this->dlDepth; i0++) {
+ DISAS_LOG(" ");
+ }
+
+ // 848
+ switch (cmd) {
+ case G_SPNOOP: {
+ // 850
+ DISAS_LOG("gsSPNoOp(),");
+ break;
+ }
+ case G_DL: {
+ // 878
+ Gdma dma = gfx->dma;
+ switch (dma.par) // minor reordering (branch instruction)
+ {
+ case 0: {
+ // 8B0
+ DISAS_LOG("gsSPDisplayList(0x%08x),", dma.addr);
+ this->dlStack[this->dlDepth++] = gfx + 1;
+ gfx = (GfxMod*)addr - 1;
+ break;
+ }
+ case 1: {
+ // 900
+ DISAS_LOG("gsSPBranchList(0x%08x),", dma.addr);
+ gfx = (GfxMod*)addr - 1;
+ break;
+ }
+ }
+ break;
+ }
+ case G_RDPHALF_1: {
+ // 928
+ DISAS_LOG("RDPHALF_1(0x%08x),", curGfx.dma.addr);
+ rdpHalf = curGfx.dma.addr;
+ break;
+ }
+ case G_TEXRECT: // small reordering
+ {
+ // 94C
+ Gtexrect rect = *(Gtexrect*)gfx;
+ DISAS_LOG("gsSPTextureRectangle(%d,%d,%d,%d,%d,%d,%d,%d,%d),", rect.xh, rect.yh, rect.xl, rect.yl,
+ rect.tile, gfx[1].words.w1 >> 16, gfx[1].words.w1 & 0xFFFF, gfx[2].words.w1 >> 16,
+ gfx[2].words.w1 & 0xFFFF);
+
+ gfx += 3 - 1;
+ this->pipeSyncRequired = true;
+
+ break;
+ }
+ case G_LOAD_UCODE: // len loaded from sp+2F2 instead of s8+2
+ {
+ // A08
+ u16 len = curGfx.dma.len;
+ if (len == 0x7FF) {
+ // A1C
+ DISAS_LOG("gsSPLoadUcode(0x%08x, 0x%08x),", curGfx.dma.addr, rdpHalf);
+ } else {
+ // A3C
+ DISAS_LOG("gsSPLoadUcodeEx(0x%08x, 0x%08x, 0x%05x),", curGfx.dma.addr, rdpHalf, len + 1);
+ }
+ // A5C
+ UCodeDisas_SetCurUCodeImpl(this, (void*)UCodeDisas_TranslateAddr(this, curGfx.dma.addr));
+ this->loaducodeCnt++;
+ break;
+ }
+ case G_ENDDL: {
+ // A84
+ DISAS_LOG("gsSPEndDisplayList(),");
+ if (this->dlDepth <= 0) {
+ // AA0
+ exit = true;
+ } else {
+ // AB0
+ GfxMod* ret = (GfxMod*)this->dlStack[--this->dlDepth];
+ gfx = ret - 1;
+ }
+ break;
+ }
+ case G_SETTILE: // reordering
+ {
+ // AD4
+ Gsettile settile = gfx->settile;
+ DISAS_LOG("gsDPSetTile(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d),", settile.fmt, settile.siz, settile.line,
+ settile.tmem, settile.tile, settile.palette, (settile.ct << 2) + (settile.mt), settile.maskt,
+ settile.shiftt, (settile.cs << 2) + (settile.ms), settile.masks, settile.shifts);
+
+ if (this->tileSyncRequired) {
+ // BB8
+ DISAS_LOG("### TileSyncが必要です。\n");
+ this->syncErr++;
+ }
+ break;
+ }
+ case G_LOADTILE: // minor reordering (branch instruction)
+ {
+ // BE0
+ Gloadtile loadtile = gfx->loadtile;
+ DISAS_LOG("gsDPLoadTile(%d,%d,%d,%d,%d),", loadtile.tile, loadtile.sh, loadtile.th, loadtile.sl,
+ loadtile.tl);
+ break;
+ }
+ // starting here, replacing gfx with curGfx breaks everything for some reason
+ case G_LOADBLOCK: // gfx instead of curGfx(?)
+ {
+ // C4C
+ Gloadtile loadtile = curGfx.loadtile;
+ DISAS_LOG("gsDPLoadBlock(%d,%d,%d,%d,%d),", loadtile.tile, loadtile.sh, loadtile.th, loadtile.sl,
+ loadtile.tl);
+ if (this->loadSyncRequired) {
+ // CB8
+ DISAS_LOG("### LoadSyncが必要です。\n");
+ this->syncErr++;
+ }
+ // CDC
+ this->pipeSyncRequired = true;
+ break;
+ }
+ case G_SETTILESIZE: // gfx instead of curGfx(?) + minor reordering (branch instruction)
+ {
+ // CE8
+ Gloadtile loadtile = curGfx.loadtile;
+ DISAS_LOG("gsDPSetTileSize(%d,%d,%d,%d,%d),", loadtile.tile, loadtile.sh, loadtile.th, loadtile.sl,
+ loadtile.tl);
+ break;
+ }
+ case G_LOADTLUT: // gfx instead of curGfx(?) + minor reordering (branch instruction)
+ {
+ // D54
+ Gloadtlut loadtlut = curGfx.loadtlut;
+ DISAS_LOG("gsDPLoadTLUTCmd(%d,%d),", loadtlut.tile, loadtlut.sh >> 2);
+ break;
+ }
+ case G_SETCOMBINE: // gfx instead of curGfx(?) + minor reordering (branch instruction)
+ {
+ // DA8
+ GsetcombineMod setcombine = curGfx.setcombine;
+ DISAS_LOG("gsDPSetCombineLERP(%s,%s,%s,%s, %s,%s,%s,%s, %s,%s,%s,%s, %s,%s,%s,%s),",
+ UCodeDisas_ParseCombineColor(setcombine.a, 1), UCodeDisas_ParseCombineColor(setcombine.b, 2),
+ UCodeDisas_ParseCombineColor(setcombine.c, 3), UCodeDisas_ParseCombineColor(setcombine.d, 4),
+
+ UCodeDisas_ParseCombineAlpha(setcombine.z, 1), UCodeDisas_ParseCombineAlpha(setcombine.y, 2),
+ UCodeDisas_ParseCombineAlpha(setcombine.x, 3), UCodeDisas_ParseCombineAlpha(setcombine.w, 4),
+
+ UCodeDisas_ParseCombineColor(setcombine.e, 1), UCodeDisas_ParseCombineColor(setcombine.f, 2),
+ UCodeDisas_ParseCombineColor(setcombine.g, 3), UCodeDisas_ParseCombineColor(setcombine.h, 4),
+
+ UCodeDisas_ParseCombineAlpha(setcombine.v, 1), UCodeDisas_ParseCombineAlpha(setcombine.u, 2),
+ UCodeDisas_ParseCombineAlpha(setcombine.t, 3), UCodeDisas_ParseCombineAlpha(setcombine.s, 4));
+
+ // F98
+ if (this->pipeSyncRequired) {
+ // FA8
+ DISAS_LOG("### PipeSyncが必要です。\n");
+ this->syncErr++;
+ }
+ break;
+ }
+ case G_SETOTHERMODE_H: // small reordering
+ {
+ // FD0
+ static F3dzexSetModeMacro sUCodeDisasModeHMacros[] = {
+ F3DZEX_SETRENDERMACRO("SetAlphaDither", G_MDSFT_ALPHADITHER, 2, G_AD_PATTERN, G_AD_NOTPATTERN,
+ G_AD_NOISE, G_AD_DISABLE),
+ F3DZEX_SETRENDERMACRO("SetColorDither", G_MDSFT_RGBDITHER, 2, G_CD_MAGICSQ, G_CD_BAYER, G_CD_NOISE,
+ -1),
+ F3DZEX_SETRENDERMACRO("SetCombineKey", G_MDSFT_COMBKEY, 1, G_CK_NONE, G_CK_KEY, -1, -1),
+ F3DZEX_SETRENDERMACRO("SetTextureConvert", G_MDSFT_TEXTCONV, 3, G_TC_CONV, G_TC_FILTCONV, G_TC_FILT,
+ -1),
+ F3DZEX_SETRENDERMACRO("SetTextureFilter", G_MDSFT_TEXTFILT, 2, G_TF_POINT, G_TF_AVERAGE,
+ G_TF_BILERP, -1),
+ F3DZEX_SETRENDERMACRO("SetTextureLUT", G_MDSFT_TEXTLUT, 2, G_TT_NONE, G_TT_RGBA16, G_TT_IA16, -1),
+ F3DZEX_SETRENDERMACRO("SetTextureLOD", G_MDSFT_TEXTLOD, 1, G_TL_TILE, G_TL_LOD, -1, -1),
+ F3DZEX_SETRENDERMACRO("SetTextureDetail", G_MDSFT_TEXTDETAIL, 2, G_TD_CLAMP, G_TD_SHARPEN,
+ G_TD_DETAIL, -1),
+ F3DZEX_SETRENDERMACRO("SetTexturePersp", G_MDSFT_TEXTPERSP, 1, G_TP_PERSP, G_TP_NONE, -1, -1),
+ F3DZEX_SETRENDERMACRO("SetCycleType", G_MDSFT_CYCLETYPE, 2, G_CYC_1CYCLE, G_CYC_2CYCLE, G_CYC_COPY,
+ G_CYC_FILL),
+ F3DZEX_SETRENDERMACRO("SetColorDither", G_MDSFT_COLORDITHER, 2, G_CD_MAGICSQ, G_CD_BAYER,
+ G_CD_NOISE, -1),
+ F3DZEX_SETRENDERMACRO("PipelineMode", G_MDSFT_PIPELINE, 1, G_PM_1PRIMITIVE, G_PM_NPRIMITIVE, -1,
+ -1),
+ };
+
+ u32 len = curGfx.setothermode.len + 1;
+ u32 sft = (-curGfx.setothermode.sft - len) + 32;
+ u32 i1;
+ u32 i2;
+
+ for (i1 = 0; i1 < ARRAY_COUNTU(sUCodeDisasModeHMacros); i1++) {
+ // 1004
+ if (sft == sUCodeDisasModeHMacros[i1].shift) {
+ for (i2 = 0; i2 < 4; i2++) {
+ // 102C ?
+ if (curGfx.setothermode.data == sUCodeDisasModeHMacros[i1].values[i2].value) {
+ // 1038
+ DISAS_LOG("gsDP%s(%s),", sUCodeDisasModeHMacros[i1].name,
+ sUCodeDisasModeHMacros[i1].values[i2].name);
+ goto block_1;
+ }
+ }
+ }
+ }
+ // 1078
+ DISAS_LOG("gsSPSetOtherModeH(%d, %d, 0x%08x),", sft, len, curGfx.setothermode.data);
+ block_1:
+ // 1098
+ this->modeH &= (((1 - (1 << len)) << sft) - 1);
+ this->modeH |= curGfx.setothermode.data;
+
+ // 10C0
+ if (this->pipeSyncRequired) {
+ DISAS_LOG("### PipeSyncが必要です。\n");
+ this->syncErr++;
+ }
+
+ break;
+ }
+ case G_SETOTHERMODE_L: // small reordering + (i1 != 2) instead of (i1 < 2)
+ {
+ // 10F0
+ static F3dzexSetModeMacro sUCodeDisasModeLMacros[] = {
+ F3DZEX_SETRENDERMACRO("gsDPSetAlphaCompare", G_MDSFT_ALPHACOMPARE, 2, G_AC_NONE, G_AC_THRESHOLD,
+ G_AC_DITHER, -1),
+ F3DZEX_SETRENDERMACRO("gsDPSetDepthSource", G_MDSFT_ZSRCSEL, 1, G_ZS_PIXEL, G_ZS_PRIM, -1, -1),
+ };
+
+ u32 len = curGfx.setothermode.len + 1;
+ u32 sft = (-curGfx.setothermode.sft - len) + 32;
+ u32 i1;
+ u32 i2;
+
+ // 1114
+ if (sft == G_MDSFT_RENDERMODE) {
+ // 111C
+ DISAS_LOG("\ngsDPSetRenderBlender(");
+ UCodeDisas_ParseRenderMode(this, curGfx.setothermode.data);
+ DISAS_LOG("\n),");
+ } else {
+ // 1154
+ // checks (i1 != 2) instead of (i1 < 2) for some reason (this does not happen above)
+ for (i1 = 0; i1 < ARRAY_COUNTU(sUCodeDisasModeLMacros); i1++) {
+ if (sft == sUCodeDisasModeLMacros[i1].shift) {
+ for (i2 = 0; i2 < 4; i2++) {
+ if (curGfx.setothermode.data == sUCodeDisasModeLMacros[i1].values[i2].value) {
+ // 1198
+ DISAS_LOG("gsDP%s(%s),", sUCodeDisasModeLMacros[i1].name,
+ sUCodeDisasModeLMacros[i1].values[i2].name);
+ goto block_2;
+ }
+ }
+ }
+ }
+ // 11D8
+ DISAS_LOG("gsSPSetOtherModeL(%d, %d, 0x%08x),", sft, len, curGfx.setothermode.data);
+ }
+ block_2:
+ // 11F4
+ this->modeL &= (((1 - (1 << len)) << sft) - 1);
+ this->modeL |= curGfx.setothermode.data;
+
+ if (this->pipeSyncRequired) {
+ DISAS_LOG("### PipeSyncが必要です。\n");
+ this->syncErr++;
+ }
+ break;
+ }
+ case G_RDPSETOTHERMODE: {
+ // 1250
+ DISAS_LOG("gsDPSetOtherMode(0x%08x, 0x%08x),", curGfx.words.w0 & 0xFFFFFF, curGfx.words.w1);
+ this->modeH = curGfx.words.w0 & 0xFFF;
+ this->modeL = curGfx.words.w1;
+
+ if (this->pipeSyncRequired) {
+ DISAS_LOG("### PipeSyncが必要です。\n");
+ this->syncErr++;
+ }
+ break;
+ }
+ case G_SETSCISSOR: // gfx instead of curGfx(?) + reordering
+ {
+ // 12C0
+ Gfillrect setscissor = curGfx.fillrect;
+ const char* modeStr;
+
+ modeStr = (setscissor.pad == G_SC_NON_INTERLACE)
+ ? "G_SC_NON_INTERLACE"
+ : (setscissor.pad == G_SC_ODD_INTERLACE)
+ ? "G_SC_ODD_INTERLACE"
+ : (setscissor.pad == G_SC_EVEN_INTERLACE) ? "G_SC_EVEN_INTERLACE" : "???";
+ if ((setscissor.x0frac | setscissor.y0frac | setscissor.x1frac | setscissor.y1frac)) {
+ // 1368
+ // reordering here
+ DISAS_LOG("gsDPSetScissorFrac(%s, %d, %d, %d, %d),", modeStr,
+ (setscissor.x0 << 2) + setscissor.x0frac, (setscissor.y0 << 2) + setscissor.y0frac,
+ (setscissor.x1 << 2) + setscissor.x1frac, (setscissor.y1 << 2) + setscissor.y1frac);
+ } else {
+ // 13E8
+ DISAS_LOG("gsDPSetScissor(%s, %d, %d, %d, %d),", modeStr, setscissor.x0, setscissor.y0,
+ setscissor.x1, setscissor.y1);
+ }
+ break;
+ }
+ case G_FILLRECT: // gfx instead of curGfx(?)
+ {
+ // 1438
+ Gfillrect fillrect = curGfx.fillrect;
+
+ DISAS_LOG("gsDPFillRectangle(%d, %d, %d, %d),", fillrect.x0, fillrect.y0, fillrect.x1, fillrect.y1);
+
+ this->pipeSyncRequired = true;
+ break;
+ }
+ case G_SETCIMG: // reordering
+ {
+ // 14a4
+ u8 fmt = (curGfx.words.w0 & 0xE00000) >> 0x15;
+ u8 siz = (curGfx.words.w0 & 0x180000) >> 0x13;
+
+ DISAS_LOG("gsDPSetColorImage(G_IM_FMT_%s, G_IM_SIZ_%s, %d, 0x%08x(0x%08x) ),",
+ (fmt == G_IM_FMT_RGBA)
+ ? "RGBA"
+ : (fmt == G_IM_FMT_YUV) ? "YUV"
+ : (fmt == G_IM_FMT_CI) ? "CI" : (fmt == G_IM_FMT_IA) ? "IA" : "I",
+ (siz == G_IM_SIZ_4b) ? "4b"
+ : (siz == G_IM_SIZ_8b) ? "8b" : (siz == G_IM_SIZ_16b) ? "16b" : "32b",
+ curGfx.setimg.wd + 1, curGfx.setimg.dram, addr);
+
+ if (this->pipeSyncRequired) {
+ DISAS_LOG("### PipeSyncが必要です。\n");
+ this->syncErr++;
+ }
+ break;
+ }
+ case G_SETZIMG: {
+ // 15E0
+ DISAS_LOG("gsDPSetDepthImage(0x%08x(0x%08x)),", curGfx.words.w1, addr);
+
+ if (this->pipeSyncRequired) {
+ DISAS_LOG("### PipeSyncが必要です。\n");
+ this->syncErr++;
+ }
+ break;
+ }
+ case G_SETTIMG: // reordering
+ {
+ // 1630
+ u8 fmt = (curGfx.words.w0 & 0xE00000) >> 0x15;
+ u8 siz = (curGfx.words.w0 & 0x180000) >> 0x13;
+
+ DISAS_LOG("gsDPSetTextureImage(G_IM_FMT_%s, G_IM_SIZ_%s, %d, 0x%08x(0x%08x)),",
+ (fmt == G_IM_FMT_RGBA)
+ ? "RGBA"
+ : (fmt == G_IM_FMT_YUV) ? "YUV"
+ : (fmt == G_IM_FMT_CI) ? "CI" : (fmt == G_IM_FMT_IA) ? "IA" : "I",
+ (siz == G_IM_SIZ_4b) ? "4b"
+ : (siz == G_IM_SIZ_8b) ? "8b" : (siz == G_IM_SIZ_16b) ? "16b" : "32b",
+ curGfx.setimg.wd + 1, curGfx.setimg.dram, addr);
+ break;
+ }
+ case G_SETENVCOLOR: // minor reordering
+ {
+ // 1740
+ DISAS_LOG("gsDPSetEnvColor(%d, %d, %d, %d),", curGfx.setcolor.r, curGfx.setcolor.g, curGfx.setcolor.b,
+ curGfx.setcolor.a);
+
+ if (this->pipeSyncRequired) {
+ DISAS_LOG("### PipeSyncが必要です。\n");
+ this->syncErr++;
+ }
+ break;
+ }
+ case G_SETBLENDCOLOR: // minor reordering
+ {
+ // 17A0
+ DISAS_LOG("gsDPSetBlendColor(%d, %d, %d, %d),", curGfx.setcolor.r, curGfx.setcolor.g, curGfx.setcolor.b,
+ curGfx.setcolor.a);
+
+ if (this->pipeSyncRequired) {
+ DISAS_LOG("### PipeSyncが必要です。\n");
+ this->syncErr++;
+ }
+ break;
+ }
+ case G_SETFOGCOLOR: // minor reordering
+ {
+ // 1800
+ DISAS_LOG("gsDPSetFogColor(%d, %d, %d, %d),", curGfx.setcolor.r, curGfx.setcolor.g, curGfx.setcolor.b,
+ curGfx.setcolor.a);
+
+ if (this->pipeSyncRequired) {
+ DISAS_LOG("### PipeSyncが必要です。\n");
+ this->syncErr++;
+ }
+ break;
+ }
+ case G_SETFILLCOLOR: {
+ // 1860
+ DISAS_LOG("gsDPSetFillColor(0x%08x),", curGfx.words.w1);
+
+ if (this->pipeSyncRequired) {
+ DISAS_LOG("### PipeSyncが必要です。\n");
+ this->syncErr++;
+ }
+ break;
+ }
+ case G_SETPRIMDEPTH: {
+ // 18AC
+ DISAS_LOG("gsDPSetPrimDepth(%d, %d),", curGfx.setprimdepth.z, curGfx.setprimdepth.d);
+
+ if (this->pipeSyncRequired) {
+ DISAS_LOG("### PipeSyncが必要です。\n");
+ this->syncErr++;
+ }
+ break;
+ }
+ case G_SETPRIMCOLOR: // reordering
+ {
+ // 18FC
+ DISAS_LOG("gsDPSetPrimColor(%d, %d, %d, %d, %d, %d),", curGfx.setcolor.prim_min_level,
+ curGfx.setcolor.prim_level, curGfx.setcolor.r, curGfx.setcolor.g, curGfx.setcolor.b,
+ curGfx.setcolor.a);
+ break;
+ }
+ case G_RDPFULLSYNC: {
+ // 1940
+ DISAS_LOG("gsDPFullSync(),");
+ if (this->pipeSyncRequired) {
+ DISAS_LOG("### PipeSyncが必要です。\n");
+ this->syncErr++;
+ }
+ break;
+ }
+ case G_RDPTILESYNC: {
+ // 1988
+ DISAS_LOG("gsDPTileSync(),");
+ this->tileSyncRequired = false;
+ break;
+ }
+ case G_RDPPIPESYNC: {
+ // 19A8
+ DISAS_LOG("gsDPPipeSync(),");
+ this->pipeSyncRequired = false;
+ break;
+ }
+ case G_RDPLOADSYNC: {
+ // 19C8
+ DISAS_LOG("gsDPLoadSync(),");
+ this->loadSyncRequired = false;
+ break;
+ }
+ case G_NOOP: {
+ // 19E8
+ switch (curGfx.noop.type) {
+ case 0: // curGfx.noop.value.u32 should be reused
+ {
+ // 1A10
+ if (curGfx.noop.value.u32 == 0) {
+ DISAS_LOG("gsDPNoOp(),");
+ } else {
+ DISAS_LOG("gsDPNoOpTag(%08x),", curGfx.noop.value.u32);
+ }
+ break;
+ }
+ case 1: {
+ // 1A4C
+ DISAS_LOG("count_gsDPNoOpHere([%s:%d]),", curGfx.noop.value.u32, curGfx.dma.len);
+ break;
+ }
+ case 7: {
+ // 1A6C
+ DISAS_LOG("count_gsDPNoOpOpenDisp([%s:%d]),", curGfx.noop.value.u32, curGfx.noop.len);
+ break;
+ }
+ case 8: {
+ // 1A8C
+ DISAS_LOG("count_gsDPNoOpCloseDisp([%s:%d]),", curGfx.noop.value.u32, curGfx.noop.len);
+ break;
+ }
+ case 2: // minor reordering
+ {
+ // 1AAC
+ DISAS_LOG("count_gsDPNoOpString(%c%s%c, %d),", '"', curGfx.noop.value.u32, '"',
+ curGfx.noop.len);
+ break;
+ }
+ case 3: {
+ // 1AD8
+ DISAS_LOG("count_gsDPNoOpWord(0x%08x, %d),", curGfx.noop.value.u32, curGfx.noop.len);
+ break;
+ }
+ case 4: {
+ // 1AFC
+ DISAS_LOG("count_gsDPNoOpFloat(%8.3f, %d),", curGfx.noop.value.f32, curGfx.noop.len);
+ break;
+ }
+ case 5: // missing a move
+ {
+ // 1B30
+ if (curGfx.noop.len == 0) {
+ DISAS_LOG("count_gsDPNoOpQuiet(),");
+ } else {
+ DISAS_LOG("count_gsDPNoOpVerbose(),");
+ }
+ this->enableLog = curGfx.noop.len;
+ break;
+ }
+ case 6: {
+ // 1B74
+ /*! @bug arguments are not printed */
+ DISAS_LOG("count_gsDPNoOpCallBack(%08x,%d),");
+ ((void (*)(UCodeDisas*, u32))curGfx.noop.value.u32)(this, curGfx.noop.len);
+ break;
+ }
+ default: // curGfx.noop.type seems reused
+ {
+ // 1BA0
+ DISAS_LOG("gsDPNoOpTag3(%02x, %08x, %04x),", curGfx.noop.type, curGfx.noop.value.u32,
+ curGfx.noop.len);
+ break;
+ }
+ }
+ break;
+ }
+ default: {
+ // 1BBC
+ // there's a problem here
+ switch (this->ucodeType) {
+ case UCODE_F3DZEX:
+ case UCODE_UNK: {
+ // 1BE8
+ switch (curGfx.dma.cmd) // which one to choose here?
+ {
+ case G_MTX: // gfx instead of curGfx(?) + lbu -> lb + reordering
+ {
+ // 1C3C
+ Gmatrix gmtx = curGfx.matrix;
+ MtxF mtx;
+ MatrixInternal* mtxp = (MatrixInternal*)addr;
+ s32 i1;
+ u32 params;
+ DISAS_LOG("gsSPMatrix(0x%08x(%08x), 0", gmtx.addr, addr);
+
+ params = (gmtx.params ^ G_MTX_PUSH);
+
+ for (i1 = 0; i1 < ARRAY_COUNT(sUCodeDisasMtxFlags); i1++) {
+ DISAS_LOG("|%s", (sUCodeDisasMtxFlags[i1].value & params)
+ ? sUCodeDisasMtxFlags[i1].setName
+ : sUCodeDisasMtxFlags[i1].unsetName);
+ }
+ DISAS_LOG("),", gmtx.addr); /*! @bug gmtx.addr shouldn't be here*/
+
+ if (this->enableLog >= 2) {
+ MtxConv_L2F(&mtx, mtxp);
+ DISAS_LOG("\n");
+ /*! @bug %.04x.%04x is a typo, should be %04x.%04x */
+ DISAS_LOG(
+ "/ %04x.%04x %04x.%04x %04x.%04x %.04x.%04x \\/ %12.6f %12.6f %12.6f %12.6f "
+ "\\\n"
+ "| %04x.%04x %04x.%04x %04x.%04x %.04x.%04x || %12.6f %12.6f %12.6f %12.6f |\n"
+ "| %04x.%04x %04x.%04x %04x.%04x %.04x.%04x || %12.6f %12.6f %12.6f %12.6f |\n"
+ "\\ %04x.%04x %04x.%04x %04x.%04x %.04x.%04x /\\ %12.6f %12.6f %12.6f %12.6f "
+ "/\n",
+ mtxp->intPart[0][0], mtxp->fracPart[0][0], mtxp->intPart[1][0],
+ mtxp->fracPart[1][0], mtxp->intPart[2][0], mtxp->fracPart[2][0],
+ mtxp->intPart[3][0], mtxp->fracPart[3][0], mtx.mf[0][0], mtx.mf[1][0],
+ mtx.mf[2][0], mtx.mf[3][0],
+
+ mtxp->intPart[0][1], mtxp->fracPart[0][1], mtxp->intPart[1][1],
+ mtxp->fracPart[1][1], mtxp->intPart[2][1], mtxp->fracPart[2][1],
+ mtxp->intPart[3][1], mtxp->fracPart[3][1], mtx.mf[0][1], mtx.mf[1][1],
+ mtx.mf[2][1], mtx.mf[3][1],
+
+ mtxp->intPart[0][2], mtxp->fracPart[0][2], mtxp->intPart[1][2],
+ mtxp->fracPart[1][2], mtxp->intPart[2][2], mtxp->fracPart[2][2],
+ mtxp->intPart[3][2], mtxp->fracPart[3][2], mtx.mf[0][2], mtx.mf[1][2],
+ mtx.mf[2][2], mtx.mf[3][2],
+
+ mtxp->intPart[0][3], mtxp->fracPart[0][3], mtxp->intPart[1][3],
+ mtxp->fracPart[1][3], mtxp->intPart[2][3], mtxp->fracPart[2][3],
+ mtxp->intPart[3][3], mtxp->fracPart[3][3], mtx.mf[0][3], mtx.mf[1][3],
+ mtx.mf[2][3], mtx.mf[3][3]);
+ }
+ break;
+ }
+ case G_VTX: {
+ // 1EF4
+ // this is not correct
+ s32 numv = (curGfx.words.w0 >> 12) & 0xFF;
+ s32 vbidx = ((curGfx.words.w0 & 0xFF) >> 1) - numv;
+ DISAS_LOG("gsSPVertex(0x%08x(0x%08x), %d, %d),", curGfx.words.w1, addr, numv, vbidx);
+
+ this->vtxCnt += numv;
+ this->spvtxCnt++;
+
+ if (this->enableLog >= 2) {
+ UCodeDisas_PrintVertices(this, addr, numv, vbidx);
+ }
+ break;
+ }
+ case G_MODIFYVTX: // additional move
+ {
+ // 1F74
+ u16 where = curGfx.dma.len;
+ DISAS_LOG("gsSPModifyVertex(%d, %s, %08x),", curGfx.dma.par,
+ (where == G_MWO_POINT_RGBA)
+ ? "G_MWO_POINT_RGBA"
+ : (where == G_MWO_POINT_ST)
+ ? "G_MWO_POINT_ST"
+ : (where == G_MWO_POINT_XYSCREEN)
+ ? "G_MWO_POINT_XYSCREEN"
+ : (where == G_MWO_POINT_ZSCREEN) ? "G_MWO_POINT_ZSCREEN"
+ : "G_MWO_POINT_????",
+ curGfx.dma.addr);
+ this->vtxCnt += curGfx.dma.par;
+ this->spvtxCnt++;
+ break;
+ }
+ case G_TRI1: // a Gtri1 struct should probably be used here + code missing
+ {
+ // 2024
+ Gwords words2 = curGfx.words;
+ DISAS_LOG("gsSP1Triangle(%d, %d, %d),", ((words2.w0 >> 16) & 0xFF) / 2,
+ ((words2.w0 >> 8) & 0xFF) / 2, ((words2.w0 >> 0) & 0xFF) / 2);
+
+ this->pipeSyncRequired = true;
+ this->tri1Cnt++;
+ break;
+ }
+ case G_LINE3D: // curGfx should be used here(?)
+ {
+ // 20BC
+ Gline3DFix* line = (Gline3DFix*)&curGfx;
+ if (line->wd == 0) {
+ DISAS_LOG("gsSPLine3D(%d, %d),", line->v0, line->v1);
+ } else {
+ DISAS_LOG("gsSPLineW3D(%d, %d, %d),", line->v0, line->v1, line->wd);
+ }
+ this->pipeSyncRequired = true;
+ this->lineCnt++;
+ break;
+ }
+ case G_TRI2: // gfx instead of curGfx(?) + a Gtri2 struct should probably be used here +
+ // code missing
+ {
+ Gwords words2 = curGfx.words;
+ DISAS_LOG("gsSP2Triangles(%d, %d, %d, 0, %d, %d, %d, 0),",
+ ((words2.w0 >> 16) & 0xFF) / 2, ((words2.w0 >> 8) & 0xFF) / 2,
+ ((words2.w0 >> 0) & 0xFF) / 2, ((words2.w1 >> 16) & 0xFF) / 2,
+ ((words2.w1 >> 8) & 0xFF) / 2, ((words2.w1 >> 0) & 0xFF) / 2);
+
+ this->pipeSyncRequired = true;
+ this->tri2Cnt++;
+ break;
+ }
+ case G_QUAD: // gfx instead of curGfx(?) + a Gquad struct should probably be used here +
+ // code missing
+ {
+ Gwords words2 = curGfx.words;
+ DISAS_LOG("gsSP1Quadrangle(%d, %d, %d, %d, 0),", ((words2.w0 >> 16) & 0xFF) / 2,
+ ((words2.w0 >> 8) & 0xFF) / 2, ((words2.w0 >> 0) & 0xFF) / 2,
+ ((words2.w1 >> 0) & 0xFF) / 2);
+ this->pipeSyncRequired = true;
+ this->quadCnt++;
+ break;
+ }
+ case G_CULLDL: // code missing
+ {
+ DISAS_LOG("gsSPCullDisplayList(%d, %d),", (curGfx.words.w0 & 0xFFFF) / 2,
+ (curGfx.words.w1 & 0xFFFF) / 2);
+ break;
+ }
+ case G_BRANCH_Z: {
+ GfxMod* dst = UCodeDisas_TranslateAddr(this, rdpHalf);
+ DISAS_LOG("gsSPBranchLessZraw(0x%08x(0x%08x), %d, 0x%08x),", rdpHalf, dst,
+ (curGfx.words.w0 & 0xFFF) / 2, curGfx.words.w1);
+ gfx = dst - 1;
+ break;
+ }
+ case G_TEXTURE: // gfx instead of curGfx(?) + reordering + arithmetic issue?
+ {
+ Gtexture texture = curGfx.texture;
+ if (texture.lodscale == 0) {
+ DISAS_LOG("gsSPTexture(%d, %d, %d, %d, %s),", texture.s, texture.t,
+ texture.tile >> 3, texture.tile & 7, texture.on ? "G_ON" : "G_OFF");
+ } else {
+ DISAS_LOG("gsSPTextureL(%d, %d, %d, %d, %d, %s),", texture.s, texture.t,
+ texture.tile >> 3, texture.lodscale, texture.tile & 7,
+ texture.on ? "G_ON" : "G_OFF");
+ }
+ break;
+ }
+ case G_POPMTX: // gfx instead of curGfx(?) + reordering
+ {
+ Gwords words2 = curGfx.words;
+ s32 num = words2.w1 / 64;
+ if (num == 1) {
+ DISAS_LOG("gsSPPopMatrix(G_MTX_MODELVIEW),");
+ } else {
+ DISAS_LOG("gsSPPopMatrixN(G_MTX_MODELVIEW, %d),", num);
+ }
+ break;
+ }
+ case G_GEOMETRYMODE: {
+ u32 clearbits = curGfx.words.w0 & 0xFFFFFF;
+ u32 setbits = curGfx.words.w1 & 0xFFFFFF; // ?? setbits should be 32bit
+
+ if (clearbits == 0) {
+ DISAS_LOG("gsSPLoadGeometryMode(");
+ UCodeDisas_ParseGeometryMode(this, setbits);
+ DISAS_LOG("),");
+ } else {
+ if (setbits == 0) {
+ DISAS_LOG("gsSPClearGeometryMode(");
+ UCodeDisas_ParseGeometryMode(this, ~clearbits);
+ DISAS_LOG("),");
+ } else {
+ if (clearbits == 0xFFFFFF) {
+ DISAS_LOG("gsSPSetGeometryMode(");
+ UCodeDisas_ParseGeometryMode(this, setbits);
+ DISAS_LOG("),");
+ } else {
+ DISAS_LOG("gsSPGeometryMode(");
+ UCodeDisas_ParseGeometryMode(this, ~clearbits);
+ DISAS_LOG(",");
+ UCodeDisas_ParseGeometryMode(this, setbits);
+ DISAS_LOG("),");
+ }
+ }
+ }
+ this->geometryMode &= clearbits;
+ this->geometryMode |= setbits;
+ break;
+ }
+ case G_MOVEWORD: // gfx instead of curGfx(?) + missing code + missing copy
+ {
+ Gdma dma = curGfx.dma; // Gsegment ?
+ switch (dma.par) {
+ case G_MW_SEGMENT: {
+ DISAS_LOG("gsSPSegment(%d, 0x%08x),", dma.len, dma.addr / 4);
+ break;
+ }
+ case G_MW_CLIP: {
+ DISAS_LOG("gsSPClipRatio(FRUSTRATIO_%d), ",
+ (dma.addr != 0) ? dma.addr : -dma.addr);
+ gfx += 4 - 1;
+ break;
+ }
+ case G_MW_NUMLIGHT: {
+ DISAS_LOG("gsSPNumLights(%d), ", dma.addr / 24);
+ break;
+ }
+ case G_MW_LIGHTCOL: {
+ DISAS_LOG("gsSPLightColor(%d, %d), ", ((dma.addr & 0xF0) >> 5) + 1, dma.addr);
+ break;
+ gfx += 2 - 1;
+ }
+ case G_MW_FOG: {
+ DISAS_LOG("gsSPFogFactor(%d, %d),", dma.addr >> 16, dma.addr & 0xFFFF);
+ break;
+ }
+ case G_MW_PERSPNORM: {
+ DISAS_LOG("gsSPPerspNormalize(%d),", dma.addr);
+ break;
+ }
+ default: {
+ DISAS_LOG("gsMoveWd(%d, %d, %d), ", dma.par, dma.len, dma.addr);
+ break;
+ }
+ }
+ break;
+ }
+ case G_MOVEMEM: // gfx instead of curGfx(?) + code is wrong
+ {
+ Gwords words2 = curGfx.words;
+ s32 offset = (words2.w0 >> 8) & 0xFF;
+ s32 size = (((words2.w0 >> 16) >> 3) + 1) * 8;
+ s32 index = words2.w0 & 0xFF;
+ Vp_t* vp = (Vp_t*)addr;
+
+ switch (index) {
+ case G_MV_VIEWPORT: {
+ DISAS_LOG("gsSPViewport(0x%08x(0x%08x)),", words2.w1, vp);
+ DISAS_LOG("\t# vscale=[%d %d %d %d], ", vp->vscale[0], vp->vscale[1],
+ vp->vscale[2], vp->vscale[3]);
+ DISAS_LOG("vtrans=[%d %d %d %d] ", vp->vtrans[0], vp->vtrans[1], vp->vtrans[2],
+ vp->vtrans[3]);
+ break;
+ }
+ case G_MV_MATRIX: {
+ DISAS_LOG("gsSPForceMatrix(0x%08x),", words2.w1);
+ break;
+ }
+ case G_MV_LIGHT: {
+ switch ((offset * 8)) {
+ case G_MVO_LOOKATX: {
+ DISAS_LOG("gsSPLookAtX(0x%08x),", words2.w1);
+ break;
+ }
+ case G_MVO_LOOKATY: {
+ DISAS_LOG("gsSPLookAtY(0x%08x),", words2.w1);
+ break;
+ }
+ default: {
+ DISAS_LOG("gsSPLight(0x%08x,%d),", words2.w1, (offset * 8 - 24) / 24);
+ break;
+ }
+ }
+ break;
+ }
+ default: {
+ DISAS_LOG("gsMoveMem(0x%08x, %d, %d, %d),", words2.w1, size, index, offset * 8);
+ break;
+ }
+ }
+ break;
+ }
+ default: {
+ DISAS_LOG("AnyDisplayList(),");
+ }
+ }
+ }
+ case UCODE_S2DEX: {
+ // 29FC?
+ switch (curGfx.dma.cmd) // which one to choose here?
+ {
+ case G_BG_COPY: // gfx instead of curGfx(?) + missing copy
+ {
+ DISAS_LOG("gsSPBgRectCopy(0x%08x(0x%08x)),", curGfx.words.w1, addr);
+ this->pipeSyncRequired = true;
+ break;
+ }
+ case G_BG_1CYC: // gfx instead of curGfx(?) + missing copy
+ {
+ DISAS_LOG("gsSPBgRect1Cyc(0x%08x(0x%08x)),", curGfx.words.w1, addr);
+ this->pipeSyncRequired = true;
+ break;
+ }
+ case G_OBJ_SPRITE: // gfx instead of curGfx(?) + missing copy
+ {
+ DISAS_LOG("gsSPObjSprite(0x%08x(0x%08x)),", curGfx.words.w1, addr);
+ this->pipeSyncRequired = true;
+ break;
+ }
+ case G_OBJ_RECTANGLE: // gfx instead of curGfx(?) + missing copy
+ {
+ DISAS_LOG("gsSPObjRectangle(0x%08x(0x%08x)),", curGfx.words.w1, addr);
+ this->pipeSyncRequired = true;
+ break;
+ }
+ case G_OBJ_RECTANGLE_R: // gfx instead of curGfx(?)
+ {
+ DISAS_LOG("gsSPObjRectangleR(0x%08x(0x%08x)),", curGfx.words.w1, addr);
+ this->pipeSyncRequired = true;
+ break;
+ }
+ case G_RDPHALF_0: {
+ DISAS_LOG("RDPHALF_0(0x%02x, 0x%08x, 0x%04x),", curGfx.dma.par, curGfx.dma.addr,
+ curGfx.dma.len);
+ sid = curGfx.dma.par;
+ rdpHalf = curGfx.dma.addr;
+ linkDlLow = curGfx.dma.len;
+ break;
+ }
+ case G_OBJ_MOVEMEM: // gfx instead of curGfx(?)
+ {
+ Gdma dma = curGfx.dma;
+ if (dma.par == 23) {
+ DISAS_LOG("gsSPObjMatrix(0x%08x(0x%08x)),", dma.addr, addr);
+ } else {
+ DISAS_LOG("gsSPObjSubMatrix(0x%08x(0x%08x)),", dma.addr, addr);
+ }
+ break;
+ }
+ case G_OBJ_LOADTXTR: // gfx instead of curGfx(?)
+ {
+ DISAS_LOG("gsSPObjLoadTxtr(0x%08x(0x%08x)),", curGfx.dma.addr, addr);
+ break;
+ }
+ case G_OBJ_LDTX_SPRITE: // gfx instead of curGfx(?)
+ {
+ DISAS_LOG("gsSPObjLoadTxSprite(0x%08x(0x%08x)),", curGfx.dma.addr, addr);
+ break;
+ }
+ case G_OBJ_LDTX_RECT: // gfx instead of curGfx(?)
+ {
+ DISAS_LOG("gsSPObjLoadTxRect(0x%08x(0x%08x)),", curGfx.dma.addr, addr);
+ break;
+ }
+ case G_OBJ_LDTX_RECT_R: // gfx instead of curGfx(?)
+ {
+ DISAS_LOG("gsSPObjLoadTxRectR(0x%08x(0x%08x)),", curGfx.dma.addr, addr);
+ break;
+ }
+ case G_SELECT_DL: // gfx instead of curGfx(?)
+ {
+ Gdma dma = curGfx.dma;
+ u32 dlAddr = UCodeDisas_TranslateAddr(this, (linkDlLow << 16) | dma.len);
+ if (dma.par == 0) {
+ DISAS_LOG("gsSPSelectDL(0x%08x, %d, 0x%08x, 0x%08x),", dlAddr, sid, rdpHalf,
+ dma.addr);
+ } else {
+ DISAS_LOG("gsSPSelectBranchDL(0x%08x, %d, 0x%08x, 0x%08x),", dlAddr, sid, rdpHalf,
+ dma.addr);
+ }
+
+ break;
+ }
+ case 0xDB: // gfx instead of curGfx(?)
+ {
+ Gdma dma = curGfx.dma;
+ switch (dma.par) {
+ case 6: {
+ u32 segId = dma.len / 2;
+ DISAS_LOG("gsSPSegment(%d, 0x%08x),", segId, dma.addr);
+ this->segments[segId] = dma.addr & 0xFFFFFF;
+ break;
+ }
+ case 8: {
+ DISAS_LOG("gsSPSetStatus(0x%08x, 0x%08x),", dma.len, dma.addr);
+ break;
+ }
+ default: {
+ DISAS_LOG("gsMoveWd(%d, %d, %d), ", dma, dma.len, dma.addr);
+ break;
+ }
+ }
+ break;
+ }
+ case G_OBJ_RENDERMODE: // gfx instead of curGfx(?)
+ {
+ DISAS_LOG("gsSPObjRenderMode(0x%08x),", curGfx.dma.addr);
+ }
+ default: {
+ DISAS_LOG("AnyDisplayList(),");
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ DISAS_LOG("\n");
+
+ gfx++;
+ }
+}
+#else
void UCodeDisas_Disassemble(UCodeDisas* this, Gfx* gfx0);
#pragma GLOBAL_ASM("asm/non_matchings/code/ucode_disas/UCodeDisas_Disassemble.rodata.s")
F3dzexSetModeMacro sUCodeDisasModeHMacros[] = {
@@ -273,6 +1349,7 @@ F3dzexSetModeMacro sUCodeDisasModeLMacros[] = {
F3DZEX_SETRENDERMACRO("gsDPSetDepthSource", G_MDSFT_ZSRCSEL, 1, G_ZS_PIXEL, G_ZS_PRIM, -1, -1),
};
#pragma GLOBAL_ASM("asm/non_matchings/code/ucode_disas/UCodeDisas_Disassemble.s")
+#endif
void UCodeDisas_RegisterUCode(UCodeDisas* this, s32 count, UCodeInfo* ucodeArray) {
this->ucodeInfoCount = count;