Ninja Gaiden (USA)

Ninja Gaiden (USA) is on a MMC1 board with 131,072 bytes of program. A crawl of 8,000 steps from power-on kept 142 paths that found new code. Played back over 304,842 frames, they executed 12,425 bytes of it, 9 percent.

What the rules named

The 177 routines the runs entered

Every place the game's code was entered, by a call, an interrupt or a jump through a table. The ones a rule named come first, with what the rule saw, and their names in the listing say what they are: a poll, an engine, a drain.

atits name in the listingentered bytimeswhat it is, and the evidence
$80F4 (bank 3)b3_sound_80F4a call261,747
The sound driver: frames it ran in 65,968, writes 745,908
$C028 (bank 7)b7_bank_C028a call196,540
The bank switch: writes 982,017, in the blank 0, while drawing 982,017
$E819 (bank 7)b7_poll_E819a call182,984
The poll: port $4016, reads a frame 15, strobes a frame 3
$80A8 (bank 5)b5_engine_80A8a call97,924
The jump engine: tables 3, jumps through them 97,924
$C02A (bank 7)b7_bank_C02Aa call97,872
The bank switch: writes 489,200, in the blank 0, while drawing 489,200
$F91A (bank 7)b7_nmieach frame (NMI)91,492
The bank switch: writes 2,053,599, in the blank 1,710,668, while drawing 342,931
The palette writers: frames it ran in 91,762, writes 518,962
The scroll writer: frames it ran in 91,762, writes in the blank 182,961
The picture writer: frames it ran in 91,762, writes 766,930, in the blank 766,930, while drawing 0
$823B (bank 4)b4_wait_823Ba call47,404
The wait for the frame: waits on the byte at $001F, times entered 47,402, turns 78,034,703, writes of it under the frame interrupt 91,358, frames in all 92,742
$8181 (bank 4)b4_sprites_8181a call47,382
The sprite writers: frames it ran in 47,382, writes to the sprite page 2,772,141
$F104 (bank 7)b7_wait_F104a call42,884
The wait for the frame: waits on the byte at $001F, times entered 42,971, turns 123,471,937, writes of it under the frame interrupt 91,358, frames in all 92,742
$F5A2 (bank 7)b7_split_F5A2a call42,291
The bank switch: writes 422,419, in the blank 0, while drawing 422,419
The split: frames it ran in 42,289, scroll writes while drawing 84,544, status reads while drawing 30,007,392
$F77C (bank 7)b7_sprites_F77Ca call28,346
The sprite writers: frames it ran in 15,396, writes to the sprite page 441,661
$837A (bank 3)b3_handlers_837Aa call27,258
The handler kept in memory: jumps 27,258, places it landed 15, address copied from $0627
$8013 (bank 5)b5_sprites_8013a call26,117
The sprite writers: frames it ran in 22,355, writes to the sprite page 846,976
$F768 (bank 7)b7_sprites_F768a call25,850
The sprite writers: frames it ran in 25,850, writes to the sprite page 1,627,170
$F0A7 (bank 7)b7_sprites_F0A7a call25,730
The sprite writers: frames it ran in 25,730, writes to the sprite page 418,394
$D8D5 (bank 7)b7_bank_D8D5a call25,337
The bank switch: writes 126,639, in the blank 0, while drawing 126,639
$EB7B (bank 7)b7_handlers_EB7Ba call25,337
The handler kept in memory: jumps 18,804, places it landed 5, address copied from $0000,$006F,$0438
$F1AC (bank 7)b7_bank_F1ACa call25,337
The bank switch: writes 940, in the blank 0, while drawing 940
$F7E4 (bank 7)b7_handlers_F7E4a call24,985
The handler kept in memory: jumps 24,985, places it landed 6, address copied from $005F,$0086,$00A3
$E243 (bank 7)b7_handlers_E243a call20,143
The handler kept in memory: jumps 20,143, places it landed 11, address copied from $0051,$0061
$E144 (bank 7)b7_compare_E144a call12,873
Where two things are compared: instructions 2, pairs of bytes 14, bytes in all 16, times compared 15,934, X positions at $0086,$0454,$0457,$0462,$0463,$0464,$0465,$0466,$0467, Y positions at $008A,$0474,$0477,$0482,$0485,$0486,$0487
$DAA2 (bank 7)b7_compare_DAA2a call7,763
Where two things are compared: instructions 2, pairs of bytes 1, bytes in all 2, times compared 7, X positions at $0086,$04D9
$C014 (bank 7)b7_bank_C014a call6,767
The bank switch: writes 33,824, in the blank 0, while drawing 33,824
$F47E (bank 7)b7_bank_F47Ea call2,377
The bank switch: writes 23,770, in the blank 0, while drawing 23,770
$F5EA (bank 7)b7_bank_F5EAa call1,225
The bank switch: writes 6,125, in the blank 0, while drawing 6,125
$8301 (bank 4)b4_wait_8301a call1,084
The wait for the frame: waits on the byte at $001F, times entered 1,084, turns 3,018,154, writes of it under the frame interrupt 91,358, frames in all 92,742
$818E (bank 6)b6_engine_818Ea call969
The jump engine: tables 1, jumps through them 969
$81E9 (bank 4)b4_bank_81E9a call795
The bank switch: writes 3,975, in the blank 0, while drawing 3,975
$86D2 (bank 4)b4_sprites_86D2a call557
The sprite writers: frames it ran in 557, writes to the sprite page 557
$817D (bank 4)b4_sprites_817Da call523
The sprite writers: frames it ran in 523, writes to the sprite page 32,949
$8328 (bank 4)b4_sprites_8328a call401
The sprite writers: frames it ran in 401, writes to the sprite page 1,604
$880F (bank 4)b4_random_880Fa call246
The random byte: frames it ran in 246, bytes $001D, rotates 2, exclusive-ors 1
$FFDA (bank 7)b7_resetpower-on142
The bank switch: writes 994, in the blank 994, while drawing 0
The sprite writers: frames it ran in 426, writes to the sprite page 36,352
$DE2B (bank 7)b7_compare_DE2Ba call129
Where two things are compared: instructions 1, pairs of bytes 6, bytes in all 7, times compared 129, X positions at $0086,$0462,$0463,$0464,$0465,$0466,$0467
$DE5A (bank 7)b7_compare_DE5Aa call129
Where two things are compared: instructions 1, pairs of bytes 6, bytes in all 7, times compared 129, X positions at $0086,$0462,$0463,$0464,$0465,$0466,$0467
$E902 (bank 7)b7_bank_E902a call120
The bank switch: writes 1,150, in the blank 0, while drawing 1,150
$EAC1 (bank 7)b7_split_EAC1a call120
The bank switch: writes 1,200, in the blank 0, while drawing 1,200
The split: frames it ran in 480, scroll writes while drawing 240, status reads while drawing 88,080
The sprite writers: frames it ran in 480, writes to the sprite page 480
$F8F0 (bank 7)b7_split_F8F0a call120
The bank switch: writes 1,200, in the blank 0, while drawing 1,200
The split: frames it ran in 240, scroll writes while drawing 240, status reads while drawing 82,440
$DE40 (bank 7)b7_compare_DE40a call21
Where two things are compared: instructions 1, pairs of bytes 2, bytes in all 3, times compared 21, X positions at $0086,$0465,$0466
$DECF (bank 7)b7_compare_DECFa call21
Where two things are compared: instructions 3, pairs of bytes 5, bytes in all 7, times compared 25, X positions at $0086,$0465,$0466,$0467, Y positions at $008A,$0486,$0487
$8161 (bank 3)a call282,760
$E792 (bank 7)a call184,855
$BF98 (bank 4)a call97,872
$BFB3 (bank 5)a call96,903
$8000 (bank 3)a call91,483
$82B9 (bank 3)a call55,371
$8003 (bank 5)a table47,382
$8006 (bank 5)a table47,382
$83A9 (bank 4)a call47,382
$83B5 (bank 4)a call47,382
$DFD3 (bank 7)a call32,672
$82E0 (bank 4)a call28,267
$81D7 (bank 6)a call28,219
$81C8 (bank 6)a call27,250
$8193 (bank 5)a call26,117
$80D6 (bank 5)a call25,986
$D85D (bank 7)a call25,730
$DC88 (bank 7)a call25,730
$EB64 (bank 7)a call25,730
$F10D (bank 7)a call25,730
$D710 (bank 7)a call25,337
$D9E4 (bank 7)a call25,337
$E625 (bank 7)a call25,337
$E677 (bank 7)a call25,337
$EFF1 (bank 7)a call25,337
$DD32 (bank 7)a call24,985
$E560 (bank 7)a call24,985
$81A4 (bank 6)a call23,210
$81B5 (bank 6)a call23,210
$81E5 (bank 6)a call23,210
$DD6C (bank 7)a call20,173
$DFE9 (bank 7)a call20,143
$E024 (bank 7)a call20,143
$E054 (bank 7)a call19,545
$E07B (bank 7)a call18,353
$F53E (bank 7)a call14,826
$F568 (bank 7)a call14,826
$C3E1 (bank 7)a table14,580
$DF87 (bank 7)a call14,580
$867F (bank 4)a call14,256
$EC7B (bank 7)a table9,980
$ED0D (bank 7)a table7,431
$87A0 (bank 4)a call7,276
$84F2 (bank 3)a table6,188
$84D7 (bank 3)a table5,282
$8535 (bank 3)a table4,910
$8225 (bank 3)a table4,730
$820A (bank 3)a table4,700
$EEE7 (bank 7)a call4,634
$81F0 (bank 3)a table4,530
$F85D (bank 7)a table4,217
$F86F (bank 7)a table4,188
$F850 (bank 7)a table4,171
$F86A (bank 7)a table4,148
$F83E (bank 7)a table4,140
$F831 (bank 7)a table4,121
$8471 (bank 3)a table3,713
$822F (bank 4)a call2,632
$F62D (bank 7)a call2,421
$83E6 (bank 3)a table2,374
$823A (bank 3)a table2,301
$8205 (bank 3)a table2,265
$83CB (bank 3)a table2,192
$8009 (bank 5)a table2,131
$F2DD (bank 7)a call2,119
$81AA (bank 4)a call1,888
$D5B2 (bank 7)a table1,790
$815D (bank 5)a call1,688
$C431 (bank 7)a table1,515
$C487 (bank 7)a table1,286
$EDB1 (bank 7)a table1,269
$8340 (bank 4)a call1,191
$8398 (bank 4)a call1,191
$8243 (bank 3)a call1,128
$E5B3 (bank 7)a call1,024
$8000 (bank 6)a table969
$8157 (bank 6)a call969
$8166 (bank 6)a call969
$BFB3 (bank 6)a call969
$83A3 (bank 5)a call965
$8192 (bank 4)a call944
$81CF (bank 4)a call944
$81DE (bank 4)a call944
$E2C3 (bank 7)a call923
$F745 (bank 7)a call920
$80DD (bank 5)a call844
$8210 (bank 5)a table823
$8448 (bank 3)a table817
$81FD (bank 4)a call815
$8396 (bank 5)a call809
$84C3 (bank 3)a table631
$85EB (bank 4)a call564
$80BE (bank 4)a call401
$860A (bank 4)a call347
$8407 (bank 3)a table346
$C6B3 (bank 7)a table308
$C466 (bank 7)a table297
$E132 (bank 7)a call293
$868D (bank 4)a call289
$C4BE (bank 7)a table270
$8500 (bank 3)a table176
$850D (bank 3)a table165
$8327 (bank 5)a table156
$E254 (bank 7)a call151
$8000 (bank 4)a call142
$E526 (bank 7)a call142
$8431 (bank 3)a table133
$83FA (bank 3)a table125
$E7DC (bank 7)a call120
$E7E7 (bank 7)a call120
$F0F3 (bank 7)a call120
$E233 (bank 7)a call116
$D97C (bank 7)a call115
$E30A (bank 7)a call115
$F653 (bank 7)a call115
$F6B5 (bank 7)a call115
$851C (bank 3)a table109
$E2AF (bank 7)a call106
$8516 (bank 3)a table97
$E285 (bank 7)a call85
$C3BD (bank 7)a table81
$EE55 (bank 7)a table62
$EE99 (bank 7)a table62
$8296 (bank 5)a table22
$CB37 (bank 7)a call21
$E28F (bank 7)a call17
$C41B (bank 7)a table12
$800C (bank 5)a table8
$8270 (bank 5)a table8
$82B0 (bank 5)a table6
$830D (bank 5)a table6
$D98E (bank 7)a call5
$D989 (bank 7)a call4
$E1BD (bank 7)a call3
$86C1 (bank 4)a call2
$C402 (bank 7)a table2
$C67F (bank 7)a table2

