Q-bert (USA)

Q-bert (USA) is on a CNROM board with 32,768 bytes of program. A crawl of 6,400 steps from power-on kept 56 paths that found new code. Played back over 251,556 frames, they executed 8,718 bytes of it, 27 percent.

What the rules named

The 227 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
$911Esprites_911Ea call1,304,277
The sprite writers: frames it ran in 81,519, writes to the sprite page 3,237,903
$91ECsprites_91ECa call1,079,301
The sprite writers: frames it ran in 66,686, writes to the sprite page 1,079,299
$8207engine_8207a call282,967
The jump engine: tables 18, jumps through them 282,967
$CE58sound_CE58a call179,428
The sound driver: frames it ran in 45,282, writes 15,987
$CC12poll_CC12a call163,051
The poll: port $4016, reads a frame 16, strobes a frame 4
The poll: port $4017, reads a frame 16, strobes a frame 4
$CAF5nmieach frame (NMI)81,735
The game inside the interrupt: frames it ran in 81,791, frames in all 82,296, the spin is at $CAF2
$90A5drain_90A5a call81,573
The palette writers: frames it ran in 81,573, writes 7,136
The picture writer: frames it ran in 81,573, writes 257,177, in the blank 256,645, while drawing 532
$CB69scroll_CB69a call81,573
The scroll writer: frames it ran in 81,545, writes in the blank 163,090
$8000random_8000a call81,525
The random byte: frames it ran in 80,637, bytes $003C,$003D, rotates 2, exclusive-ors 1
$9292sprites_9292a call81,520
The sprite writers: frames it ran in 81,519, writes to the sprite page 4,137,789
$BA3Ccompare_BA3Ca call11,684
Where two things are compared: instructions 2, pairs of bytes 25, bytes in all 20, times compared 12,986, X positions at $0480,$0482,$0483,$0484,$0485,$0490,$0492,$0493,$0494,$0495, Y positions at $0460,$0462,$0463,$0464,$0465,$0470,$0472,$0473,$0474,$0475
$B39Edispatch_B39Ea table2,654
Where two things are compared: instructions 1, pairs of bytes 6, bytes in all 5, times compared 373, X positions at $0480,$0482,$0483,$0484,$0490
$B4D7dispatch_B4D7a table2,150
Where two things are compared: instructions 3, pairs of bytes 9, bytes in all 9, times compared 4,211, X positions at $0480,$0482,$0490, Y positions at $0460,$0462,$0463,$0464,$0465,$0470
$E88Dsprites_E88Da call971
The sprite writers: frames it ran in 971, writes to the sprite page 971
$B404dispatch_B404a table743
Where two things are compared: instructions 1, pairs of bytes 2, bytes in all 3, times compared 328, Y positions at $0460,$0462,$0470
$CC3Bbank_CC3Ba call194
The bank switch: writes 388, in the blank 4, while drawing 384
$CA85resetpower-on56
The bank switch: writes 112, in the blank 112, while drawing 0
The sprite writers: frames it ran in 81,791, writes to the sprite page 14,336
$CC37bank_CC37a call56
The bank switch: writes 112, in the blank 0, while drawing 112
$9329a call1,160,818
$8452a call664,576
$D3CDa call179,428
$D430a call104,220
$CE35a call98,459
$D4C9a call91,411
$CB9Fa call81,573
$CBB5a call81,530
$CD6Ca call81,530
$CDDAa call81,530
$CE3Ca call81,530
$CBDBa call81,526
$84FDa call81,517
$CBF7a call81,500
$9C73a table50,426
$D20Ea call47,694
$D237a call47,694
$D1A7a call35,214
$D1C6a call35,214
$9CDCa table31,422
$E510a call31,390
$D252a call29,546
$E8B9a call26,880
$E8E0a call26,196
$E85Fa call26,096
$8132a call24,896
$E4E9a call23,441
$E5D4a table22,899
$E611a table21,912
$84F4a call18,620
$8220a call18,021
$84A1a call17,911
$C4FFa call15,395
$C272a call14,309
$D0B7a call14,270
$811Ca table14,095
$802Da table12,958
$D1D3a call12,483
$C1F1a call12,376
$C7C8a call12,213
$A1A4a call11,809
$9EF1a table11,721
$E4C6a call11,721
$C12Ea call11,720
$B9C3a call11,574
$A7C5a call11,552
$A880a call11,552
$B123a call11,552
$C28Ea table11,416
$C29Da call11,416
$C54Aa call10,771
$B17Ea call10,060
$C286a table9,591
$C4E3a call9,133
$C216a table8,155
$C4C4a call8,155
$C55Fa call7,985
$E6D6a table7,508
$C56Aa call7,410
$81B5a call6,436
$9D9Aa table5,600
$CC8Ea call4,767
$BCE7a call4,704
$C555a call4,624
$B1D3a table4,300
$E741a table4,185
$E7A3a call4,185
$D3E7a table4,053
$A8C1a call4,041
$D2BAa table3,854
$80AEa table3,834
$B1B3a table3,712
$BFD9a call3,544
$C243a call2,984
$C268a call2,878
$EF72a call2,801
$EF88a call2,800
$E796a table2,704
$B4F3a table2,605
$84EEa call2,334
$84F6a call2,334
$F01Ba table1,985
$A9B6a call1,957
$D1FDa call1,788
$BFADa call1,772
$9E0Da table1,676
$BC73a call1,568
$BC82a call1,568
$BDCBa call1,568
$BDD9a call1,568
$BDE7a call1,568
$BDF5a call1,568
$C145a call1,492
$C190a call1,492
$C196a call1,492
$E81Aa call1,406
$B4E7a table1,374
$B233a table1,339
$D370a table1,108
$D39Ca call1,000
$A1C9a table962
$D38Fa call856
$D2C1a table806
$C21Fa table787
$C2F7a call786
$E59Aa table784
$E5AFa table784
$B1C3a table709
$CEBEa call674
$E94Da call642
$C2AFa table599
$C33Ea call599
$E575a call594
$CBC3a call584
$C23Ca call580
$A222a table561
$CB89a call533
$E5DFa table495
$E5FAa table492
$9E73a table476
$CD57a call418
$C000a call408
$A217a table384
$B6C0a call381
$D2D4a table379
$E940a call322
$E730a table300
$9E1Fa table297
$F0A6a table256
$814Ca call253
$B73Da call236
$F102a call232
$83E0a call228
$C37Da table215
$EFDAa table200
$E51Da table199
$E918a call198
$83E4a call193
$9E2Ba table174
$F04Ea table148
$D3DAa call144
$D340a table138
$9E23a table132
$8143a call121
$8303a call117
$B31Ea table116
$CC56a call115
$E645a call115
$81D4a call114
$B267a table113
$E70Da table100
$E6E9a table99
$B243a table94
$B37Fa table93
$D2EBa table90
$E77Fa table87
$EFFDa table80
$A2CAa table78
$C448a call72
$F072a table72
$9E27a table70
$B665a table64
$A871a call62
$A913a call62
$A99Ca call62
$AA50a call62
$AA6Aa call62
$83BAa call59
$9E9Da call58
$8157a table56
$8174a table56
$817Fa table56
$9E5Da call56
$BC24a call56
$BE1Ca call56
$CA8Aan interrupt (IRQ)56
$CB53a call56
$9CA8a call55
$B149a call54
$9CE7a table52
$80F2a table50
$8107a table50
$81CFa call50
$81D8a call50
$8236a call43
$8290a call39
$E6FBa table33
$9D20a table30
$8265a call28
$9E41a table28
$9EC8a table28
$BBE2a call28
$C77Aa call28
$B2B3a table27
$B2F7a table27
$EFCCa table25
$EFE5a table25
$C356a table19
$C806a call18
$A1D4a table17
$C219a call15
$C42Fa call15
$E908a call9
$C451a call6
$EFA2a table5
$F037a table4
$C459a table3
$C49Da table2
$CD9Ba call1

