Street Fighter III: 3rd Strike
Capcom's 1999 arcade fighter, read through the crowded-street decompilation of its 2004 PlayStation 2 port.
On this page
The atlas reads Street Fighter III: 3rd Strike through the Crowded Street community’s decompilation, C that rebuilds the PlayStation 2 port sold in the Street Fighter Anniversary Collection. Names quoted here are theirs, from the port’s debug data. The claims describe that port; the 1999 arcade game hasn’t been compared, and nothing has been measured in the game yet.
A parry is a lever tap that opens a window instead of a held block: for 10 passes1 of the input check after a high or low tap, a hit whose attack can be parried is parried1. A defender already guarding can still parry, but only if the tap came in the window’s first 2 or 3 passes2,2. A parry stops the attacker for 16 to 203 counts. The defender’s stop is 15, set negative, a kind the code counts down with char_move still running3.
The Super Art gauge fills from a table by character and move, on a move’s start, on guard, on hit, and on parry, and stores whole stocks up to each Super Art’s limit4. Hits also fill a stun gauge toward a limit of 56 to 72 by character, which drains while play runs5.
Mechanics
| Mechanic | Kind | How |
|---|---|---|
| Blocking | Parry | a tap of the lever opens a 10-pass parry window (7 in the air), and a hit that lands in it is parried instead of guarded |
| Parry | Tap window | a fresh lever tap sets a counter of 11 (8 in the air, 6 against jumping attacks) that counts down each pass, and the parry works while it's nonzero |
| Parry | From a guard | while already guarding, the tap must come within the window's first 3 passes against a normal move, 2 against others |
| Super meter | Stocked | gains on starting a move, on guard, on hit (cut through a combo), and on parry, stored in stocks of 64 to 128 points up to each Super Art's limit |
| Stun gauge | Draining | each hit adds stun toward a limit of 56 to 72 by character; the gauge drains outside hit stop |
Every claim about this game, by concept (5)
References
- ^ abIn the PS2 port of Street Fighter III: 3rd Strike that crowded-street/3s-decomp rebuilds (the Street Fighter Anniversary Collection build), the parry is an input command that
check_10in CMD_MAIN.c reads. Once the lever has been neutral, a fresh lever press equal to the command's lever value (4 for the high parry and the air parry, 2 for the low one; the whole lever is compared, so a diagonal doesn't match; the air parry only while the character is above the ground) sets the parry's counter inwaza_flagto the command'sresetvalue, andcommand_ok_movetakes 1 off it on every pass, the tap's own included. When a press sets one parry counter,check_10zeroes each of the other parry counters (entries 3, 4, 5, 6, and 12) that is smaller than the new one, and an air parry press (entry 5) is zeroed at once while the entry-6 command'sfree3is above 0. The command tables every character shares givereset11 for the high and low parries (entries 3 and 4), 8 for the air parry (entry 5), and 6 for entry 12, so the counter stays nonzero for 10, 7, and 5 passes (computed).defense_groundchecks entry 12, not entry 3, against a jumping attack parried high (guard bit 2 withjump_att_flag); a jumping attack parried low still uses entry 4, and both of those branches are gated by bit 0x800. The System Direction setting adds −2, 0, 2, or 4 to each, and its defaults add 0. The window closes early if the held lever turns to another value or includes bit 8, if it's still held 6 passes after the press, or if any direction is pressed after it's let go. The command arms again only after a second counter, set toresetplus 10, has counted below zero. While the defender'sguard_chuuisn't 1 to 4 (the test isguard_chuu != 0 && guard_chuu < 5),defense_groundanddefense_skyturn a hit that the attack's guard bits let it parry into a parry when the matching counter is nonzero, unless the defender is stunned, itsguard_flaghas bit 2 set, or a System Direction setting has switched that parry off.Codecrowded-street/3s-decomprevisedHow we know
610void check_10() { 611 switch (waza_ptr->shot_ok) { 612 case 0: 613 if (chk_pl->sw_lever == 0) { 614 waza_ptr->shot_ok++; ⋮ 618 case 1: 619 if ((cmd_pl->wu.xyz[1].disp.pos > 0 || (waza_type[cmd_id] != 5 && waza_type[cmd_id] != 6)) && 620 chk_pl->now_lvbt & 0xF) { 621 if (chk_pl->sw_lever == waza_ptr->w_lvr) { 622 waza_ptr->shot_ok++; 623 wcp[cmd_id].waza_flag[waza_type[cmd_id]] = wcp[cmd_id].reset[waza_type[cmd_id]]; 624 waza_ptr->free3 = wcp[cmd_id].reset[waza_type[cmd_id]] + 10; ⋮
src/anniversary/sf33rd/Source/Game/CMD_MAIN.c lines 610–625 at be9b9bc · upstream ↗ 627 switch (waza_type[cmd_id]) { 628 case 3: 629 if (wcp[cmd_id].waza_flag[3] > wcp[cmd_id].waza_flag[4]) { 630 wcp[cmd_id].waza_flag[4] = 0; ⋮ 634 wcp[cmd_id].waza_flag[5] = 0; ⋮ 641 if (wcp[cmd_id].waza_flag[3] > wcp[cmd_id].waza_flag[12]) { 642 wcp[cmd_id].waza_flag[12] = 0; ⋮ 649 wcp[cmd_id].waza_flag[3] = 0; ⋮ 653 wcp[cmd_id].waza_flag[5] = 0; ⋮ 661 wcp[cmd_id].waza_flag[12] = 0; ⋮ 666 case 5: ⋮ 668 wcp[cmd_id].waza_flag[3] = 0; ⋮
src/anniversary/sf33rd/Source/Game/CMD_MAIN.c lines 627–728 at be9b9bc · upstream ↗ 739 case 2: 740 waza_ptr->w_int--; 741 waza_ptr->free3--; ⋮ 743 if (waza_ptr->w_int > 0) { 744 if (chk_pl->sw_lever == 0) { 745 waza_ptr->shot_ok++; 746 break; ⋮ 749 if (chk_pl->sw_lever & 8) { 750 wcp[cmd_id].waza_flag[waza_type[cmd_id]] = 0; 751 waza_ptr->shot_ok++; 752 break; ⋮ 755 if (chk_pl->sw_lever != waza_ptr->w_lvr) { ⋮
src/anniversary/sf33rd/Source/Game/CMD_MAIN.c lines 739–785 at be9b9bc · upstream ↗ 107 for (j = 0; j < 56; j++) { 108 if (wcp[cmd_id].waza_flag[j] != -1) { ⋮ 111 waza_ptr = &waza_work[cmd_id][j]; 112 chk_move_jp[waza_ptr->w_type](); ⋮ 116 for (j = 0; j < 56; j++) { 117 if ((wcp[cmd_id].waza_flag[j] != -1) && (wcp[cmd_id].waza_flag[j] != 0)) { 118 waza_ptr = &waza_work[cmd_id][j]; 119 command_ok_move(j);
src/anniversary/sf33rd/Source/Game/CMD_MAIN.c lines 107–121 at be9b9bc · upstream ↗ 1530void command_ok_move(s16 waza_num) { 1531 if (dead_lvr_check()) { ⋮ 1536 wcp[cmd_id].waza_flag[waza_num]--;
src/anniversary/sf33rd/Source/Game/CMD_MAIN.c lines 1530–1536 at be9b9bc · upstream ↗ 9void (*chk_move_jp[28])() = { check_init, check_0, check_1, check_2, check_3, check_4, check_5, 10 check_6, check_7, check_7, check_9, check_10, check_11, check_12,
src/anniversary/sf33rd/Source/Game/CMD_MAIN.c lines 9–10 at be9b9bc · upstream ↗ 124void check_init() { 125 cmd_tbl_ptr += 12; 126 waza_ptr->w_type = *cmd_tbl_ptr++; 127 waza_ptr->w_int = *cmd_tbl_ptr++; 128 waza_ptr->free1 = *cmd_tbl_ptr; 129 waza_ptr->free2 = *cmd_tbl_ptr++; 130 waza_ptr->w_lvr = *cmd_tbl_ptr++;
src/anniversary/sf33rd/Source/Game/CMD_MAIN.c lines 124–130 at be9b9bc · upstream ↗ 37 wcp[cmd_id].reset[i] = *cmd_tbl_ptr++;src/anniversary/sf33rd/Source/Game/CMD_MAIN.c line 37 at be9b9bc · upstream ↗ 43const s16 pc_cmd_03[17] = { 11, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 11, 0, 0, 4, 28 }; ⋮ 45const s16 pc_cmd_04[17] = { 11, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 11, 0, 0, 2, 28 }; ⋮ 47const s16 pc_cmd_05[17] = { 8, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 11, 0, 0, 4, 28 };
src/anniversary/sf33rd/Source/Game/cmd_data.c lines 43–49 at be9b9bc · upstream ↗ 61const s16 pc_cmd_12[17] = { 6, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 11, 0, 0, 4, 28 };src/anniversary/sf33rd/Source/Game/cmd_data.c line 61 at be9b9bc · upstream ↗ 781const_s16_arr p0_cmd[56] = { pc_cmd_00, pc_cmd_01, pc_cmd_02, pc_cmd_03, pc_cmd_04, pc_cmd_05, pc_cmd_06, pc_cmd_07, 782 pc_cmd_08, pc_cmd_09, pc_cmd_10, pc_cmd_11, pc_cmd_12, pc_cmd_13, pc_cmd_14, pc_cmd_15,
src/anniversary/sf33rd/Source/Game/cmd_data.c lines 781–782 at be9b9bc · upstream ↗ 55 switch (i) { 56 case 3: 57 case 4: 58 case 5: 59 wcp[cmd_id].reset[i] += blok_b_omake[omop_b_block_ix[cmd_id]]; 60 make_red_blocking_time(cmd_id, i, wcp[cmd_id].reset[i]); 61 break; ⋮ 63 case 6: 64 case 12: 65 wcp[cmd_id].reset[i] += blok_b_omake[omop_b_block_ix[cmd_id]]; 66 break;
src/anniversary/sf33rd/Source/Game/CMD_MAIN.c lines 55–66 at be9b9bc · upstream ↗ 45const s16 blok_b_omake[4] = { -2, 0, 2, 4 };src/anniversary/sf33rd/Source/Game/SysDir.c line 45 at be9b9bc · upstream ↗ 168void get_system_direction_parameter(DirData* sysdir_data) { 169 if (sysdir_data->contents[0][0] == 0) { 170 omop_spmv_ng_table[0] |= 0x300; ⋮ 173 if (sysdir_data->contents[0][1] == 0) { 174 omop_spmv_ng_table[0] |= 0x800; ⋮ 177 if (sysdir_data->contents[0][2] == 0) { 178 omop_spmv_ng_table[0] |= 0x400; ⋮ 181 omop_b_block_ix[0] = sysdir_data->contents[0][3];
src/anniversary/sf33rd/Source/Game/SysDir.c lines 168–181 at be9b9bc · upstream ↗ 9const DirData Dir_Default_Data = { .contents = { { 1, 1, 1, 1, 1, 1, 1 },src/anniversary/sf33rd/Source/Game/DIR_DATA.c line 9 at be9b9bc · upstream ↗ 102 system_dir[ix] = Dir_Default_Data;src/anniversary/sf33rd/Source/Game/init3rd.c line 102 at be9b9bc · upstream ↗ 1179 if (ds->py->flag == 0 && !(ds->guard_flag & 2) && as->wu.att.guard & 3) { 1180 if (as->wu.att.guard & 2) {
src/anniversary/sf33rd/Source/Game/HITCHECK.c lines 1179–1180 at be9b9bc · upstream ↗ 1198 } else if (!(ds->spmv_ng_flag & 0x100)) { 1199 if (as->wu.jump_att_flag) { 1200 if (!(ds->spmv_ng_flag & 0x800) && (ds->cp->waza_flag[12] != 0 || abs)) { ⋮ 1216 } else if (ds->cp->waza_flag[3] != 0 || abs) {
src/anniversary/sf33rd/Source/Game/HITCHECK.c lines 1198–1216 at be9b9bc · upstream ↗ 1248 } else if (!(ds->spmv_ng_flag & 0x200)) { 1249 if (as->wu.jump_att_flag) { 1250 if (!(ds->spmv_ng_flag & 0x800) && (ds->cp->waza_flag[4] != 0 || abs)) { ⋮ 1261 } else if (ds->cp->waza_flag[4] != 0 || abs) {
src/anniversary/sf33rd/Source/Game/HITCHECK.c lines 1248–1261 at be9b9bc · upstream ↗ 1172 just_now = 0; ⋮ 1174 if (ds->guard_chuu != 0 && ds->guard_chuu < 5) { 1175 just_now = 1;
src/anniversary/sf33rd/Source/Game/HITCHECK.c lines 1172–1175 at be9b9bc · upstream ↗ 1080 if (ds->py->flag == 0 && !(ds->guard_flag & 2) && as->wu.att.guard & 4) { ⋮ 1093 } else if (!(ds->spmv_ng_flag & 0x400) && ((ds->cp->waza_flag[5] != 0) || abs)) {
src/anniversary/sf33rd/Source/Game/HITCHECK.c lines 1080–1093 at be9b9bc · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Revised after a check by a second AI model, 2026-10-22.
- ^ abIn the PS2 port of Street Fighter III: 3rd Strike that crowded-street/3s-decomp rebuilds, a defender who is already guarding (
guard_chuu1 to 4, whichDamage_04000andDamage_07000set in damage routines 4 to 7) parries a hit only if the parry's counter is still at least the thresholdmake_red_blocking_timestores from that parry'sreset:resetless 3 against movescheck_normal_attackcounts as normal, and less 2 against the rest, less a second System Direction offset of −1, 0, 1, or 2 (0 at its defaults). For the high and low parries (reset11) that is 8 or 9, and for the air parry (reset8) 5 or 6, so the press must come in the window's first 3 passes against a normal move or first 2 against others (computed). Otherwise the code goes on to the guard checks. A System Direction setting (bit 0x1000) turns this parry off.Codecrowded-street/3s-decompHow we know
36void make_red_blocking_time(s16 id, s16 ix, s16 num) { 37 switch (ix) { 38 case 3: 39 grdb[id][0][0] = num - (blok_r_omake[omop_r_block_ix[id]] + 2); 40 grdb[id][1][0] = num - (blok_r_omake[omop_r_block_ix[id]] + 3); 41 break; ⋮ 43 case 4: 44 grdb[id][0][1] = num - (blok_r_omake[omop_r_block_ix[id]] + 2); 45 grdb[id][1][1] = num - (blok_r_omake[omop_r_block_ix[id]] + 3); 46 break; ⋮ 48 case 5: 49 grdb2[id][0] = num - (blok_r_omake[omop_r_block_ix[id]] + 2); ⋮
src/anniversary/sf33rd/Source/Game/HITCHECK.c lines 36–52 at be9b9bc · upstream ↗ 1172 just_now = 0; ⋮ 1174 if (ds->guard_chuu != 0 && ds->guard_chuu < 5) { 1175 just_now = 1; 1176 attr_att = check_normal_attack(as->wu.kind_of_waza); ⋮ 1179 if (ds->py->flag == 0 && !(ds->guard_flag & 2) && as->wu.att.guard & 3) { 1180 if (as->wu.att.guard & 2) { 1181 if (just_now) { 1182 if (!(ds->spmv_ng_flag & 0x1000) && ((ds->cp->waza_flag[3] >= grdb[ds->wu.id][attr_att][0]) || abs)) {
src/anniversary/sf33rd/Source/Game/HITCHECK.c lines 1172–1182 at be9b9bc · upstream ↗ 1236 if (just_now) { 1237 if (!(ds->spmv_ng_flag & 0x1000) && (!(ds->cp->waza_flag[4] < grdb[ds->wu.id][attr_att][1]) || abs)) {
src/anniversary/sf33rd/Source/Game/HITCHECK.c lines 1236–1237 at be9b9bc · upstream ↗ 1081 if (just_now) { 1082 if (!(ds->spmv_ng_flag & 0x1000) && (ds->cp->waza_flag[5] >= grdb2[ds->wu.id][attr_att] || abs)) {
src/anniversary/sf33rd/Source/Game/HITCHECK.c lines 1081–1082 at be9b9bc · upstream ↗ 759s32 check_normal_attack(u8 waza) { 760 return sel_sp_ch_tbl[waza >> 3] == 0;
src/anniversary/sf33rd/Source/Game/HITCHECK.c lines 759–760 at be9b9bc · upstream ↗ 147const u8 guard_kind[12] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0 }; ⋮ 150 Damage_00000, Damage_01000, Damage_01000, Damage_01000, Damage_04000, Damage_04000, Damage_04000, Damage_07000, 151 Damage_04000, Damage_04000, Damage_04000, Damage_07000, Damage_12000, Damage_12000, Damage_14000, Damage_14000,
src/anniversary/sf33rd/Source/Game/PLPDM.c lines 147–151 at be9b9bc · upstream ↗ 304void Damage_04000(PLW* wk) { ⋮ 310 wk->guard_chuu = guard_kind[wk->wu.routine_no[2] - 4];
src/anniversary/sf33rd/Source/Game/PLPDM.c lines 304–310 at be9b9bc · upstream ↗ 353void Damage_07000(PLW* wk) { ⋮ 359 wk->guard_chuu = guard_kind[wk->wu.routine_no[2] - 4];
src/anniversary/sf33rd/Source/Game/PLPDM.c lines 353–359 at be9b9bc · upstream ↗ 47const s16 blok_r_omake[4] = { -1, 0, 1, 2 };src/anniversary/sf33rd/Source/Game/SysDir.c line 47 at be9b9bc · upstream ↗ 183 if (sysdir_data->contents[0][4] == 0) { 184 omop_spmv_ng_table[0] |= 0x1000; ⋮ 187 omop_r_block_ix[0] = sysdir_data->contents[0][5];
src/anniversary/sf33rd/Source/Game/SysDir.c lines 183–187 at be9b9bc · upstream ↗ 9const DirData Dir_Default_Data = { .contents = { { 1, 1, 1, 1, 1, 1, 1 },src/anniversary/sf33rd/Source/Game/DIR_DATA.c line 9 at be9b9bc · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Checked by a second AI model, 2026-10-22.
- ^ abIn the PS2 port of Street Fighter III: 3rd Strike that crowded-street/3s-decomp rebuilds, when a parried attack has any hit stop,
set_paring_statussets the parrying defender'sdm_stopto −15 and the attacker'shit_stopto 16. When the attacker is on the ground and the parry is a ground one (routines 31 to 33), a move whosekind_of_wazais 0 to 7 gets 4, 3, 2, or 1 more, bykind_of_waza / 2. The defender's parry status makes its stop negative and moves it tohit_stop.check_hit_stopcounts a negative stop up to 0 while still callingchar_move, and a positive one down without calling it. The attacker's count is 1 to 5 longer than the defender's 15 (computed). The same routine sets the hit's stun (dm_piyo) and its gauge points (dm_arts_point) to 0.Codecrowded-street/3s-decompHow we know
662const s16 sel_hs_add_tbl[6] = { 4, 3, 2, 1, 0, 0 }; ⋮ 664void set_paring_status(PLW* as, PLW* ds) { ⋮ 667 if ((as->wu.att.hs_you == 0) && (as->wu.att.hs_me == 0)) { 668 ds->wu.routine_no[2] = ds->wu.old_rno[2]; 669 } else { 670 hsadix = 4; 671 if ((as->wu.kind_of_waza & 0xF8) == 0) { 672 hsadix = (as->wu.kind_of_waza / 2) & 3; ⋮ 677 dm_status_copy(&as->wu, &ds->wu); 678 ds->wu.dm_piyo = 0; ⋮ 681 switch ((as->wu.xyz[1].disp.pos > 0) + (ds->wu.routine_no[2] - 31) * 2) { 682 case 0: ⋮
src/anniversary/sf33rd/Source/Game/HITCHECK.c lines 662–689 at be9b9bc · upstream ↗ 690 case 1: 691 case 3: 692 case 5: 693 ds->wu.dm_stop = -15; 694 as->wu.hit_stop = 16; 695 as->wu.hit_quake = 16; 696 break; ⋮ 699 ds->wu.dm_stop = -15; 700 as->wu.hit_stop = 16; 701 as->wu.hit_quake = 16; 702 break; ⋮ 705 ds->wu.dm_stop = -15; ⋮
src/anniversary/sf33rd/Source/Game/HITCHECK.c lines 690–735 at be9b9bc · upstream ↗ 586void Normal_31000(PLW* wk) { ⋮ 604 if (wk->wu.dm_stop > 0) { 605 wk->wu.dm_stop = -wk->wu.dm_stop; ⋮ 608 set_hit_stop_hit_quake(&wk->wu);
src/anniversary/sf33rd/Source/Game/PLPNM.c lines 586–608 at be9b9bc · upstream ↗ 833void set_hit_stop_hit_quake(WORK* wk) { 834 if (wk->dm_stop) { 835 wk->hit_stop = wk->dm_stop; 836 wk->dm_stop = 0;
src/anniversary/sf33rd/Source/Game/PLS02.c lines 832–836 at be9b9bc · upstream ↗ 329 if (wk->wu.hit_stop) { 330 num = 1; ⋮ 332 if (wk->wu.hit_stop > 0) { 333 wk->wu.hit_stop--; ⋮ 337 wk->wu.hit_stop++; ⋮ 345 } else { 346 wk->wu.hit_stop++; 347 char_move(&wk->wu);
src/anniversary/sf33rd/Source/Game/PLMAIN.c lines 329–348 at be9b9bc · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Checked by a second AI model, 2026-10-22.
- ^In the PS2 port of Street Fighter III: 3rd Strike that crowded-street/3s-decomp rebuilds, the Super Art gauge fills from
_add_arts_gauge, a table by character, by the move's gauge points (the top four bits of its attack data'spiyobyte), and by one of four columns. The attacker gains column 0 when a move starts a new attack, whether it hits or not (unless bit 0x20000000 of itsspmv_ng_flag2is set), and column 1 when it's guarded (set_guard_status, for an attack with any hit stop). When damage is applied (subtract_dm_vital, which the parry statuses also run), a nonzero column 2 gives the defender a third of the table value as read. The attacker then gets the value plus a difficulty bonus,asagh_zuru(−2 to 4), if the attacker is CPU-controlled (operator0), at least 1, cut to (32 − 2(n − 1))/32 for the defender's nth hit of a combo (at least 1/32), and raised by 120/100 for a CPU attacker whenBreak_Into_CPUis 1; so the combo cut reaches only the attacker's share. Column 3 goes to the defender when its parry status starts, plusasagh_zuruif the parrying player is CPU-controlled, and nothing whilesa_stop_check()is nonzero.add_super_arts_gaugemultiplies each gain by 120/100, by 150/100 more whenBattle_Numberis 0, and by an Extra Option factor of 0, 24, 32, or 44 over 32 (0 stops all gain), and adds nothing while the stocks are full, in a bonus game, or in a few other states the function tests. Pastgauge_lenthe gauge adds a stock and keeps the rest, and atstore_maxstocks it stops. Each Super Art'sgauge_lenandstore_maxcome from thesuper_arts_datatable, or fromsuper_arts_DATAwhencmd_selorno_sais set for that side, shifted by Extra Options and held to 64 to 128 and 1 to 9.Codecrowded-street/3s-decomprevisedHow we know
2781 aag_sw = 0; ⋮ 2783 if (wk->cg_att_ix < 0) { 2784 wk->cg_att_ix = -wk->cg_att_ix; 2785 wk->attack_num = att_req; 2786 wk->att_hit_ok = 1; 2787 aag_sw = 1; ⋮ 2809 wk->add_arts_point = (wk->att.piyo >> 4) & 0xF; ⋮ 2815 if (aag_sw) { 2816 add_sp_arts_gauge_init((PLW*)wk);
src/anniversary/sf33rd/Source/Game/CHARSET.c lines 2781–2817 at be9b9bc · upstream ↗ 856 if ((mwk->wu.work_id == 1) && !(mwk->spmv_ng_flag2 & 0x20000000)) { 857 asag = _add_arts_gauge[mwk->player_number][wk->wu.add_arts_point][0]; ⋮ 860 } else if (!(wk->spmv_ng_flag2 & 0x20000000)) { 861 asag = _add_arts_gauge[wk->player_number][wk->wu.add_arts_point][0];
src/anniversary/sf33rd/Source/Game/PLS02.c lines 855–862 at be9b9bc · upstream ↗ 627void set_guard_status(PLW* as, PLW* ds) { ⋮ 633 if (as->wu.att.hs_you == 0 && as->wu.att.hs_me == 0) { 634 ds->wu.routine_no[2] = ds->wu.old_rno[2]; 635 } else { ⋮ 651 as->wu.cmwk[8]++; 652 add_sp_arts_gauge_guard(as);
src/anniversary/sf33rd/Source/Game/HITCHECK.c lines 627–652 at be9b9bc · upstream ↗ 878 asag = _add_arts_gauge[mwk->player_number][wk->wu.add_arts_point][1]; ⋮ 882 asag = _add_arts_gauge[wk->player_number][wk->wu.add_arts_point][1];
src/anniversary/sf33rd/Source/Game/PLS02.c lines 878–883 at be9b9bc · upstream ↗ 887void add_sp_arts_gauge_hit_dm(PLW* wk) { ⋮ 900 emwk = (PLW*)wk->wu.target_adrs; 901 asag = _add_arts_gauge[emwk->player_number][wk->wu.dm_arts_point][2]; ⋮ 903 if (asag != 0) { 904 add_super_arts_gauge(wk->sa, wk->wu.id, asag / 3, wk->metamorphose); ⋮ 914 asag = cal_sa_gauge_waribiki(wk, asag); ⋮ 920 add_super_arts_gauge(emwk->sa, emwk->wu.id, asag, emwk->metamorphose); ⋮ 926s16 cal_sa_gauge_waribiki(PLW* wk, s16 asag) { ⋮ 929 if (wk->cb->total < 2) { 930 return asag; ⋮ 933 num = 32 - (wk->cb->total - 1) * 2; ⋮ 935 if (num <= 0) { ⋮
src/anniversary/sf33rd/Source/Game/PLS02.c lines 887–944 at be9b9bc · upstream ↗ 1533void subtract_dm_vital(PLW* wk) { ⋮ 1539 add_sp_arts_gauge_hit_dm(wk);
src/anniversary/sf33rd/Source/Game/PLPDM.c lines 1533–1539 at be9b9bc · upstream ↗ 32const s16 asagh_zuru[8] = { -2, -1, 0, 0, 1, 2, 3, 4 };src/anniversary/sf33rd/Source/Game/PLS02.c line 32 at be9b9bc · upstream ↗ 903 if (asag != 0) { 904 add_super_arts_gauge(wk->sa, wk->wu.id, asag / 3, wk->metamorphose); ⋮ 906 if (emwk->wu.operator == 0) { 907 asag += asagh_zuru[save_w[Present_Mode].Difficulty]; ⋮ 910 if (asag <= 0) { 911 asag = 1; ⋮ 914 asag = cal_sa_gauge_waribiki(wk, asag); ⋮ 916 if (emwk->wu.operator == 0 && Break_Into_CPU == 1) { 917 asag = (asag * 120) / 100; ⋮ 920 add_super_arts_gauge(emwk->sa, emwk->wu.id, asag, emwk->metamorphose);
src/anniversary/sf33rd/Source/Game/PLS02.c lines 903–920 at be9b9bc · upstream ↗ 948void add_sp_arts_gauge_paring(PLW* wk) { ⋮ 956 if (sa_stop_check() != 0) { 957 return; ⋮ 961 return; ⋮ 965 asag = _add_arts_gauge[emwk->player_number][wk->wu.dm_arts_point][3]; ⋮ 967 if (asag != 0) { 968 if (wk->wu.operator == 0) { 969 asag += asagh_zuru[save_w[Present_Mode].Difficulty]; ⋮ 976 add_super_arts_gauge(wk->sa, wk->wu.id, asag, wk->metamorphose);
src/anniversary/sf33rd/Source/Game/PLS02.c lines 948–976 at be9b9bc · upstream ↗ 608 set_hit_stop_hit_quake(&wk->wu); 609 add_sp_arts_gauge_paring(wk); 610 subtract_dm_vital(wk);
src/anniversary/sf33rd/Source/Game/PLPNM.c lines 605–610 at be9b9bc · upstream ↗ 1672void get_damage_reaction_data(PLW* wk) { ⋮ 1679 subtract_dm_vital(wk);
src/anniversary/sf33rd/Source/Game/PLPDM.c lines 1672–1679 at be9b9bc · upstream ↗ 1100void add_super_arts_gauge(SA_WORK* wk, s16 ix, s16 asag, u8 mf) { ⋮ 1106 if (!pcon_dp_flag && !Bonus_Game_Flag && (sa_gauge_omake[omop_sa_gauge_ix[ix]] != 0) && (asag > 0) && 1107 (wk->store != wk->store_max)) { 1108 asag = asag * 0x78 / 100; ⋮ 1110 if (save_w[Present_Mode].Battle_Number[Play_Type] == 0) { 1111 asag = asag * 0x96 / 100; ⋮ 1114 asag = asag * sa_gauge_omake[omop_sa_gauge_ix[ix]] / 32; ⋮ 1116 if (asag == 0) { 1117 asag = 1; ⋮ 1120 wk->gauge.s.h += asag; ⋮ 1123 if (wk->gauge.s.h > wk->gauge_len) { 1124 wk->store += 1; ⋮
src/anniversary/sf33rd/Source/Game/PLS02.c lines 1100–1134 at be9b9bc · upstream ↗ 37const s16 sa_gauge_omake[4] = { 0, 24, 32, 44 };src/anniversary/sf33rd/Source/Game/SysDir.c line 37 at be9b9bc · upstream ↗ 1399 if (cmd_sel[ix] || no_sa[ix]) { 1400 saptr = &super_arts_DATA[My_char[ix]][Super_Arts[ix]]; 1401 } else { 1402 saptr = &super_arts_data[My_char[ix]][Super_Arts[ix]];
src/anniversary/sf33rd/Source/Game/PLCNT.c lines 1399–1403 at be9b9bc · upstream ↗ 1415 super_arts[ix].gauge_len = remake_sa_gauge_len(ix, saptr->gauge_len); 1416 super_arts[ix].store_max = remake_sa_store_max(ix, saptr->store_max);
src/anniversary/sf33rd/Source/Game/PLCNT.c lines 1415–1416 at be9b9bc · upstream ↗ 1426s16 remake_sa_store_max(s16 ix, s16 store_max) { 1427 s16 num = store_max + sag_stock_omake[omop_sag_max_ix[ix]]; ⋮ 1429 if (num <= 0) { 1430 num = 1; ⋮ 1433 if (num > 9) { 1434 num = 9; ⋮ 1440s16 remake_sa_gauge_len(s16 ix, s16 gauge_len) { 1441 s16 num = gauge_len + sag_length_omake[omop_sag_len_ix[ix]] * 8; ⋮ 1443 if (num < 0x40) { 1444 num = 0x40; ⋮ 1447 if (num > 0x80) { 1448 num = 0x80;
src/anniversary/sf33rd/Source/Game/PLCNT.c lines 1426–1453 at be9b9bc · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Revised after a check by a second AI model, 2026-10-22.
- ^In the PS2 port of Street Fighter III: 3rd Strike that crowded-street/3s-decomp rebuilds, each character's stun limit (
genkai) is itspl_piyo_tblvalue, 56, 64, or 72, plus an Extra Option offset of −16, −8, 0, 8, or 16, held to 56 to 72. A hit that finds the defender neither knocked out nor already stunned, and doesn't knock it out, addsdm_piyoto the gauge: the_add_piyo_gaugevalue for the attacker's character and the move's stun value (the low four bits of itspiyobyte), scaled by an Extra Option factor of 0, 24, 32, or 44 over 32. A parried hit adds none (sf3/parry-freeze). When the gauge reaches the limit, the stun flag (py->flag) is set. Outside hit stop, and while the timers aren't frozen (Timer_Freeze), the gauge drains each pass by the character'spl_nr_piyo_tblvalue times an Extra Option factor (0, 20, 32, or 44) over 32, taken from a 32-bit count whose top 16 bits are the gauge (2730 to 3276 in the first ten entries, about 0.042 to 0.050 a pass at the factor 32, computed). Which Extra Option factor applies by default isn't shown in the lines read. Code in PLPAT02.c, plpat16.c, and plpat17.c multiplies a character'srecoverby 110/100 each time it runs whiletk_successis below 3, and plpat18.c by 120/100 while it's 0 or less.Codecrowded-street/3s-decomprevisedHow we know
290const s16 pl_piyo_tbl[20] = { 72, 72, 64, 64, 72, 64, 72, 64, 64, 72, 64, 64, 64, 64, 56, 64, 64, 72, 64, 56 }; ⋮ 292const s32 pl_nr_piyo_tbl[20] = { 3276, 2849, 2978, 2730, 2978, 2849, 3120, 2730, 2978, 2730,
src/anniversary/sf33rd/Source/Game/PLCNT.c lines 290–292 at be9b9bc · upstream ↗ 1371 piyori_type[ix].recover = pl_nr_piyo_tbl[plnum]; 1372 piyori_type[ix].genkai = pl_piyo_tbl[plnum] + stun_gauge_len_omake[omop_stun_gauge_len[ix]]; ⋮ 1374 if (piyori_type[ix].genkai < 56) { 1375 piyori_type[ix].genkai = 56; ⋮ 1378 if (piyori_type[ix].genkai > 72) { 1379 piyori_type[ix].genkai = 72;
src/anniversary/sf33rd/Source/Game/PLCNT.c lines 1371–1380 at be9b9bc · upstream ↗ 39const s16 stun_gauge_omake[4] = { 0, 24, 32, 44 }; ⋮ 41const s16 stun_gauge_r_omake[4] = { 0, 20, 32, 44 }; ⋮ 43const s16 stun_gauge_len_omake[5] = { -16, -8, 0, 8, 16 };
src/anniversary/sf33rd/Source/Game/SysDir.c lines 39–43 at be9b9bc · upstream ↗ 961 cal_damage_vitality(as, ds); 962 ds->wu.dm_piyo = _add_piyo_gauge[as->player_number][as->wu.att.piyo]; 963 ds->wu.dm_piyo = ds->wu.dm_piyo * stun_gauge_omake[omop_stun_gauge_add[(ds->wu.id + 1) & 1]] / 32;
src/anniversary/sf33rd/Source/Game/HITCHECK.c lines 961–963 at be9b9bc · upstream ↗ 2810 wk->att.piyo &= 0xF;src/anniversary/sf33rd/Source/Game/CHARSET.c line 2810 at be9b9bc · upstream ↗ 1533void subtract_dm_vital(PLW* wk) { 1534 if (wk->dead_flag == 0) {
src/anniversary/sf33rd/Source/Game/PLPDM.c lines 1533–1534 at be9b9bc · upstream ↗ 1563 if (wk->wu.vital_new < 0) { 1564 wk->wu.vital_new = -1; 1565 wk->dead_flag = 1; ⋮ 1576 } else if (wk->py->flag == 0) { 1577 wk->py->now.quantity.h += wk->wu.dm_piyo; ⋮ 1579 if (wk->py->now.quantity.h >= wk->py->genkai) { 1580 wk->py->now.timer = 0; 1581 wk->py->flag = 1;
src/anniversary/sf33rd/Source/Game/PLPDM.c lines 1563–1582 at be9b9bc · upstream ↗ 301 if (Timer_Freeze == 0) { 302 look_after_timers(wk);
src/anniversary/sf33rd/Source/Game/PLMAIN.c lines 301–302 at be9b9bc · upstream ↗ 415 if (wk->py->now.quantity.h && (wk->wu.hit_stop == 0)) { 416 wk->py->now.timer -= (wk->py->recover * stun_gauge_r_omake[omop_stun_gauge_rcv[wk->wu.id]]) / 32; ⋮ 418 if (wk->py->now.quantity.h <= 0) { 419 wk->py->now.timer = 0;
src/anniversary/sf33rd/Source/Game/PLMAIN.c lines 415–420 at be9b9bc · upstream ↗ 83 if (wk->tk_success < 3) { 84 wk->tk_success++; 85 wk->py->recover = (wk->py->recover * 110) / 100;
src/anniversary/sf33rd/Source/Game/PLPAT02.c lines 83–85 at be9b9bc · upstream ↗ 62 if (wk->tk_success < 3) { 63 wk->tk_success++; 64 wk->py->recover = (wk->py->recover * 110) / 100;
src/anniversary/sf33rd/Source/Game/plpat16.c lines 62–64 at be9b9bc · upstream ↗ 305 if (wk->tk_success < 3) { 306 wk->tk_success++; 307 wk->py->recover = (wk->py->recover * 110) / 100;
src/anniversary/sf33rd/Source/Game/plpat17.c lines 305–307 at be9b9bc · upstream ↗ 111 if (wk->tk_success <= 0) { 112 wk->tk_success++; 113 wk->py->recover = (wk->py->recover * 120) / 100;
src/anniversary/sf33rd/Source/Game/plpat18.c lines 111–113 at be9b9bc · upstream ↗ 9typedef struct { 10 // total size: 0x4 11 s16 l; // offset 0x0, size 0x2 12 s16 h; // offset 0x2, size 0x2 13} LoHi16;
include/structs.h lines 9–13 at be9b9bc · upstream ↗ 262 union { 263 s32 timer; // offset 0x0, size 0x4 264 LoHi16 quantity; // offset 0x0, size 0x4 265 } now; // offset 0x8, size 0x4
include/structs.h lines 262–265 at be9b9bc · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Revised after a check by a second AI model, 2026-10-22.
Sources
Code
- Crowded Street contributors. 2026. “3s-decomp: a decompilation of Street Fighter III: 3rd Strike for PlayStation 2 (crowded-street/3s-decomp).” Commit be9b9bc. crowded-street/3s-decomp @ be9b9bc · licence, all uses