The tables it jumps through

A table of addresses the game picks one from. Some sit right after a call to a jump engine; others are anywhere in the cartridge, and we find them by where the address the game jumped through was loaded from. Some games jump by pushing an address and returning to it, and some keep a table as two, the low bytes of its addresses in one place and the high bytes in another; both are found the same way. An entry is counted as far as the runs saw one taken; the true table may be longer. The last column is the byte of memory whose value picked the entry, where we could follow it: the game's mode, or what one of its objects is doing.

atreachedentriestakenchosen by the byte at
$81E0 (bank 3)through a pointer85$00F8
$838B (bank 3)through a pointer3215$066C, $067C
$820C (bank 5)after a call22$0319
$8221 (bank 5)after a call84
$BFB6 (bank 5)after a call54
$BFB6 (bank 6)after a call11
$F087 (bank 7)through a pointer95$0028, $0094, $043F, $006F
$F8E4 (bank 7)through a pointer66$003E, $0086, $00A3, $005F

The memory its routines share

599 bytes of memory were written by one routine and read by another, and 83 places were reached through an index, which is what a table or a set of object slots in memory looks like.

004080C0$0000$0100$0200$0300$0400$0500$0600$070011→1→111X11X1+1Y1Y111122X2
The console's 2,048 bytes of memory, one row for each 256. A numbered span is a column of one of the object tables drawn below, counted in the same order, as long as the table and filled as it is there. Where a table's columns overlap, its things lie one after another, each with all its properties, so the table is one outline with a mark where each property starts. A dark square is a position a rule saw compared. A tick under a row is one of the 24 busiest shared bytes. The second row is the page the processor keeps its stack in. Reaches through an index that belong to no table are not drawn: the loops that clear memory reach nearly every byte. 1 label is left out where columns sit too close to name each one; the drawings below name them all.

