On this page
  1. Related
  2. Mechanics
  3. References
  4. Sources

The atlas reads Tecmo Super Bowl’s US NES release through bruddog’s commented asm6f disassembly, which grew from jstout’s earlier one. Built with the ROM’s graphics, its program code matches the ROM’s byte for byte. Labels and comments quoted here are bruddog’s. Nothing has been measured in the ROM yet.

Each rating is one of 16 steps, shown as 6 to 1001, moved up or down by the player’s condition. The max speed rating gives a max speed of 21 to 36 on offense and 37 to 52 on defense2, so at the same rating a defender’s cap is higher than an offensive player’s; running speed sets the starting speed and rushing power how often it rises2.

At each snap the defense’s play comes from a table keyed by the offense’s play id and the defense’s slot. Calling the column of the play’s group, which a playbook set on the playbook screen makes the offense’s own slot, is the only way to get one of 11 guess-only defensive plays3. Some of their scripts, such as reaction 128, set the top running-speed step and add 48 more max speed and 48 more HP4 before the player rushes. A computer defense picks a slot at random, except on short third and fourth downs, where it calls a run slot 80% of the time (computed) with 3 yards or less to go5. As the atlas reads it, the check meant to favor pass defense on long yardage compares the wrong byte, so it never fires5.

When two players lock up, hitting power decides between computer players, with random holds and rolls6. A human player against a computer one mashes A and needs 2 A presses in a 64-frame hold7, unless a large enough hitting-power lead throws the computer player at once7.

A pass adds the passer’s pass control to the receiver’s reception, and each nearby defender subtracts his interception value before a random roll; the thresholds give a catch at 79 or more uncovered and an interception under 51 covered8. When the target isn’t near the ball, the interception check reads a leftover script argument in place of the passer’s value, which the disassembly calls a major bug9.

Mechanics

MechanicKindHow
Player ratingsSteps into tables16 steps per rating, shown as 6 to 100, moved by condition; separate speed tables for offense and defense
Play callingSlot pairing8 slots a side; the defense's slot matching the play's group gets one of 11 defensive plays, some with boosted rushers
Button mashingPress counta human needs 2 A presses in a 64-frame hold to beat a computer player, unless 32 more HP wins at once
Pass completionRatings rollPC plus REC less each defender's INT scales a random roll against fixed catch and interception lines
Every claim about this game, by concept (9)
Button mashingWhen two computer-controlled players collide, the game compares their hitting power (HP), loaded from a table at 4 per rating step (0 to 60). If neither leads by 16 (4 steps), they hold for 8 frames plus random waits of up to 255, 255, and 63 frames, and one random bit picks the winner. With a lead of 16 to 31, the stronger player wins when a random byte is under 170 (computed: 66%); otherwise they grapple as before. With a lead of 32 or more, the stronger player wins on a byte under 205 (computed: 80%); otherwise they hold 64 frames and then grapple.Code
An ordinary collision (not a dive or a chop block) between a human-controlled and a computer-controlled player goes to MAN_VS_COM_POPCORN_CHECK. If the human player's HP is at least 32 higher (8 rating steps), the computer player is thrown at once; otherwise both hold for 64 frames while the game counts the human's A presses, and 2 or more throw the computer player, and fewer throw the human. Between two human players, both players' presses count over the same 64 frames. The defender wins with at least as many presses as the offensive player; if neither pressed, both go down.Code
Pass completionWhen a pass reaches its target, Tecmo Super Bowl adds the passer's pass control (PC) value, 61 to 91 at 2 per step, to the receiver's reception (REC) value, also 61 to 91. With no defender near the ball, a random byte forced into 128–255, times that sum and divided by 256, gives a roll from half the sum to one less than it; 79 or more is a catch, and less is incomplete. Each of up to three nearby defenders in turn subtracts his interception (INT) value, 51 to 81, from the sum (floored at 0) for a roll made the same way: under 51 is an interception, under 80 is incomplete, and 80 or more passes the ball to the next defender's check. A pass that clears every check is a catch.Code
When the target isn't close enough to the ball, nearby defenders can still intercept: each in turn subtracts his INT value from the variable the code names PASS_CONTROL_VALUE and rolls as for a covered pass, intercepting under 14; otherwise the pass is incomplete. This path doesn't call ADD_PASS_CONTROL_SKILL_AND_REC_SKILL, the routine that stores the passer's value in that variable (the close-target and the jump-or-dive paths call it), so it uses whatever player-command argument was last stored there. The disassembly marks it "***MAJOR BUG!!".Code
Play callingEach side picks one of eight slots. The offense's slot reads a play id (0 to 63) from its playbook, and before the snap the game reads the defense's play from a 64-row table: the row is the offense's play id, and the column is the defense's slot. In all 64 rows, the entry in column id ÷ 8, the play's group, is a defensive play that appears nowhere else in the table, one of 11 such plays (computed from the table by the atlas). The playbook-change screen offers slot k only the plays of group k (ids k × 8 to k × 8 + 7), so for a playbook set there, that column is the slot the offense called.Code
Reactions 128 and 177 are player scripts used only by the 11 guess-only defensive plays (computed by the atlas over bank 4). Reaction 128 waits for the snap, sets the player's running-speed rating to 15, adds 48 to his max speed and 48 to his hitting power, moves, and then loops a runRush command; reaction 177 stands for 30 frames after the snap and then jumps into reaction 128's boosts. Execution 188, one of the 11, gives reactions 128 to 134 to its first seven players. The script command the disassembly's macro calls boostRS emits $E3, which the command table maps to the routine that adds to max speed.Code
A computer-controlled defense picks its slot at random, 0 to 7, except on third and fourth down. There, with under 25 eighths of a yard to the first-down line (3 yards or less), it calls a run slot (0–3) when a sum of random bytes is under 205 (computed: 80%) and a pass slot (4–7) otherwise. As the atlas reads it, the check meant to favor passes on longer yardage compares the distance's high byte with 57 ($39), and that byte is at most 3 on a 100-yard field, so every longer third or fourth down also gets a random slot.Code
Player ratingsTecmo Super Bowl stores each player rating as a 4-bit index from 0 to 15, two to a byte. The player data screen shows an index as 6, 13, 19, 25, 31, 38, 44, 50, 56, 63, 69, 75, 81, 88, 94, or 100. When the game reads a rating, it adds the player's condition (bad 0, average 1, good 2, excellent 3) less 1 and clamps the result to 0–15, so a bad player plays one step down and an excellent one two steps up.Code
On the field each player carries a current speed and a max speed. The max speed (MS) rating picks a max speed of 21 to 36 for an offensive player and 37 to 52 for a defender, one per step. Running speed (RS) sets the starting current speed, 14 to 29, and rushing power (RP) sets a countdown of 13 frames at step 0 down to 1 at steps 14 and 15. On each frame a player is moving, the countdown drops by 1; when it reaches 0 it reloads, and the current speed rises by 1 unless it has reached max speed. A computer-controlled defense facing a human-controlled offense loads differently: it adds CPU_DEF_MS_BOOST to its max speed and to its RS and RP steps, capping the steps at 15.Code

