Super C
Konami's 1990 NES sequel to Contra, a port of the arcade Super Contra, read through vermiceli's annotated disassembly of the US release.
On this page
The atlas reads Super C through vermiceli’s annotated ca65 disassembly of the US release. Built with the ROM’s assets, it matches the ROM byte for byte after the header. Labels and comments quoted here are vermiceli’s. Nothing has been measured in the ROM yet.
Most of Super C’s rules are Contra’s with the numbers moved. The weapon items are the same seven, but a new gun always drops rapid fire1. The cheat code is a different six presses, Right Left Down Up A B, and raises the starting lives byte from 2 to 9 where Contra’s raises it to 292. A game has 2 continues, not 33, and the extra life thresholds swap, 30,000 and then every 20,0004.
The rank is narrower. Beating the game sets a flag rather than counting loops, and only the spread gun speeds up the enemies5. The jump keeps Contra’s outdoor take-off and gravity, and falls cap at 5 px/frame6.
Mechanics
| Mechanic | Kind | How |
|---|---|---|
| Weapon pickup | Replace | Contra's seven item types, but a new gun always drops rapid fire |
| Cheat code | On the title | Right Left Down Up A B on the title screen: the lives byte starts at 9 instead of 2 |
| Continue | Limited | 2 continues a game, one fewer than Contra |
| Extra life | Repeating | at 30,000 points and every 20,000 after, up to 99 lives |
| Rank | Loops and guns | enemies come faster once the game is beaten and for each player holding the spread gun |
| Jump | One speed | Contra's outdoor 4.06 px/frame, or 3 out of water |
| Gravity | One gravity | Contra's 0.137 px/frame², with falls capped at 5 px/frame |
Every claim about this game, by concept (6)
References
- ^The US NES Super C dispatches a weapon item on its type: M, S, L, and F replace the gun, R sets rapid fire, B sets an invincibility timer to
$80, and the falcon destroys the enemies. A new gun drops rapid fire even when it's the gun already held, where Contra keeps it for the same gun.Codevermiceli/nes-super-c · vermiceli/nes-contra-usrevisedHow we know
411weapon_item_pickup_tbl: 412 .addr weapon_item_pickup ; machine (M) 413 .addr weapon_item_pickup ; spray (S) 414 .addr weapon_item_pickup ; laser (L) 415 .addr weapon_item_pickup ; flame (F) 416 .addr r_weapon_item_pickup ; rapid fire (R) 417 .addr b_weapon_item_pickup ; barrier (B) 418 .addr falcon_weapon_item_pickup ; falcon ⋮ 422 lda #$80 423 sta INVINCIBILITY_TIMER,y ; set player invincible timer to #$80 frames ⋮ 428 jsr destroy_all_enemies ; destroy all appropriate enemies ⋮ 431r_weapon_item_pickup: ⋮
src/bank-3.asm lines 411–445 at be6ccce · upstream ↗ 6933@compare_and_set_weapon: 6934 ldy #$f0 ; y = #$f0 (keep rapid fire flag) ⋮ 6938 beq @set_player_weapon ; keep rapid fire flag (if set) when picking up same weapon 6939 ldy #$e0 ; remove rapid fire flag since picking up different weapon ⋮ 6943 and P1_CURRENT_WEAPON,x ; strip/set rapid fire flag 6944 ora $08 ; merge in rapid fire flag with weapon being picked up 6945 sta P1_CURRENT_WEAPON,x ; set current player's weapon
src/bank7.asm lines 6933–6945 at 687d651 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-21.
Revised after a check by a second AI model, 2026-10-21.
- ^The US NES Super C checks a different code from Contra's on its title screen: six presses, Right Left Down Up A B, against Contra's ten-press Up Up Down Down Left Right Left Right B A. Like Contra, a wrong press locks the check out. The code raises the starting lives byte from 2 to 9, where Contra's raises it from 2 to 29.Codevermiceli/nes-super-c · vermiceli/nes-contra-usrevised
How we know
539; checks for 10 extra lives cheat, i.e. right left down up a b 540extra_lives_cheat_input_check: 541 ldy EXTRA_LIVES_CHEAT_NUM_CORRECT ; load number of correct inputs to 10 extra lives cheat 542 bmi @exit ; exit if failed inputting ⋮ 546 cmp extra_lives_code_tbl,y ; compare input to next valid input for 10 lives cheat 547 bne @mark_failure ; branch if incorrect to mark failure ⋮ 552 lda #$01 553 sta CHEAT_CODE_STATUS ; successfully entered full cheat code, mark success ⋮ 555@mark_failure: 556 lda #$ff 557 sta EXTRA_LIVES_CHEAT_NUM_CORRECT ; mark failure entering code ⋮ 564extra_lives_code_tbl: ⋮
src/bank-1.asm lines 539–565 at be6ccce · upstream ↗ 1154 jsr load_banks_extra_lives_cheat_input_check ; still animating intro, check for 10 extra lives cheatsrc/bank-f.asm line 1154 at be6ccce · upstream ↗ 1504 lda #$02 ; default to 3 lives 1505 ldy CHEAT_CODE_STATUS ; check if 10 lives cheat entered 1506 beq @continue ; branch if not entered ⋮ 1510 lda #$09 ; 10 lives cheat entered, set number of lives to 10 ⋮ 1515 sta PLAYER_NUM_LIVES,x ; set player number of lives
src/bank-f.asm lines 1504–1515 at be6ccce · upstream ↗ 930konami_input_check: ⋮ 938 lda #$ff ; incorrect sequence for Konami code 939 sta KONAMI_CODE_NUM_CORRECT ; since incorrect set KONAMI_CODE_NUM_CORRECT (number of successful inputs) to $ff ⋮ 954konami_code_lookup_table: 955 .byte $08,$08,$04,$04,$02,$01,$02,$01,$40,$80
src/bank7.asm lines 930–955 at 687d651 · upstream ↗ 1165init_player_lives: 1166 lda #$02 ; start off with #$02 lives 1167 ldy KONAMI_CODE_STATUS ; 30-lives code switch ($01 = code activated) 1168 beq init_player_num_lives ; if KONAMI_CODE_STATUS is not set, then just set 2 lives 1169 lda #$1d ; KONAMI_CODE_STATUS active so set lives to #$1d (29 decimal)
src/bank7.asm lines 1165–1169 at 687d651 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-21.
Revised after a check by a second AI model, 2026-10-21.
- ^The US NES Super C allows 2 continues a game, where Contra allows 3: the count is set to 2 at the start, and each game over spends one before offering CONTINUE/END.Codevermiceli/nes-super-c · vermiceli/nes-contra-usrevised
How we know
1484init_player_for_level_a: ⋮ 1489 lda #$02 1490 sta NUM_CONTINUES
src/bank-f.asm lines 1484–1490 at be6ccce · upstream ↗ 2465level_routine_06: 2466 dec LEVEL_ROUTINE_DELAY ; decrement level routine delay 2467 bne game_over_exit ; exit if level delay hasn't elapsed 2468 dec NUM_CONTINUES ; decrement number of continues 2469 bmi restart_game ; branch if no more continues to reset the game 2470 lda #$0a ; store "CONTINUE END" in CPU_GRAPHICS_BUFFER
src/bank-f.asm lines 2465–2470 at be6ccce · upstream ↗ 1322 jsr clear_mid_high_ram 1323 jsr init_player_level_1 ; set level 1, initialize player state, number of lives, player count, player mode, etc.
src/bank-f.asm lines 1322–1323 at be6ccce · upstream ↗ 1478init_player_level_1: 1479 lda #$00
src/bank-f.asm lines 1478–1479 at be6ccce · upstream ↗ 1143init_score_player_lives: ⋮ 1146 lda #$03 ; a = #$03 1147 sta NUM_CONTINUES ; continues remaining
src/bank7.asm lines 1143–1147 at 687d651 · upstream ↗ 3301 dec NUM_CONTINUES ; subtract from number of continues remaining 3302 bmi @no_continues_remaining ; if run out of continues, jump
src/bank7.asm lines 3301–3302 at 687d651 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-21.
Revised after a check by a second AI model, 2026-10-21.
- ^The US NES Super C awards its first extra life at 30,000 points and each later one 20,000 points past the last threshold, the reverse of Contra's 20,000 and 30,000, and caps lives at 99 as Contra does.Codevermiceli/nes-super-c · vermiceli/nes-contra-us
How we know
1516 lda #$30 1517 sta NEXT_1_UP_SCORE_MID,x 1518 lda #$00 1519 sta NEXT_1_UP_SCORE_HI,x ; sets initial score to obtain to get an extra life to 0030000
src/bank-f.asm lines 1516–1519 at be6ccce · upstream ↗ 1757@give_1_up: ⋮ 1759 ldx #$20 1760 lda NEXT_1_UP_SCORE_MID,y 1761 clc ; adding 0020000 to the required score to get the next 1-up
src/bank-f.asm lines 1757–1763 at be6ccce · upstream ↗ 1777 lda PLAYER_NUM_LIVES,x 1778 cmp #$63 ; see if at max number of lives (99 in decimal) 1779 bcc @inc_num_lives 1780 lda #$63 1781 sta PLAYER_NUM_LIVES,x ; set number of lives to #$63 if #$63 or greater
src/bank-f.asm lines 1777–1781 at be6ccce · upstream ↗ 1177 lda #$c8 ; set default high score. #$c8 is 200 decimal 1178 sta EXTRA_LIFE_SCORE_LOW ; starting score for extra life (20,000)
src/bank7.asm lines 1177–1178 at 687d651 · upstream ↗ 1283; every time an extra life is obtained, #$12c is added to points required to get next extra life (300 decimal, 30,000 in game score) ⋮ 1291 lda #$2c ; a = #$2c (12c = 300 decimal) (high byte will be set to #$01 a few lines down) ⋮ 1293@set_extra_life_inc_num_lives: 1294 adc EXTRA_LIFE_SCORE_LOW,y ; add 300 decimal to low byte of score required to get extra life 1295 sta EXTRA_LIFE_SCORE_LOW,y ; player score for extra life - low byte 1296 lda #$01 ; a = #$01
src/bank7.asm lines 1283–1296 at 687d651 · upstream ↗ 1312 cmp #$63 ; compare to #$63 (99 decimal) 1313 bcc @set_num_lives ; can't have more than 99 lives 1314 lda #$63 ; a = #$63 (63 = 99 decimal)
src/bank7.asm lines 1312–1314 at 687d651 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-25.
Checked by a second AI model, 2026-10-21.
Checked by a second AI model, 2026-10-25.
- ^The US NES Super C takes 16 off the delay between random enemies once the game has been beaten and 4 for each living player holding the spread gun. The delay's start is read from an eight-entry per-level table with an index that isn't the level; the disassembly reads it as always
$80, a value the table doesn't hold, and the atlas hasn't confirmed it. Where Contra counts loops up to 3, Super C keeps a beaten-once flag that stays at 1; where Contra reads every gun's strength, Super C counts only the spread gun.Codevermiceli/nes-super-c · vermiceli/nes-contra-usrevisedHow we know
3755enemy_gen_routine_00: 3756 lda CURRENT_LEVEL ; !(BUG) a is immediately overwritten 3757 ; this should probably have been ldy CURRENT_LEVEL 3758 lda level_enemy_gen_delay_tbl,y ; y is actually PRG bank number, e.g. #$33 and not current level 3759 ; this causes the delay to always be #$80 ⋮ 3762 ldy GAME_COMPLETED ; load whether or not the game has been completed 3763 beq @adj_for_difficulty ; branch if haven't beaten the game yet ⋮ 3770 lda #$10 3771 jsr @set_enemy_gen_delay ; subtract #$10 * GAME_COMPLETED from ENEMY_GEN_DELAY ⋮ 3775 ldy ENEMY_DIFFICULTY ; load current difficulty 3776 beq @adv_routine ; branch to not adjust initial enemy generation delay 3777 lda #$04 ; difficulty is non-zero, subtract #$04 * ENEMY_DIFFICULTY from ENEMY_GEN_DELAY
src/bank-0.asm lines 3755–3779 at be6ccce · upstream ↗ 4286level_enemy_gen_delay_tbl: 4287 .byte $7b,$53,$53,$53,$53,$53,$53,$53
src/bank-0.asm lines 4286–4287 at be6ccce · upstream ↗ 165; calculate ENEMY_DIFFICULTY based on number of active players with S weapon ⋮ 172 lda PLAYER_CURRENT_WEAPON,x ; 0 = Regular, 1 = M, 2 = S, 3 = L, 4 = F 173 and #$0f ; strip rapid fire flag 174 cmp #$02 ; compare to S weapon 175 bne @next_player ; move to next player if current player doesn't have S weapon 176 iny ; increment number of players in normal state that have the S weapon ⋮ 181 sty ENEMY_DIFFICULTY ; set enemy difficulty
src/bank-0.asm lines 165–181 at be6ccce · upstream ↗ 2421 lda GAME_COMPLETED ; load whether or not the game has been completed 2422 adc #$00 ; increment game completion count (carry is set) 2423 cmp #$02 ; see if game already completed 2424 bcc @continue ; branch if first time completing game to set value to #$01 2425 lda #$01 ; game already beaten at least once, keep value of #$01 (don't set to #$02)
src/bank-f.asm lines 2421–2431 at be6ccce · upstream ↗ 1736adjust_generation_timer: ⋮ 1742 cmp #$04 ; compare GAME_COMPLETION_COUNT to #$04 1743 bcc @continue ; branch if GAME_COMPLETION_COUNT < #$04 1744 ldy #$03 ; maximum multiplier of increase chance for generating soldier is #$03 ⋮ 1752 ldy PLAYER_WEAPON_STRENGTH ; load player weapon strength (damage strength)
src/bank2.asm lines 1736–1757 at 687d651 · upstream ↗ 4111weapon_strength: 4112 .byte $00 ; Regular = Weak 4113 .byte $02 ; M = Strong 4114 .byte $01 ; F = Medium 4115 .byte $03 ; S = Very Strong 4116 .byte $02 ; L = Strong
src/bank7.asm lines 4111–4116 at 687d651 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-21.
Revised after a check by a second AI model, 2026-10-21.
- ^The US NES Super C keeps Contra's outdoor jump: a take-off speed of
$FB.$F0(4.06 px/frame up) and gravity of$23a frame. Super C caps a fall at 5 px/frame and jumps out of water at$FD.$00(3 px/frame).Codevermiceli/nes-super-c · vermiceli/nes-contra-usrevisedHow we know
1539 ldy #$00 ; default jump velocity index (-4.0625) 1540 lda PLAYER_SURFACE,x ; load the kind of surface the player is standing on 1541 cmp #$04 ; see if player in water 1542 bne @set_init_jump_y_vel ; branch if player not in water 1543 ldy #$02 ; player in water, set Y fractional velocity index ⋮ 1559@apply_gravity: 1560 lda PLAYER_Y_FRACT_VELOCITY,x 1561 clc ; clear carry in preparation for addition 1562 adc #$23 ⋮ 1568 cmp #$05 1569 bcc @continue_jump ; branch if falling velocity is less than #$05 1570 lda #$05 ; player falling very fast, cap falling velocity at #$05
src/bank-0.asm lines 1538–1573 at be6ccce · upstream ↗ 1755player_jump_initial_y_vel_tbl: 1756 .byte $f0,$fb ; player not in water (-4.0625) 1757 .byte $00,$fd ; jumping from water (-3)
src/bank-0.asm lines 1755–1757 at be6ccce · upstream ↗ 4547 lda #$fb ; a = #$fb (-5) 4548 ldy #$f0 ; y = #$f0 (.94)
src/bank7.asm lines 4547–4550 at 687d651 · upstream ↗ 5139apply_gravity: 5140 clc 5141 lda PLAYER_Y_FRACT_VELOCITY,x ; load player's Y fractional velocity 5142 adc #$23 ; add #$23 to Y fractional velocity (.1367 decimal)
src/bank7.asm lines 5139–5142 at 687d651 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-21.
Revised after a check by a second AI model, 2026-10-21.
Sources
Code
- (vermiceli), Michael Miceli. 2026. “Super C (US), annotated disassembly (vermiceli).” Commit be6ccce. vermiceli/nes-super-c @ be6ccce · licence, all uses
- (vermiceli), Michael Miceli. 2026. “Contra (US), annotated disassembly (vermiceli).” Commit 687d651. vermiceli/nes-contra-us @ 687d651 · licence, all uses