Enchanced Draw Mode Lint (#1589)

A few updates that didn't make it into the first round:

* masks are now identified and expanded
* AND-EQUALS and OR-EQUALS are supported
* `sotn-lint` is run before `clang-format` to avoid having to run the
`format-src` target twice to catch line breaks
* `.h` files are included in `sotn-lint` since they are being used for
shared code
* `sotn` lint ignores the `mednafen` directory
This commit is contained in:
Jonathan Hohle 2024-09-07 13:00:44 -07:00 committed by GitHub
parent edb4f0ebc0
commit aff02911f9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
25 changed files with 99 additions and 50 deletions

View File

@ -138,6 +138,7 @@ clean:
format: format-src format-tools format-symbols format-license
format-src: bin/clang-format
cargo run --release --manifest-path ./tools/lints/sotn-lint/Cargo.toml ./src
@# find explainer:
@# find $(SRC_DIR) $(INCLUDE_DIR) : look in src and include
@# -type d \( -name 3rd -o -name CMakeFiles \) -prune : if an entry is both a directory and 3rd or CMakeFiles
@ -151,7 +152,6 @@ format-src: bin/clang-format
-o \( -type f \( -name '*.c' -o -name '*.h' \) \) \
-print0 \
| xargs -0 -n10 -P$$(nproc) bin/clang-format -i
cargo run --release --manifest-path ./tools/lints/sotn-lint/Cargo.toml ./src
format-tools:
black tools/*.py
black tools/splat_ext/*.py

View File

@ -176,7 +176,7 @@ void EntityStopWatch(Entity* self) {
prim->v0 = prim->v1 = 0x40;
prim->u1 = prim->u3 = x + 0x1E;
prim->v2 = prim->v3 = 0x49;
prim->drawMode &= 0xFFF7;
prim->drawMode &= ~DRAW_HIDE;
prim = prim->next;
} else {
self->ext.stopwatch.unk8E = 0;
@ -189,14 +189,14 @@ void EntityStopWatch(Entity* self) {
prim->v0 = prim->v1 = 0x40;
prim->u1 = prim->u3 = x + 0x1E;
prim->v2 = prim->v3 = 0x49;
prim->drawMode &= 0xFFF7;
prim->drawMode &= ~DRAW_HIDE;
}
break;
case 4:
self->flags &= ~FLAG_UNK_40000;
prim = &g_PrimBuf[self->primIndex];
prim->priority = 0xC2;
prim->drawMode &= 0xFDFF;
prim->drawMode &= ~DRAW_UNK_200;
prim = prim->next;
prim->drawMode |= DRAW_HIDE;
prim = prim->next;

View File

@ -629,7 +629,7 @@ void RicEntityHitByCutBlood(Entity* self) {
tilePrim->posY.val =
(tilePrim->posY.val + tilePrim->velocityY.val);
if (--tilePrim->delay < 0) {
tilePrim->drawMode |= 8;
tilePrim->drawMode |= DRAW_HIDE;
}
break;
case 4:

View File

@ -873,10 +873,10 @@ void RicEntityHitByIce(Entity* self) {
prim->r0 = prim->r1 = prim->r2 = prim->r3;
prim->b0 = prim->b1 = prim->b2 = prim->b3;
prim->g0 = prim->g1 = prim->g2 = prim->g3;
prim->drawMode |= 2;
prim->drawMode |= DRAW_UNK02;
prim->drawMode &= ~0x300;
if (--prim->v0 == 0) {
prim->drawMode |= 8;
prim->drawMode |= DRAW_HIDE;
}
}
prim = prim->next;

View File

@ -1244,7 +1244,7 @@ void RicEntityCrashAxe(Entity* self) {
prim->y2 = temp_s5 - (((rsin(var_s3) << 4) * twentyone) >> 0x10);
prim->x3 = temp_s4 + (((rcos(var_v0) << 4) * twentyone) >> 0x10);
prim->y3 = temp_s5 - (((rsin(var_v0) << 4) * twentyone) >> 0x10);
prim->drawMode &= 0xFFF7;
prim->drawMode &= ~DRAW_HIDE;
} else if (self->ext.axeCrash.unk8B[sp10 + 4] != 0) {
if (self->ext.axeCrash.unk8B[sp10 + 8] != 0) {
self->ext.axeCrash.unk8B[sp10 + 8] = 0;

View File

@ -148,7 +148,7 @@ void func_8016D9C4(Entity* self) {
self, BP_CRASH_REBOUND_STONE_PARTICLES, 0);
if (primLine->preciseY.val < 0) {
primLine->delay = 0;
primLine->drawMode |= 8;
primLine->drawMode |= DRAW_HIDE;
self->ext.et_8016D9C4.unk90--;
}
}
@ -498,7 +498,8 @@ void RicEntityCrashBible(Entity* self) {
if (++self->ext.et_8016E9E4.unk82 >= 6) {
prim = &g_PrimBuf[self->primIndex];
prim->clut = 0x19F;
prim->drawMode |= 0x35;
prim->drawMode |=
DRAW_TPAGE2 | DRAW_TPAGE | DRAW_COLORS | DRAW_TRANSP;
prim = prim->next;
for (i = 0; i < BIBLE_PAGE_COUNT; i++) {
prim->drawMode &= ~DRAW_HIDE;
@ -1692,7 +1693,7 @@ void RicEntitySubwpnStopwatch(Entity* self) {
prim->g0 = prim->g1 = prim->g2 = prim->g3 = prim->r0 = prim->r1 =
prim->r2 = prim->r3 = 0x40;
prim->b0 = prim->b1 = prim->b2 = prim->b3 = 0x60;
prim->drawMode |= 4;
prim->drawMode |= DRAW_COLORS;
g_api.PlaySfx(0x6A4);
self->step++;
}

View File

@ -543,7 +543,8 @@ void EntityPrizeDrop(Entity* self) {
prim->x1 = prim->x3 = self->posX.i.hi + 1;
prim->y0 = prim->y1 = self->posY.i.hi - 1;
prim->y2 = prim->y3 = self->posY.i.hi + 1;
prim->drawMode = 0x37;
prim->drawMode = DRAW_TPAGE2 | DRAW_TPAGE | DRAW_COLORS |
DRAW_UNK02 | DRAW_TRANSP;
}
break;
case 2:

View File

@ -88,16 +88,16 @@ void EntityRedDoor(Entity* self) {
prim->y0 = prim->y1 = y;
prim->y2 = prim->y3 = y + 62;
}
prim->drawMode = 6;
prim->drawMode = DRAW_COLORS | DRAW_UNK02;
prim->r0 = prim->b0 = prim->g0 = 0x7F;
prim->r1 = prim->b1 = prim->g1 = 0x7F;
prim->r2 = prim->b2 = prim->g2 = 0x7F;
prim->r3 = prim->b3 = prim->g3 = 0x7F;
if (i == 2 && !(self->params & 0x100)) {
prim->drawMode |= 8;
prim->drawMode |= DRAW_HIDE;
}
if (i == 1 && (self->params & 0x100)) {
prim->drawMode |= 8;
prim->drawMode |= DRAW_HIDE;
}
i++;
uv += 8;
@ -122,7 +122,7 @@ void EntityRedDoor(Entity* self) {
prim = &g_PrimBuf[self->primIndex];
i = 0;
while (prim != NULL) {
prim->drawMode |= 8;
prim->drawMode |= DRAW_HIDE;
i++;
if (i == 3) {
break;
@ -229,7 +229,7 @@ void EntityRedDoor(Entity* self) {
if (self->ext.door.angle == 0xC00) {
prim = &g_PrimBuf[self->primIndex];
for (i = 0; prim != NULL; i++, prim = prim->next) {
prim->drawMode |= 8;
prim->drawMode |= DRAW_HIDE;
}
if (!(self->params & 0x100)) {
g_api.PlaySfxVolPan(SFX_DOOR_CLOSE_A, 0x60, -6);

View File

@ -229,7 +229,7 @@ void EntityStageNamePopup(Entity* self) {
prim->x1 = prim->x3 = 0x80;
prim->y0 = prim->y1 = 0xB1;
prim->y2 = prim->y3 = 0xB1;
prim->drawMode = 0x15;
prim->drawMode = DRAW_TPAGE | DRAW_COLORS | DRAW_TRANSP;
self->step_s++;
}
break;
@ -260,7 +260,8 @@ void EntityStageNamePopup(Entity* self) {
}
prim = self->ext.stpopup.unk88;
for (i = 0; i < 2; i++) {
prim->drawMode = 0x75;
prim->drawMode = DRAW_UNK_40 | DRAW_TPAGE2 | DRAW_TPAGE |
DRAW_COLORS | DRAW_TRANSP;
prim->r0 = prim->g0 = prim->b0 = prim->r1 = prim->g1 =
prim->b1 = prim->r2 = prim->g2 = prim->b2 = prim->r3 =
prim->g3 = prim->b3 = self->ext.stpopup.unk90;
@ -274,7 +275,8 @@ void EntityStageNamePopup(Entity* self) {
}
prim = self->ext.stpopup.unk88;
for (i = 0; i < 2; i++) {
prim->drawMode = 0x35;
prim->drawMode =
DRAW_TPAGE2 | DRAW_TPAGE | DRAW_COLORS | DRAW_TRANSP;
prim->r0 = prim->g0 = prim->b0 = prim->r1 = prim->g1 =
prim->b1 = prim->r2 = prim->g2 = prim->b2 = prim->r3 =
prim->g3 = prim->b3 = self->ext.stpopup.unk90;
@ -291,14 +293,15 @@ void EntityStageNamePopup(Entity* self) {
}
prim = self->ext.stpopup.prim;
for (i = 0; i < 2; i++) {
prim->drawMode = 0x35;
prim->drawMode =
DRAW_TPAGE2 | DRAW_TPAGE | DRAW_COLORS | DRAW_TRANSP;
prim->r0 = prim->g0 = prim->b0 = prim->r1 = prim->g1 =
prim->b1 = prim->r2 = prim->g2 = prim->b2 = prim->r3 =
prim->g3 = prim->b3 = self->ext.stpopup.unk92;
prim = prim->next;
}
for (i = 0; i < 2; i++) {
prim->drawMode = 0x15;
prim->drawMode = DRAW_TPAGE | DRAW_COLORS | DRAW_TRANSP;
prim->r0 = prim->g0 = prim->b0 = prim->r1 = prim->g1 =
prim->b1 = prim->r2 = prim->g2 = prim->b2 = prim->r3 =
prim->g3 = prim->b3 = self->ext.stpopup.unk92;
@ -329,7 +332,7 @@ void EntityStageNamePopup(Entity* self) {
prim = prim->next;
prim = prim->next;
for (i = 0; i < 2; i++) {
prim->drawMode = 0x15;
prim->drawMode = DRAW_TPAGE | DRAW_COLORS | DRAW_TRANSP;
prim->r0 = prim->g0 = prim->b0 = prim->r1 = prim->g1 =
prim->b1 = prim->r2 = prim->g2 = prim->b2 = prim->r3 =
prim->g3 = prim->b3 = self->ext.stpopup.unk92;
@ -375,7 +378,8 @@ void EntityStageNamePopup(Entity* self) {
prim->p1 = -((0x14 - i) * 4);
prim->p2 = Random() & 3;
prim->p3 = 0;
prim->drawMode = 0x35;
prim->drawMode =
DRAW_TPAGE2 | DRAW_TPAGE | DRAW_COLORS | DRAW_TRANSP;
prim = prim->next;
}
@ -404,7 +408,8 @@ void EntityStageNamePopup(Entity* self) {
prim->p1 = -((0x14 - i) * 4);
prim->p2 = Random() & 3;
prim->p3 = 0;
prim->drawMode = 0x35;
prim->drawMode =
DRAW_TPAGE2 | DRAW_TPAGE | DRAW_COLORS | DRAW_TRANSP;
prim = prim->next;
}

View File

@ -14,7 +14,7 @@ void EntityExplosion(Entity* entity) {
entity->animFrameIdx = 0;
entity->animFrameDuration = 0;
entity->animSet = ANIMSET_DRA(2);
entity->drawMode = 0x30;
entity->drawMode = DRAW_TPAGE2 | DRAW_TPAGE;
if (entity->params & 0xF0) {
entity->palette = PAL_OVL(0x195);
entity->drawMode = DRAW_TPAGE;

View File

@ -5,7 +5,7 @@ void EntityIntenseExplosion(Entity* self) {
self->palette = PAL_OVL(0x170);
self->animSet = ANIMSET_DRA(5);
self->animCurFrame = 1;
self->drawMode = 0x30;
self->drawMode = DRAW_TPAGE2 | DRAW_TPAGE;
if (self->params & 0xF0) {
self->palette = PAL_OVL(0x195);
self->drawMode = DRAW_TPAGE;

View File

@ -94,7 +94,7 @@ void EntityMessageBox(Entity* self) {
prim->g0 = prim->g1 = prim->g2 = prim->g3 = 0x80;
}
prim->priority = 0x1FC;
prim->drawMode = 0x11;
prim->drawMode = DRAW_TPAGE | DRAW_TRANSP;
}
}
self->step++;
@ -189,7 +189,7 @@ void EntityMessageBox(Entity* self) {
break;
case 4:
prim = &g_PrimBuf[self->primIndex];
prim->drawMode = 0;
prim->drawMode = DRAW_DEFAULT;
self->ext.messageBox.duration++;
if (self->ext.messageBox.duration > self->params) {
DestroyEntity(self);

View File

@ -115,7 +115,7 @@ void EntityRelicOrb(Entity* self) {
prim->u1 = prim->u3 = texSrcX | 0x0F;
prim->v0 = prim->v1 = texSrcY | 0x81;
prim->v2 = prim->v3 = texSrcY | 0x8F;
prim->drawMode = 6;
prim->drawMode = DRAW_COLORS | DRAW_UNK02;
}
prim->priority = 0x7E;
prim = prim->next;
@ -183,7 +183,7 @@ void EntityRelicOrb(Entity* self) {
prim->g0 = prim->g1 = prim->g2 = prim->g3 = 0x80;
}
prim->priority = 0x1FD;
prim->drawMode = 0x11;
prim->drawMode = DRAW_TPAGE | DRAW_TRANSP;
}
prim = prim->next;
}
@ -315,7 +315,7 @@ void EntityRelicOrb(Entity* self) {
#else
prim->x0 = 0x80 - self->ext.relicOrb.unk7E * 6;
#endif
prim->drawMode = 0;
prim->drawMode = DRAW_DEFAULT;
self->ext.relicOrb.unk7C++;
if (self->ext.relicOrb.unk7C > 0x60) {
DestroyEntity(self);
@ -392,7 +392,8 @@ void EntityRelicOrb(Entity* self) {
prim->b0 = prim->b1 = prim->b2 = prim->b3 = 0x80;
prim->p1 = 0;
prim->priority = 0x7F;
prim->drawMode = 0x37;
prim->drawMode = DRAW_TPAGE2 | DRAW_TPAGE | DRAW_COLORS |
DRAW_UNK02 | DRAW_TRANSP;
break;
}
prim = prim->next;

View File

@ -1329,7 +1329,7 @@ void EntityMermanWaterSplash(Entity* self) {
}
if (prim->y0 & 0xFF00) {
prim->p1 = 1;
prim->drawMode |= 8;
prim->drawMode |= DRAW_HIDE;
}
prim->x0 = sp.x0;
prim->x1 = sp.x1;

View File

@ -1324,7 +1324,7 @@ void EntityMermanWaterSplash(Entity* self) {
}
if (prim->y0 & 0xFF00) {
prim->p1 = 1;
prim->drawMode |= 8;
prim->drawMode |= DRAW_HIDE;
}
prim->x0 = sp.x0;
prim->x1 = sp.x1;

View File

@ -467,7 +467,8 @@ void func_801CAE0C(Entity* self) { // BloodDrips
prim->b0 = 48;
prim->b1 = 16;
prim->priority = self->zPriority + 1;
prim->drawMode |= 0x37;
prim->drawMode |= DRAW_TPAGE2 | DRAW_TPAGE | DRAW_COLORS |
DRAW_UNK02 | DRAW_TRANSP;
prim = prim->next;
}
} else {

View File

@ -495,7 +495,8 @@ void func_801C5D20(Entity* self) { // BloodDrips
prim->b0 = 48;
prim->b1 = 16;
prim->priority = self->zPriority + 1;
prim->drawMode |= 0x37;
prim->drawMode |= DRAW_TPAGE2 | DRAW_TPAGE | DRAW_COLORS |
DRAW_UNK02 | DRAW_TRANSP;
prim = prim->next;
}
} else {

View File

@ -73,7 +73,7 @@ void BottomCornerText(u8* str, u8 lower_left) {
prim->y0 = prim->y1 = 0xD0;
prim->y2 = prim->y3 = 0xDF;
prim->priority = 0x1EE;
prim->drawMode = 0x11;
prim->drawMode = DRAW_TPAGE | DRAW_TRANSP;
prim = prim->next;
prim->tpage = 0x1F;
@ -241,7 +241,7 @@ void BottomCornerText(u8* str, u8 lower_left) {
prim->y0 = prim->y1 = 0xD0;
prim->y2 = prim->y3 = 0xDF;
prim->priority = 0x1EE;
prim->drawMode = 0x11;
prim->drawMode = DRAW_TPAGE | DRAW_TRANSP;
prim = prim->next;
prim->tpage = 0x1F;

View File

@ -225,7 +225,7 @@ void UnkPolyFunc2(Primitive* prim) {
prim->p3 = 8;
prim->next->p3 = 1;
prim->next->type = PRIM_LINE_G2;
prim->next->drawMode = 0xA;
prim->next->drawMode = DRAW_HIDE | DRAW_UNK02;
}
#if !defined(VERSION_PSP)

View File

@ -319,7 +319,7 @@ void EntityStageTitleCard(Entity* self) {
case 3:
prim = self->ext.stageTitleCard.prim;
prim->drawMode |= 0x31;
prim->drawMode |= DRAW_TPAGE2 | DRAW_TPAGE | DRAW_TRANSP;
prim = prim->next;
prim->u1 = prim->u3 = 0x7F;

View File

@ -576,7 +576,7 @@ static void func_ptr_80170024(Entity* self) {
rotTransResult = RotTransPers4(
vecs[0], vecs[1], vecs[2], vecs[3], &prim->x0, &prim->x1, &prim->x3,
&prim->x2, &unused1, &unusedFlag);
prim->drawMode |= 8;
prim->drawMode |= DRAW_HIDE;
if (0 < rotTransResult && rotTransResult <= 0x1BE) {
prim->r0 = prim->g0 = prim->b0 = prim->r1 = prim->g1 = prim->b1 =
prim->r2 = prim->g2 = prim->b2 = prim->r3 = prim->g3 =

View File

@ -277,7 +277,7 @@ static void EntityWeaponShieldSpell(Entity* self) {
if (self->ext.shield.unk82 >= 160) {
prim->b3 = 6;
prim = &g_PrimBuf[self->primIndex];
prim->drawMode |= 8;
prim->drawMode |= DRAW_HIDE;
self->ext.shield.unk80 = 4;
// Blueprint 98 has child 9, which makes func_ptr_80170024.
g_api.CreateEntFactoryFromEntity(

View File

@ -321,7 +321,7 @@ static void EntityWeaponShieldSpell(Entity* self) {
prim->r0 = prim->g0 = prim->b0 = prim->r1 = prim->g1 = prim->b1 =
prim->r2 = prim->g2 = prim->b2 = prim->r3 = prim->g3 = prim->b3;
if (--self->ext.weapon.unk80 == 0) {
prim->drawMode |= 8;
prim->drawMode |= DRAW_HIDE;
g_api.PlaySfx(SFX_FIREBALL_SHOT_A);
// TODO: FACTORY()
g_api.CreateEntFactoryFromEntity(

View File

@ -36,7 +36,7 @@ lazy_static! {
};
static ref REGEX: Regex = {
let pattern = r"([.>]drawMode\s*=\s*)((?:0x)?[A-Fa-f0-9]*)(?:;)";
let pattern = r"([.>]drawMode\s*(?:[&|]?)=\s*)((?:0x)?[A-Fa-f0-9]*)(?:;)";
Regex::new(pattern).unwrap()
};
}
@ -45,7 +45,7 @@ fn replace_enum(captures: &regex::Captures) -> String {
if let Some(assignment) = captures.get(1).map(|m| m.as_str().to_string()) {
if let Some(draw_mode) = captures.get(2).map(|m| m.as_str().to_string()) {
// if it starts with 0x, hex string, otherwise int
let draw_mode_value: u16;
let mut draw_mode_value: u16;
if draw_mode.starts_with("0x") {
if let Ok(v) = u16::from_str_radix(draw_mode.strip_prefix("0x").unwrap(), 16) {
draw_mode_value = v;
@ -57,7 +57,15 @@ fn replace_enum(captures: &regex::Captures) -> String {
draw_mode_value = draw_mode.parse::<u16>().unwrap();
}
let rvalue: String;
let invert: String;
if (draw_mode_value & 0x8000) != 0 {
invert = "~".to_string();
draw_mode_value = !draw_mode_value;
} else {
invert = "".to_string();
}
let mut rvalue: String;
if draw_mode_value == 0 {
rvalue = "DRAW_DEFAULT".to_string();
} else {
@ -72,8 +80,11 @@ fn replace_enum(captures: &regex::Captures) -> String {
.map(|e| *e.unwrap())
.collect::<Vec<&str>>()
.join(" | ");
if u16::count_ones(draw_mode_value) > 1 && invert == "~" {
rvalue = format!("({})", rvalue);
}
}
return format!("{}{};", assignment.to_string(), rvalue);
return format!("{}{}{};", assignment.to_string(), invert, rvalue);
}
}
captures
@ -128,4 +139,28 @@ mod tests {
let result = transform_line_draw_mode(input_line);
assert_eq!(result, expected_line)
}
#[test]
fn test_draw_mode_set() {
let input_line = "self->drawMode |= 0x80;";
let expected_line = "self->drawMode |= DRAW_MENU;";
let result = transform_line_draw_mode(input_line);
assert_eq!(result, expected_line)
}
#[test]
fn test_draw_mode_clear() {
let input_line = "self->drawMode &= 0xFF7F;";
let expected_line = "self->drawMode &= ~DRAW_MENU;";
let result = transform_line_draw_mode(input_line);
assert_eq!(result, expected_line)
}
#[test]
fn test_draw_mode_clear_many() {
let input_line = "self->drawMode &= 0xFFCF;";
let expected_line = "self->drawMode &= ~(DRAW_TPAGE2 | DRAW_TPAGE);";
let result = transform_line_draw_mode(input_line);
assert_eq!(result, expected_line)
}
}

View File

@ -58,11 +58,15 @@ fn process_directory(dir_path: &str) {
entries.par_bridge().for_each(|entry| {
if let Ok(entry) = entry {
let item_path = entry.path();
if item_path.is_file() && item_path.to_string_lossy().ends_with(".c") {
if item_path.is_file() &&
(item_path.to_string_lossy().ends_with(".c") ||
item_path.to_string_lossy().ends_with(".h")) {
println!("checking {:?}", item_path);
transform_file(&item_path.to_string_lossy(), &transformers);
} else if item_path.is_dir() {
process_directory(&item_path.to_string_lossy());
if item_path.file_name().unwrap() != "mednafen" {
process_directory(&item_path.to_string_lossy());
}
}
}
});