References

  1. ^Tecmo Super Bowl stores each player rating as a 4-bit index from 0 to 15, two to a byte. The player data screen shows an index as 6, 13, 19, 25, 31, 38, 44, 50, 56, 63, 69, 75, 81, 88, 94, or 100. When the game reads a rating, it adds the player's condition (bad 0, average 1, good 2, excellent 3) less 1 and clamps the result to 0–15, so a bad player plays one step down and an excellent one two steps up.Codebruddog/Tecmo_Super_Bowl_NES_Disassembly
    How we know
    5039@get_player_skill:                                                   ; GET PLAYER SKILL(Y=STARTER ID, A = SKILL TO GET)
    ⋮
    5042	LSR                                                              ; SHIFT RIGHT SINCE TWO SKILLS PER BYTE
    ⋮
    5045	BCS @save_skill_value                                            ; SKILL IN SECOND NIBBLE? YES-> SKILL IS IN SECOND NIBBLE OF BYTE
    ⋮
    5049	AND #$0F                                                         ; MASK OUT UPPER NIBBLE
    
    Bank31_fixed_bank.asm lines 5039–5050 at f3bae0e · upstream ↗
    5063@add_condition_to_skill:                                             ; UPDATE PLAYER SKILL VALUE BASED ON CONDITION
    ⋮
    5066	CLC                                                              ; FINAL SKILL INDEX= SKILL VALUE INDEX + PLAYER CONDITION
    5067	ADC player_addr                                          		 ;
    5068	SEC                                                              ; SET FINAL SKILL INDEX = 0, IF FINAL SKILL INDEX <0
    5069	SBC #$01                                                         ;
    ⋮
    5073	CMP #MAX_SKILL + 1                                               ; SET FINAL SKILL INDEX = 0X0F, IF FINAL SKILL INDEX >0X0F
    
    Bank31_fixed_bank.asm lines 5063–5075 at f3bae0e · upstream ↗
    128BAD_CONDITION						= $00
    129AVERAGE_CONDITION					= $01
    130GOOD_CONDITION						= $02
    131EXCELLENT_CONDITION					= $03
    
    constants_variables/constants.asm lines 128–131 at f3bae0e · upstream ↗
    2726SKILL_NUMBER_VALUE_TABLE:							                                            ; SKILL VALUES 
    2727	.WORD $0006, $0013, $0019, $0025, $0031, $0038, $0044, $0050
    2728	.WORD $0056, $0063, $0069, $0075, $0081, $0088, $0094, $0100
    
    Bank25_leaders_player_data_pro_bowl_abbrev.asm lines 2726–2728 at f3bae0e · upstream ↗
    2245@draw_skill_number:		
    2246	LDA skill_value						                                        ; LOAD SKILL INDEX 
    2247	ASL							                                                ; SHIFT SINCE EACH ENTRY IS TWO DIGITS 
    2248	TAY							                                                ; LOAD FIRST DIGIT FROM SKILL VALUES
    2249	LDA SKILL_NUMBER_VALUE_TABLE+1,Y					                        ; 
    
    Bank25_leaders_player_data_pro_bowl_abbrev.asm lines 2245–2249 at f3bae0e · 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 claim ledger

  2. ^ abOn the field each player carries a current speed and a max speed. The max speed (MS) rating picks a max speed of 21 to 36 for an offensive player and 37 to 52 for a defender, one per step. Running speed (RS) sets the starting current speed, 14 to 29, and rushing power (RP) sets a countdown of 13 frames at step 0 down to 1 at steps 14 and 15. On each frame a player is moving, the countdown drops by 1; when it reaches 0 it reloads, and the current speed rises by 1 unless it has reached max speed. A computer-controlled defense facing a human-controlled offense loads differently: it adds CPU_DEF_MS_BOOST to its max speed and to its RS and RP steps, capping the steps at 15.Codebruddog/Tecmo_Super_Bowl_NES_Disassemblyrevised
    How we know
    1211SET_OFFENSIVE_PLAYER_SKILLS:                        ; SET OFFENSIVE PLAYER SKILLS ($40 = PLAYER POINTER)
    ⋮
    1215	LDY #MAX_SPEED_INDEX                            ; SET SKILL INDEX = MAX SPEED INDEX 
    1216	JSR GET_PLAYER_SKILL                            ; GET PLAYER SKILL ( Y= SKILL INDEX)
    1217	LDA OFF_MAX_SPEED_VALS,Y                        ; LOAD SPEED VALUE FROM OFFENSIVE MAX SPEED TABLE
    ⋮
    1220SET_DEFENSIVE_PLAYER_SKILLS:                        ; SET DEFENSIVE PLAYER SKILLS NORMAL($40 = PLAYER POINTER)
    1221	LDY #MAX_SPEED_INDEX                            ; SET SKILL INDEX = MAX SPEED INDEX
    1222	JSR GET_PLAYER_SKILL                            ; GET PLAYER SKILL ( Y= SKILL INDEX)
    1223	LDA DEF_MAX_SPEED_VALS,Y                        ; LOAD SPEED VALUE FROM DEFENSIVE MAX SPEED TABLE
    ⋮
    1225SET_PLAYER_RUNNING_SPEED:                           ; SET PLAYER SPEED
    1226	LDY #MAX_SPEED                                  ; SET CURRENT PLAYER MAX SPEED = MAX SPEED VALUE
    ⋮
    1229	JSR GET_PLAYER_SKILL                            ; GET PLAYER SKILL ( Y= SKILL INDEX)
    ⋮
    1233	JSR GET_PLAYER_SKILL                            ; GET PLAYER SKILL ( Y= SKILL INDEX)
    ⋮
    
    Bank27_misc.asm lines 1211–1238 at f3bae0e · upstream ↗
    1146@p1_on_defense:                                     ; P1 ON DEFENSE
    ⋮
    1149	LDA TEAM_CONTROL_TYPES                          ; IS P1 PLAYER TYPE = MAN
    1150	AND #$F0                                        ;
    1151	BEQ @set_p1_defensive_skills                       ; YES->SET NORMAL DEFENSE SKILLS
    ⋮
    1153	LDA TEAM_CONTROL_TYPES                          ; IS P2 PLAYER TYPE = COA,COM, SKP
    1154	AND #$0F                                        ;
    1155	BNE @set_p1_defensive_skills                       ; YES->SET NORMAL DEFENSE SKILLS
    ⋮
    1158	JSR SET_DEFENSIVE_SKILLS_WITH_COM_BOOST          ; SET BOOSTED COM DEFENSIVE RS,RP,MS AND NORMAL HP($40 = PLAYER POINTER)
    
    Bank27_misc.asm lines 1146–1158 at f3bae0e · upstream ↗
    1241SET_DEFENSIVE_SKILLS_WITH_COM_BOOST:                ; SET BOOSTED COM DEFENSIVE RS,RP,MS AND NORMAL HP($40 = PLAYER POINTER)
    ⋮
    1244	LDA DEF_MAX_SPEED_VALS,Y                        ; LOAD SPEED VALUE FROM DEFENSIVE MAX SPEED TABLE 
    1245	CLC                                             ;
    1246	ADC CPU_DEF_MS_BOOST                            ; + DEFENSIVE COM MAXIMUM SPEED BOOST
    ⋮
    1251	JSR ADD_COM_DEF_MS_BOOST                                   ; ADD COM DEFENSIVE RS,RP,MS BOOST INDEX, SET TO MAX VALUE IF TO LARGE(A= MAX SPEED INDEX)
    ⋮
    1256	JSR ADD_COM_DEF_MS_BOOST                                   ; ADD COM DEFENSIVE RS,RP,MS BOOST INDEX, SET TO MAX VALUE IF TO LARGE(A= MAX SPEED INDEX)
    
    Bank27_misc.asm lines 1241–1261 at f3bae0e · upstream ↗
    1308ADD_COM_DEF_MS_BOOST:                               ; ADD COM DEFENSIVE SPEED BOOST INDEX, SET TO MAX VALUE IF TO LARGE(A= MAX SPEED INDEX)
    1309	CLC                                             ; = MAX SPEED INDEX
    1310	ADC CPU_DEF_MS_BOOST                            ; +  COM DEFENSIVE SPEED BOOST INDEX
    1311	CMP #MAX_SKILL + 1                               ; IS INDEX < MAX INDEX?
    ⋮
    1314	LDA #MAX_SKILL                                  ; SET MAXIMUM SPEED SKILL INDEX = MAX INDEX
    
    Bank27_misc.asm lines 1308–1314 at f3bae0e · upstream ↗
    5427OFF_MAX_SPEED_VALS:                                                  ; OFFENSIVE_MAX_SPEED_VALUES
    5428	.DB $15, $16, $17, $18, $19, $1A, $1B, $1C
    5429	.DB $1D, $1E, $1F, $20, $21, $22, $23, $24
    ⋮
    5431DEF_MAX_SPEED_VALS:                                                  ; DEFENSIVE_MAX_SPEED_VALUES
    5432	.DB $25, $26, $27, $28, $29, $2A, $2B, $2C
    5433	.DB $2D, $2E, $2F, $30, $31, $32, $33, $34
    
    Bank31_fixed_bank.asm lines 5427–5433 at f3bae0e · upstream ↗
    423RESET_CURRENT_SPEED_RP_TO_INITIAL_VALUES:                          ; INITIALIZE PLAYER RUSHING POWER AND CURRENT SPEED TO DEFAULT VALUES 
    ⋮
    428	LDA RUSHING_POWER_VALUES_TABLE,Y                              ; SET PLAYER RUSHING POWER COUNTER  FROM RUSHING POWER TABLE ADDR  + SKILL INDEX OFFSET
    ⋮
    433	LDA RUNNING_SPEED_VALUES_TABLE,Y                              ; SET PLAYER RUSHING CURRENT SPEED = STARTING SPEED TABLE ADDR + SKILL INDEX OFFSET
    
    Bank21_22_play_commands_on_field_logic.asm lines 423–434 at f3bae0e · upstream ↗
    440UPDATE_RP_CNT_AND_CUR_SPEED_THEN_COLL_CHECK:                      ; CHECK FOR PLAYER MOVING AND UPDATE SPEED. IF MOVING RP= RP - 1
    441	RETURN_PLAYER_ACTIONS_IN_1_FRAME
    ⋮
    452	BNE COLL_CHECK_START                                          ; RUSHING POWER COUNTER > 0 YES->COLLISION CHECK START. 
    ⋮
    459	LDA RUSHING_POWER_VALUES_TABLE,X                              ; SET PLAYER RUSHING POWER COUNTER = FROM RUSHING POWER TABLE ADDR + SKILL INDEX OFFSET
    ⋮
    467	CMP (CURRENT_PLAYER_ADDR),Y                                   ; PLAYER CURRENT SPEED >= MAX SPEED? 
    468	BCS COLL_CHECK_START                                          ; YES->COLLISION CHECK START
    ⋮
    471	CLC                                                           ; NO->PLAYER CURRENT SPEED++
    472	ADC #$01                                                      ; 
    
    Bank21_22_play_commands_on_field_logic.asm lines 440–475 at f3bae0e · upstream ↗
    11366RUSHING_POWER_VALUES_TABLE:                                       ;RUSHING_POWER_VALUES
    11367	.DB $0D,$0C,$0B,$0A,$09,$08,$07,$06,$05,$04,$03,$03,$02,$02,$01,$01
    ⋮
    11369RUNNING_SPEED_VALUES_TABLE:                                       ;RUNNING_SPEED_VALUES
    11370	.DB $0E,$0F,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$1A,$1B,$1C,$1D
    
    Bank21_22_play_commands_on_field_logic.asm lines 11366–11370 at f3bae0e · 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 claim ledger

  3. ^Each side picks one of eight slots. The offense's slot reads a play id (0 to 63) from its playbook, and before the snap the game reads the defense's play from a 64-row table: the row is the offense's play id, and the column is the defense's slot. In all 64 rows, the entry in column id ÷ 8, the play's group, is a defensive play that appears nowhere else in the table, one of 11 such plays (computed from the table by the atlas). The playbook-change screen offers slot k only the plays of group k (ids k × 8 to k × 8 + 7), so for a playbook set there, that column is the slot the offense called.Codebruddog/Tecmo_Super_Bowl_NES_Disassemblyrevised
    How we know
    3061P1_ON_OFF_LOAD_PLAY_INFO_PLAYER_RAM:           ; P1 ON OFFENSE LOAD PLAY INFORMATION INTO PLAYER RAM(A=PLAY SELECTED
    3062   LDX P1_PLAY_CALL                            ; LOAD P1 SLOT CALLED 
    3063   LDA P1_PLAYBOOK_EDIT,X                      ; GET ACTUAL PLAY CALLED USING SLOT AS INDEX TO P1 PLAYBOOK IN SRAM
    ⋮
    3089   TAX                                         ; 
    ⋮
    3092@get_def_reaction_based_on_off_play:   
    ⋮
    3095   LDY P1_PLAY_CALL                            ; LOAD PLAYER 1 PLAY CALL 
    3096   LDA P1_PLAYBOOK_EDIT,Y                      ; GET ACTUAL PLAY
    3097@multiply_by_eight_add_starting_offset:  
    ⋮
    3105   ADC #<DEF_REACTION_START_ADDR               ; = OFFSET PLUS DEFENSIVE REACTION LIST STARTING ADDR  0X1DC10= $BC00 
    ⋮
    3112   LDY P2_PLAY_CALL                            ; SAVE DEFENSIVE PLAY INDEX IN X
    3113   LDA (def_reaction_addr),Y                   ; 
    3114   TAX                                         ; 
    ⋮
    
    Bank19_20_on_field_gameplay_loop.asm lines 3061–3115 at f3bae0e · upstream ↗
    2979DRAW_SUB_PLAYS_IN_SCROLLING_WINDOW:                              ; DRAW SUBSTITUTE PLAYS (A= PLAY SLOT)
    2980	ASL                                                          ; SHIFT BY 8 SINCE 8 PLAYS PER SLOT
    2981	ASL                                                          ;
    2982	ASL                                                          ;
    2983	AND #$38                                                     ; MAKE SURE ADJUSTED PLAY SLOT IS 0 THROUGH 7 
    
    Bank17_18_main_game_loop.asm lines 2979–2983 at f3bae0e · upstream ↗
    2885	LDA current_play_index_in_slot                               ; MAKE SURE PLAY INDEX IS BETWEEN 0 -7 
    2886	AND #$07                                                     ;
    2887	STA current_play_index_in_slot                               ;
    2888	CLC                                                          ;
    2889	ADC MENU_X                                                   ; + PLAY SLOT OFFSET
    2890	STA current_play_id                                                      ; = PLAY ID
    
    Bank17_18_main_game_loop.asm lines 2885–2890 at f3bae0e · upstream ↗
    2812DEFENSIVE_PLAY_INDEX_TABLE:										; DEFENSE REACTION INDEX TO SET OF PLAYER POINTERS 
    2813	.DB $5B,$5A,$5A,$58,$58,$59,$59,$59							; REACTION TO T- FAKE SWEEP	
    ⋮
    2876	.DB $2A,$2A,$29,$29,$2B,$2B,$2B,$22	; REACTIONS TO RED-GUN SLANT
    
    Bank15_faces_playbooks.asm lines 2812–2876 at f3bae0e · 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 claim ledger

  4. ^Reactions 128 and 177 are player scripts used only by the 11 guess-only defensive plays (computed by the atlas over bank 4). Reaction 128 waits for the snap, sets the player's running-speed rating to 15, adds 48 to his max speed and 48 to his hitting power, moves, and then loops a runRush command; reaction 177 stands for 30 frames after the snap and then jumps into reaction 128's boosts. Execution 188, one of the 11, gives reactions 128 to 134 to its first seven players. The script command the disassembly's macro calls boostRS emits $E3, which the command table maps to the routine that adds to max speed.Codebruddog/Tecmo_Super_Bowl_NES_Disassemblyrevised
    How we know
    4811DEFENSE_PLAYER_REACTION_128:
    ⋮
    4814DEFENSE_PLAYER_REACTION_JUMP_059:
    
    Bank5_6_off_def_play_data.asm lines 4811–4819 at f3bae0e · upstream ↗
    5200DEFENSE_PLAYER_REACTION_177:
    
    Bank5_6_off_def_play_data.asm lines 5200–5204 at f3bae0e · upstream ↗
    5281DEFENSE_PLAYER_REACTION_191:
    
    Bank5_6_off_def_play_data.asm lines 5281–5284 at f3bae0e · upstream ↗
    258.MACRO PlayerCommandData.setRS value
    259    .DB $E0
    ⋮
    273.MACRO PlayerCommandData.boostRS boost
    274    .DB $E3
    
    macros/play_data_macros.asm lines 258–276 at f3bae0e · upstream ↗
    350.MACRO PlayerCommandData.boostHP boost
    351    .DB $F7
    
    macros/play_data_macros.asm lines 350–352 at f3bae0e · upstream ↗
    383	.WORD SET_RS_COMMAND_START-1                                       ; EO SET RS
    ⋮
    386	.WORD INCR_DECR_MS_COMMAND_START-1                                 ; E3 BOOST MS
    ⋮
    409	.WORD CHANGE_HITTING_POWER_COMMAND_START-1                         ; F7 BOOST HP 
    
    Bank21_22_play_commands_on_field_logic.asm lines 383–409 at f3bae0e · upstream ↗
    329.MACRO PlayerCommandData.stand time
    330    .DB $F3
    
    macros/play_data_macros.asm lines 329–330 at f3bae0e · upstream ↗
    4321stand_frames = PLAYER_COMMAND_ARG1 
    ⋮
    4323STAND_COMMAND_START:                                              ; F3 STAND (TIME)
    ⋮
    4325	LDA stand_frames                                              ; LOAD # OF FRAMES TO WAIT
    
    Bank21_22_play_commands_on_field_logic.asm lines 4321–4329 at f3bae0e · upstream ↗
    3131SET_RS_COMMAND_START:                                             ; E0 SET RS
    3132	LOAD_CUR_PLAYER_RP_RS_INDEXES 
    3133	AND #$F0                                                      ; MASK OUT RS SKILL INDEX NIBBLE
    3134	ORA new_rs_value                                              ; = OLD RP INDEX + NEW RS INDEX
    
    Bank21_22_play_commands_on_field_logic.asm lines 3131–3135 at f3bae0e · upstream ↗
    3212INCR_DECR_MS_COMMAND_START:                                       ; E3 CHANGE MS (AMOUNT)
    3213	LOAD_CUR_PLAYER_MAX_SPEED
    3214	CLC                                                           ; 
    3215	ADC change_max_speed_value                                    ; + AMOUNT TO BOOST MAX SPEED
    3216	STA (CURRENT_PLAYER_ADDR),Y                                   ; SAVE PLAYER MAX SPEED
    
    Bank21_22_play_commands_on_field_logic.asm lines 3212–3216 at f3bae0e · upstream ↗
    4421CHANGE_HITTING_POWER_COMMAND_START:                               ; F7 BOOST HP
    4422	LDA hp_change_value                                           ; = AMOUNT TO BOOST HP + CURRENT HP
    4423	LDY #HP_INDEX                                                 ;
    4424	CLC                                                           ;
    4425	ADC (CURRENT_PLAYER_ADDR),Y                                   ; 
    
    Bank21_22_play_commands_on_field_logic.asm lines 4421–4428 at f3bae0e · upstream ↗
    3233LOAD_DEFENSIVE_CODE_ADDRESSES:                ; LOAD DEFENSIVE PLAYER POINTERS STARTING ADDRESS
    3234   LDA #SIZE_OF_ALL_PLAY_POINTERS              ; LOAD 11 PLAYERS * 2 BYTES PER PLAYER = 22 PLAY POINTER BYTES/ PLAY
    3235   JSR MULTIPLY_A_TIMES_X                      ;
    3236											   ; PLAY POINTER OFFSET + DEFENSIVE PLAY POINTER STARTING ADDRESS 
    3237   ADD_16BIT_CONST_TO_ZP[val_addr] $A000, play_ptrs_addr
    
    Bank19_20_on_field_gameplay_loop.asm lines 3233–3237 at f3bae0e · upstream ↗
    2252DEFENSIVE_EXECUTION_188:
    
    Bank4_def_spec_play_pointers_data.asm lines 2252–2259 at f3bae0e · 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 claim ledger

  5. ^ abA computer-controlled defense picks its slot at random, 0 to 7, except on third and fourth down. There, with under 25 eighths of a yard to the first-down line (3 yards or less), it calls a run slot (0–3) when a sum of random bytes is under 205 (computed: 80%) and a pass slot (4–7) otherwise. As the atlas reads it, the check meant to favor passes on longer yardage compares the distance's high byte with 57 ($39), and that byte is at most 3 on a 100-yard field, so every longer third or fourth down also gets a random slot.Codebruddog/Tecmo_Super_Bowl_NES_Disassemblyrevised
    How we know
    4342DO_COM_DEFENSIVE_PLAY_CALL:							                                    ; CHECK FOR COM DEFENSIVE PLAY CALL
    ⋮
    4345	LDA DOWN						                                                    ; IS DOWN = 3RD DOWN
    4346	CMP #THIRD_DOWN						                                                ;
    4347	BEQ @check_yards_less_three_third_or_fourth_down					                ; YES->CHECK FOR YDS TO GO <3 ON 3RD ANF 4TH DOWN
    4348	CMP #FOURTH_DOWN						                                            ; IS DOWN = 4TH DOWN
    4349	BEQ @check_yards_less_three_third_or_fourth_down						            ; YES->CHECK FOR YDS TO GO <3 ON 3RD ANF 4TH DOWN
    ⋮
    4354	AND #$07						                                                    ; MAKE RAND # 0 THRU 7 = EQUAL CHANCE OF ANY PLAY
    ⋮
    4359	LDA yards_to_go						                                                ; IS YARDS TO FIRST >= 3
    4360	CMP #$19						                                                    ;
    4361	LDA yards_to_go + 1						                                            ;
    4362	SBC #$00						                                                    ;
    4363	BCS @check_yards_to_go_greater_than_7					                            ; YES->
    ⋮
    
    Bank12_13_sim_update_stats.asm lines 4342–4372 at f3bae0e · upstream ↗
    4123HEAVY_RUN_80PCT_COM_PLAY_CALL:							                                ; HEAVILY RANDOMIZED PLAY CALL 80% RUN, 20% PASS
    ⋮
    4135	CMP #$CD						                                                    ; RAND # < 0XCD = 80% CHANCE RUN PLAY, 20% PASS
    4136	BCC @call_random_com_run_play						                                                    ; YES->CALL RANDOM RUN PLAY
    ⋮
    4139	LDA temp_rand_value + 1							                                    ; MAKE PLAY CALL = RANDOM PASS PLAY CALL(4-7)
    ⋮
    4150	LDA temp_rand_value + 1							                                ; MAKE PLAY CALL = RANDOM RUN PLAY CALL (0-3)
    
    Bank12_13_sim_update_stats.asm lines 4123–4153 at f3bae0e · upstream ↗
    4285CHECK_IF_COM_TAKES_TIMEOUT_ON_DEFENSE:							                       ; COM ON DEFENSE CHECK IF TIMEOUTS NEEDED
    ⋮
    4292	BPL DO_COM_DEFENSIVE_PLAY_CALL						                                ; NO->CHECK FOR COM DEFENSIVE PLAY CALL
    
    Bank12_13_sim_update_stats.asm lines 4285–4296 at f3bae0e · upstream ↗
    3468yards_to_go				= LOCAL_5
    
    Bank12_13_sim_update_stats.asm line 3468 at f3bae0e · upstream ↗
    1864yards_for_first			= LOCAL_5
    ⋮
    1918	SBC LOS_X
    ⋮
    1925	ADC #$50									                                      ; ADD 10 yards 
    ⋮
    1931	CMP #<FRONT_RIGHT_ENDZONE	
    ⋮
    1942	SBC LOS_X
    
    Bank20_playcall.asm lines 1864–1946 at f3bae0e · upstream ↗
    30FRONT_RIGHT_ENDZONE         = $0990
    
    constants_variables/field_locations.asm lines 22–30 at f3bae0e · 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 claim ledger

  6. ^When two computer-controlled players collide, the game compares their hitting power (HP), loaded from a table at 4 per rating step (0 to 60). If neither leads by 16 (4 steps), they hold for 8 frames plus random waits of up to 255, 255, and 63 frames, and one random bit picks the winner. With a lead of 16 to 31, the stronger player wins when a random byte is under 170 (computed: 66%); otherwise they grapple as before. With a lead of 32 or more, the stronger player wins on a byte under 205 (computed: 80%); otherwise they hold 64 frames and then grapple.Codebruddog/Tecmo_Super_Bowl_NES_Disassembly
    How we know
    1263SET_PLAYER_HP_AND_SKIN_COLOR:                       ; SET PLAYER HITTING POWER
    1264	LDY #HITTING_POWER_INDEX                        ; SET SKILL INDEX = HITTING POWER INDEX
    1265	JSR GET_PLAYER_SKILL                            ; GET PLAYER SKILL ( Y= SKILL INDEX)
    1266	TAX                                             ;
    1267	LDA HITTING_POWER_VALS,X                        ; LOAD HITTING POWER FROM HITTING POWER TABLE
    
    Bank27_misc.asm lines 1263–1269 at f3bae0e · upstream ↗
    5435HITTING_POWER_VALS:                                                  ; HITTING_POWER_VALUES:
    5436	.DB $00, $04, $08, $0C, $10, $14, $18, $1C
    5437	.DB $20, $24, $28, $2C, $30, $34, $38, $3C
    
    Bank31_fixed_bank.asm lines 5435–5437 at f3bae0e · upstream ↗
    4COM_VS_COM_OFF_HP_THRESH_1                          = $10                                           ; 25 HP
    5COM_VS_COM_OFF_HP_THRESH_2                          = $20                                           ; 50 HP
    ⋮
    7COM_VS_COM_DEF_HP_THRESH_1                          = $F0                                           ; 25 HP
    8COM_VS_COM_DEF_HP_THRESH_2                          = $E0                                           ; 50 HP
    
    Bank21_22_play_commands_on_field_logic.asm lines 4–8 at f3bae0e · upstream ↗
    55MEDIUM_COM_COM_OL_THROW_CHANCE                      = $AA                                           ; 33% dont throw                                                                  
    56HIGH_COM_COM_OL_THROW_CHANCE                        = $CD 	                                        ; 20% dont throw
    ⋮
    60MEDIUM_COM_COM_DEF_THROW_CHANCE                     = $AA                                           ; 66% chance player busts in vs continue grapple                                                                  
    61HIGH_COM_COM_DEF_THROW_CHANCE                       = $CD 		                                    ; 20% dont throw
    
    Bank21_22_play_commands_on_field_logic.asm lines 55–61 at f3bae0e · upstream ↗
    777COM_V_COM_COLLIDED_START:                                         ; COM VS COM GRAPPLE START 
    778	LOAD_CUR_PLAYER_HITTING_POWER                                 ; PLAYER HP- TARGET HP 
    779	SEC                                                           ; 
    780	SBC (defense_addr),Y                                          ; 
    781	BCC COM_DEF_HP_MORE_THAN_OFF                                  ; DEFENSE HP > OFFENSE HP? YES-> DEFENSE HP > OFFENSE
    ⋮
    787	CMP #COM_VS_COM_OFF_HP_THRESH_1                               ; OFFENSE HP > DEFENSE HP BY >= 4 NOTCHES (25HP)?
    788	BCC COM_VS_COM_LONG_GRAPPLE_START                             ; NO-> COM V COM NORMAL GRAPPLE
    ⋮
    791	CMP #COM_VS_COM_OFF_HP_THRESH_2                               ; OFFENSE HP > DEFENSE HP BY >=8 NOTCHES (50HP)?
    ⋮
    801	CMP #COM_VS_COM_DEF_HP_THRESH_1 +1                            ; DEFENSE HP < 4 NOTCHES GREATER? 
    802	BCS COM_VS_COM_LONG_GRAPPLE_START                             ; YES->COM V COM NORMAL GRAPPLE
    ⋮
    805	CMP #COM_VS_COM_DEF_HP_THRESH_2 +1                            ; DEFENSE HP >= 8 NOTCHES MORE THAN OFFENSE HP
    
    Bank21_22_play_commands_on_field_logic.asm lines 777–810 at f3bae0e · upstream ↗
    817COM_VS_COM_SET_RANDOM_GRAPPLE_TIME:                               ; NORMAL GRAPPLE TIME DELAY START
    818	RETURN_PLAYER_ACTIONS_IN_NUM_FRAMES[frames] 8
    819	JSR UPDATE_RANDOM_1                                           ; UPDATE RANDOM $3B AND LOAD VALUE() = SET FRAMES TO WAIT = RANDOM 0-0xFF FRAMES (0-4.2 sec) 
    ⋮
    824	AND #$3F                                                      ; 
    ⋮
    826	JSR UPDATE_RANDOM_1                                           ; UPDATE RANDOM $3B AND LOAD VALUE() 
    827	BMI DEFENSE_WINS_COM_COM_GRAPPLE                               ; 50%->COM V COM DEFENDER WINS, BUSTS IN WITH OFFENSE RANDOMLY THROWN ON GROUND
    
    Bank21_22_play_commands_on_field_logic.asm lines 817–827 at f3bae0e · upstream ↗
    862MEDIUM_CHANCE_DEF_COM_THROWN:                                     ; OFFENSE HP > DEFENSE BY > 4 NOTCHES <8
    ⋮
    867	JSR UPDATE_RANDOM_3                                           ; UPDATE RANDOM $3D AND LOAD VALUE()
    868	CMP #MEDIUM_COM_COM_OL_THROW_CHANCE                           ; 
    869	BCC @defender_thrown                                          ; 60% -> COM DEFENDER THROWN, OFFENSIVE PLAYER FLATTENED OR STAYS STANDING 
    870	JMP COM_VS_COM_SET_RANDOM_GRAPPLE_TIME                        ; 40% -> COM V COM NORMAL GRAPPLE
    
    Bank21_22_play_commands_on_field_logic.asm lines 862–870 at f3bae0e · upstream ↗
    895HIGH_CHANCE_DEF_COM_THROWN:                                       ; OFFENSE HP > DEFENSE BY 8 NOTCHES
    ⋮
    901	CMP #HIGH_COM_COM_OL_THROW_CHANCE                                                      ; 
    902	BCS DELAY_THEN_NORMAL_GRAPPLE                                 ; 25% ->64(1 SEC) FRAME DELAY THEN JUMP TO NORMAL GRAPPLE
    ⋮
    922DELAY_THEN_NORMAL_GRAPPLE:                                      ; 64 (~1 SEC) FRAME DELAY THEN JUMP TO COM V COM GRAPPLE
    923	RETURN_PLAYER_ACTIONS_IN_NUM_FRAMES[frames] 64
    924	JMP COM_VS_COM_SET_RANDOM_GRAPPLE_TIME                        ; JUMP -> COM V COM NORMAL GRAPPLE
    
    Bank21_22_play_commands_on_field_logic.asm lines 895–924 at f3bae0e · upstream ↗
    926MEDIUM_CHANCE_OFF_COM_THROWN:                                     ; DEFENSE HP > OFFFENSE BY > 4 NOTCHES <8
    ⋮
    932	CMP #MEDIUM_COM_COM_DEF_THROW_CHANCE                          ; 
    933	BCC @offense_thrown                                           ; 66%-> DEFENDER WINS GRAPPLE OFFENSIVE PLAYER THROWN
    ⋮
    958HIGH_CHANCE_OFF_COM_THROWN:                                       ; OFFENSIVE PLAYER THROWN DEFENSE HP > OFFFENSE BY > 8 NOTHCES
    ⋮
    964	CMP #HIGH_COM_COM_DEF_THROW_CHANCE                            ; 
    965	BCS DELAY_THEN_NORMAL_GRAPPLE                                 ; 20% ->(~1 SEC) FRAME DELAY THEN JUMP TO COM V COM GRAPPLE
    
    Bank21_22_play_commands_on_field_logic.asm lines 926–965 at f3bae0e · 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 claim ledger

  7. ^ abAn ordinary collision (not a dive or a chop block) between a human-controlled and a computer-controlled player goes to MAN_VS_COM_POPCORN_CHECK. If the human player's HP is at least 32 higher (8 rating steps), the computer player is thrown at once; otherwise both hold for 64 frames while the game counts the human's A presses, and 2 or more throw the computer player, and fewer throw the human. Between two human players, both players' presses count over the same 64 frames. The defender wins with at least as many presses as the offensive player; if neither pressed, both go down.Codebruddog/Tecmo_Super_Bowl_NES_Disassemblyrevised
    How we know
    530@offense_colliding_defender:                                      ;                                                       ; /OFFENSIVE PLAYER COLLIDING WITH DEFENDER START/
    531	LOAD_CUR_PLAYER_MOVEMENT_STATUS                               ; IS PLAYER DIVING FOR TACKLE/ CHOP BLOCKING?  
    532	AND #(PLAYER_DIVE_TACKLE_BITFLAG+PLAYER_CHOP_BLOCK_BITFLAG)                                                
    ⋮
    535	JMP OFFENSE_DIVING_FOR_TACKLE                                 ; YES->OFFENSE PLAYER DIVING FOR TACKLE COLLISION
    ⋮
    540	JMP OFFENSIVE_CHOP_BLOCK_COLLISION                            ; YES-> OFFENSIVE PLAYER CHOP BLOCK
    ⋮
    548@check_defender_diving_chop_block:                                ; CHECK FOR DEFENDER DIVING OR CHOPPING
    549	LDA (defender_addr),Y                                         ; DOES DEFENDER MOVEMENT = DIVING FOR TACKLE OR CHOP BLOCKING?
    550	AND #(PLAYER_DIVE_TACKLE_BITFLAG+PLAYER_CHOP_BLOCK_BITFLAG)                                              
    551	BEQ START_OF_NORMAL_COLLISION_OFF_DEF                         ; NO-> NORMAL PLAYER COLLISION
    
    Bank21_22_play_commands_on_field_logic.asm lines 530–551 at f3bae0e · upstream ↗
    570START_OF_NORMAL_COLLISION_OFF_DEF:                                ; NORMAL OFF AND DEF PLAYER COLLISION
    ⋮
    574	LDY #<(CHECK_COL_TYPE_MAN_OR_COM-1)                           ; SET COLLISION ADDR = CHECK COLLISION TYPE (MAN,COM)
    
    Bank21_22_play_commands_on_field_logic.asm lines 570–576 at f3bae0e · upstream ↗
    749CHECK_COL_TYPE_MAN_OR_COM:                                        ; CHECK COLLISION TYPE (MAN,COM)                     
    ⋮
    752	AND #PLAYER_MAN_COM_BITFLAG                                   ; 
    753	BEQ @com_vs_com_check                                         ; NO->CHECK FOR MAN DEFENDER
    ⋮
    757	AND #PLAYER_MAN_COM_BITFLAG                                   ; 
    758	BEQ @man_vs_com_jump_popcorn_check                            ; NO->MAN VS COM POPCORN CHECK JUMP
    ⋮
    761	JMP MAN_VS_MAN_GRAPPLE_START                                  ; YES->MAN V MAN GRAPPLE START
    ⋮
    764	JMP MAN_VS_COM_POPCORN_CHECK                                  ; JUMP->MAN VS COM POPCORN CHECK
    ⋮
    766@com_vs_com_check:                                                ; CHECK FOR MAN DEFENDER GRAPPLE
    ⋮
    768	AND #PLAYER_MAN_COM_BITFLAG                                   ; 
    ⋮
    770	JMP PAUSE_COLL_CHECK_RECHECK_COLL_TYPE                         ; *** should never reach here
    
    Bank21_22_play_commands_on_field_logic.asm lines 749–770 at f3bae0e · upstream ↗
    987PAUSE_COLL_CHECK_RECHECK_COLL_TYPE:                               ; *** should never reach here
    988	LDY #<(CHECK_COL_TYPE_MAN_OR_COM-1)                           ; SET COMMAND ADDR = CHECK COLLISION TYPE (MAN,COM)
    989	LDX #>(CHECK_COL_TYPE_MAN_OR_COM-1)                           ; 
    990	JSR UPDATE_LOCAL_PLAYER_COMMAND_ADDR_IF_VALID                          ; LOAD COMMAND ADDRESS AND UPDATE COMMAND COUNTER ( TARGET: $3E $3F)                    
    
    Bank21_22_play_commands_on_field_logic.asm lines 987–991 at f3bae0e · upstream ↗
    10MAN_VS_COM_POPCORN_THRESHOLD		                = $20		                                    ; 50 HP differential	
    
    Bank21_22_play_commands_on_field_logic.asm line 10 at f3bae0e · upstream ↗
    1001MAN_VS_COM_POPCORN_CHECK:                                         ; MAN VS COM POPCORN CHECK
    ⋮
    1003	LDY #HP_INDEX                                                 ; MAN HP - COM HP 
    1004	LDA (CURRENT_PLAYER_ADDR),Y                                   ;   
    1005	SEC                                                           ;
    1006	SBC (com_addr ),Y                                             ; 
    1007	BCC @man_vs_com_grapple_check                                 ; COM HP >MAN? YES->MAN VS COM GRAPPLE CHECK
    1008	CMP #MAN_VS_COM_POPCORN_THRESHOLD                             ; MAN HP 50 HP MORE THAN COM? 
    1009	BCS @com_popcorned_or_outapped                                            ; YES->COM THROWN
    ⋮
    1015	RETURN_PLAYER_ACTIONS_IN_NUM_FRAMES[frames] 64
    1016	LDY #players_taps                                             ; LOAD MAN PRESSES
    1017	LDA (CURRENT_PLAYER_ADDR),Y                                   ; 
    1018	CMP #com_total_taps                                           ; MAN PRESSES > (COM PRESSES = 2)
    ⋮
    
    Bank21_22_play_commands_on_field_logic.asm lines 1001–1019 at f3bae0e · upstream ↗
    998players_taps      = EXTRA_PLAYER_RAM_3
    999com_total_taps    = $02
    
    Bank21_22_play_commands_on_field_logic.asm lines 998–999 at f3bae0e · upstream ↗
    606COUNT_PRESSES_GRAPPLE_IF_MAN:                                     ; SET GRAPPLES PRESSES TO ZERO, CHECK FOR MAN OR COM   
    607	RETURN_PLAYER_ACTIONS_IN_1_FRAME
    608	LDA #$00                                                      ; SET COLLISION PRESSES  =  ZERO
    609	LDY #presses                                                  ; 
    ⋮
    615@count_man_a_presses:                                             ; GRAPPLE COLLISION MAN BUTTON PRESS LOOP                         
    616	RETURN_PLAYER_ACTIONS_IN_1_FRAME                           
    617	JSR GET_PLAYER_JOY_PRESS                                      ; GET P1 OR P2 JOYPAD PRESS()
    ⋮
    619	LDY #presses                                                  ; PRESSES++
    ⋮
    624	JMP @count_man_a_presses                                      ; JUMP->GRAPPLE COLLISION MAN BUTTON PRESS LOOP
    
    Bank21_22_play_commands_on_field_logic.asm lines 606–624 at f3bae0e · upstream ↗
    1043MAN_VS_MAN_GRAPPLE_START:                                         ; MAN V MAN GRAPPLE START
    ⋮
    1047	RETURN_PLAYER_ACTIONS_IN_NUM_FRAMES[frames] 64
    ⋮
    1049	LDY #players_taps                                             ; DEFENSE PRESSES >= OFFENSE PRESSES 
    1050	LDA (defender_addr),Y                                         ; 
    1051	CMP (CURRENT_PLAYER_ADDR),Y                                   ; 
    1052	BCS @defense_wins_man_man_grapple                             ; YES->DEFENSE WINS GRAPPLE
    ⋮
    1060@defense_wins_man_man_grapple:                                    ; DEFENSE WINS MAN GRAPPLE
    1061	TAX                                                           ; DID DEFENSE TIE OFFENSE?  
    1062	BEQ @defense_wins_man_man_grapple_equal_presses               ; YES->DEFENSE WINS GRAPPLE EQUAL PRESSES
    ⋮
    1069@defense_wins_man_man_grapple_equal_presses:                      ; DEFENSE TIES MAN GRAPPLE EQUAL PRESSES
    1070	LDY #<(PLAYER_ON_GRND_CHECK_TACKLE_IF_BALL_CARRIER-1)         ; SET DEFENDER COMMAND ADDR = PLAYER FLATTENED,IF PLAYER BALL CARRIER CHECK FOR TACKLE 
    ⋮
    1074	JMP PLAYER_ON_GRND_CHECK_TACKLE_IF_BALL_CARRIER               ; JUMP->PLAYER FLATTENED,IF PLAYER BALL CARRIER CHECK FOR TACKLE  
    
    Bank21_22_play_commands_on_field_logic.asm lines 1043–1074 at f3bae0e · 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 claim ledger

  8. ^When a pass reaches its target, Tecmo Super Bowl adds the passer's pass control (PC) value, 61 to 91 at 2 per step, to the receiver's reception (REC) value, also 61 to 91. With no defender near the ball, a random byte forced into 128–255, times that sum and divided by 256, gives a roll from half the sum to one less than it; 79 or more is a catch, and less is incomplete. Each of up to three nearby defenders in turn subtracts his interception (INT) value, 51 to 81, from the sum (floored at 0) for a roll made the same way: under 51 is an interception, under 80 is incomplete, and 80 or more passes the ball to the next defender's check. A pass that clears every check is a catch.Codebruddog/Tecmo_Super_Bowl_NES_Disassembly
    How we know
    184COVERED_INTERCEPTION_THRESHOLD		                = $33
    185UNCOVERED_RECEPTION_THRESHOLD		                = $4F						
    186COVERED_RECEPTION_THRESHOLD			                = $50
    187TARGET_NOT_CLOSE_INT_THRESHOLD		                = $0E
    
    Bank21_22_play_commands_on_field_logic.asm lines 184–187 at f3bae0e · upstream ↗
    5675ADD_PASS_CONTROL_SKILL_AND_REC_SKILL:                             ; GET PC TABLE VALUE, REC TABLE VALUE, PC VAL in $DC, PC+REC VAL in $DD()
    ⋮
    5679	JSR GET_PASS_CONTROL_SKILL_VALUE                              ; GET PLAYER PASSING CONTROL INDEX()
    5680	TAY                                                           ; SET  PASSING ABILITY TABLE INDEX
    5681	LDA PASSING_VALUES_TABLE,Y                                    ; LOAD PASS CONTROL ABILITY VALUE FROM PASSING ABILITY TABLE
    5682	STA PASS_CONTROL_VALUE                                                       ; 
    ⋮
    5685	LDY #RECEPTION_INDEX                                          ; SET SKILL INDEX = RECEPTTION
    ⋮
    5687	TAY                                                           ;
    ⋮
    5692	CLC                                                           ; 
    ⋮
    5694	TAY                                                           ;
    ⋮
    5700	LDA RECEPTION_VALUES_TABLE,Y                                  ; LOAD RECEIVING ABILITY VALUE FROM PASSING ABILITY TABLE
    5701	CLC                                                           ;
    5702	ADC PASS_CONTROL_VALUE                                        ; + PASS CONTROL VALUE
    ⋮
    
    Bank21_22_play_commands_on_field_logic.asm lines 5675–5703 at f3bae0e · upstream ↗
    5972GET_PASS_CONTROL_SKILL_VALUE:                                     ; GET PLAYER PASSING CONTROL SKILL VALUE()
    5973	LDY #PASS_CONTROL_INDEX                                       ; LOAD PASS CONTROL SKILL INDEX
    5974	JSR GET_PLAYER_SKILL_OR_FACE                                  ; GET SKILL RATING(A=PLAYER, Y=SKILL TO GET, X=TEAM)
    
    Bank21_22_play_commands_on_field_logic.asm lines 5972–5974 at f3bae0e · upstream ↗
    11465PASSING_VALUES_TABLE:                                             ; PASSING_VALUES
    11466	.DB $3D,$3F,$41,$43,$45,$47,$49,$4B,$4D,$4F,$51,$53,$55,$57,$59,$5B
    ⋮
    11468RECEPTION_VALUES_TABLE:                                           ; RECEPTION_VALUES
    11469	.DB $3D,$3F,$41,$43,$45,$47,$49,$4B,$4D,$4F,$51,$53,$55,$57,$59,$5B
    ⋮
    11471INTERCEPTION_VALUES_TABLE:                                        ; INTERCEPTION_VALUES
    11472	.DB $33,$35,$37,$39,$3B,$3D,$3F,$41,$43,$45,$47,$49,$4B,$4D,$4F,$51
    
    Bank21_22_play_commands_on_field_logic.asm lines 11465–11472 at f3bae0e · upstream ↗
    5481PASS_RESULT_CALCS_NO_DEFENDER_NEAR:	
    ⋮
    5486	LDA RANDOM_3                                                  ; MAKE RAND # 3D RANGE = 0X80 TO 0XFF
    5487	ORA #$80                                                      ; 
    5488	LDX PC_PLUS_RECEPTION                                         ; LOAD PC+REC
    5489	JSR MULTIPLY_A_TIMES_X                                        ; MULTIPLY (A * X) (X-1 to X/2 Stored in $45)
    5490	LDA qb_to_wr_check_value                                      ; RANGE = PC+REC-1 to (PC+REC-1)/2
    5491	CMP #UNCOVERED_RECEPTION_THRESHOLD                            ; VALUE > RECEPTION THRESHOLD
    5492	BCS RECEPTION_NORMAL                                          ; YES->RECEPTION
    
    Bank21_22_play_commands_on_field_logic.asm lines 5481–5492 at f3bae0e · upstream ↗
    5502PASS_RESULT_CALCS_DEFENDER_NEAR:	
    ⋮
    5505	LDX PC_PLUS_RECEPTION                                         ; LOAD X WITH PC+REC TABLE VALS
    5506	LDA PLAYERS_CAN_COLLIDE_BALL_PASS                             ; LOAD 1st PRIORITY DEFENDER 
    5507	JSR PC_REC_INT_ADJUST_BY_RAND_FOR_PASS_OUTCOME                ; PC,REC,INT CALCULATION ROUTINE (A=DEFENDER VALUE, X=PC OR PC+REC)
    5508	BCC @check_2nd_def_wr_near                                    ; 1ST DEFENDER CANT DEFEND->2ND DEFENDER WITH WR CHECK
    ⋮
    5512	CMP #COVERED_INTERCEPTION_THRESHOLD                           ; VALUE < INTERCEPTION THRESHOLD 
    5513	BCC INTERCEPTION_NORMAL                                       ; YES-> BALL INTERCEPTED
    ⋮
    5516	CMP #COVERED_RECEPTION_THRESHOLD                              ; VALUE > RECEPTION THRESHOLD
    5517	BCC BALL_TIPPED_OR_INCOMPLETE                                 ; NO->BALL INCOMPLETE
    ⋮
    5520	LDX PC_PLUS_RECEPTION                                         ; LOAD X WITH PC+REC TABLE VALS
    ⋮
    5522	JSR PC_REC_INT_ADJUST_BY_RAND_FOR_PASS_OUTCOME                ; PC,REC,INT CALCULATION ROUTINE (A=DEFENDER VALUE, X=PC OR PC+REC
    ⋮
    5527	CMP #COVERED_INTERCEPTION_THRESHOLD                           ; VALUE < INTERCEPTION THRESHOLD
    ⋮
    
    Bank21_22_play_commands_on_field_logic.asm lines 5502–5547 at f3bae0e · upstream ↗
    5713PC_REC_INT_ADJUST_BY_RAND_FOR_PASS_OUTCOME:                       ; PC,REC,INT CALCULATION ROUTINE (A=DEFENDER VALUE, X=PC OR PC+REC)
    ⋮
    5722	LDY #INTERCEPTION_INDEX                                       ; SET SKILL INDEX = INTERCEPTTION
    ⋮
    5742	LDA pc_rec_value                                              ; LOAD PC+REC OR JUST PC
    5743	SEC                                                           ;
    5744	SBC INTERCEPTION_VALUES_TABLE,Y                               ; - INT VALUE VALUE FROM INT ABILITY TABLE
    5745	BCS @get_final_calculation_value                              ;
    5746	LDA #$00                                                      ; MAKES ALWAYS AN INT 
    ⋮
    5751	JSR HEAVIER_RANDOMIZE                                         ; MORE RANDOM RANDOM # SAVE INTO A REGISTER()
    5752	ORA #$80                                                      ; MAKE RAND # RANGE (80-FF)
    5753	JSR MULTIPLY_A_TIMES_X                                        ; MULTIPLY (A * X)  
    5754	LDA pc_rec_int_result                                         ; RANGE= X-1 to X/2   X = (PC+REC-INT)
    
    Bank21_22_play_commands_on_field_logic.asm lines 5713–5754 at f3bae0e · upstream ↗
    4054a_register			= LOCAL_8
    ⋮
    4058MULTIPLY_A_TIMES_X:                                                  ; 8 BIT MULTIPLY (A times X)  RESULT IN $44,45
    
    Bank31_fixed_bank.asm lines 4054–4077 at f3bae0e · 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 claim ledger

  9. ^When the target isn't close enough to the ball, nearby defenders can still intercept: each in turn subtracts his INT value from the variable the code names PASS_CONTROL_VALUE and rolls as for a covered pass, intercepting under 14; otherwise the pass is incomplete. This path doesn't call ADD_PASS_CONTROL_SKILL_AND_REC_SKILL, the routine that stores the passer's value in that variable (the close-target and the jump-or-dive paths call it), so it uses whatever player-command argument was last stored there. The disassembly marks it "***MAJOR BUG!!".Codebruddog/Tecmo_Super_Bowl_NES_Disassemblyrevised
    How we know
    5675ADD_PASS_CONTROL_SKILL_AND_REC_SKILL:                             ; GET PC TABLE VALUE, REC TABLE VALUE, PC VAL in $DC, PC+REC VAL in $DD()
    ⋮
    5682	STA PASS_CONTROL_VALUE                                                       ; 
    
    Bank21_22_play_commands_on_field_logic.asm lines 5675–5682 at f3bae0e · upstream ↗
    5451PASS_CONTROL_VALUE				    = PLAYER_COMMAND_ARG1		 ; *** could maybe use local 
    ⋮
    5458	JSR CHECK_PLAYER_CLOSE_ENOUGH_TO_BALL                         ; IS PLAYER CLOSE ENOUGH TO BALL()
    5459	BCC PASS_CALCULATION_TARGET_NOT_CLOSE_TO_BALL                 ; NO->CHECK IF DEFENDERS CAN INTERCEPT TARGET NOT CLOSE ENOUGH()
    ⋮
    5466TARGET_JUMP_DIVE_PASS_CALC_START:                                 ; PASS TARGET JUMP/DIVE CALCULATIONS() IF PASS RESULT ALREADY RET AND SEC & ClV
    ⋮
    5469CHECK_ANY_DEFENDER_CAN_AFFECT_PASS:                                ; CHECK IF ANY DEFENDER CAN IMPACT PASS
    5470	JSR ADD_PASS_CONTROL_SKILL_AND_REC_SKILL                      ; GET PC TABLE VALUE, REC TABLE VALUE, PC VAL in $DC, PC+REC VAL in $DD()
    
    Bank21_22_play_commands_on_field_logic.asm lines 5451–5470 at f3bae0e · upstream ↗
    5552																  ; ***MAJOR BUG!! $DC NOT LOADED WITH PASS CONTROL VALUE
    5553																  ; WILL BE WHATEVER COMMAND ARGUMENT BYTE WAS IN THERE LAST
    5554PASS_CALCULATION_TARGET_NOT_CLOSE_TO_BALL:                        ; CHECK IF DEFENDERS CAN INTERCEPT TARGET NOT CLOSE ENOUGH()
    ⋮
    5563	LDX PASS_CONTROL_VALUE                                        ; LOAD X WITH PC VALUE *** BUG
    5564	LDA PLAYERS_CAN_COLLIDE_BALL_PASS                             ; LOAD 1ST PRIORITY DEFENDER STATUS + ID
    5565	JSR PC_REC_INT_ADJUST_BY_RAND_FOR_PASS_OUTCOME                ; PC,REC,INT CALCULATION ROUTINE (A=DEFENDER VALUE, X=PC OR PC+REC)
    ⋮
    5568	CMP #TARGET_NOT_CLOSE_INT_THRESHOLD                           ; VALUE < NO WR INTERCEPTION THRESHOLD 
    5569	BCC INTERCEPTION_NORMAL                                       ; YES->INTERCEPTION
    ⋮
    5572	LDX PASS_CONTROL_VALUE                                        ; LOAD X WITH PC VALUE *** BUG
    ⋮
    5574	JSR PC_REC_INT_ADJUST_BY_RAND_FOR_PASS_OUTCOME                ; PC,REC,INT CALCULATION ROUTINE (A=DEFENDER VALUE, X=PC OR PC+REC)
    ⋮
    5577	CMP #TARGET_NOT_CLOSE_INT_THRESHOLD                           ; VALUE < NO WR INTERCEPTION THRESHOLD 
    5578	BCC INTERCEPTION_NORMAL                                       ; YES->INTERCEPTION
    ⋮
    
    Bank21_22_play_commands_on_field_logic.asm lines 5552–5588 at f3bae0e · upstream ↗
    187TARGET_NOT_CLOSE_INT_THRESHOLD		                = $0E
    
    Bank21_22_play_commands_on_field_logic.asm line 187 at f3bae0e · 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 claim ledger

Sources

Code