1
0
Fork 0
mirror of https://github.com/zeldaret/oot.git synced 2025-02-20 13:55:26 +00:00

ucode_disas.c progress (#188)

* ucode_disas.c progress

* fix

* minor fixes

* minor comment changes
This commit is contained in:
Random 2020-06-05 19:18:39 +02:00 committed by GitHub
parent e67c51b155
commit 94d810193a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 1749 additions and 2099 deletions

View file

@ -100,6 +100,7 @@ build/src/code/fault.o: CFLAGS += -trapuv
build/src/code/fault.o: OPTFLAGS := -O2 -g3 build/src/code/fault.o: OPTFLAGS := -O2 -g3
build/src/code/fault_drawer.o: CFLAGS += -trapuv build/src/code/fault_drawer.o: CFLAGS += -trapuv
build/src/code/fault_drawer.o: OPTFLAGS := -O2 -g3 build/src/code/fault_drawer.o: OPTFLAGS := -O2 -g3
build/src/code/ucode_disas.o: OPTFLAGS := -O2 -g3
build/src/code/code_801068B0.o: OPTFLAGS := -g build/src/code/code_801068B0.o: OPTFLAGS := -g
build/src/code/code_80106860.o: OPTFLAGS := -g build/src/code/code_80106860.o: OPTFLAGS := -g
build/src/code/code_801067F0.o: OPTFLAGS := -g build/src/code/code_801067F0.o: OPTFLAGS := -g

View file

@ -9,7 +9,7 @@
.balign 16 .balign 16
glabel Yaz0_Old_Decompress glabel Mio0_Decompress
/* 0031B0 800025B0 8C870008 */ lw $a3, 8($a0) /* 0031B0 800025B0 8C870008 */ lw $a3, 8($a0)
/* 0031B4 800025B4 8C99000C */ lw $t9, 0xc($a0) /* 0031B4 800025B4 8C99000C */ lw $t9, 0xc($a0)
/* 0031B8 800025B8 8C980004 */ lw $t8, 4($a0) /* 0031B8 800025B8 8C980004 */ lw $t8, 4($a0)

View file

@ -0,0 +1,84 @@
.rdata
glabel D_80147E58
.asciz "%08x:"
.balign 4
glabel D_80147E60
.asciz "%08x-%08x:"
.balign 4
glabel D_80147E6C
.asciz " "
.balign 4
glabel D_80147E70
.asciz "gsSPNoOp(),"
.balign 4
glabel D_80147E7C
.asciz "gsSPDisplayList(0x%08x),"
.balign 4
glabel D_80147E98
.asciz "gsSPBranchList(0x%08x),"
.balign 4
glabel D_80147EB0
.asciz "RDPHALF_1(0x%08x),"
.balign 4
glabel D_80147EC4
.asciz "gsSPTextureRectangle(%d,%d,%d,%d,%d,%d,%d,%d,%d),"
.balign 4
glabel D_80147EF8
.asciz "gsSPLoadUcode(0x%08x, 0x%08x),"
.balign 4
glabel D_80147F18
.asciz "gsSPLoadUcodeEx(0x%08x, 0x%08x, 0x%05x),"
.balign 4
glabel D_80147F44
.asciz "gsSPEndDisplayList(),"
.balign 4
glabel D_80147F5C
.asciz "gsDPSetTile(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d),"
.balign 4
glabel D_80147F90
.asciz "\x23\x23\x23 TileSync\n"
# EUC-JP: | Is required.
.balign 4
glabel D_80147FAC
.asciz "gsDPLoadTile(%d,%d,%d,%d,%d),"
.balign 4
glabel D_80147FCC
.asciz "gsDPLoadBlock(%d,%d,%d,%d,%d),"
.balign 4
glabel D_80147FEC
.asciz "\x23\x23\x23 LoadSync\n"
# EUC-JP: | Is required.
.balign 4
glabel D_80148008
.asciz "gsDPSetTileSize(%d,%d,%d,%d,%d),"
.balign 4
glabel D_8014802C
.asciz "gsDPLoadTLUTCmd(%d,%d),"
.balign 4
glabel D_80148044
.asciz "gsDPSetCombineLERP(%s,%s,%s,%s, %s,%s,%s,%s, %s,%s,%s,%s, %s,%s,%s,%s),"
.balign 4
glabel D_8014808C
.asciz "\x23\x23\x23 PipeSync\n"
# EUC-JP: | Is required.
.balign 4

View file

@ -0,0 +1,14 @@
.rdata
glabel D_80148374
.asciz "gsDP%s(%s),"
.balign 4
glabel D_80148380
.asciz "gsSPSetOtherModeH(%d, %d, 0x%08x),"
.balign 4
glabel D_801483A4
.asciz "\x23\x23\x23 PipeSync\n"
# EUC-JP: | Is required.
.balign 4

View file

@ -0,0 +1,67 @@
.rdata
glabel D_80147C04
.asciz "|"
.balign 4
glabel D_80147C08
.asciz "%s"
.balign 4
.text
glabel UCodeDisas_ParseGeometryMode
/* B4F1FC 800D805C 27BDFFC8 */ addiu $sp, $sp, -0x38
/* B4F200 800D8060 AFB30024 */ sw $s3, 0x24($sp)
/* B4F204 800D8064 AFB20020 */ sw $s2, 0x20($sp)
/* B4F208 800D8068 00809025 */ move $s2, $a0
/* B4F20C 800D806C 00A09825 */ move $s3, $a1
/* B4F210 800D8070 AFBF0034 */ sw $ra, 0x34($sp)
/* B4F214 800D8074 AFB60030 */ sw $s6, 0x30($sp)
/* B4F218 800D8078 AFB5002C */ sw $s5, 0x2c($sp)
/* B4F21C 800D807C AFB40028 */ sw $s4, 0x28($sp)
/* B4F220 800D8080 AFB1001C */ sw $s1, 0x1c($sp)
/* B4F224 800D8084 AFB00018 */ sw $s0, 0x18($sp)
/* B4F228 800D8088 3C108013 */ lui $s0, %hi(sUCodeDisasGeometryModes) # $s0, 0x8013
/* B4F22C 800D808C 3C168014 */ lui $s6, %hi(D_80147C04) # $s6, 0x8014
/* B4F230 800D8090 3C158014 */ lui $s5, %hi(D_80147C08) # $s5, 0x8014
/* B4F234 800D8094 3C148013 */ lui $s4, %hi(sUCodeDisasMtxFlags) # $s4, 0x8013
/* B4F238 800D8098 24110001 */ li $s1, 1
/* B4F23C 800D809C 2694DCF8 */ addiu $s4, %lo(sUCodeDisasMtxFlags) # addiu $s4, $s4, -0x2308
/* B4F240 800D80A0 26B57C08 */ addiu $s5, %lo(D_80147C08) # addiu $s5, $s5, 0x7c08
/* B4F244 800D80A4 26D67C04 */ addiu $s6, %lo(D_80147C04) # addiu $s6, $s6, 0x7c04
/* B4F248 800D80A8 2610DCA0 */ addiu $s0, %lo(sUCodeDisasGeometryModes) # addiu $s0, $s0, -0x2360
/* B4F24C 800D80AC 8E0E0000 */ lw $t6, ($s0)
.L800D80B0:
/* B4F250 800D80B0 0011102B */ sltu $v0, $zero, $s1
/* B4F254 800D80B4 01D37824 */ and $t7, $t6, $s3
/* B4F258 800D80B8 51E0000E */ beql $t7, $zero, .L800D80F4
/* B4F25C 800D80BC 26100008 */ addiu $s0, $s0, 8
/* B4F260 800D80C0 8E4300BC */ lw $v1, 0xbc($s2)
/* B4F264 800D80C4 14400006 */ bnez $v0, .L800D80E0
/* B4F268 800D80C8 00008825 */ move $s1, $zero
/* B4F26C 800D80CC 10600004 */ beqz $v1, .L800D80E0
/* B4F270 800D80D0 00000000 */ nop
/* B4F274 800D80D4 0C00084C */ jal osSyncPrintf
/* B4F278 800D80D8 02C02025 */ move $a0, $s6
/* B4F27C 800D80DC 8E4300BC */ lw $v1, 0xbc($s2)
.L800D80E0:
/* B4F280 800D80E0 10600003 */ beqz $v1, .L800D80F0
/* B4F284 800D80E4 02A02025 */ move $a0, $s5
/* B4F288 800D80E8 0C00084C */ jal osSyncPrintf
/* B4F28C 800D80EC 8E050004 */ lw $a1, 4($s0)
.L800D80F0:
/* B4F290 800D80F0 26100008 */ addiu $s0, $s0, 8
.L800D80F4:
/* B4F294 800D80F4 5614FFEE */ bnel $s0, $s4, .L800D80B0
/* B4F298 800D80F8 8E0E0000 */ lw $t6, ($s0)
/* B4F29C 800D80FC 8FBF0034 */ lw $ra, 0x34($sp)
/* B4F2A0 800D8100 8FB00018 */ lw $s0, 0x18($sp)
/* B4F2A4 800D8104 8FB1001C */ lw $s1, 0x1c($sp)
/* B4F2A8 800D8108 8FB20020 */ lw $s2, 0x20($sp)
/* B4F2AC 800D810C 8FB30024 */ lw $s3, 0x24($sp)
/* B4F2B0 800D8110 8FB40028 */ lw $s4, 0x28($sp)
/* B4F2B4 800D8114 8FB5002C */ lw $s5, 0x2c($sp)
/* B4F2B8 800D8118 8FB60030 */ lw $s6, 0x30($sp)
/* B4F2BC 800D811C 03E00008 */ jr $ra
/* B4F2C0 800D8120 27BD0038 */ addiu $sp, $sp, 0x38

View file

@ -0,0 +1,116 @@
.rdata
glabel D_80147D98
.asciz "%s|"
.balign 4
glabel D_80147D9C
.asciz "\nGBL_c1(%s, %s, %s, %s)|"
.balign 4
glabel D_80147DB8
.asciz "\nGBL_c2(%s, %s, %s, %s)"
.balign 4
.text
glabel UCodeDisas_ParseRenderMode
/* B4F2C4 800D8124 27BDFFC8 */ addiu $sp, $sp, -0x38
/* B4F2C8 800D8128 AFB40030 */ sw $s4, 0x30($sp)
/* B4F2CC 800D812C AFB3002C */ sw $s3, 0x2c($sp)
/* B4F2D0 800D8130 00809825 */ move $s3, $a0
/* B4F2D4 800D8134 00A0A025 */ move $s4, $a1
/* B4F2D8 800D8138 AFBF0034 */ sw $ra, 0x34($sp)
/* B4F2DC 800D813C AFB20028 */ sw $s2, 0x28($sp)
/* B4F2E0 800D8140 AFB10024 */ sw $s1, 0x24($sp)
/* B4F2E4 800D8144 AFB00020 */ sw $s0, 0x20($sp)
/* B4F2E8 800D8148 3C108013 */ lui $s0, %hi(sUCodeDisasRenderModeFlags) # $s0, 0x8013
/* B4F2EC 800D814C 3C128014 */ lui $s2, %hi(D_80147D98) # $s2, 0x8014
/* B4F2F0 800D8150 3C118013 */ lui $s1, %hi(D_8012DDDC) # $s1, 0x8013
/* B4F2F4 800D8154 2631DDDC */ addiu $s1, %lo(D_8012DDDC) # addiu $s1, $s1, -0x2224
/* B4F2F8 800D8158 26527D98 */ addiu $s2, %lo(D_80147D98) # addiu $s2, $s2, 0x7d98
/* B4F2FC 800D815C 2610DD1C */ addiu $s0, %lo(sUCodeDisasRenderModeFlags) # addiu $s0, $s0, -0x22e4
/* B4F300 800D8160 8E6200BC */ lw $v0, 0xbc($s3)
/* B4F304 800D8164 8E0E0008 */ lw $t6, 8($s0)
.L800D8168:
/* B4F308 800D8168 8E180004 */ lw $t8, 4($s0)
/* B4F30C 800D816C 028E7824 */ and $t7, $s4, $t6
/* B4F310 800D8170 55F80007 */ bnel $t7, $t8, .L800D8190
/* B4F314 800D8174 2610000C */ addiu $s0, $s0, 0xc
/* B4F318 800D8178 10400004 */ beqz $v0, .L800D818C
/* B4F31C 800D817C 02402025 */ move $a0, $s2
/* B4F320 800D8180 0C00084C */ jal osSyncPrintf
/* B4F324 800D8184 8E050000 */ lw $a1, ($s0)
/* B4F328 800D8188 8E6200BC */ lw $v0, 0xbc($s3)
.L800D818C:
/* B4F32C 800D818C 2610000C */ addiu $s0, $s0, 0xc
.L800D8190:
/* B4F330 800D8190 5611FFF5 */ bnel $s0, $s1, .L800D8168
/* B4F334 800D8194 8E0E0008 */ lw $t6, 8($s0)
/* B4F338 800D8198 14400004 */ bnez $v0, .L800D81AC
/* B4F33C 800D819C 3C108013 */ lui $s0, %hi(D_8012DDDC)
/* B4F340 800D81A0 3C108013 */ lui $s0, %hi(D_8012DDDC) # $s0, 0x8013
/* B4F344 800D81A4 1000001C */ b .L800D8218
/* B4F348 800D81A8 2610DDDC */ addiu $s0, %lo(D_8012DDDC) # addiu $s0, $s0, -0x2224
.L800D81AC:
/* B4F34C 800D81AC 00141482 */ srl $v0, $s4, 0x12
/* B4F350 800D81B0 30423333 */ andi $v0, $v0, 0x3333
/* B4F354 800D81B4 0002CB03 */ sra $t9, $v0, 0xc
/* B4F358 800D81B8 33280003 */ andi $t0, $t9, 3
/* B4F35C 800D81BC 00084880 */ sll $t1, $t0, 2
/* B4F360 800D81C0 2610DDDC */ addiu $s0, %lo(D_8012DDDC)
/* B4F364 800D81C4 02095021 */ addu $t2, $s0, $t1
/* B4F368 800D81C8 00025A03 */ sra $t3, $v0, 8
/* B4F36C 800D81CC 316C0003 */ andi $t4, $t3, 3
/* B4F370 800D81D0 8D450000 */ lw $a1, ($t2)
/* B4F374 800D81D4 30490003 */ andi $t1, $v0, 3
/* B4F378 800D81D8 00027903 */ sra $t7, $v0, 4
/* B4F37C 800D81DC 31F80003 */ andi $t8, $t7, 3
/* B4F380 800D81E0 00095080 */ sll $t2, $t1, 2
/* B4F384 800D81E4 000C6880 */ sll $t5, $t4, 2
/* B4F388 800D81E8 020A5821 */ addu $t3, $s0, $t2
/* B4F38C 800D81EC 0018C880 */ sll $t9, $t8, 2
/* B4F390 800D81F0 8D6C0030 */ lw $t4, 0x30($t3)
/* B4F394 800D81F4 02194021 */ addu $t0, $s0, $t9
/* B4F398 800D81F8 020D7021 */ addu $t6, $s0, $t5
/* B4F39C 800D81FC 8DC60010 */ lw $a2, 0x10($t6)
/* B4F3A0 800D8200 8D070020 */ lw $a3, 0x20($t0)
/* B4F3A4 800D8204 3C048014 */ lui $a0, %hi(D_80147D9C) # $a0, 0x8014
/* B4F3A8 800D8208 24847D9C */ addiu $a0, %lo(D_80147D9C) # addiu $a0, $a0, 0x7d9c
/* B4F3AC 800D820C 0C00084C */ jal osSyncPrintf
/* B4F3B0 800D8210 AFAC0010 */ sw $t4, 0x10($sp)
/* B4F3B4 800D8214 8E6200BC */ lw $v0, 0xbc($s3)
.L800D8218:
/* B4F3B8 800D8218 10400019 */ beqz $v0, .L800D8280
/* B4F3BC 800D821C 3C048014 */ lui $a0, %hi(D_80147DB8) # $a0, 0x8014
/* B4F3C0 800D8220 00141402 */ srl $v0, $s4, 0x10
/* B4F3C4 800D8224 30423333 */ andi $v0, $v0, 0x3333
/* B4F3C8 800D8228 00026B03 */ sra $t5, $v0, 0xc
/* B4F3CC 800D822C 31AE0003 */ andi $t6, $t5, 3
/* B4F3D0 800D8230 000E7880 */ sll $t7, $t6, 2
/* B4F3D4 800D8234 020FC021 */ addu $t8, $s0, $t7
/* B4F3D8 800D8238 0002CA03 */ sra $t9, $v0, 8
/* B4F3DC 800D823C 33280003 */ andi $t0, $t9, 3
/* B4F3E0 800D8240 8F050000 */ lw $a1, ($t8)
/* B4F3E4 800D8244 304F0003 */ andi $t7, $v0, 3
/* B4F3E8 800D8248 00025903 */ sra $t3, $v0, 4
/* B4F3EC 800D824C 316C0003 */ andi $t4, $t3, 3
/* B4F3F0 800D8250 000FC080 */ sll $t8, $t7, 2
/* B4F3F4 800D8254 00084880 */ sll $t1, $t0, 2
/* B4F3F8 800D8258 0218C821 */ addu $t9, $s0, $t8
/* B4F3FC 800D825C 000C6880 */ sll $t5, $t4, 2
/* B4F400 800D8260 8F280030 */ lw $t0, 0x30($t9)
/* B4F404 800D8264 020D7021 */ addu $t6, $s0, $t5
/* B4F408 800D8268 02095021 */ addu $t2, $s0, $t1
/* B4F40C 800D826C 8D460010 */ lw $a2, 0x10($t2)
/* B4F410 800D8270 8DC70020 */ lw $a3, 0x20($t6)
/* B4F414 800D8274 24847DB8 */ addiu $a0, %lo(D_80147DB8) # addiu $a0, $a0, 0x7db8
/* B4F418 800D8278 0C00084C */ jal osSyncPrintf
/* B4F41C 800D827C AFA80010 */ sw $t0, 0x10($sp)
.L800D8280:
/* B4F420 800D8280 8FBF0034 */ lw $ra, 0x34($sp)
/* B4F424 800D8284 8FB00020 */ lw $s0, 0x20($sp)
/* B4F428 800D8288 8FB10024 */ lw $s1, 0x24($sp)
/* B4F42C 800D828C 8FB20028 */ lw $s2, 0x28($sp)
/* B4F430 800D8290 8FB3002C */ lw $s3, 0x2c($sp)
/* B4F434 800D8294 8FB40030 */ lw $s4, 0x30($sp)
/* B4F438 800D8298 03E00008 */ jr $ra
/* B4F43C 800D829C 27BD0038 */ addiu $sp, $sp, 0x38

View file

@ -1,52 +0,0 @@
.include "macro.inc"
# assembler directives
.set noat # allow manual use of $at
.set noreorder # don't insert nops after branches
.set gp=64 # allow use of 64-bit general purpose registers
.section .data
.balign 16
glabel D_8012DCA0
.incbin "baserom.z64", 0xBA4E40, 0x58
glabel D_8012DCF8
.incbin "baserom.z64", 0xBA4E98, 0x24
glabel D_8012DD1C
.incbin "baserom.z64", 0xBA4EBC, 0xC0
glabel D_8012DDDC
.incbin "baserom.z64", 0xBA4F7C, 0x40
glabel D_8012DE1C
.incbin "baserom.z64", 0xBA4FBC, 0x210
glabel D_8012E02C
.incbin "baserom.z64", 0xBA51CC, 0x64
glabel D_8012E090
.incbin "baserom.z64", 0xBA5230, 0x200
glabel D_8012E290
.incbin "baserom.z64", 0xBA5430, 0x200
glabel D_8012E490
.incbin "baserom.z64", 0xBA5630, 0x200
glabel D_8012E690
.incbin "baserom.z64", 0xBA5830, 0x200
glabel D_8012E890
.incbin "baserom.z64", 0xBA5A30, 0x200
glabel D_8012EA90
.incbin "baserom.z64", 0xBA5C30, 0x200
glabel D_8012EC90
.incbin "baserom.z64", 0xBA5E30, 0x200
glabel D_8012EE90
.incbin "baserom.z64", 0xBA6030, 0x200

File diff suppressed because it is too large Load diff

View file

@ -9,6 +9,30 @@
.balign 16 .balign 16
glabel D_8012E090
.incbin "baserom.z64", 0xBA5230, 0x200
glabel D_8012E290
.incbin "baserom.z64", 0xBA5430, 0x200
glabel D_8012E490
.incbin "baserom.z64", 0xBA5630, 0x200
glabel D_8012E690
.incbin "baserom.z64", 0xBA5830, 0x200
glabel D_8012E890
.incbin "baserom.z64", 0xBA5A30, 0x200
glabel D_8012EA90
.incbin "baserom.z64", 0xBA5C30, 0x200
glabel D_8012EC90
.incbin "baserom.z64", 0xBA5E30, 0x200
glabel D_8012EE90
.incbin "baserom.z64", 0xBA6030, 0x200
glabel gWaveSamples glabel gWaveSamples
.word D_8012E090 .word D_8012E090
.word D_8012E290 .word D_8012E290

515
diff.py
View file

@ -12,12 +12,16 @@ import threading
import queue import queue
import time import time
def fail(msg): def fail(msg):
print(msg, file=sys.stderr) print(msg, file=sys.stderr)
sys.exit(1) sys.exit(1)
MISSING_PREREQUISITES = "Missing prerequisite python module {}. " \
MISSING_PREREQUISITES = (
"Missing prerequisite python module {}. "
"Run `python3 -m pip install --user colorama ansiwrap attrs watchdog python-Levenshtein` to install prerequisites (python-Levenshtein only needed for --algorithm=levenshtein)." "Run `python3 -m pip install --user colorama ansiwrap attrs watchdog python-Levenshtein` to install prerequisites (python-Levenshtein only needed for --algorithm=levenshtein)."
)
try: try:
import attr import attr
@ -28,7 +32,7 @@ except ModuleNotFoundError as e:
fail(MISSING_PREREQUISITES.format(e.name)) fail(MISSING_PREREQUISITES.format(e.name))
# Prefer to use diff_settings.py from the current working directory # Prefer to use diff_settings.py from the current working directory
sys.path.insert(0, '.') sys.path.insert(0, ".")
try: try:
import diff_settings import diff_settings
except ModuleNotFoundError: except ModuleNotFoundError:
@ -36,40 +40,96 @@ except ModuleNotFoundError:
# ==== CONFIG ==== # ==== CONFIG ====
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(description="Diff MIPS assembly.")
description="Diff MIPS assembly.") parser.add_argument("start", help="Function name or address to start diffing from.")
parser.add_argument('start', parser.add_argument("end", nargs="?", help="Address to end diff at.")
help="Function name or address to start diffing from.") parser.add_argument(
parser.add_argument('end', nargs='?', "-o",
help="Address to end diff at.") dest="diff_obj",
parser.add_argument('-o', dest='diff_obj', action='store_true', action="store_true",
help="Diff .o files rather than a whole binary. This makes it possible to see symbol names. (Recommended)") help="Diff .o files rather than a whole binary. This makes it possible to see symbol names. (Recommended)",
parser.add_argument('--base-asm', dest='base_asm', metavar='FILE', )
help="Read assembly from given file instead of configured base img.") parser.add_argument(
parser.add_argument('--write-asm', dest='write_asm', metavar='FILE', "--base-asm",
help="Write the current assembly output to file, e.g. for use with --base-asm.") dest="base_asm",
parser.add_argument('-m', '--make', dest='make', action='store_true', metavar="FILE",
help="Automatically run 'make' on the .o file or binary before diffing.") help="Read assembly from given file instead of configured base img.",
parser.add_argument('-l', '--skip-lines', dest='skip_lines', type=int, default=0, )
help="Skip the first N lines of output.") parser.add_argument(
parser.add_argument('-s', '--stop-jr-ra', dest='stop_jrra', action='store_true', "--write-asm",
help="Stop disassembling at the first 'jr ra'. Some functions have multiple return points, so use with care!") dest="write_asm",
parser.add_argument('-i', '--ignore-large-imms', dest='ignore_large_imms', action='store_true', metavar="FILE",
help="Pretend all large enough immediates are the same.") help="Write the current assembly output to file, e.g. for use with --base-asm.",
parser.add_argument('-B', '--no-show-branches', dest='show_branches', action='store_false', )
help="Don't visualize branches/branch targets.") parser.add_argument(
parser.add_argument('-S', '--base-shift', dest='base_shift', type=str, default='0', "-m",
"--make",
dest="make",
action="store_true",
help="Automatically run 'make' on the .o file or binary before diffing.",
)
parser.add_argument(
"-l",
"--skip-lines",
dest="skip_lines",
type=int,
default=0,
help="Skip the first N lines of output.",
)
parser.add_argument(
"-s",
"--stop-jr-ra",
dest="stop_jrra",
action="store_true",
help="Stop disassembling at the first 'jr ra'. Some functions have multiple return points, so use with care!",
)
parser.add_argument(
"-i",
"--ignore-large-imms",
dest="ignore_large_imms",
action="store_true",
help="Pretend all large enough immediates are the same.",
)
parser.add_argument(
"-B",
"--no-show-branches",
dest="show_branches",
action="store_false",
help="Don't visualize branches/branch targets.",
)
parser.add_argument(
"-S",
"--base-shift",
dest="base_shift",
type=str,
default="0",
help="Diff position X in our img against position X + shift in the base img. " help="Diff position X in our img against position X + shift in the base img. "
"Arithmetic is allowed, so e.g. |-S \"0x1234 - 0x4321\"| is a reasonable " 'Arithmetic is allowed, so e.g. |-S "0x1234 - 0x4321"| is a reasonable '
"flag to pass if it is known that position 0x1234 in the base img syncs " "flag to pass if it is known that position 0x1234 in the base img syncs "
"up with position 0x4321 in our img. Not supported together with -o.") "up with position 0x4321 in our img. Not supported together with -o.",
parser.add_argument('-w', '--watch', dest='watch', action='store_true', )
parser.add_argument(
"-w",
"--watch",
dest="watch",
action="store_true",
help="Automatically update when source/object files change. " help="Automatically update when source/object files change. "
"Recommended in combination with -m.") "Recommended in combination with -m.",
parser.add_argument('--width', dest='column_width', type=int, default=50, )
help="Sets the width of the left and right view column.") parser.add_argument(
parser.add_argument('--algorithm', dest='algorithm', default='difflib', "--width",
choices=['levenshtein', 'difflib'], help="Diff algorithm to use.") dest="column_width",
type=int,
default=50,
help="Sets the width of the left and right view column.",
)
parser.add_argument(
"--algorithm",
dest="algorithm",
default="difflib",
choices=["levenshtein", "difflib"],
help="Diff algorithm to use.",
)
# Project-specific flags, e.g. different versions/make arguments. # Project-specific flags, e.g. different versions/make arguments.
if hasattr(diff_settings, "add_custom_arguments"): if hasattr(diff_settings, "add_custom_arguments"):
@ -81,14 +141,14 @@ args = parser.parse_args()
config = {} config = {}
diff_settings.apply(config, args) diff_settings.apply(config, args)
baseimg = config.get('baseimg', None) baseimg = config.get("baseimg", None)
myimg = config.get('myimg', None) myimg = config.get("myimg", None)
mapfile = config.get('mapfile', None) mapfile = config.get("mapfile", None)
makeflags = config.get('makeflags', []) makeflags = config.get("makeflags", [])
source_directories = config.get('source_directories', None) source_directories = config.get("source_directories", None)
MAX_FUNCTION_SIZE_LINES = 1024 MAX_FUNCTION_SIZE_LINES = 4096
MAX_FUNCTION_SIZE_BYTES = 1024 * 4 MAX_FUNCTION_SIZE_BYTES = MAX_FUNCTION_SIZE_LINES * 4
COLOR_ROTATION = [ COLOR_ROTATION = [
Fore.MAGENTA, Fore.MAGENTA,
@ -102,15 +162,15 @@ COLOR_ROTATION = [
Fore.LIGHTBLACK_EX, Fore.LIGHTBLACK_EX,
] ]
BUFFER_CMD = ["tail", "-c", str(10**9)] BUFFER_CMD = ["tail", "-c", str(10 ** 9)]
LESS_CMD = ["less", "-Ric"] LESS_CMD = ["less", "-Ric"]
DEBOUNCE_DELAY = 0.1 DEBOUNCE_DELAY = 0.1
FS_WATCH_EXTENSIONS = ['.c', '.h'] FS_WATCH_EXTENSIONS = [".c", ".h"]
# ==== LOGIC ==== # ==== LOGIC ====
if args.algorithm == 'levenshtein': if args.algorithm == "levenshtein":
try: try:
import Levenshtein import Levenshtein
except ModuleNotFoundError as e: except ModuleNotFoundError as e:
@ -118,9 +178,13 @@ if args.algorithm == 'levenshtein':
binutils_prefix = None binutils_prefix = None
for binutils_cand in ['mips-linux-gnu-', 'mips64-elf-']: for binutils_cand in ["mips-linux-gnu-", "mips64-elf-"]:
try: try:
subprocess.check_call([binutils_cand + "objdump", "--version"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) subprocess.check_call(
[binutils_cand + "objdump", "--version"],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
)
binutils_prefix = binutils_cand binutils_prefix = binutils_cand
break break
except subprocess.CalledProcessError: except subprocess.CalledProcessError:
@ -129,7 +193,10 @@ for binutils_cand in ['mips-linux-gnu-', 'mips64-elf-']:
pass pass
if not binutils_prefix: if not binutils_prefix:
fail("Missing binutils; please ensure mips-linux-gnu-objdump or mips64-elf-objdump exist.") fail(
"Missing binutils; please ensure mips-linux-gnu-objdump or mips64-elf-objdump exist."
)
def eval_int(expr, emsg=None): def eval_int(expr, emsg=None):
try: try:
@ -142,33 +209,46 @@ def eval_int(expr, emsg=None):
fail(emsg) fail(emsg)
return None return None
def run_make(target, capture_output=False): def run_make(target, capture_output=False):
if capture_output: if capture_output:
return subprocess.run(["make"] + makeflags + [target], stderr=subprocess.PIPE, stdout=subprocess.PIPE) return subprocess.run(
["make"] + makeflags + [target],
stderr=subprocess.PIPE,
stdout=subprocess.PIPE,
)
else: else:
subprocess.check_call(["make"] + makeflags + [target]) subprocess.check_call(["make"] + makeflags + [target])
def restrict_to_function(dump, fn_name): def restrict_to_function(dump, fn_name):
out = [] out = []
search = f'<{fn_name}>:' search = f"<{fn_name}>:"
found = False found = False
for line in dump.split('\n'): for line in dump.split("\n"):
if found: if found:
if len(out) >= MAX_FUNCTION_SIZE_LINES: if len(out) >= MAX_FUNCTION_SIZE_LINES:
break break
out.append(line) out.append(line)
elif search in line: elif search in line:
found = True found = True
return '\n'.join(out) return "\n".join(out)
def run_objdump(cmd): def run_objdump(cmd):
flags, target, restrict = cmd flags, target, restrict = cmd
out = subprocess.check_output([binutils_prefix + "objdump"] + flags + [target], universal_newlines=True) out = subprocess.check_output(
[binutils_prefix + "objdump"] + flags + [target], universal_newlines=True
)
if restrict is not None: if restrict is not None:
return restrict_to_function(out, restrict) return restrict_to_function(out, restrict)
return out return out
base_shift = eval_int(args.base_shift, "Failed to parse --base-shift (-S) argument as an integer.")
base_shift = eval_int(
args.base_shift, "Failed to parse --base-shift (-S) argument as an integer."
)
def search_map_file(fn_name): def search_map_file(fn_name):
if not mapfile: if not mapfile:
@ -176,7 +256,7 @@ def search_map_file(fn_name):
try: try:
with open(mapfile) as f: with open(mapfile) as f:
lines = f.read().split('\n') lines = f.read().split("\n")
except Exception: except Exception:
fail(f"Failed to open map file {mapfile} for reading.") fail(f"Failed to open map file {mapfile} for reading.")
@ -184,22 +264,23 @@ def search_map_file(fn_name):
cur_objfile = None cur_objfile = None
ram_to_rom = None ram_to_rom = None
cands = [] cands = []
last_line = '' last_line = ""
for line in lines: for line in lines:
if line.startswith(' .text'): if line.startswith(" .text"):
cur_objfile = line.split()[3] cur_objfile = line.split()[3]
if 'load address' in line: if "load address" in line:
tokens = last_line.split() + line.split() tokens = last_line.split() + line.split()
ram = int(tokens[1], 0) ram = int(tokens[1], 0)
rom = int(tokens[5], 0) rom = int(tokens[5], 0)
ram_to_rom = rom - ram ram_to_rom = rom - ram
if line.endswith(' ' + fn_name): if line.endswith(" " + fn_name):
ram = int(line.split()[0], 0) ram = int(line.split()[0], 0)
if cur_objfile is not None and ram_to_rom is not None: if cur_objfile is not None and ram_to_rom is not None:
cands.append((cur_objfile, ram + ram_to_rom)) cands.append((cur_objfile, ram + ram_to_rom))
last_line = line last_line = line
except Exception as e: except Exception as e:
import traceback import traceback
traceback.print_exc() traceback.print_exc()
fail(f"Internal error while parsing map file") fail(f"Internal error while parsing map file")
@ -209,12 +290,13 @@ def search_map_file(fn_name):
return cands[0] return cands[0]
return None, None return None, None
def dump_objfile(): def dump_objfile():
if base_shift: if base_shift:
fail("--base-shift not compatible with -o") fail("--base-shift not compatible with -o")
if args.end is not None: if args.end is not None:
fail("end address not supported together with -o") fail("end address not supported together with -o")
if args.start.startswith('0'): if args.start.startswith("0"):
fail("numerical start address not supported with -o; pass a function name") fail("numerical start address not supported with -o; pass a function name")
objfile, _ = search_map_file(args.start) objfile, _ = search_map_file(args.start)
@ -235,9 +317,10 @@ def dump_objfile():
return ( return (
objfile, objfile,
(objdump_flags, refobjfile, args.start), (objdump_flags, refobjfile, args.start),
(objdump_flags, objfile, args.start) (objdump_flags, objfile, args.start),
) )
def dump_binary(): def dump_binary():
if not baseimg or not myimg: if not baseimg or not myimg:
fail("Missing myimg/baseimg in config.") fail("Missing myimg/baseimg in config.")
@ -252,41 +335,52 @@ def dump_binary():
end_addr = eval_int(args.end, "End address must be an integer expression.") end_addr = eval_int(args.end, "End address must be an integer expression.")
else: else:
end_addr = start_addr + MAX_FUNCTION_SIZE_BYTES end_addr = start_addr + MAX_FUNCTION_SIZE_BYTES
objdump_flags = ['-Dz', '-bbinary', '-mmips', '-EB'] objdump_flags = ["-Dz", "-bbinary", "-mmips", "-EB"]
flags1 = [f"--start-address={start_addr + base_shift}", f"--stop-address={end_addr + base_shift}"] flags1 = [
f"--start-address={start_addr + base_shift}",
f"--stop-address={end_addr + base_shift}",
]
flags2 = [f"--start-address={start_addr}", f"--stop-address={end_addr}"] flags2 = [f"--start-address={start_addr}", f"--stop-address={end_addr}"]
return ( return (
myimg, myimg,
(objdump_flags + flags1, baseimg, None), (objdump_flags + flags1, baseimg, None),
(objdump_flags + flags2, myimg, None) (objdump_flags + flags2, myimg, None),
) )
# Alignment with ANSI colors is broken, let's fix it. # Alignment with ANSI colors is broken, let's fix it.
def ansi_ljust(s, width): def ansi_ljust(s, width):
needed = width - ansiwrap.ansilen(s) needed = width - ansiwrap.ansilen(s)
if needed > 0: if needed > 0:
return s + ' ' * needed return s + " " * needed
else: else:
return s return s
re_int = re.compile(r'[0-9]+')
re_comments = re.compile(r'<.*?>') re_int = re.compile(r"[0-9]+")
re_regs = re.compile(r'\$?\b(a[0-3]|t[0-9]|s[0-7]|at|v[01]|f[12]?[0-9]|f3[01]|fp)\b') re_comments = re.compile(r"<.*?>")
re_sprel = re.compile(r',([1-9][0-9]*|0x[1-9a-f][0-9a-f]*)\(sp\)') re_regs = re.compile(r"\$?\b(a[0-3]|t[0-9]|s[0-8]|at|v[01]|f[12]?[0-9]|f3[01]|fp)\b")
re_large_imm = re.compile(r'-?[1-9][0-9]{2,}|-?0x[0-9a-f]{3,}') re_sprel = re.compile(r",([1-9][0-9]*|0x[1-9a-f][0-9a-f]*)\(sp\)")
re_imm = re.compile(r'(\b|-)([0-9]+|0x[0-9a-fA-F]+)\b(?!\(sp)|%(lo|hi)\([^)]*\)') re_large_imm = re.compile(r"-?[1-9][0-9]{2,}|-?0x[0-9a-f]{3,}")
forbidden = set(string.ascii_letters + '_') re_imm = re.compile(r"(\b|-)([0-9]+|0x[0-9a-fA-F]+)\b(?!\(sp)|%(lo|hi)\([^)]*\)")
forbidden = set(string.ascii_letters + "_")
branch_likely_instructions = { branch_likely_instructions = {
'beql', 'bnel', 'beqzl', 'bnezl', 'bgezl', 'bgtzl', 'blezl', 'bltzl', "beql",
'bc1tl', 'bc1fl' "bnel",
"beqzl",
"bnezl",
"bgezl",
"bgtzl",
"blezl",
"bltzl",
"bc1tl",
"bc1fl",
} }
branch_instructions = branch_likely_instructions.union({ branch_instructions = branch_likely_instructions.union(
'b', 'beq', 'bne', 'beqz', 'bnez', 'bgez', 'bgtz', 'blez', 'bltz', {"b", "beq", "bne", "beqz", "bnez", "bgez", "bgtz", "blez", "bltz", "bc1t", "bc1f"}
'bc1t', 'bc1f' )
}) jump_instructions = branch_instructions.union({"jal", "j"})
jump_instructions = branch_instructions.union({
'jal', 'j'
})
def hexify_int(row, pat): def hexify_int(row, pat):
full = pat.group(0) full = pat.group(0)
@ -300,40 +394,43 @@ def hexify_int(row, pat):
return full return full
return hex(int(full)) return hex(int(full))
def parse_relocated_line(line): def parse_relocated_line(line):
try: try:
ind2 = line.rindex(',') ind2 = line.rindex(",")
except ValueError: except ValueError:
ind2 = line.rindex('\t') ind2 = line.rindex("\t")
before = line[:ind2+1] before = line[: ind2 + 1]
after = line[ind2+1:] after = line[ind2 + 1 :]
ind2 = after.find('(') ind2 = after.find("(")
if ind2 == -1: if ind2 == -1:
imm, after = after, '' imm, after = after, ""
else: else:
imm, after = after[:ind2], after[ind2:] imm, after = after[:ind2], after[ind2:]
if imm == '0x0': if imm == "0x0":
imm = '0' imm = "0"
return before, imm, after return before, imm, after
def process_reloc(row, prev): def process_reloc(row, prev):
before, imm, after = parse_relocated_line(prev) before, imm, after = parse_relocated_line(prev)
repl = row.split()[-1] repl = row.split()[-1]
if imm != '0': if imm != "0":
if before.strip() == 'jal' and not imm.startswith('0x'): if before.strip() == "jal" and not imm.startswith("0x"):
imm = '0x' + imm imm = "0x" + imm
repl += '+' + imm if int(imm,0) > 0 else imm repl += "+" + imm if int(imm, 0) > 0 else imm
if 'R_MIPS_LO16' in row: if "R_MIPS_LO16" in row:
repl = f'%lo({repl})' repl = f"%lo({repl})"
elif 'R_MIPS_HI16' in row: elif "R_MIPS_HI16" in row:
# Ideally we'd pair up R_MIPS_LO16 and R_MIPS_HI16 to generate a # Ideally we'd pair up R_MIPS_LO16 and R_MIPS_HI16 to generate a
# correct addend for each, but objdump doesn't give us the order of # correct addend for each, but objdump doesn't give us the order of
# the relocations, so we can't find the right LO16. :( # the relocations, so we can't find the right LO16. :(
repl = f'%hi({repl})' repl = f"%hi({repl})"
else: else:
assert 'R_MIPS_26' in row, f"unknown relocation type '{row}'" assert "R_MIPS_26" in row, f"unknown relocation type '{row}'"
return before + repl + after return before + repl + after
def process(lines): def process(lines):
mnemonics = [] mnemonics = []
diff_rows = [] diff_rows = []
@ -348,41 +445,41 @@ def process(lines):
lines.pop() lines.pop()
for row in lines: for row in lines:
if args.diff_obj and ('>:' in row or not row): if args.diff_obj and (">:" in row or not row):
continue continue
if 'R_MIPS_' in row: if "R_MIPS_" in row:
# N.B. Don't transform the diff rows, they already ignore immediates # N.B. Don't transform the diff rows, they already ignore immediates
# if diff_rows[-1] != '<delay-slot>': # if diff_rows[-1] != '<delay-slot>':
# diff_rows[-1] = process_reloc(row, rows_with_imms[-1]) # diff_rows[-1] = process_reloc(row, rows_with_imms[-1])
originals[-1] = process_reloc(row, originals[-1]) originals[-1] = process_reloc(row, originals[-1])
continue continue
row = re.sub(re_comments, '', row) row = re.sub(re_comments, "", row)
row = row.rstrip() row = row.rstrip()
tabs = row.split('\t') tabs = row.split("\t")
row = '\t'.join(tabs[2:]) row = "\t".join(tabs[2:])
line_num = tabs[0].strip() line_num = tabs[0].strip()
row_parts = row.split('\t', 1) row_parts = row.split("\t", 1)
mnemonic = row_parts[0].strip() mnemonic = row_parts[0].strip()
if mnemonic not in jump_instructions: if mnemonic not in jump_instructions:
row = re.sub(re_int, lambda s: hexify_int(row, s), row) row = re.sub(re_int, lambda s: hexify_int(row, s), row)
original = row original = row
if skip_next: if skip_next:
skip_next = False skip_next = False
row = '<delay-slot>' row = "<delay-slot>"
mnemonic = '<delay-slot>' mnemonic = "<delay-slot>"
if mnemonic in branch_likely_instructions: if mnemonic in branch_likely_instructions:
skip_next = True skip_next = True
row = re.sub(re_regs, '<reg>', row) row = re.sub(re_regs, "<reg>", row)
row = re.sub(re_sprel, ',addr(sp)', row) row = re.sub(re_sprel, ",addr(sp)", row)
row_with_imm = row row_with_imm = row
if mnemonic in jump_instructions: if mnemonic in jump_instructions:
row = row.strip() row = row.strip()
row, _ = split_off_branch(row) row, _ = split_off_branch(row)
row += '<imm>' row += "<imm>"
else: else:
row = re.sub(re_imm, '<imm>', row) row = re.sub(re_imm, "<imm>", row)
mnemonics.append(mnemonic) mnemonics.append(mnemonic)
rows_with_imms.append(row_with_imm) rows_with_imms.append(row_with_imm)
@ -390,24 +487,28 @@ def process(lines):
originals.append(original) originals.append(original)
line_nums.append(line_num) line_nums.append(line_num)
if mnemonic in branch_instructions: if mnemonic in branch_instructions:
target = row_parts[1].strip().split(',')[-1] target = row_parts[1].strip().split(",")[-1]
if mnemonic in branch_likely_instructions: if mnemonic in branch_likely_instructions:
target = hex(int(target, 16) - 4)[2:] target = hex(int(target, 16) - 4)[2:]
branch_targets.append(target) branch_targets.append(target)
else: else:
branch_targets.append(None) branch_targets.append(None)
if args.stop_jrra and mnemonic == 'jr' and row_parts[1].strip() == 'ra': if args.stop_jrra and mnemonic == "jr" and row_parts[1].strip() == "ra":
break break
# Cleanup whitespace # Cleanup whitespace
originals = [original.strip() for original in originals] originals = [original.strip() for original in originals]
originals = [''.join(f'{o:<8s}' for o in original.split('\t')) for original in originals] originals = [
"".join(f"{o:<8s}" for o in original.split("\t")) for original in originals
]
# return diff_rows, diff_rows, line_nums # return diff_rows, diff_rows, line_nums
return mnemonics, diff_rows, originals, line_nums, branch_targets return mnemonics, diff_rows, originals, line_nums, branch_targets
def format_single_line_diff(line1, line2, column_width): def format_single_line_diff(line1, line2, column_width):
return f"{ansi_ljust(line1,column_width)}{ansi_ljust(line2,column_width)}" return f"{ansi_ljust(line1,column_width)}{ansi_ljust(line2,column_width)}"
class SymbolColorer: class SymbolColorer:
def __init__(self, base_index): def __init__(self, base_index):
self.color_index = base_index self.color_index = base_index
@ -421,23 +522,27 @@ class SymbolColorer:
self.color_index += 1 self.color_index += 1
self.symbol_colors[s] = color self.symbol_colors[s] = color
t = t or s t = t or s
return f'{color}{t}{Fore.RESET}' return f"{color}{t}{Fore.RESET}"
def maybe_normalize_large_imms(row): def maybe_normalize_large_imms(row):
if args.ignore_large_imms: if args.ignore_large_imms:
row = re.sub(re_large_imm, '<imm>', row) row = re.sub(re_large_imm, "<imm>", row)
return row return row
def normalize_imms(row): def normalize_imms(row):
return re.sub(re_imm, '<imm>', row) return re.sub(re_imm, "<imm>", row)
def split_off_branch(line): def split_off_branch(line):
parts = line.split(',') parts = line.split(",")
if len(parts) < 2: if len(parts) < 2:
parts = line.split() parts = line.split()
off = len(line) - len(parts[-1]) off = len(line) - len(parts[-1])
return line[:off], line[off:] return line[:off], line[off:]
def color_imms(out1, out2): def color_imms(out1, out2):
g1 = [] g1 = []
g2 = [] g2 = []
@ -446,31 +551,40 @@ def color_imms(out1, out2):
if len(g1) == len(g2): if len(g1) == len(g2):
diffs = [x != y for (x, y) in zip(g1, g2)] diffs = [x != y for (x, y) in zip(g1, g2)]
it = iter(diffs) it = iter(diffs)
def maybe_color(s): def maybe_color(s):
return f'{Fore.LIGHTBLUE_EX}{s}{Style.RESET_ALL}' if next(it) else s return f"{Fore.LIGHTBLUE_EX}{s}{Style.RESET_ALL}" if next(it) else s
out1 = re.sub(re_imm, lambda s: maybe_color(s.group()), out1) out1 = re.sub(re_imm, lambda s: maybe_color(s.group()), out1)
it = iter(diffs) it = iter(diffs)
out2 = re.sub(re_imm, lambda s: maybe_color(s.group()), out2) out2 = re.sub(re_imm, lambda s: maybe_color(s.group()), out2)
return out1, out2 return out1, out2
def color_branch_imms(br1, br2): def color_branch_imms(br1, br2):
if br1 != br2: if br1 != br2:
br1 = f'{Fore.LIGHTBLUE_EX}{br1}{Style.RESET_ALL}' br1 = f"{Fore.LIGHTBLUE_EX}{br1}{Style.RESET_ALL}"
br2 = f'{Fore.LIGHTBLUE_EX}{br2}{Style.RESET_ALL}' br2 = f"{Fore.LIGHTBLUE_EX}{br2}{Style.RESET_ALL}"
return br1, br2 return br1, br2
def diff_sequences_difflib(seq1, seq2): def diff_sequences_difflib(seq1, seq2):
differ = difflib.SequenceMatcher(a=seq1, b=seq2, autojunk=False) differ = difflib.SequenceMatcher(a=seq1, b=seq2, autojunk=False)
return differ.get_opcodes() return differ.get_opcodes()
def diff_sequences(seq1, seq2): def diff_sequences(seq1, seq2):
if (args.algorithm != 'levenshtein' or len(seq1) * len(seq2) > 4 * 10**8 or if (
len(seq1) + len(seq2) >= 0x110000): args.algorithm != "levenshtein"
or len(seq1) * len(seq2) > 4 * 10 ** 8
or len(seq1) + len(seq2) >= 0x110000
):
return diff_sequences_difflib(seq1, seq2) return diff_sequences_difflib(seq1, seq2)
# The Levenshtein library assumes that we compare strings, not lists. Convert. # The Levenshtein library assumes that we compare strings, not lists. Convert.
# (Per the check above we know we have fewer than 0x110000 unique elements, so chr() works.) # (Per the check above we know we have fewer than 0x110000 unique elements, so chr() works.)
remapping = {} remapping = {}
def remap(seq): def remap(seq):
seq = seq[:] seq = seq[:]
for i in range(len(seq)): for i in range(len(seq)):
@ -479,23 +593,28 @@ def diff_sequences(seq1, seq2):
val = chr(len(remapping)) val = chr(len(remapping))
remapping[seq[i]] = val remapping[seq[i]] = val
seq[i] = val seq[i] = val
return ''.join(seq) return "".join(seq)
seq1 = remap(seq1) seq1 = remap(seq1)
seq2 = remap(seq2) seq2 = remap(seq2)
return Levenshtein.opcodes(seq1, seq2) return Levenshtein.opcodes(seq1, seq2)
def do_diff(basedump, mydump): def do_diff(basedump, mydump):
asm_lines1 = basedump.split('\n') asm_lines1 = basedump.split("\n")
asm_lines2 = mydump.split('\n') asm_lines2 = mydump.split("\n")
output = [] output = []
# TODO: status line? # TODO: status line?
# output.append(sha1sum(mydump)) # output.append(sha1sum(mydump))
mnemonics1, asm_lines1, originals1, line_nums1, branch_targets1 = process(asm_lines1) mnemonics1, asm_lines1, originals1, line_nums1, branch_targets1 = process(
mnemonics2, asm_lines2, originals2, line_nums2, branch_targets2 = process(asm_lines2) asm_lines1
)
mnemonics2, asm_lines2, originals2, line_nums2, branch_targets2 = process(
asm_lines2
)
sc1 = SymbolColorer(0) sc1 = SymbolColorer(0)
sc2 = SymbolColorer(0) sc2 = SymbolColorer(0)
@ -507,7 +626,10 @@ def do_diff(basedump, mydump):
bts2 = set() bts2 = set()
if args.show_branches: if args.show_branches:
for (bts, btset, sc) in [(branch_targets1, bts1, sc5), (branch_targets2, bts2, sc6)]: for (bts, btset, sc) in [
(branch_targets1, bts1, sc5),
(branch_targets2, bts2, sc6),
]:
for bt in bts: for bt in bts:
if bt is not None: if bt is not None:
btset.add(bt + ":") btset.add(bt + ":")
@ -518,38 +640,40 @@ def do_diff(basedump, mydump):
lines2 = asm_lines2[j1:j2] lines2 = asm_lines2[j1:j2]
for k, (line1, line2) in enumerate(itertools.zip_longest(lines1, lines2)): for k, (line1, line2) in enumerate(itertools.zip_longest(lines1, lines2)):
if tag == 'replace': if tag == "replace":
if line1 is None: if line1 is None:
tag = 'insert' tag = "insert"
elif line2 is None: elif line2 is None:
tag = 'delete' tag = "delete"
try: try:
original1 = originals1[i1+k] original1 = originals1[i1 + k]
line_num1 = line_nums1[i1+k] line_num1 = line_nums1[i1 + k]
except: except:
original1 = '' original1 = ""
line_num1 = '' line_num1 = ""
try: try:
original2 = originals2[j1+k] original2 = originals2[j1 + k]
line_num2 = line_nums2[j1+k] line_num2 = line_nums2[j1 + k]
except: except:
original2 = '' original2 = ""
line_num2 = '' line_num2 = ""
line_color1 = line_color2 = sym_color = Fore.RESET line_color1 = line_color2 = sym_color = Fore.RESET
line_prefix = ' ' line_prefix = " "
if line1 == line2: if line1 == line2:
if maybe_normalize_large_imms(original1) == maybe_normalize_large_imms(original2): if maybe_normalize_large_imms(original1) == maybe_normalize_large_imms(
out1 = f'{original1}' original2
out2 = f'{original2}' ):
elif line1 == '<delay-slot>': out1 = f"{original1}"
out1 = f'{Style.DIM}{original1}' out2 = f"{original2}"
out2 = f'{Style.DIM}{original2}' elif line1 == "<delay-slot>":
out1 = f"{Style.DIM}{original1}"
out2 = f"{Style.DIM}{original2}"
else: else:
mnemonic = original1.split()[0] mnemonic = original1.split()[0]
out1, out2 = original1, original2 out1, out2 = original1, original2
branch1 = branch2 = '' branch1 = branch2 = ""
if mnemonic in jump_instructions: if mnemonic in jump_instructions:
out1, branch1 = split_off_branch(original1) out1, branch1 = split_off_branch(original1)
out2, branch2 = split_off_branch(original2) out2, branch2 = split_off_branch(original2)
@ -562,60 +686,72 @@ def do_diff(basedump, mydump):
if normalize_imms(branchless1) == normalize_imms(branchless2): if normalize_imms(branchless1) == normalize_imms(branchless2):
# only imms differences # only imms differences
sym_color = Fore.LIGHTBLUE_EX sym_color = Fore.LIGHTBLUE_EX
line_prefix = 'i' line_prefix = "i"
else: else:
# regs differences and maybe imms as well # regs differences and maybe imms as well
line_color1 = line_color2 = sym_color = Fore.YELLOW line_color1 = line_color2 = sym_color = Fore.YELLOW
line_prefix = 'r' line_prefix = "r"
out1 = re.sub(re_regs, lambda s: sc1.color_symbol(s.group()), out1) out1 = re.sub(
out2 = re.sub(re_regs, lambda s: sc2.color_symbol(s.group()), out2) re_regs, lambda s: sc1.color_symbol(s.group()), out1
out1 = re.sub(re_sprel, lambda s: sc3.color_symbol(s.group()), out1) )
out2 = re.sub(re_sprel, lambda s: sc4.color_symbol(s.group()), out2) out2 = re.sub(
out1 = f'{Fore.YELLOW}{out1}{Style.RESET_ALL}' re_regs, lambda s: sc2.color_symbol(s.group()), out2
out2 = f'{Fore.YELLOW}{out2}{Style.RESET_ALL}' )
elif tag in ['replace', 'equal']: out1 = re.sub(
line_prefix = '|' re_sprel, lambda s: sc3.color_symbol(s.group()), out1
)
out2 = re.sub(
re_sprel, lambda s: sc4.color_symbol(s.group()), out2
)
out1 = f"{Fore.YELLOW}{out1}{Style.RESET_ALL}"
out2 = f"{Fore.YELLOW}{out2}{Style.RESET_ALL}"
elif tag in ["replace", "equal"]:
line_prefix = "|"
line_color1 = Fore.LIGHTBLUE_EX line_color1 = Fore.LIGHTBLUE_EX
line_color2 = Fore.LIGHTBLUE_EX line_color2 = Fore.LIGHTBLUE_EX
sym_color = Fore.LIGHTBLUE_EX sym_color = Fore.LIGHTBLUE_EX
out1 = f"{Fore.LIGHTBLUE_EX}{original1}{Style.RESET_ALL}" out1 = f"{Fore.LIGHTBLUE_EX}{original1}{Style.RESET_ALL}"
out2 = f"{Fore.LIGHTBLUE_EX}{original2}{Style.RESET_ALL}" out2 = f"{Fore.LIGHTBLUE_EX}{original2}{Style.RESET_ALL}"
elif tag == 'delete': elif tag == "delete":
line_prefix = '<' line_prefix = "<"
line_color1 = line_color2 = sym_color = Fore.RED line_color1 = line_color2 = sym_color = Fore.RED
out1 = f"{Fore.RED}{original1}{Style.RESET_ALL}" out1 = f"{Fore.RED}{original1}{Style.RESET_ALL}"
out2 = '' out2 = ""
elif tag == 'insert': elif tag == "insert":
line_prefix = '>' line_prefix = ">"
line_color1 = line_color2 = sym_color = Fore.GREEN line_color1 = line_color2 = sym_color = Fore.GREEN
out1 = '' out1 = ""
out2 = f"{Fore.GREEN}{original2}{Style.RESET_ALL}" out2 = f"{Fore.GREEN}{original2}{Style.RESET_ALL}"
in_arrow1 = ' ' in_arrow1 = " "
in_arrow2 = ' ' in_arrow2 = " "
out_arrow1 = '' out_arrow1 = ""
out_arrow2 = '' out_arrow2 = ""
line_num1 = line_num1 if out1 else '' line_num1 = line_num1 if out1 else ""
line_num2 = line_num2 if out2 else '' line_num2 = line_num2 if out2 else ""
if args.show_branches and out1: if args.show_branches and out1:
if line_num1 in bts1: if line_num1 in bts1:
in_arrow1 = sc5.color_symbol(line_num1, '~>') in_arrow1 = sc5.color_symbol(line_num1, "~>")
if branch_targets1[i1+k] is not None: if branch_targets1[i1 + k] is not None:
out_arrow1 = ' ' + sc5.color_symbol(branch_targets1[i1+k] + ":", '~>') out_arrow1 = " " + sc5.color_symbol(
branch_targets1[i1 + k] + ":", "~>"
)
if args.show_branches and out2: if args.show_branches and out2:
if line_num2 in bts2: if line_num2 in bts2:
in_arrow2 = sc6.color_symbol(line_num2, '~>') in_arrow2 = sc6.color_symbol(line_num2, "~>")
if branch_targets2[j1+k] is not None: if branch_targets2[j1 + k] is not None:
out_arrow2 = ' ' + sc6.color_symbol(branch_targets2[j1+k] + ":", '~>') out_arrow2 = " " + sc6.color_symbol(
branch_targets2[j1 + k] + ":", "~>"
)
if sym_color == line_color2: if sym_color == line_color2:
line_color2 = '' line_color2 = ""
out1 = f"{line_color1}{line_num1} {in_arrow1} {out1}{Style.RESET_ALL}{out_arrow1}" out1 = f"{line_color1}{line_num1} {in_arrow1} {out1}{Style.RESET_ALL}{out_arrow1}"
out2 = f"{sym_color}{line_prefix} {line_color2}{line_num2} {in_arrow2} {out2}{Style.RESET_ALL}{out_arrow2}" out2 = f"{sym_color}{line_prefix} {line_color2}{line_num2} {in_arrow2} {out2}{Style.RESET_ALL}{out_arrow2}"
output.append(format_single_line_diff(out1, out2, args.column_width)) output.append(format_single_line_diff(out1, out2, args.column_width))
return output[args.skip_lines:] return output[args.skip_lines :]
def debounced_fs_watch(targets, outq, debounce_delay): def debounced_fs_watch(targets, outq, debounce_delay):
@ -639,7 +775,9 @@ def debounced_fs_watch(targets, outq, debounce_delay):
for target in self.file_targets: for target in self.file_targets:
if path == target: if path == target:
return True return True
if args.make and any(path.endswith(suffix) for suffix in FS_WATCH_EXTENSIONS): if args.make and any(
path.endswith(suffix) for suffix in FS_WATCH_EXTENSIONS
):
return True return True
return False return False
@ -658,7 +796,7 @@ def debounced_fs_watch(targets, outq, debounce_delay):
observer.schedule(event_handler, target, recursive=True) observer.schedule(event_handler, target, recursive=True)
else: else:
file_targets.append(target) file_targets.append(target)
target = os.path.dirname(target) or '.' target = os.path.dirname(target) or "."
if target not in observed: if target not in observed:
observed.add(target) observed.add(target)
observer.schedule(event_handler, target) observer.schedule(event_handler, target)
@ -679,11 +817,12 @@ def debounced_fs_watch(targets, outq, debounce_delay):
except queue.Empty: except queue.Empty:
pass pass
outq.put(t) outq.put(t)
th = threading.Thread(target=debounce_thread, daemon=True) th = threading.Thread(target=debounce_thread, daemon=True)
th.start() th.start()
class Display(): class Display:
def __init__(self, basedump, mydump): def __init__(self, basedump, mydump):
self.basedump = basedump self.basedump = basedump
self.mydump = mydump self.mydump = mydump
@ -693,14 +832,15 @@ class Display():
if self.emsg is not None: if self.emsg is not None:
output = self.emsg output = self.emsg
else: else:
output = '\n'.join(do_diff(self.basedump, self.mydump)) output = "\n".join(do_diff(self.basedump, self.mydump))
# Pipe the output through 'tail' and only then to less, to ensure the # Pipe the output through 'tail' and only then to less, to ensure the
# write call doesn't block. ('tail' has to buffer all its input before # write call doesn't block. ('tail' has to buffer all its input before
# it starts writing.) This also means we don't have to deal with pipe # it starts writing.) This also means we don't have to deal with pipe
# closure errors. # closure errors.
buffer_proc = subprocess.Popen(BUFFER_CMD, stdin=subprocess.PIPE, buffer_proc = subprocess.Popen(
stdout=subprocess.PIPE) BUFFER_CMD, stdin=subprocess.PIPE, stdout=subprocess.PIPE
)
less_proc = subprocess.Popen(LESS_CMD, stdin=buffer_proc.stdout) less_proc = subprocess.Popen(LESS_CMD, stdin=buffer_proc.stdout)
buffer_proc.stdin.write(output.encode()) buffer_proc.stdin.write(output.encode())
buffer_proc.stdin.close() buffer_proc.stdin.close()
@ -798,8 +938,10 @@ def main():
display.run_sync() display.run_sync()
else: else:
if not args.make: if not args.make:
yn = input("Warning: watch-mode (-w) enabled without auto-make (-m). You will have to run make manually. Ok? (Y/n) ") yn = input(
if yn.lower() == 'n': "Warning: watch-mode (-w) enabled without auto-make (-m). You will have to run make manually. Ok? (Y/n) "
)
if yn.lower() == "n":
return return
if args.make: if args.make:
watch_sources = None watch_sources = None
@ -826,11 +968,16 @@ def main():
display.progress("Building...") display.progress("Building...")
ret = run_make(make_target, capture_output=True) ret = run_make(make_target, capture_output=True)
if ret.returncode != 0: if ret.returncode != 0:
display.update(ret.stderr.decode('utf-8-sig', 'replace') or ret.stdout.decode('utf-8-sig', 'replace'), error=True) display.update(
ret.stderr.decode("utf-8-sig", "replace")
or ret.stdout.decode("utf-8-sig", "replace"),
error=True,
)
continue continue
mydump = run_objdump(mycmd) mydump = run_objdump(mycmd)
display.update(mydump, error=False) display.update(mydump, error=False)
except KeyboardInterrupt: except KeyboardInterrupt:
display.terminate() display.terminate()
main() main()

View file

@ -48,7 +48,7 @@ void rmonPrintf(const char* fmt, ...);
u32 is_proutSyncPrintf(void* arg0, const char* str, s32 count); u32 is_proutSyncPrintf(void* arg0, const char* str, s32 count);
void func_80002384(const char* exp, const char* file, u32 line); void func_80002384(const char* exp, const char* file, u32 line);
OSPiHandle* osDriveRomInit(); OSPiHandle* osDriveRomInit();
void Yaz0_Old_DecompressImpl(Yaz0Header* hdr, u8* dst); void Mio0_Decompress(Yaz0Header* hdr, u8* dst);
void StackCheck_Init(StackEntry* entry, void* stackTop, void* stackBottom, u32 initValue, s32 minSpace, void StackCheck_Init(StackEntry* entry, void* stackTop, void* stackBottom, u32 initValue, s32 minSpace,
const char* name); const char* name);
void StackCheck_Cleanup(StackEntry* entry); void StackCheck_Cleanup(StackEntry* entry);
@ -1859,18 +1859,18 @@ void FaultDrawer_DrawText(s32, s32, const char*, ...);
void FaultDrawer_SetDrawerFB(void*, u16, u16); void FaultDrawer_SetDrawerFB(void*, u16, u16);
void FaultDrawer_SetInputCallback(void (*)()); void FaultDrawer_SetInputCallback(void (*)());
void FaultDrawer_SetDefault(); void FaultDrawer_SetDefault();
// ? func_800D7CD0(?); // ? UCodeDisas_TranslateAddr(?);
// ? func_800D7D04(?); // ? UCodeDisas_ParseCombineColor(?);
// ? func_800D7EA4(?); // ? UCodeDisas_ParseCombineAlpha(?);
// ? func_800D7F5C(?); // ? UCodeDisas_Init(?);
// ? func_800D7FC4(?); // ? UCodeDisas_Destroy(?);
// ? func_800D7FD0(?); // ? UCodeDisas_SetCurUCodeImpl(?);
// ? func_800D805C(?); // ? UCodeDisas_ParseGeometryMode(?);
// ? func_800D8124(?); // ? UCodeDisas_ParseRenderMode(?);
// ? func_800D82A0(?); // ? UCodeDisas_PrintVertices(?);
// ? func_800D8400(?); // ? UCodeDisas_Disassemble(?);
// ? func_800DAC80(?); // ? UCodeDisas_RegisterUCode(?);
// ? func_800DAC90(?); // ? UCodeDisas_SetCurUCode(?);
// ? func_800DACC0(?); // ? func_800DACC0(?);
// ? func_800DB03C(?); // ? func_800DB03C(?);
// ? func_800DB0C4(?); // ? func_800DB0C4(?);
@ -2280,7 +2280,8 @@ void GfxPrint_Printf(GfxPrint*, const char*, ...);
void func_800FBCE0(); void func_800FBCE0();
void func_800FBFD8(void); void func_800FBFD8(void);
void* Overlay_AllocateAndLoad(u32 vRomStart, u32 vRomEnd, void* vRamStart, void* vRamEnd); void* Overlay_AllocateAndLoad(u32 vRomStart, u32 vRomEnd, void* vRamStart, void* vRamEnd);
// ? MtxConv_L2F(?); void MtxConv_F2L(MatrixInternal* m1, MtxF* m2);
void MtxConv_L2F(MtxF* m1, MatrixInternal* m2);
void Overlay_DoRelocation(void* allocatedVRamAddress, OverlayRelocationSection* overlayInfo, void* vRamAddress); void Overlay_DoRelocation(void* allocatedVRamAddress, OverlayRelocationSection* overlayInfo, void* vRamAddress);
s32 Overlay_Load(u32 vRomStart, u32 vRomEnd, void* vRamStart, void* vRamEnd, void* allocatedVRamAddress); s32 Overlay_Load(u32 vRomStart, u32 vRomEnd, void* vRamStart, void* vRamEnd, void* allocatedVRamAddress);
// ? func_800FC800(?); // ? func_800FC800(?);

View file

@ -4488,9 +4488,10 @@ _DW({ \
#define gDPNoOpFloat(pkt, data, n) gDma1p(pkt, G_NOOP, data, n, 4) #define gDPNoOpFloat(pkt, data, n) gDma1p(pkt, G_NOOP, data, n, 4)
#define gDPNoOpQuiet(pkt) gDma1p(pkt, G_NOOP, 0, 0, 5) #define gDPNoOpQuiet(pkt) gDma1p(pkt, G_NOOP, 0, 0, 5)
#define gDPNoOpVerbose(pkt, n) gDma1p(pkt, G_NOOP, 0, n, 5) #define gDPNoOpVerbose(pkt, n) gDma1p(pkt, G_NOOP, 0, n, 5)
#define gDPNoOpCallBack(pkt, callback) gDma1p(pkt, G_NOOP, callback, 0, 6) #define gDPNoOpCallBack(pkt, callback, arg) gDma1p(pkt, G_NOOP, callback, arg, 6)
#define gDPNoOpOpenDisp(pkt, file, line) gDma1p(pkt, G_NOOP, file, line, 7) #define gDPNoOpOpenDisp(pkt, file, line) gDma1p(pkt, G_NOOP, file, line, 7)
#define gDPNoOpCloseDisp(pkt, file, line) gDma1p(pkt, G_NOOP, file, line, 8) #define gDPNoOpCloseDisp(pkt, file, line) gDma1p(pkt, G_NOOP, file, line, 8)
#define gDPNoOpTag3(pkt, type, data, n) gDma1p(pkt, G_NOOP, data, n, type)
#endif #endif

View file

@ -620,12 +620,12 @@ extern u32 D_8012DBC0;
extern volatile u32 gIrqMgrResetStatus; extern volatile u32 gIrqMgrResetStatus;
extern volatile OSTime gIrqMgrRetraceTime; extern volatile OSTime gIrqMgrRetraceTime;
extern s32 gDebugArenaLogSeverity; extern s32 gDebugArenaLogSeverity;
//extern ? D_8012DCA0; //extern ? sUCodeDisasGeometryModes;
//extern ? D_8012DCF8; //extern ? sUCodeDisasMtxFlags;
//extern ? D_8012DD1C; //extern ? sUCodeDisasRenderModeFlags;
//extern ? D_8012DDDC; //extern ? D_8012DDDC;
//extern ? D_8012DE1C; //extern ? sUCodeDisasModeHMacros;
//extern ? D_8012E02C; //extern ? sUCodeDisasModeLMacros;
extern s16* gWaveSamples[6]; extern s16* gWaveSamples[6];
//extern ? D_8012F098; //extern ? D_8012F098;
//extern ? D_8012F0B0; //extern ? D_8012F0B0;

View file

@ -262,10 +262,10 @@ typedef struct OSScTask {
} OSScTask; } OSScTask;
typedef struct GraphicsContext { typedef struct GraphicsContext {
/* 0x0000 */ Gfx* polyOpaBuffer; /* 0x0000 */ Gfx* polyOpaBuffer; // Pointer to "Zelda 0"
/* 0x0004 */ Gfx* polyXluBuffer; /* 0x0004 */ Gfx* polyXluBuffer; // Pointer to "Zelda 1"
/* 0x0008 */ char unk_008[0x08]; /* 0x0008 */ char unk_008[0x08]; // Unused, could this be pointers to "Zelda 2" / "Zelda 3"
/* 0x0010 */ Gfx* overlayBuffer; /* 0x0010 */ Gfx* overlayBuffer; // Pointer to "Zelda 4"
/* 0x0014 */ u32 unk_014; /* 0x0014 */ u32 unk_014;
/* 0x0018 */ char unk_018[0x20]; /* 0x0018 */ char unk_018[0x20];
/* 0x0038 */ OSMesg msgBuff[0x08]; /* 0x0038 */ OSMesg msgBuff[0x08];
@ -278,10 +278,10 @@ typedef struct GraphicsContext {
/* 0x01B4 */ TwoHeadGfxArena work; /* 0x01B4 */ TwoHeadGfxArena work;
/* 0x01C4 */ char unk_01C4[0xC0]; /* 0x01C4 */ char unk_01C4[0xC0];
/* 0x0284 */ OSViMode* viMode; /* 0x0284 */ OSViMode* viMode;
/* 0x0288 */ char unk_0288[0x20]; /* 0x0288 */ char unk_0288[0x20]; // Unused, could this be Zelda 2/3 ?
/* 0x02A8 */ TwoHeadGfxArena overlay; /* 0x02A8 */ TwoHeadGfxArena overlay; // "Zelda 4"
/* 0x02B8 */ TwoHeadGfxArena polyOpa; /* 0x02B8 */ TwoHeadGfxArena polyOpa; // "Zelda 0"
/* 0x02C8 */ TwoHeadGfxArena polyXlu; /* 0x02C8 */ TwoHeadGfxArena polyXlu; // "Zelda 1"
/* 0x02D8 */ u32 gfxPoolIdx; /* 0x02D8 */ u32 gfxPoolIdx;
/* 0x02DC */ u16* curFrameBuffer; /* 0x02DC */ u16* curFrameBuffer;
/* 0x02E0 */ char unk_2E0[0x04]; /* 0x02E0 */ char unk_2E0[0x04];
@ -910,7 +910,7 @@ typedef struct {
/* 0x000A */ u8 mainKeepIndex; // "gameplay_keep" index in bank /* 0x000A */ u8 mainKeepIndex; // "gameplay_keep" index in bank
/* 0x000B */ u8 subKeepIndex; // "gameplay_field_keep" or "gameplay_dangeon_keep" index in bank /* 0x000B */ u8 subKeepIndex; // "gameplay_field_keep" or "gameplay_dangeon_keep" index in bank
/* 0x000C */ ObjectStatus status[OBJECT_EXCHANGE_BANK_MAX]; /* 0x000C */ ObjectStatus status[OBJECT_EXCHANGE_BANK_MAX];
} ObjectContext; // size = 0x514 } ObjectContext; // size = 0x518
typedef struct { typedef struct {
/* 0x00 */ Gfx* opa; /* 0x00 */ Gfx* opa;
@ -1497,8 +1497,8 @@ typedef struct {
typedef struct { typedef struct {
/* 0x00 */ char magic[4]; // Yaz0 /* 0x00 */ char magic[4]; // Yaz0
/* 0x04 */ u32 decSize; /* 0x04 */ u32 decSize;
/* 0x08 */ u32 compInfoOffset; // only used in yaz0_old.c /* 0x08 */ u32 compInfoOffset; // only used in mio0
/* 0x0C */ u32 uncompDataOffset; // only used in yaz0_old.c /* 0x0C */ u32 uncompDataOffset; // only used in mio0
/* 0x10 */ u32 data[1]; /* 0x10 */ u32 data[1];
} Yaz0Header; // size = 0x10 ("data" is not part of the header) } Yaz0Header; // size = 0x10 ("data" is not part of the header)
@ -1706,15 +1706,21 @@ typedef struct {
/* 0x20 */ f32 unk_20; /* 0x20 */ f32 unk_20;
} UnkQuakeCalcStruct; // size = 0x24 } UnkQuakeCalcStruct; // size = 0x24
#define UCODE_NULL 0
#define UCODE_F3DZEX 1
#define UCODE_UNK 2
#define UCODE_S2DEX 3
typedef struct { typedef struct {
/* 0x00 */ u32 idx; /* 0x00 */ u32 type;
/* 0x04 */ void* ptr; /* 0x04 */ void* ptr;
} UCodeInfo; // size = 0x8 } UCodeInfo; // size = 0x8
typedef struct { typedef struct {
/* 0x00 */ u32 segments[NUM_SEGMENTS]; /* 0x00 */ u32 segments[NUM_SEGMENTS];
/* 0x40 */ u32 dlStack[18]; /* 0x40 */ u32 dlStack[18];
/* 0x88 */ u32 dlDepth; /* 0x88 */ s32 dlDepth;
/* 0x8C */ u32 dlCnt; /* 0x8C */ u32 dlCnt;
/* 0x90 */ u32 vtxCnt; /* 0x90 */ u32 vtxCnt;
/* 0x94 */ u32 spvtxCnt; /* 0x94 */ u32 spvtxCnt;
@ -1727,9 +1733,9 @@ typedef struct {
/* 0xB0 */ u32 tileSyncRequired; /* 0xB0 */ u32 tileSyncRequired;
/* 0xB4 */ u32 loadSyncRequired; /* 0xB4 */ u32 loadSyncRequired;
/* 0xB8 */ u32 syncErr; /* 0xB8 */ u32 syncErr;
/* 0xBC */ u32 enableLog; /* 0xBC */ s32 enableLog;
/* 0xC0 */ u32 ucodeInfoIdx; /* 0xC0 */ s32 ucodeType;
/* 0xC4 */ u32 ucodeInfoCount; /* 0xC4 */ s32 ucodeInfoCount;
/* 0xC8 */ UCodeInfo* ucodeInfo; /* 0xC8 */ UCodeInfo* ucodeInfo;
/* 0xCC */ u32 modeH; /* 0xCC */ u32 modeH;
/* 0xD0 */ u32 modeL; /* 0xD0 */ u32 modeL;
@ -1867,8 +1873,38 @@ typedef struct {
} SpeedMeterTimeEntry; // size = 0x08 } SpeedMeterTimeEntry; // size = 0x08
typedef struct { typedef struct {
/* 0x00 */ s16 intPart[4][4]; /* 0x00 */ u16 intPart[4][4];
/* 0x20 */ u16 fracPart[4][4]; /* 0x20 */ u16 fracPart[4][4];
} MatrixInternal; // size = 0x40 } MatrixInternal; // size = 0x40
typedef struct {
/* 0x00 */ u32 value;
/* 0x04 */ const char* name;
} F3dzexConst; // size = 0x8
typedef struct {
/* 0x00 */ u32 value;
/* 0x04 */ const char* setName;
/* 0x08 */ const char* unsetName;
} F3dzexFlag; // size = 0x0C
typedef struct {
/* 0x00 */ const char* name;
/* 0x04 */ u32 value;
/* 0x08 */ u32 mask;
} F3dzexRenderMode; // size = 0x0C
typedef struct {
/* 0x00 */ const char* name;
/* 0x04 */ u32 value;
} F3dzexSetModeMacroValue; // size = 0x8
typedef struct {
/* 0x00 */ const char* name;
/* 0x04 */ u32 shift;
/* 0x08 */ u32 len;
/* 0x0C */ F3dzexSetModeMacroValue values[4];
} F3dzexSetModeMacro; // size = 0x2C
#endif #endif

6
spec
View file

@ -24,7 +24,7 @@ beginseg
include "build/src/boot/assert.o" include "build/src/boot/assert.o"
include "build/src/boot/is_debug.o" include "build/src/boot/is_debug.o"
include "build/src/libultra_boot_O2/osDriveRomInit.o" include "build/src/libultra_boot_O2/osDriveRomInit.o"
include "build/asm/yaz0_old.o" include "build/asm/mio0.o"
include "build/src/boot/stackcheck.o" include "build/src/boot/stackcheck.o"
include "build/src/boot/logutils.o" include "build/src/boot/logutils.o"
include "build/src/libultra_boot_O2/sprintf.o" include "build/src/libultra_boot_O2/sprintf.o"
@ -418,9 +418,7 @@ beginseg
include "build/src/code/fault_drawer.o" include "build/src/code/fault_drawer.o"
include "build/data/fault_drawer.bss.o" include "build/data/fault_drawer.bss.o"
include "build/asm/code_800D71F0.o" include "build/asm/code_800D71F0.o"
include "build/asm/code_800D7CD0.o" include "build/src/code/ucode_disas.o"
include "build/data/code_800D7CD0.data.o"
include "build/data/code_800D7CD0.rodata.o"
include "build/asm/code_800DACC0.o" include "build/asm/code_800DACC0.o"
include "build/data/code_800DACC0.data.o" include "build/data/code_800DACC0.data.o"
include "build/data/code_800DACC0.rodata.o" include "build/data/code_800DACC0.rodata.o"

View file

@ -1750,7 +1750,7 @@ const char* DmaMgr_GetFileNameImpl(u32 vrom) {
iter++; iter++;
name++; name++;
} }
// BUG: since the devs forgot to return in case the file isn't found, the return value will be a pointer to the end //! @bug Since the devs forgot to return in case the file isn't found, the return value will be a pointer to the end
// of gDmaDataTable // of gDmaDataTable
} }

View file

@ -249,7 +249,7 @@ void Fault_Sleep(u32 duration) {
} }
void Fault_PadCallback(Input* input) { void Fault_PadCallback(Input* input) {
// BUG: this function is not called correctly and thus will crash from reading a bad pointer at 0x800C7E4C //! @bug This function is not called correctly and thus will crash from reading a bad pointer at 0x800C7E4C
PadMgr_RequestPadData(input, 0); PadMgr_RequestPadData(input, 0);
} }

View file

@ -14,15 +14,15 @@ FaultClient sGraphUcodeFaultClient;
// clang-format off // clang-format off
UCodeInfo D_8012D230[3] = { UCodeInfo D_8012D230[3] = {
{ 1, D_80155F50 }, { UCODE_F3DZEX, D_80155F50 },
{ 2, NULL }, { UCODE_UNK, NULL },
{ 3, D_80113070 }, { UCODE_S2DEX, D_80113070 },
}; };
UCodeInfo D_8012D248[3] = { UCodeInfo D_8012D248[3] = {
{ 1, D_80155F50 }, { UCODE_F3DZEX, D_80155F50 },
{ 2, NULL }, { UCODE_UNK, NULL },
{ 3, D_80113070 }, { UCODE_S2DEX, D_80113070 },
}; };
// clang-format on // clang-format on
@ -42,11 +42,11 @@ void Graph_DisassembleUCode(void* arg0) {
UCodeDisas disassembler; UCodeDisas disassembler;
if (HREG(80) == 7 && HREG(81) != 0) { if (HREG(80) == 7 && HREG(81) != 0) {
func_800D7F5C(&disassembler); UCodeDisas_Init(&disassembler);
disassembler.enableLog = HREG(83); disassembler.enableLog = HREG(83);
func_800DAC80(&disassembler, 3, D_8012D230); UCodeDisas_RegisterUCode(&disassembler, ARRAY_COUNT(D_8012D230), D_8012D230);
func_800DAC90(&disassembler, D_80155F50); UCodeDisas_SetCurUCode(&disassembler, D_80155F50);
func_800D8400(&disassembler, arg0); UCodeDisas_Disassemble(&disassembler, arg0);
HREG(93) = disassembler.dlCnt; HREG(93) = disassembler.dlCnt;
HREG(84) = disassembler.tri2Cnt * 2 + disassembler.tri1Cnt + (disassembler.quadCnt * 2) + disassembler.lineCnt; HREG(84) = disassembler.tri2Cnt * 2 + disassembler.tri1Cnt + (disassembler.quadCnt * 2) + disassembler.lineCnt;
HREG(85) = disassembler.vtxCnt; HREG(85) = disassembler.vtxCnt;
@ -69,19 +69,19 @@ void Graph_DisassembleUCode(void* arg0) {
osSyncPrintf("dl_depth=%d\n", disassembler.dlDepth); osSyncPrintf("dl_depth=%d\n", disassembler.dlDepth);
osSyncPrintf("dl_cnt=%d\n", disassembler.dlCnt); osSyncPrintf("dl_cnt=%d\n", disassembler.dlCnt);
} }
func_800D7FC4(&disassembler); UCodeDisas_Destroy(&disassembler);
} }
} }
void Graph_UCodeFaultClient(void* arg0) { void Graph_UCodeFaultClient(void* arg0) {
UCodeDisas disassembler; UCodeDisas disassembler;
func_800D7F5C(&disassembler); UCodeDisas_Init(&disassembler);
disassembler.enableLog = true; disassembler.enableLog = true;
func_800DAC80(&disassembler, 3, D_8012D248); UCodeDisas_RegisterUCode(&disassembler, ARRAY_COUNT(D_8012D248), D_8012D248);
func_800DAC90(&disassembler, D_80155F50); UCodeDisas_SetCurUCode(&disassembler, D_80155F50);
func_800D8400(&disassembler, arg0); UCodeDisas_Disassemble(&disassembler, arg0);
func_800D7FC4(&disassembler); UCodeDisas_Destroy(&disassembler);
} }
void* Graph_InitTHGA(GraphicsContext* gfxCtx) { void* Graph_InitTHGA(GraphicsContext* gfxCtx) {
@ -221,7 +221,7 @@ void Graph_TaskSet00(GraphicsContext* gfxCtx) {
task->dram_stack = gGfxSPTaskStack; task->dram_stack = gGfxSPTaskStack;
task->dram_stack_size = sizeof(gGfxSPTaskStack); task->dram_stack_size = sizeof(gGfxSPTaskStack);
task->output_buff = gGfxSPTaskOutputBuffer; task->output_buff = gGfxSPTaskOutputBuffer;
task->output_buff_size = gGfxSPTaskYieldBuffer; // ?? task->output_buff_size = gGfxSPTaskYieldBuffer; //! @bug (?) should be sizeof(gGfxSPTaskYieldBuffer), probably a typo
task->data_ptr = gfxCtx->workBuffer; task->data_ptr = gfxCtx->workBuffer;
Graph_OpenDisps(dispRefs, gfxCtx, "../graph.c", 828); Graph_OpenDisps(dispRefs, gfxCtx, "../graph.c", 828);
@ -333,7 +333,7 @@ void Graph_Update(GraphicsContext* gfxCtx, GameState* gameState) {
problem = false; problem = false;
pool = &gGfxPools[gfxCtx->gfxPoolIdx & 1]; pool = &gGfxPools[gfxCtx->gfxPoolIdx & 1];
if (pool->headMagic != GFXPOOL_HEAD_MAGIC) { if (pool->headMagic != GFXPOOL_HEAD_MAGIC) {
// BUG (?) : devs might've forgotten "problem = true;" /*! @bug (?) : devs might've forgotten "problem = true;" */
osSyncPrintf("%c", 7); osSyncPrintf("%c", 7);
// Dynamic area head is destroyed // Dynamic area head is destroyed
osSyncPrintf(VT_COL(RED, WHITE) "ダイナミック領域先頭が破壊されています\n" VT_RST); osSyncPrintf(VT_COL(RED, WHITE) "ダイナミック領域先頭が破壊されています\n" VT_RST);

View file

@ -16,7 +16,7 @@ void MtxConv_F2L(MatrixInternal* m1, MtxF* m2) {
} }
} }
void MtxConv_L2F(MtxF* m1, Mtx* m2) { void MtxConv_L2F(MtxF* m1, MatrixInternal* m2) {
LogUtils_CheckNullPointer("m1", m1, "../mtxuty-cvt.c", 55); LogUtils_CheckNullPointer("m1", m1, "../mtxuty-cvt.c", 55);
LogUtils_CheckNullPointer("m2", m2, "../mtxuty-cvt.c", 56); LogUtils_CheckNullPointer("m2", m2, "../mtxuty-cvt.c", 56);
func_80102FA0(m1, m2); // guMtxL2F ? func_80102FA0(m1, m2); // guMtxL2F ?

317
src/code/ucode_disas.c Normal file
View file

@ -0,0 +1,317 @@
#include <global.h>
#define F3DZEX_CONST(name) \
{ name, #name }
#define F3DZEX_FLAG(set, unset) \
{ set, #set, #unset }
#define F3DZEX_RENDERMODE(name, mask) \
{ #name, name, mask }
#define F3DZEX_SETRENDERMACRO(name, shift, len, value0, value1, value2, value3) \
{ \
name, shift, len, { \
{ #value0, value0 }, { #value1, value1 }, { #value2, value2 }, { #value3, value3 }, \
} \
}
#define DISAS_LOG \
if (this->enableLog) \
osSyncPrintf
u32 UCodeDisas_TranslateAddr(UCodeDisas* this, u32 addr) {
u32 physical = this->segments[SEGMENT_NUMBER(addr)] + SEGMENT_OFFSET(addr);
return PHYSICAL_TO_VIRTUAL(physical);
}
F3dzexConst sUCodeDisasGeometryModes[] = {
F3DZEX_CONST(G_ZBUFFER), F3DZEX_CONST(G_TEXTURE_ENABLE),
F3DZEX_CONST(G_SHADE), F3DZEX_CONST(G_SHADING_SMOOTH),
F3DZEX_CONST(G_CULL_FRONT), F3DZEX_CONST(G_CULL_BACK),
F3DZEX_CONST(G_FOG), F3DZEX_CONST(G_LIGHTING),
F3DZEX_CONST(G_TEXTURE_GEN), F3DZEX_CONST(G_TEXTURE_GEN_LINEAR),
F3DZEX_CONST(G_LOD),
};
F3dzexFlag sUCodeDisasMtxFlags[] = {
F3DZEX_FLAG(G_MTX_PROJECTION, G_MTX_MODELVIEW),
F3DZEX_FLAG(G_MTX_LOAD, G_MTX_MUL),
F3DZEX_FLAG(G_MTX_PUSH, G_MTX_NOPUSH),
};
const char* UCodeDisas_ParseCombineColor(u32 value, u32 idx) {
const char* ret = "?";
switch (value) {
case G_CCMUX_COMBINED:
ret = "COMBINED";
break;
case G_CCMUX_TEXEL0:
ret = "TEXEL0";
break;
case G_CCMUX_TEXEL1:
ret = "TEXEL1";
break;
case G_CCMUX_PRIMITIVE:
ret = "PRIMITIVE";
break;
case G_CCMUX_SHADE:
ret = "SHADE";
break;
case G_CCMUX_ENVIRONMENT:
ret = "ENVIRONMENT";
break;
case 6:
ret = (idx == 2) ? "CENTER" : (idx == 3) ? "SCALE" : "1";
break;
case 7:
ret = (idx == 1) ? "NOISE" : (idx == 2) ? "K4" : (idx == 3) ? "COMBINED_ALPHA" : "0";
break;
default:
if (idx == 3) {
switch (value) {
case G_CCMUX_TEXEL0_ALPHA:
ret = "TEXEL0_ALPHA";
break;
case G_CCMUX_TEXEL1_ALPHA:
ret = "TEXEL1_ALPHA";
break;
case G_CCMUX_PRIMITIVE_ALPHA:
ret = "PRIMITIVE_ALPHA";
break;
case G_CCMUX_SHADE_ALPHA:
ret = "SHADE_ALPHA";
break;
case G_CCMUX_ENV_ALPHA:
ret = "ENV_ALPHA";
break;
case G_CCMUX_LOD_FRACTION:
ret = "LOD_FRACTION";
break;
case G_CCMUX_PRIM_LOD_FRAC:
ret = "PRIM_LOD_FRAC";
break;
case G_CCMUX_K5:
ret = "K5";
break;
default:
ret = "0";
break;
}
} else {
ret = "0";
}
}
return ret;
}
const char* UCodeDisas_ParseCombineAlpha(u32 value, u32 idx) {
const char* ret = "?";
switch (value) {
case 0:
ret = (idx == 3) ? "LOD_FRACTION" : "COMBINED";
break;
case G_ACMUX_TEXEL0:
ret = "TEXEL0";
break;
case G_ACMUX_TEXEL1:
ret = "TEXEL1";
break;
case G_ACMUX_PRIMITIVE:
ret = "PRIMITIVE";
break;
case G_ACMUX_SHADE:
ret = "SHADE";
break;
case G_ACMUX_ENVIRONMENT:
ret = "ENVIRONMENT";
break;
case 6:
ret = (idx == 3) ? "PRIM_LOD_FRAC" : "1";
break;
case G_ACMUX_0:
ret = "0";
break;
}
return ret;
}
void UCodeDisas_Init(UCodeDisas* this) {
u32 i;
bzero(this, sizeof(UCodeDisas));
for (i = 0; i < NUM_SEGMENTS; i++) {
this->segments[i] = gSegments[i];
}
}
void UCodeDisas_Destroy(UCodeDisas* this) {
}
void UCodeDisas_SetCurUCodeImpl(UCodeDisas* this, void* ptr) {
s32 i;
for (i = 0; i < this->ucodeInfoCount; i++) {
if (ptr == this->ucodeInfo[i].ptr) {
this->ucodeType = this->ucodeInfo[i].type;
break;
}
}
if (i >= this->ucodeInfoCount) {
// Microcode did not match
DISAS_LOG("マイクロコードが一致しなかった\n");
this->ucodeType = UCODE_NULL;
}
}
#ifdef NON_MATCHING
// s4/s6 swap (basically same diff as UCodeDisas_ParseRenderMode)
void UCodeDisas_ParseGeometryMode(UCodeDisas* this, u32 mode) {
u32 first = true;
s32 i;
for (i = 0; i < ARRAY_COUNT(sUCodeDisasGeometryModes); i++) {
if (sUCodeDisasGeometryModes[i].value & mode) {
u32 cond = first;
if (!cond) {
DISAS_LOG("|");
}
first = false;
DISAS_LOG("%s", sUCodeDisasGeometryModes[i].name);
}
}
}
#else
void UCodeDisas_ParseGeometryMode(UCodeDisas* this, u32 mode);
#pragma GLOBAL_ASM("asm/non_matchings/code/ucode_disas/UCodeDisas_ParseGeometryMode.s")
#endif
#ifdef NON_MATCHING
// s1/s2 swap (basically same diff as UCodeDisas_ParseGeometryMode)
void UCodeDisas_ParseRenderMode(UCodeDisas* this, u32 mode) {
s32 i;
s32 a;
s32 b;
static F3dzexRenderMode sUCodeDisasRenderModeFlags[] = {
F3DZEX_RENDERMODE(AA_EN, 0x8),
F3DZEX_RENDERMODE(Z_CMP, 0x10),
F3DZEX_RENDERMODE(Z_UPD, 0x20),
F3DZEX_RENDERMODE(IM_RD, 0x40),
F3DZEX_RENDERMODE(CLR_ON_CVG, 0x80),
F3DZEX_RENDERMODE(CVG_DST_CLAMP, 0x300),
F3DZEX_RENDERMODE(CVG_DST_WRAP, 0x300),
F3DZEX_RENDERMODE(CVG_DST_FULL, 0x300),
F3DZEX_RENDERMODE(CVG_DST_SAVE, 0x300),
F3DZEX_RENDERMODE(ZMODE_OPA, 0xC00),
F3DZEX_RENDERMODE(ZMODE_INTER, 0xC00),
F3DZEX_RENDERMODE(ZMODE_XLU, 0xC00),
F3DZEX_RENDERMODE(ZMODE_DEC, 0xC00),
F3DZEX_RENDERMODE(CVG_X_ALPHA, 0x1000),
F3DZEX_RENDERMODE(ALPHA_CVG_SEL, 0x2000),
F3DZEX_RENDERMODE(FORCE_BL, 0x4000),
};
static const char* D_8012DDDC[4][4] = {
{ "G_BL_CLR_IN", "G_BL_CLR_MEM", "G_BL_CLR_BL", "G_BL_CLR_FOG" },
{ "G_BL_A_IN", "G_BL_A_FOG", "G_BL_A_SHADE", "G_BL_0" },
{ "G_BL_CLR_IN", "G_BL_CLR_MEM", "G_BL_CLR_BL", "G_BL_CLR_FOG" },
{ "G_BL_1MA", "G_BL_A_MEM", "G_BL_1", "G_BL_0" },
};
for (i = 0; i < ARRAY_COUNT(sUCodeDisasRenderModeFlags); i++) {
if ((mode & sUCodeDisasRenderModeFlags[i].mask) == sUCodeDisasRenderModeFlags[i].value) {
DISAS_LOG("%s|", sUCodeDisasRenderModeFlags[i].name);
}
}
a = (mode >> 18) & 0x3333;
b = (mode >> 16) & 0x3333;
if (1) {}
// clang-format off
if (this->enableLog == 0) {} else { osSyncPrintf("\nGBL_c1(%s, %s, %s, %s)|", D_8012DDDC[0][a >> 12 & 3], D_8012DDDC[1][a >> 8 & 3], D_8012DDDC[2][a >> 4 & 3], D_8012DDDC[3][a >> 0 & 3]); }
// clang-format on
if (this->enableLog) {
osSyncPrintf("\nGBL_c2(%s, %s, %s, %s)", D_8012DDDC[0][b >> 12 & 3], D_8012DDDC[1][b >> 8 & 3],
D_8012DDDC[2][b >> 4 & 3], D_8012DDDC[3][b >> 0 & 3]);
}
}
#else
F3dzexRenderMode sUCodeDisasRenderModeFlags[] = {
F3DZEX_RENDERMODE(AA_EN, 0x8),
F3DZEX_RENDERMODE(Z_CMP, 0x10),
F3DZEX_RENDERMODE(Z_UPD, 0x20),
F3DZEX_RENDERMODE(IM_RD, 0x40),
F3DZEX_RENDERMODE(CLR_ON_CVG, 0x80),
F3DZEX_RENDERMODE(CVG_DST_CLAMP, 0x300),
F3DZEX_RENDERMODE(CVG_DST_WRAP, 0x300),
F3DZEX_RENDERMODE(CVG_DST_FULL, 0x300),
F3DZEX_RENDERMODE(CVG_DST_SAVE, 0x300),
F3DZEX_RENDERMODE(ZMODE_OPA, 0xC00),
F3DZEX_RENDERMODE(ZMODE_INTER, 0xC00),
F3DZEX_RENDERMODE(ZMODE_XLU, 0xC00),
F3DZEX_RENDERMODE(ZMODE_DEC, 0xC00),
F3DZEX_RENDERMODE(CVG_X_ALPHA, 0x1000),
F3DZEX_RENDERMODE(ALPHA_CVG_SEL, 0x2000),
F3DZEX_RENDERMODE(FORCE_BL, 0x4000),
};
const char* D_8012DDDC[4][4] = {
{ "G_BL_CLR_IN", "G_BL_CLR_MEM", "G_BL_CLR_BL", "G_BL_CLR_FOG" },
{ "G_BL_A_IN", "G_BL_A_FOG", "G_BL_A_SHADE", "G_BL_0" },
{ "G_BL_CLR_IN", "G_BL_CLR_MEM", "G_BL_CLR_BL", "G_BL_CLR_FOG" },
{ "G_BL_1MA", "G_BL_A_MEM", "G_BL_1", "G_BL_0" },
};
#pragma GLOBAL_ASM("asm/non_matchings/code/ucode_disas/UCodeDisas_ParseRenderMode.s")
#endif
void UCodeDisas_PrintVertices(UCodeDisas* this, Vtx* vtx, s32 count, s32 start) {
s32 i;
for (i = 0; i < count; i++) {
if (this->geometryMode & G_LIGHTING) {
DISAS_LOG("\n{{%6d, %6d, %6d, %d, %6d, %6d, %3d, %3d, %3d, %3d}}, /* vc%d */", vtx->n.ob[0], vtx->n.ob[1],
vtx->n.ob[2], vtx->n.flag, vtx->n.tc[0], vtx->n.tc[1], vtx->n.n[0], vtx->n.n[1], vtx->n.n[2],
vtx->n.a, start + i);
} else {
DISAS_LOG("\n{{%6d, %6d, %6d, %d, %6d, %6d, %3d, %3d, %3d, %3d}}, /* vn%d */", vtx->v.ob[0], vtx->v.ob[1],
vtx->v.ob[2], vtx->v.flag, vtx->v.tc[0], vtx->v.tc[1], vtx->v.cn[0], vtx->v.cn[1], vtx->v.cn[2],
vtx->v.cn[3], start + i);
}
vtx++;
if (1) {}
}
}
void UCodeDisas_Disassemble(UCodeDisas* this, Gfx* gfx0);
#pragma GLOBAL_ASM("asm/non_matchings/code/ucode_disas/UCodeDisas_Disassemble.rodata.s")
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),
};
#pragma GLOBAL_ASM("asm/non_matchings/code/ucode_disas/UCodeDisas_Disassemble.rodata2.s")
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),
};
#pragma GLOBAL_ASM("asm/non_matchings/code/ucode_disas/UCodeDisas_Disassemble.s")
void UCodeDisas_RegisterUCode(UCodeDisas* this, s32 count, UCodeInfo* ucodeArray) {
this->ucodeInfoCount = count;
this->ucodeInfo = ucodeArray;
}
void UCodeDisas_SetCurUCode(UCodeDisas* this, void* ptr) {
UCodeDisas_SetCurUCodeImpl(this, ptr);
}

View file

@ -1177,7 +1177,7 @@ s32 CollisionCheck_SetOC_SAC(GlobalContext* globalCtx, CollisionCheckContext* co
// larger than the total number of data. // larger than the total number of data.
return -1; return -1;
} }
// BUG: Should be colOc //! @bug Should be colOc
colChkCtx->colAt[index] = collider; colChkCtx->colAt[index] = collider;
} else { } else {
if (!(colChkCtx->colOcCount < COLLISION_CHECK_OC_MAX)) { if (!(colChkCtx->colOcCount < COLLISION_CHECK_OC_MAX)) {

View file

@ -84,7 +84,7 @@ void* KaleidoManager_GetRamAddr(void* vram) {
ovl = iter; ovl = iter;
goto KaleidoManager_GetRamAddr_end; goto KaleidoManager_GetRamAddr_end;
} }
// BUG: devs probably forgot iter++ here //! @bug Devs probably forgot iter++ here
} }
osSyncPrintf("異常\n"); // Abnormal osSyncPrintf("異常\n"); // Abnormal

View file

@ -126,7 +126,7 @@ void EnBoom_Fly(EnBoom* this, GlobalContext* globalCtx) {
} }
if ((target != (Actor*)player) && ((target->update == NULL) || (ABS(yawDiff) > 0x4000))) { if ((target != (Actor*)player) && ((target->update == NULL) || (ABS(yawDiff) > 0x4000))) {
// BUG: This condition is why the boomerang will randomly fly off in a the down left direction sometimes. //! @bug This condition is why the boomerang will randomly fly off in a the down left direction sometimes.
// If the actor targetted is not Link and the difference between the 2 y angles is greater than 0x4000, // If the actor targetted is not Link and the difference between the 2 y angles is greater than 0x4000,
// the moveTo pointer is nulled and it flies off in a seemingly random direction. // the moveTo pointer is nulled and it flies off in a seemingly random direction.
this->moveTo = NULL; this->moveTo = NULL;