Where it waits

Loops a rule named that sit inside a routine and are not themselves a place the code is entered.

atits name in the listingwhat it is, and the evidence
$CAF2spin_CAF2
The idle spin: turns 550,559,895, turns a frame 6,689

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
$801Bafter a call98$0018
$8179after a call11$0090
$9C8Aafter a call149$0034
$9CE1after a call33$0090
$9DD4after a call55
$A1CEafter a call33$0088
$B1A1after a call94$0613, $0614, $0615, $0616
$B1B9after a call44$061B
$B1C9after a call44$061E, $061B
$B1D9after a call55$061C, $061D, $061B
$B239after a call44$061B
$C1F8after a call119$0053
$D457through a pointer217
$E515after a call44$008E
$E59Fafter a call11$008F
$E5D9after a call33$008F
$E6DBafter a call77$008F
$E885after a call44$002E
$EF8Eafter a call1010$060A

The memory its routines share

567 bytes of memory were written by one routine and read by another, and 73 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$07001YX→
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.

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

frombytes reachedinstructionspositions it holds
$046016245 down
$048016155 across
$0470635 down
$0490635 across
$030025639
$070025614
$040025612
$05002561
$02002532
$02012531
$02022531
$02032531

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.

0123456789101112131415$0400+240$0410$0420$0440$0460Y$0470Y$0480X$0490X$0611→$0619→
Table 1: 10 arrays of up to 16 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. A number under a column is how many more bytes that array was reached across than the table is long. 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
161024$0480, $0490$0460, $0470$0611, $0619$0400, $0410, $0420, $0440, $0611, $0619

The 24 busiest shared bytes

bytereads and writesroutines writingroutines reading
$00009,977,12866
$00088,630,69866
$00098,406,23166
$00017,593,10766
$00036,703,81366
$00025,145,87866
$00055,067,35466
$000E3,430,92946
$00042,963,67866
$000C2,501,84423
$000B2,260,33133
$00221,013,18323
$00AB926,22426
$009A608,72166
$00F7489,11223
$00A5440,41766
$000D421,83956
$0032384,95266
$0030376,59056
$0098375,02736
$0099375,02736
$001E311,56866
$009B306,22266
$0601287,42565

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

All the games