Reaches through an index: those that hold positions, then the longest

frombytes reachedinstructionspositions it holds
$04608176 across
$04508132 across
$04808134 down
$0470862 down
$04D9461 across
$03002562
$02002534
$02032533
$02012532
$02022532
$06271131
$06281131

What travels with a position

Arrays that at least two routines step through together with an array of positions, across the same range. That is what a table of the things on the screen looks like in memory: one array for each property, one slot for each thing. We can say which arrays hold positions, which of the others get added into them, which is what a speed does, which pick the way through a jump table, which is what a state or a kind does, and which are only ever counted down, which is what a timer does. What the rest hold is not named yet.

01234567$0400$0410→$0438→$0440$0448$0450X$0458$0460X$0468+$0470Y$0480Y$0488$0490$0498$04B0
Table 1: 15 arrays of up to 8 slots that 24 routines step through together. Each column is an array at its address and each row a slot, so one thing on the screen is one row across all of them. X and Y are positions, and the darker squares are the slots a rule saw compared. + is added into a position, which is what a speed does. → chose a jump, which is what a state or a kind does. ↓ is only ever counted down, which is what a timer does. A plain outline travels with them and is not named yet.
0123$04D1$04D5$04D9X$04E1
Table 2: 4 arrays of up to 4 slots that 3 routines step through together. Each column is an array at its address and each row a slot, so one thing on the screen is one row across all of them. X and Y are positions, and the darker squares are the slots a rule saw compared. + is added into a position, which is what a speed does. → chose a jump, which is what a state or a kind does. ↓ is only ever counted down, which is what a timer does. A plain outline travels with them and is not named yet.
slotsarraysroutinespositions acrosspositions downadded into themchoosing a jumpcounted downtravelling with them
81524$0450, $0460$0470, $0480$0468$0410, $0438$0400, $0410, $0438, $0440, $0448, $0458, $0468, $0488, $0490, $0498, $04B0
443$04D9$04D1, $04D5, $04E1

The 24 busiest shared bytes

bytereads and writesroutines writingroutines reading
$00F04,924,73336
$00284,816,64046
$00F34,420,21126
$00F24,111,34025
$00003,631,05266
$00F13,494,07936
$00012,904,63166
$00021,509,70866
$0031688,89544
$0030688,89144
$00F4479,80366
$0073469,21766
$00F5453,19166
$0034448,10343
$033F434,80356
$0003415,52745
$0380408,55345
$004E393,40324
$005C386,13533
$001C284,59466
$008C282,22945
$0004268,96766
$0033264,29644
$0032264,27644

This page shows none of the game's bytes. The listing these figures were read from stays with the cartridge.

All the games