Destructible terrain
Level geometry that play changes, from shields worn away a few pixels at a time to bricks that break and walls with holes blown in them.
Destructible terrain is level geometry that play changes: shields that wear away, bricks that break, ground that is dug out or blown into craters. In Space Invaders the shields are pixels on the screen, and a shot’s explosion erases a pattern of them1. In Super Mario Bros. a brick is a tile, there or gone, and only big Mario breaks one2. Red Faction cuts the shape of each explosion out of its 3D walls and floors3.
- Dwarf Fortress (2006). Dwarves dig out any tile the player marks, on any level of a three-dimensional map; mining clears the wall, and channelling takes the floor as well.4,5
- ErodesSpace Invaders (1978). The shields are screen pixels; a shot's explosion pattern is erased from them, and aliens drawn over them overwrite them.6,7,1,8,9
- Dug and refillsLode Runner (1983).10
- Breakable tilesBomberman (1985).11Super Mario Bros. (1985). Big Mario breaks a plain brick he hits from below; small Mario only bumps it, and either size only bumps a ? block.2,12,13,14,15Mega Man 6 (1993). The Power adaptor's punch breaks cracked stone walls.16Infiniminer (2009). The pickaxe digs dirt, ore, gold, and diamonds out a block at a time; rock gives way only to a Sapper's explosives.17,18Minecraft (2009). Every block but a few, such as bedrock, can be broken; a hard one broken with the wrong pickaxe leaves nothing behind.19,20,21
- DeformsScorched Earth (1991).22Worms (1995).23
- StructuralRed Faction (2001).3Battlefield: Bad Company (2008).24
#How it works
#Space Invaders (1978)
The shields are not objects. Each player’s four shields live in a RAM buffer, copied from one 22 × 16 px image, and the game ORs them onto the 1-bit screen at the start of a turn6. Nothing tests for a shield as such. Every shot is drawn with a routine that checks its pixels against what is already lit, and any overlap counts as a hit7.
every step of a shot: # MovePlyShot / HandleAlienShot
erase the shot (AND NOT its pixels)
move it
draw it (OR), noting whether any pixel was already lit
if one was: start the explosion
the explosion: # GameObj1 status 3 / ShotBlowingUp
erase the shot
draw the explosion pattern (OR)
after the blow-up timer: erase the pattern (AND NOT)
Erasing with an inverted AND clears every lit pixel under the pattern, shield pixels included, so the hole is the explosion’s shape. The player’s shot leaves an 8 × 8 px pattern with 38 set bits1. An alien shot leaves a 6 × 8 px pattern of 268. The player’s shot moves 4 px a step and is 4 px long, so it meets every pixel row on its path7.
Aliens erase shields too. The routine that draws an alien stores its bytes over the screen instead of ORing them in, so wherever an alien passes, its own image and blank pixels replace the shield’s9. In a two-player game each player’s shields are copied back to that player’s buffer at the end of a turn, so damage carries over until the next rack6.
#Super Mario Bros. (1985)
Mario’s head is one point, 8 px in from his left edge, tested after the frame’s movement while he moves up25. Only the block under that point can be hit, so when his head spans two blocks the other one is ignored. A block in the solid ranges stops him: his vertical speed becomes 1 px/frame, with no push out of the block26. Bricks, ? blocks, and hidden blocks are hit instead14.
after the frame's move, while moving up: # PlayerBGCollision → PlayerHeadCollision
m = metatile at (x + 8, head y)
if m is nothing or a coin, or Y's low nybble < 4: skip
if m is solid, a bounce is under way, or water: # BlockBounceTimer
y speed = 1
else if big and m is a plain brick: # not in BrickQBlockMetatiles
break it: y speed = -2, cell -> $23, then empty next frame
else:
bump it: y speed = 0, cell -> $23 while the block bounces
start BlockBounceTimer at 16
Big Mario breaks a plain brick; anything else, and anything small Mario hits, is bumped2. A bump sets Mario’s vertical speed to 0 and throws the block up 8 px and back in 14 frames. Its cell then holds a used block, or the brick itself when small Mario hit it13. For 16 frames after any hit, no other block can be bumped or broken27. The bouncing block is a sprite. Collision uses its cell, which holds an invisible solid block until the bounce ends28.
A break scores 50 points and throws four chunks of debris12,29. The chunks start up at 6 and 4 px/frame29. A brick with coins pays out until a timer of 211 to 231 frames runs out30.
#Other games
Lode Runner’s NES booklet lets the player drill only through fissured bricks, and the holes fill in again after a time, killing any guard still inside10. Jimmy Maher puts the refill at ten seconds31. Bomberman’s booklet has bricks that bomb flames dissolve, hiding exits and power-ups, and concrete walls that bombs don’t damage11.
In Scorched Earth, whole classes of weapons remove dirt or add it, and dirt left hanging normally falls22. The Worms manual’s Bazooka damages the terrain, and its Blowtorch and Drill dig through it23.
Red Faction’s Geo-Mod system subtracts a low-polygon shape that mimics the explosion from the world’s geometry3. Battlefield: Bad Company let players destroy parts of walls and vehicles24.
#Quirks
- Big Mario can break the ground. The overworld’s ground block is in the same range as bricks, so the game breaks it like one15.
- A break doesn’t let Mario through. The cell is cleared only after the next frame’s head check, which meets the invisible block and stops the jump one frame later12.
#History
Space Invaders’ shields are the earliest case read in code here1. Ben Lindbergh’s 2024 survey for The Ringer sets 3D destruction against the “primitive environmental mayhem” of Dig Dug, Rampage, and Worms32. Worms’ programmer, Andy Davidson, traces the game to the artillery games of the 8-bit era and to his interest in generating random terrain33.
Red Faction’s lead designer, Alan Lawrance, says that when Volition looked for games with destruction on that scale, “there really wasn’t anything”34. Its lead programmer, John Slagel, had written a crater-bombing game on an IBM PCjr as a teenager35. At DICE, Karl-Magnus Troedsson says destruction came from looking for a way to stand apart36. Alan Kertz says no one was doing it in multiplayer before Battlefield: Bad Company37.
The Legend of Zelda’s NES booklet describes the bomb only as a weapon and leaves hidden doors “a secret”38.
Games
| Game | Year | How | Note |
|---|---|---|---|
| Dwarf Fortress | 2006 | dwarves dig out any tile the player marks, on any level of a three-dimensional map; mining clears the wall, and channelling takes the floor as well | |
| Space Invaders | 1978 | Erodes | the shields are screen pixels; a shot's explosion pattern is erased from them, and aliens drawn over them overwrite them |
| Lode Runner | 1983 | Dug and refills | |
| Bomberman | 1985 | Breakable tiles | |
| Super Mario Bros. | 1985 | Breakable tiles | big Mario breaks a plain brick he hits from below; small Mario only bumps it, and either size only bumps a ? block |
| Mega Man 6 | 1993 | Breakable tiles | the Power adaptor's punch breaks cracked stone walls |
| Infiniminer | 2009 | Breakable tiles | the pickaxe digs dirt, ore, gold, and diamonds out a block at a time; rock gives way only to a Sapper's explosives |
| Minecraft | 2009 | Breakable tiles | every block but a few, such as bedrock, can be broken; a hard one broken with the wrong pickaxe leaves nothing behind |
| Scorched Earth source | 1991 | Deforms | |
| Worms source | 1995 | Deforms | |
| Red Faction source | 2001 | Structural | |
| Battlefield: Bad Company source | 2008 | Structural |
Every claim about this mechanic, by game (36)
References
- ^ abcdA player's shot that hits a shield erases itself, then ORs the 8 × 8 px
ShotExplodingpattern onto the screen around the point of impact; after the blow-up timer counts down from 16,EndOfBlowuperases that pattern with an inverted AND. The erase clears every pixel under the pattern's 38 set bits (computed), shield pixels included, and the first erase had already cleared the shield pixels under the shot itself, so the hole is the explosion's shape plus the shot's last 4 px.CodeComputer Archeology, Space InvadersHow we know
770; Shot blowing up because it left the playfield, hit a shield, or hit another bullet 77103D7: 35 DEC (HL) ; Decrement the timer 77203D8: CA 36 04 JP Z,$0436 ; {code.EndOfBlowup} If done then 77303DB: 7E LD A,(HL) ; Get timer value 77403DC: FE 0F CP $0F ; Starts at 10 ... first decrement brings us here ⋮ 77903E3: CD 52 14 CALL $1452 ; {code.EraseShifted} Erase the sprite ⋮ 78203E8: 34 INC (HL) ; Change 1C90 to 1C91 ⋮ 79203F2: 36 08 LD (HL),$08 ; 202B 8 bytes in size of sprite 79303F4: CD 30 04 CALL $0430 ; {code.ReadPlyShot} Read player shot structure 79403F7: C3 00 14 JP $1400 ; {code.DrawShiftedSprite} Draw sprite and out
content/Arcade/SpaceInvaders/Code.md lines 770–794 at 1adc2a7 · upstream ↗ 836EndOfBlowup: 8370436: CD 30 04 CALL $0430 ; {code.ReadPlyShot} Read the shot structure 8380439: CD 52 14 CALL $1452 ; {code.EraseShifted} Erase the player's shot
content/Arcade/SpaceInvaders/Code.md lines 836–839 at 1adc2a7 · upstream ↗ 2870EraseShifted: 2871; Erases a shifted sprite from screen (like for player's explosion) ⋮ 2878145C: 2F CPL ; Reverse it (erasing bits) 2879145D: A6 AND (HL) ; Erase the bits from the screen
content/Arcade/SpaceInvaders/Code.md lines 2870–2879 at 1adc2a7 · upstream ↗ 4336ShotExploding: 4337; *..**..* 4338; ..****.. 4339; .******. 4340; *.****.. 4341; ..****.* 4342; .*****.. 4343; ..*****. 4344; *..**..* 43451C91: 99 3C 7E 3D BC 3E 7C 99
content/Arcade/SpaceInvaders/Code.md lines 4336–4345 at 1adc2a7 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Checked by a second AI model, 2026-10-22.
- ^ abc
PlayerHeadCollisionbumps the block unless Mario is big and the metatile is missing fromBrickQBlockMetatiles, the list of ? blocks ($C0,$C1), hidden blocks ($5F,$60), and bricks with items ($55–$5E); then it breaks it (smb1/brick-break). So big Mario breaks plain bricks ($51–$53) and bumps the rest, and small Mario bumps everything. Size isPlayerSize, so by the code a crouching big Mario breaks bricks too (not probed). Measured: big Mario, standing, broke a brick and bumped a ? block and a hidden block; small Mario bumped a brick and a ? block.VerifiedXkeeper0/smb1revisedHow we know
6151PlayerHeadCollision: 6152 PHA ; store metatile number to stack 6153 LDA #$11 ; load unbreakable block object state by default 6154 LDX SprDataOffset_Ctrl ; load offset control bit here 6155 LDY PlayerSize ; check player's size 6156 BNE DBlockSte ; if small, branch 6157 LDA #$12 ; otherwise load breakable block object state 6158DBlockSte: 6159 STA Block_State,x ; store into block object buffer
src/prg.asm lines 6151–6159 at 1cc3c92 · upstream ↗ 6168 JSR BlockBumpedChk ; do a sub to check which block player bumped head on ⋮ 6173ChkBrick: 6174 BCC PutMTileB ; if no match was found in previous sub, skip ahead 6175 LDY #$11 ; otherwise load unbreakable state into block object buffer 6176 STY Block_State,x ; note this applies to both player sizes
src/prg.asm lines 6168–6176 at 1cc3c92 · upstream ↗ 6218 LDY Block_State,x ; get block object state 6219 CPY #$11 6220 BEQ Unbreak ; if set to value loaded for unbreakable, branch 6221 JSR BrickShatter ; execute code for breakable brick 6222 JMP InvOBit ; skip subroutine to do last part of code here 6223Unbreak: 6224 JSR BumpBlock ; execute code for unbreakable brick or question block
src/prg.asm lines 6218–6224 at 1cc3c92 · upstream ↗ 6304BrickQBlockMetatiles: 6305 .db $c1, $c0, $5f, $60 ; used by question blocks ⋮ 6308 .db $55, $56, $57, $58, $59 ; used by ground level types 6309 .db $5a, $5b, $5c, $5d, $5e ; used by other level types ⋮ 6318 CLC ; if none match, return with carry clear
src/prg.asm lines 6304–6320 at 1cc3c92 · upstream ↗ Measured by a script in MesenCE 2.2.1 (build 4b8a196), on . It fails if the result disagrees with the claim.
The numbers come from the run; its author, an AI model, checked the script measures what the claim says, 2026-10-22.
Revised after a check by a second AI model, 2026-10-22.
- ^ abcRed Faction's lead designer, Alan Lawrance, told The Ringer that its Geo-Mod system takes a low-polygon shape that mimics an explosion and subtracts it from the world's geometry, floor or wall, leaving a hole; the team wanted to go beyond destroying a chair, a barrel, or a crate to destroying walls, the ground, or a structure.InterviewLindbergh, Destructible Environments, The Ringer (2024)
How we know
We take a low-[polygon] shape that mimics the explosion, and that shape gets subtracted from the world. … And you, on the fly, modify that geometry and leave a hole there.
paragraph opening "Here’s how Lawrance explains the Geo-Mod system" · archived copy ↗ We just wanted to take that beyond that and actually destroy the walls, or the ground, or bring down a structure.
Red Faction section · archived copy ↗ The quote matches our archived copy.
Checked by a second AI model, 2026-10-22.
- ^In version 53.16, as the Dwarf Fortress Wiki describes it, the Designations menu marks tiles for dwarves to work: mining, wood cutting, plant gathering, stone detailing and other jobs, by rectangle, by painting, or for some designations as a box across z-levels. Each designation takes a priority from 1 (highest) to 7, and can be placed in blueprint mode, which dwarves don't undertake, to plan work ahead. A Mine designation needs a dwarf with the Mining labor.WikiDwarf Fortress Wiki, "Designations menu"revised
How we know
provides the means to mark tiles with various designations including mining, wood cutting, plant gathering, stone detailing as well as removing constructions, controlling traffic and other miscellaneous designations. … You can also choose to "paint" an area (B), which lets you specifically designate tiles one by one. … Depending on the designation, this also works across z-levels, allowing 3-dimensional designations in the shape of a cuboid. … All designations can be prioritized, with 1 being the highest priority and 7 being the lowest. … They also can be assigned as "Blueprint only", which is similar to the job being suspended, as it marks tiles in a blue-colored square. This is useful for planning out designations and rooms without dwarves suddenly moving in to do anything yet.
opening paragraph · archived copy ↗ Dwarves will not actually undertake blueprint mode designations. This can be used to plan future projects
Blueprint mode · archived copy ↗ Mark tiles to be mined out. Removing stone/soil walls and leaving stone/soil floors. May leave stone/ore/gems. (req. Mining labor)
Designations Menu, Mine (mm) · archived copy ↗ Checked against the evidence by its author, an AI model, 2026-10-26.
Revised after a check by a second AI model, 2026-10-26.
- ^The wiki, describing version 53.16, divides each layer of the three-dimensional map into a wall part and a floor part. Mining removes the wall and leaves the floor; channelling removes the floor too, opening the tile to the layer above, and turns a wall below into an upward ramp.WikiDwarf Fortress Wiki, "Mining"
How we know
Each layer in the three-dimensional Dwarf Fortress map consists of two parts: a wall-part, and a floor-part. Mining a tunnel removes the wall-part but leaves the floor-part in place. Channeling removes the floor-part as well, leaving open space above, and if a wall-part exists below, it becomes an upward ramp.
Understanding digging · archived copy ↗ Checked against the evidence by its author, an AI model, 2026-10-26.
Checked by a second AI model, 2026-10-26.
- ^ abcThe shields are pixels in the 1-bit screen bitmap, not objects. Each player has a RAM buffer of four copies of the 44-byte
ShieldImage, 22 rows of 2 bytes, a 22 × 16 px shape of 294 lit pixels (computed);RestoreShieldsORs the buffer onto the screen, the four shields with 23 rows between them (45 from start to start), and in a two-player gameRememberShieldscopies them from the screen back into the player's buffer, so each player keeps their own damage. The buffers are redrawn from the image at the start of a game and with each new rack.CodeComputer Archeology, Space InvadersrevisedHow we know
41301F8: 0E 04 LD C,$04 ; Going to draw 4 shields 41401FA: 11 20 1D LD DE,$1D20 ; Shield pixel pattern 41501FD: D5 PUSH DE ; Hold the start for the next shield 41601FE: 06 2C LD B,$2C ; 44 bytes to copy
content/Arcade/SpaceInvaders/Code.md lines 413–420 at 1adc2a7 · upstream ↗ 448CopyShields: 449; A is 1 for screen-to-buffer, 0 for to buffer-to-screen 450; HL is screen coordinates of first shield. There are 23 rows between shields. ⋮ 4540221: 01 02 16 LD BC,$1602 ; 22 rows, 2 bytes/row (for 1 shield pattern) 4550224: 21 06 28 LD HL,$2806 ; Screen coordinates
content/Arcade/SpaceInvaders/Code.md lines 448–455 at 1adc2a7 · upstream ↗ 3977RestoreShields: 3978; Logically OR the player's shields back onto the playfield ⋮ 39861A6C: B6 OR (HL) ; OR with screen
content/Arcade/SpaceInvaders/Code.md lines 3977–3986 at 1adc2a7 · upstream ↗ 2906RememberShields: 2907; In a multi-player game the player's shields are block-copied to and from RAM between turns.
content/Arcade/SpaceInvaders/Code.md lines 2906–2907 at 1adc2a7 · upstream ↗ 4563ShieldImage: 4564; Shield image pattern. 2 x 22 = 44 bytes.
content/Arcade/SpaceInvaders/Code.md lines 4563–4590 at 1adc2a7 · upstream ↗ 17370A2A: CD F5 01 CALL $01F5 ; {code.DrawShieldPl2} Draw shields for player 2 17380A2D: CD 04 19 CALL $1904 ; {code.InitAliensP2} Initalize aliens for player 2 ⋮ 17410A33: CD EF 01 CALL $01EF ; {code.DrawShieldPl1} Draw shields for player 1 17420A36: CD C0 01 CALL $01C0 ; {code.InitAliens} Initialize aliens for player 1
content/Arcade/SpaceInvaders/Code.md lines 1737–1742 at 1adc2a7 · upstream ↗ 136707CB: CD EF 01 CALL $01EF ; {code.DrawShieldPl1} Draw shields for player-1 136807CE: CD F5 01 CALL $01F5 ; {code.DrawShieldPl2} Draw shields for player-2
content/Arcade/SpaceInvaders/Code.md lines 1367–1368 at 1adc2a7 · upstream ↗ 33The raster resolution is 256x224 at 60Hz. The monitor is rotated in the cabinet 90 degrees counter-clockwise. ⋮ 35The screens pixels are on/off (1 bit each). 256*224/8 = 7168 (7K) bytes.
content/Arcade/SpaceInvaders/Hardware.md lines 33–35 at 1adc2a7 · 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.
- ^ abcNothing tests for shields as such. Every shot is drawn with
DrawSprCollision, which ANDs each byte of the shifted sprite with the screen before ORing it in and sets the collision flag if any pixel was already lit, so a shot hits a shield when its newly drawn sprite overlaps a lit shield pixel. The player's shot is 1 px wide and 4 px long and moves 4 px a step, so it is tested against every pixel row on its path (computed). A player's shot that collides below the rack takes status 3, the code for a hit on something other than an alien.CodeComputer Archeology, Space InvadersHow we know
2928DrawSprCollision: ⋮ 293814A0: A6 AND (HL) ; Any bits from pixel collide with bits on screen? 293914A1: CA A9 14 JP Z,$14A9 ; {} No ... leave flag alone 294014A4: 3E 01 LD A,$01 ; Yes ... set ... 294114A6: 32 61 20 LD ($2061),A ; {ram.collision} ... collision flag 294214A9: F1 POP AF ; Restore the pixel pattern 294314AA: B6 OR (HL) ; OR it onto the screen
content/Arcade/SpaceInvaders/Code.md lines 2928–2954 at 1adc2a7 · upstream ↗ 805MovePlyShot: ⋮ 8100410: CD 52 14 CALL $1452 ; {code.EraseShifted} Erase the sprite from the screen ⋮ 8140416: 3A 2C 20 LD A,($202C) ; {ram.shotDeltaX} DeltaX for shot 8150419: 85 ADD A,L ; Move the shot ... ⋮ 818041E: CD 91 14 CALL $1491 ; {code.DrawSprCollision} Draw sprite with collision detection
content/Arcade/SpaceInvaders/Code.md lines 805–826 at 1adc2a7 · upstream ↗ 4319PlayerShotSpr: 43201C90: 0F ; ++++....
content/Arcade/SpaceInvaders/Code.md lines 4319–4320 at 1adc2a7 · upstream ↗ 40741B20: 00 00 00 BB 03 00 10 90 1C 28 30 01 04 00 FF FFcontent/Arcade/SpaceInvaders/Code.md line 4074 at 1adc2a7 · upstream ↗ 30081500: B8 CP B ; Compare to shot's coordinate 30091501: D2 30 15 JP NC,$1530 ; {} Outside the rack-square ... do miss explosion
content/Arcade/SpaceInvaders/Code.md lines 3008–3009 at 1adc2a7 · upstream ↗ 3058; Player shot leaving playfield, hitting shield, or hitting an alien shot 30591530: 3E 03 LD A,$03 ; Mark ... 30601532: 32 25 20 LD ($2025),A ; {ram.plyrShotStatus} ... player shot hit something other than alien
content/Arcade/SpaceInvaders/Code.md lines 3057–3060 at 1adc2a7 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Checked by a second AI model, 2026-10-22.
- ^ abAn alien shot ends when its newly drawn sprite collides with any lit pixel, or when it falls below the playfield; a collision at the player's height kills the player instead. Its blow-up timer starts at 4: on the first tick
ShotBlowingUperases the shot and draws the 6 × 8 pxAShotExplopattern, and on the tick that reaches 0 it erases that pattern with an inverted AND, so a shield loses the pattern's 26 pixels (computed) plus those under the shot itself.CodeComputer Archeology, Space InvadersHow we know
109805F0: CD 6C 06 CALL $066C ; {} Draw the alien shot 109905F3: 3A 7B 20 LD A,($207B) ; {ram.alienShotYr} Shot's Y coordinate 110005F6: FE 15 CP $15 ; Still in the active playfield? 110105F8: DA 12 06 JP C,$0612 ; {} No ... end it 110205FB: 3A 61 20 LD A,($2061) ; {ram.collision} Did shot collide ... ⋮ 1111060E: 97 SUB A ; Flag that player ... 1112060F: 32 15 20 LD ($2015),A ; {ram.playerAlive} ... has been struck ⋮ 11150615: F6 01 OR $01 ; ... start shot ...
content/Arcade/SpaceInvaders/Code.md lines 1098–1116 at 1adc2a7 · upstream ↗ 1149ShotBlowingUp: 1150; Alien shot is blowing up ⋮ 11540649: FE 03 CP $03 ; First tick, 4, we draw the explosion 1155064B: C2 67 06 JP NZ,$0667 ; {} After that just wait 1156064E: CD 75 06 CALL $0675 ; {} Erase the shot 11570651: 21 DC 1C LD HL,$1CDC ; Alien shot ... ⋮ 1165065F: 3E 06 LD A,$06 ; Alien shot descriptor ... 11660661: 32 7D 20 LD ($207D),A ; {ram.alienShotSize} ... size 6 11670664: C3 6C 06 JP $066C ; {} Draw alien shot explosion ⋮ 11710669: C3 75 06 JP $0675 ; {} Erase the explosion and out ⋮ 11750672: C3 91 14 JP $1491 ; {code.DrawSprCollision} Draw shot and out ⋮ 1179067B: C3 52 14 JP $1452 ; {code.EraseShifted} Erase the shot and out
content/Arcade/SpaceInvaders/Code.md lines 1149–1179 at 1adc2a7 · upstream ↗ 4454AShotExplo: 4455; .*.*..*. 4456; *.*.*... 4457; .*****.* 4458; ******.. 4459; .****.*. 4460; *.*..*.. 44611CDC: 4A 15 BE 3F 5E 25
content/Arcade/SpaceInvaders/Code.md lines 4454–4461 at 1adc2a7 · upstream ↗ 40751B30: 00 00 02 76 04 00 00 00 00 00 04 EE 1C 00 00 03content/Arcade/SpaceInvaders/Code.md line 4075 at 1adc2a7 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Checked by a second AI model, 2026-10-22.
- ^ abAliens that reach the shields erase them.
DrawSprite, which draws each alien, stores the shifted sprite bytes over the screen instead of ORing them in, both bytes of each of its 16 rows, so wherever an alien is drawn the shield pixels in those bytes are replaced by the alien's image and its blank pixels. The disassembly's comment onCodeBug1describes a lone alien that "enters the players shields on the lower left where it begins to eat them".CodeComputer Archeology, Space InvadersHow we know
3198DrawSprite: 3199; Draw sprite at [DE] to screen at pixel position in HL ⋮ 320815DC: DB 03 IN A,($03) ; {hard.SHFT_IN} Read back shifted amount 320915DE: 77 LD (HL),A ; Shifted sprite to screen ⋮ 321415E4: DB 03 IN A,($03) ; {hard.SHFT_IN} Read back remainder of previous 321515E6: 77 LD (HL),A ; Write remainder to adjacent
content/Arcade/SpaceInvaders/Code.md lines 3198–3215 at 1adc2a7 · upstream ↗ 235012E: 2A 0B 20 LD HL,($200B) ; {ram.alienPosLSB} Pixel position 2360131: 06 10 LD B,$10 ; 16 rows in alien sprites 2370133: CD D3 15 CALL $15D3 ; {code.DrawSprite} Draw shifted sprite
content/Arcade/SpaceInvaders/Code.md lines 235–237 at 1adc2a7 · upstream ↗ 3023; The entire rack of aliens is based on the lower left alien. Imagine all aliens are dead except the 3024; upper left. It wiggles down the screen and enters the players shields on the lower left where it begins
content/Arcade/SpaceInvaders/Code.md lines 3023–3026 at 1adc2a7 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Checked by a second AI model, 2026-10-22.
- ^ abThe NES Lode Runner booklet says the player may drill only through fissured bricks, not solid surfaces, and that drilled holes fill in again after a period of time; guards caught in a hole when it refills die and are replaced by new guards at the top of the screen.ManualLode Runner NES manual
How we know
may dig through fissured bricks only, not … that you've drilled will fill in again after a … when they refill will die and be replenished … by new guards at the top of the screen.
p. 4 · archived copy ↗ The quote matches our archived copy.
Checked by a second AI model, 2026-10-22.
- ^ abThe NES Bomberman booklet describes two kinds of wall: bricks, which the flames of exploding bombs dissolve and which hide the exitways and power-up panels, and concrete, which bomb fire doesn't damage, so Bomberman can shelter behind it.ManualBomberman NES manual
How we know
These dissolve when hit by the flames of exploding bombs. … Hidden within the bricks are exitways and “power-up” panels, so it is wise
p. 4, BRICKS · archived copy ↗ Concrete walls aren't damaged by bomb fires, so Bomberman
p. 4, CONCRETE · archived copy ↗ The quote matches our archived copy.
Checked by a second AI model, 2026-10-22.
- ^ abcBreaking a brick (
BrickShatter) sets Mario's vertical speed byte to −2, adds 50 points, spawns debris (smb1/brick-debris), and flags the cell, which holds$23meanwhile, to be cleared to 0. The clearing comes on the next frame'sBlockObjMT_Updater, after that frame'sPlayerBGCollision, so the next frame's head check still meets$23and sets the speed to 1: a break stops the jump one frame later, 1 or 2 px higher (computed), not passing through. Measured: 1 px higher, speed 1, and the cell 0 by the end of that frame, with a second brick stacked above never reached.VerifiedXkeeper0/smb1How we know
6324BrickShatter: 6325 JSR CheckTopOfBlock ; check to see if there's a coin directly above this block 6326 LDA #Sfx_BrickShatter 6327 STA Block_RepFlag,x ; set flag for block object to immediately replace metatile 6328 STA NoiseSoundQueue ; load brick shatter sound 6329 JSR SpawnBrickChunks ; create brick chunk objects 6330 LDA #$fe 6331 STA Player_Y_Speed ; set vertical speed for player 6332 LDA #$05 6333 STA DigitModifier+5 ; set digit modifier to give player 50 points
src/prg.asm lines 6324–6334 at 1cc3c92 · upstream ↗ 6170 LDY PlayerSize ; check player's size 6171 BNE ChkBrick ; if small, use metatile itself as contents of A 6172 TYA ; otherwise init A (note: big = 0)
src/prg.asm lines 6170–6172 at 1cc3c92 · upstream ↗ 6160 JSR DestroyBlockMetatile ; store blank metatile in vram buffer to write to name tablesrc/prg.asm line 6160 at 1cc3c92 · upstream ↗ 6455 LDA VRAM_Buffer1 ; if vram buffer already being used here, 6456 BNE NextBUpd ; branch to move onto next block object
src/prg.asm lines 6451–6470 at 1cc3c92 · upstream ↗ Measured by a script in MesenCE 2.2.1 (build 4b8a196), on . It fails if the result disagrees with the claim.
The numbers come from the run; its author, an AI model, checked the script measures what the claim says, 2026-10-22.
Checked by a second AI model, 2026-10-22.
- ^ abA bump (
BumpBlock) sets Mario's vertical speed byte to 0, keeping the fraction, and starts a block object at the block's row moving up at 2 px/frame under a gravity of$50/256 px/frame². The object moves on the hit frame itself, after the player; measured against its row, it reads −2, −4, −6, −7, −7, −8, −8, −8, −7, −6, −5, −4, −2, 0 px on the hit frame and the 13 after, and it ends when its Y's low nybble is under 5. The block's cell holds$23from the hit frame, and the next frame'sBlockObjMT_Updaterwrites the block back: a used block ($C4) for ? blocks, hidden blocks, and item bricks, the metatile itself for a plain brick or ground block that small Mario hit. Measured: the cell held$23for 14 frames.VerifiedXkeeper0/smb1How we know
6249BumpBlock: 6250 JSR CheckTopOfBlock ; check to see if there's a coin directly above this block ⋮ 6256 STA Player_Y_Speed ; init player's vertical speed 6257 LDA #$fe 6258 STA Block_Y_Speed,x ; set vertical speed for block object
src/prg.asm lines 6249–6258 at 1cc3c92 · upstream ↗ 6170 LDY PlayerSize ; check player's size 6171 BNE ChkBrick ; if small, use metatile itself as contents of A 6172 TYA ; otherwise init A (note: big = 0) ⋮ 6177 LDA #$c4 ; load empty block metatile into A for now ⋮ 6195PutMTileB: 6196 STA Block_Metatile,x ; store whatever metatile be appropriate here 6197 JSR InitBlock_XY_Pos ; get block object horizontal coordinates saved 6198 LDY $02 ; get vertical high nybble offset 6199 LDA #$23 6200 STA ($06),y ; write blank metatile $23 to block buffer 6201 LDA #$10 6202 STA BlockBounceTimer ; set block bounce timer
src/prg.asm lines 6170–6203 at 1cc3c92 · upstream ↗ 6434 LDA Block_Y_Position,x ; get vertical coordinate 6435 AND #$0f ; mask out high nybble 6436 CMP #$05 ; check to see if low nybble wrapped around 6437 PLA ; pull state from stack 6438 BCS UpdSte ; if still above amount, not time to kill block yet, thus branch 6439 LDA #$01 6440 STA Block_RepFlag,x ; otherwise set flag to replace metatile
src/prg.asm lines 6430–6444 at 1cc3c92 · upstream ↗ 6619ImposeGravityBlock: 6620 LDY #$01 ; set offset for maximum speed 6621 LDA #$50 ; set movement amount here
src/prg.asm lines 6619–6623 at 1cc3c92 · upstream ↗ 4103 JSR BlockObjMT_Updater ; replace block objects with metatiles if necessary ⋮ 4109 JSR BlockObjectsCore ; process first block object
src/prg.asm lines 4101–4109 at 1cc3c92 · upstream ↗ 6451BlockObjMT_Updater: ⋮ 6455 LDA VRAM_Buffer1 ; if vram buffer already being used here, 6456 BNE NextBUpd ; branch to move onto next block object 6457 LDA Block_RepFlag,x ; if flag for block object already clear, ⋮ 6466 LDA Block_Metatile,x ; get metatile to be written 6467 STA ($06),y ; write it to the block buffer
src/prg.asm lines 6451–6470 at 1cc3c92 · upstream ↗ Measured by a script in MesenCE 2.2.1 (build 4b8a196), on . It fails if the result disagrees with the claim.
The numbers come from the run; its author, an AI model, checked the script measures what the claim says, 2026-10-22.
Checked by a second AI model, 2026-10-22.
- ^ ab
CheckForSolidMTilessplits what a head can meet by the metatile's top two bits: at or above$10,$61,$88, or$C4in its group is solid (smb1/head-solid); below is hit (PlayerHeadCollision). The collision map stores nothing below$10,$51,$88, and$C0in the same groups, so the hit kinds are$51–$60(bricks, the cracked-rock ground, bricks with items, hidden blocks) and$C0–$C1(? blocks); a used block ($C4), the solid blocks from$61, and pipes are solid.CodeXkeeper0/smb1How we know
11588SolidMTileUpperExt: 11589 .db $10, $61, $88, $c4 ⋮ 11591CheckForSolidMTiles: 11592 JSR GetMTileAttrib ; find appropriate offset based on metatile's 2 MSB 11593 CMP SolidMTileUpperExt,x ; compare current metatile with solid metatiles
src/prg.asm lines 11588–11594 at 1cc3c92 · upstream ↗ 2801 CMP BlockBuffLowBounds,y ; check for certain values depending on bits set 2802 BCS StrBlock ; if equal or greater, branch 2803 LDA #$00 ; if less, init value before storing ⋮ 2818BlockBuffLowBounds: 2819 .db $10, $51, $88, $c0
src/prg.asm lines 2799–2819 at 1cc3c92 · upstream ↗ 1634 .db $45, $47, $45, $47 ; breakable brick w/ line 1635 .db $47, $47, $47, $47 ; breakable brick 1636 .db $45, $47, $45, $47 ; breakable brick (not used) 1637 .db $b4, $b6, $b5, $b7 ; cracked rock terrain 1638 .db $45, $47, $45, $47 ; brick with line (power-up) ⋮ 1649 .db $24, $24, $24, $24 ; hidden block (1-up) 1650 .db $ab, $ac, $ad, $ae ; solid block (3-d block)
src/prg.asm lines 1634–1651 at 1cc3c92 · upstream ↗ 1676Palette3_MTiles: 1677 .db $53, $55, $54, $56 ; question block (coin) 1678 .db $53, $55, $54, $56 ; question block (power-up) 1679 .db $a5, $a7, $a6, $a8 ; coin 1680 .db $c2, $c4, $c3, $c5 ; underwater coin 1681 .db $57, $59, $58, $5a ; empty block
src/prg.asm lines 1676–1681 at 1cc3c92 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Checked by a second AI model, 2026-10-22.
- ^ abBig Mario breaks a ground block he hits from below: the overworld's terrain metatile,
$54(cracked rock), is in the hit range and not inBrickQBlockMetatiles, so the game treats it as a plain brick (smb1/bump-or-break). Measured with a$54block written 4 rows above World 1-1's floor: big Mario broke it, for 50 points, and small Mario bumped it, the block bouncing and coming back as$54.VerifiedXkeeper0/smb1How we know
2639TerrainMetatiles: 2640 .db $69, $54, $52, $62
src/prg.asm lines 2639–2640 at 1cc3c92 · upstream ↗ 1637 .db $b4, $b6, $b5, $b7 ; cracked rock terrainsrc/prg.asm line 1637 at 1cc3c92 · upstream ↗ Measured by a script in MesenCE 2.2.1 (build 4b8a196), on . It fails if the result disagrees with the claim.
The numbers come from the run; its author, an AI model, checked the script measures what the claim says, 2026-10-22.
Checked by a second AI model, 2026-10-22.
- ^The manual's hints say the Power armor breaks through cracked stone walls.ManualMega Man 6 NES manual
How we know
The Power Mega Man armor can be used to break through cracked stone
hints · archived copy ↗ The quote matches our archived copy.
Checked by a second AI model, 2026-10-25.
- ^In Infiniminer v1.5 the pickaxe reaches 2 blocks along the player's view and removes dirt, ore, gold, and diamond blocks. It doesn't remove rock, lava, or built blocks. A gold or diamond block stays put while the player's loot is full; an ore block is dug even when the player's ore is full, and its ore is lost.CodeInfiniminer v1.5 source
How we know
851 if (!RayCollision(playerPosition, playerHeading, 2, 10, ref hitPoint, ref buildPoint)) 852 return;
code/InfiniminerServer/InfiniminerServer.cs lines 851–852 at 639c16e · upstream ↗ 864 switch (BlockAtPoint(hitPoint)) ⋮ 866 case BlockType.Dirt: 867 case BlockType.DirtSign: 868 removeBlock = true; 869 sound = InfiniminerSound.DigDirt; 870 break; ⋮ 872 case BlockType.Ore: 873 removeBlock = true; 874 giveOre = 20; 875 sound = InfiniminerSound.DigMetal; 876 break; ⋮ 878 case BlockType.Gold: ⋮
code/InfiniminerServer/InfiniminerServer.cs lines 864–891 at 639c16e · upstream ↗ 893 if (giveOre > 0) ⋮ 895 if (player.Ore < player.OreMax) ⋮ 897 player.Ore = Math.Min(player.Ore + giveOre, player.OreMax); 898 SendResourceUpdate(player); ⋮ 902 if (giveWeight > 0) ⋮ 904 if (player.Weight < player.WeightMax) ⋮ 906 player.Weight = Math.Min(player.Weight + giveWeight, player.WeightMax); 907 player.Cash += giveCash; 908 SendResourceUpdate(player); ⋮ 910 else 911 removeBlock = false; ⋮ 914 if (removeBlock) ⋮
code/InfiniminerServer/InfiniminerServer.cs lines 893–918 at 639c16e · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-26.
Checked by a second AI model, 2026-10-26.
- ^In Infiniminer v1.5 the detonator, which the client offers only in the Sapper's kit, sets off every explosive that player placed. Each clears the 5 × 5 × 5 cube around it of rock, dirt, ore, solid and translucent blocks, ladders, shock and jump blocks, road, and lava, and sets off any explosive inside it. Gold, diamonds, banks, and beacons survive, and so does the map's outermost layer of blocks, which the blast skips.CodeInfiniminer v1.5 sourcerevised
How we know
993 if (blockType == BlockType.Explosive) 994 player.ExplosiveList.Add(buildPoint);
code/InfiniminerServer/InfiniminerServer.cs lines 993–994 at 639c16e · upstream ↗ 1081 public void DetonateAtPoint(int x, int y, int z) ⋮ 1083 // Remove the block that is detonating. 1084 SetBlock((ushort)(x), (ushort)(y), (ushort)(z), BlockType.None, PlayerTeam.None); ⋮ 1086 // Remove this from any explosive lists it may be in. 1087 foreach (Player p in playerList.Values) 1088 p.ExplosiveList.Remove(new Vector3(x, y, z)); ⋮ 1090 // Detonate the block. 1091 for (int dx = -2; dx <= 2; dx++) 1092 for (int dy = -2; dy <= 2; dy++) 1093 for (int dz = -2; dz <= 2; dz++) ⋮ 1095 // Check that this is a sane block position. 1096 if (x + dx <= 0 || y + dy <= 0 || z + dz <= 0 || x + dx >= MAPSIZE - 1 || y + dy >= MAPSIZE - 1 || z + dz >= MAPSIZE - 1) ⋮
code/InfiniminerServer/InfiniminerServer.cs lines 1081–1126 at 639c16e · upstream ↗ 1137 public void UseDetonator(Player player) ⋮ 1139 while (player.ExplosiveList.Count > 0) ⋮ 1141 Vector3 blockPos = player.ExplosiveList[0]; 1142 ushort x = (ushort)blockPos.X; 1143 ushort y = (ushort)blockPos.Y; 1144 ushort z = (ushort)blockPos.Z; ⋮ 1146 if (blockList[x, y, z] != BlockType.Explosive) 1147 player.ExplosiveList.RemoveAt(0); 1148 else 1149 DetonateAtPoint(x, y, z);
code/InfiniminerServer/InfiniminerServer.cs lines 1137–1151 at 639c16e · upstream ↗ 446 case PlayerClass.Sapper: 447 playerTools = new PlayerTools[3] { PlayerTools.Pickaxe, 448 PlayerTools.ConstructionGun, 449 PlayerTools.Detonator };
code/InfiniminerClient/PropertyBag.cs lines 446–449 at 639c16e · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-26.
Revised after a check by a second AI model, 2026-10-26.
- ^Minecraft's world is a three-dimensional grid of cubes, each holding one type of block, and most blocks can be mined by hand or with tools; a few, such as bedrock, can't be broken in Survival.WikiMinecraft Wiki: Gameplay
How we know
The world of Minecraft takes place within a three-dimensional grid of cubes, with each cube being occupied by a certain type of block. … Most of these blocks can then by mined, by hand or with tools. Some blocks cannot be broken in Survival, such as bedrock, End portal frames, command blocks, and barriers.
Gameplay, lead · archived copy ↗ Checked against the evidence by its author, an AI model, 2026-10-26.
Checked by a second AI model, 2026-10-26.
- ^Today many blocks can be harvested by hand, but stone and metal blocks yield nothing without a pickaxe, and harder ones such as iron ore and obsidian need a pickaxe of a higher tier. A block's base breaking time is its hardness times 1.5 when the held tool can harvest it, and times 5 when it can't; a fitting tool then divides the time by its speed: 2 for wood, 4 for stone, 6 for iron, 8 for diamond.WikiMinecraft Wiki: Breaking
How we know
Although many blocks can be harvested with bare hands, certain ones require the use of a tool. In particular, to obtain resources from stone or metal-type blocks, the player must use a pickaxe. For harder blocks like iron ore or obsidian, a pickaxe made from a higher-tier material is required.
lead · archived copy ↗ The base time in seconds is the block's hardness multiplied by: 1.5 if the player can harvest the block with the current tool; 5 if the player cannot.
Speed · archived copy ↗ If the tool helps, then it increases digging speed by a constant multiplier
Speed, tool speed table · archived copy ↗ Checked against the evidence by its author, an AI model, 2026-10-26.
Checked by a second AI model, 2026-10-26.
- ^Today tools come in seven tiers: wood, gold, stone, copper, iron, diamond, and netherite. A pickaxe's mining level decides what it can harvest: wood 0, stone 1, iron 2, diamond 3, and netherite 4. Blocks tagged as needing a stone tool, such as iron, copper, and lapis lazuli ore, need level 1; diamond, emerald, gold, and redstone ore need an iron one, level 2; obsidian and ancient debris need a diamond one, level 3. Any other block needs level 0, and the wrong tier breaks a block without it dropping anything.WikiMinecraft Wiki: Tiers · Minecraft Wiki: Pickaxe
How we know
There are currently seven tiers in the game: wood, gold, stone, copper, iron, diamond, and netherite.
Tiers · archived copy ↗ Mining level
Tiers, table · archived copy ↗ A block with the tag minecraft:needs_stone_tool[note 1] requires a mining level of 1 or higher, a block with the tag minecraft:needs_iron_tool[note 2] requires a mining level of 2 or higher, and a block with the tag minecraft:needs_diamond_tool[note 3] requires a tool with mining level 3 or higher. If a block has no mining level tags, it can be mined with a mining level of 0.
Mining level · archived copy ↗ Includes iron ore, copper ore, lapis lazuli ore … Includes diamond ore, emerald ore, gold ore, redstone ore … Includes ancient debris, obsidian
Notes 1 to 3 · archived copy ↗ For example, while stone can be mined with any pickaxe, gold ore must be mined with an iron pickaxe, diamond pickaxe, or netherite pickaxe, or else the player harvests no item.
Usage, Breaking · archived copy ↗ Checked against the evidence by its author, an AI model, 2026-10-26.
Checked by a second AI model, 2026-10-26.
- ^ abScorched Earth 1.5's documentation sorts weapons that remove dirt ("Earth Destroying Weapons") from weapons that add it ("Earth Producing Weapons"): the first can clear a mountain in the way or the ground under the firer's own tank, and Liquid Dirt fills holes and smooths the terrain. Dirt left in the air normally falls; a Suspend Dirt setting, 0 by default, lets it hang.ManualScorched Earth 1.5 docs
How we know
Earth destroying weapons are weapons which cause large (or small) amounts of dirt to be destroyed. … destroying weapons are also good for removing mountains that are in your way, or even removing dirt beneath yourself
SCORCH.DOC lines 1115-1122 · archived copy ↗ The category of Earth Producing Weapons includes weapons which take some form of compacted earth that explodes into a much larger amount of dirt.
SCORCH.DOC lines 1168-1169 · archived copy ↗ Liquid Dirt Liquid Dirt oozes out wherever it lands, filling holes and smoothing the terrain.
SCORCH.DOC lines 1184-1185 · archived copy ↗ Suspend Dirt 0-100 0 This number allows dirt to remain suspended in the air some of the time.
SCORCH.DOC lines 1890-1891 · archived copy ↗ The quote matches our archived copy.
Checked by a second AI model, 2026-10-22.
- ^ abThe Worms PC manual says the Bazooka "causes devastation to the landscape", and that the Blowtorch and the Drill let worms dig and burrow in it, the Blowtorch at six angles and the Drill straight down.ManualWorms PC manualrevised
How we know
Causes devastation to the landscape and large blast wave.
p. 5, Bazooka · archived copy ↗ These utility weapons allow Worms to dig and burrow in the landscape. … The Blowtorch can be selected at any one of six different angles to dig … whereas the Drill can only drill vertically down
p. 7, Blowtorch and Drill · archived copy ↗ The quote matches our archived copy.
Revised after a check by a second AI model, 2026-10-22.
- ^ abGame Developer's 2012 feature says the Frostbite engine debuted in 2008 with Battlefield: Bad Company, which let players destroy parts of walls and parts of vehicles.InterviewNutt and Graft, How DICE fell in love with destruction (2012)
How we know
The Frostbite engine debuted in 2008, powering Battlefield … which allowed players to destroy objects such as parts of walls and parts of vehicles.
paragraph opening "Earlier DICE games" · archived copy ↗ The quote matches our archived copy.
Checked by a second AI model, 2026-10-22.
- ^While Mario moves up,
PlayerBGCollisiontests a single head point, the first of its point set (smb1/bg-points), after the frame's movement and before the feet. It acts only if his vertical speed byte is negative, the low nybble of his own Y is 4 or more, and his Y is at least$20(big) or$10(small, or big and crouching), and only if the point's metatile is nonzero and not a coin. So one block at most is hit per frame: when his head spans two blocks, the one under the point is hit and the other is ignored. Measured: big Mario under a brick that covered only his box's left part rose past it untouched.VerifiedXkeeper0/smb1revisedHow we know
11149HeadChk: 11150 LDA Player_Y_Position ; get player's vertical coordinate 11151 CMP PlayerBGUpperExtent,x ; compare with upper extent value based on offset 11152 BCC DoFootCheck ; if player is too high, skip this part 11153 JSR BlockBufferColli_Head ; do player-to-bg collision detection on top of 11154 BEQ DoFootCheck ; player, and branch if nothing above player's head 11155 JSR CheckForCoinMTiles ; check to see if player touched coin with their head 11156 BCS AwardTouchedCoin ; if so, branch to some other part of code 11157 LDY Player_Y_Speed ; check player's vertical speed 11158 BPL DoFootCheck ; if player not moving upwards, branch elsewhere 11159 LDY $04 ; check lower nybble of vertical coordinate returned 11160 CPY #$04 ; from collision detection routine ⋮
src/prg.asm lines 11149–11161 at 1cc3c92 · upstream ↗ 11097PlayerBGUpperExtent: 11098 .db $20, $10
src/prg.asm lines 11097–11098 at 1cc3c92 · upstream ↗ 11145 LDX PlayerSize ; get player's size as offset 11146 LDA CrouchingFlag 11147 BEQ HeadChk ; if player not crouching, branch ahead 11148 INX ; otherwise increment size as offset
src/prg.asm lines 11145–11148 at 1cc3c92 · upstream ↗ Measured by a script in MesenCE 2.2.1 (build 4b8a196), on . It fails if the result disagrees with the claim.
The numbers come from the run; its author, an AI model, checked the script measures what the claim says, 2026-10-22.
Revised after a check by a second AI model, 2026-10-22.
- ^When the head point finds a block in the solid ranges (smb1/head-kinds),
PlayerBGCollisionsets Mario's vertical speed byte to 1 and plays the bump sound; his position and the speed's fraction are left as they are, so the frame ends with his head inside the block and he starts down on the next. In water levels, and whileBlockBounceTimerruns (smb1/bounce-timer), a brick or ? block gets the same speed of 1 without the sound and without being hit.VerifiedXkeeper0/smb1How we know
11162 JSR CheckForSolidMTiles ; check to see what player's head bumped on 11163 BCS SolidOrClimb ; if player collided with solid metatile, branch 11164 LDY AreaType ; otherwise check area type 11165 BEQ NYSpd ; if water level, branch ahead 11166 LDY BlockBounceTimer ; if block bounce timer not expired, 11167 BNE NYSpd ; branch ahead, do not process collision 11168 JSR PlayerHeadCollision ; otherwise do a sub to process collision 11169 JMP DoFootCheck ; jump ahead to skip these other parts here ⋮ 11171SolidOrClimb: 11172 CMP #$26 ; if climbing metatile, 11173 BEQ NYSpd ; branch ahead and do not play sound 11174 LDA #Sfx_Bump ⋮
src/prg.asm lines 11162–11178 at 1cc3c92 · upstream ↗ Measured by a script in MesenCE 2.2.1 (build 4b8a196), on . It fails if the result disagrees with the claim.
The numbers come from the run; its author, an AI model, checked the script measures what the claim says, 2026-10-22.
Checked by a second AI model, 2026-10-22.
- ^Every head hit that reaches
PlayerHeadCollision, bump or break, setsBlockBounceTimerto 16, a frame timer. Until it is back at 0, the head check treats bricks and ? blocks as solid without the sound (smb1/head-solid), so no second block can be bumped or broken for 16 frames. Measured after five bumps: 16 on the hit frame, 0 sixteen frames later.VerifiedXkeeper0/smb1revisedHow we know
6201 LDA #$10 6202 STA BlockBounceTimer ; set block bounce timer
src/prg.asm lines 6201–6202 at 1cc3c92 · upstream ↗ 11166 LDY BlockBounceTimer ; if block bounce timer not expired, 11167 BNE NYSpd ; branch ahead, do not process collision
src/prg.asm lines 11166–11167 at 1cc3c92 · upstream ↗ 60Timers = $0780 ⋮ 65BlockBounceTimer = $0784
src/ram.asm lines 60–65 at 1cc3c92 · upstream ↗ 126DecTimers: 127 LDX #$14 ; load end offset for end of frame timers ⋮ 136 DEC Timers,x ; otherwise decrement the current timer
src/prg.asm lines 126–136 at 1cc3c92 · upstream ↗ Measured by a script in MesenCE 2.2.1 (build 4b8a196), on . It fails if the result disagrees with the claim.
The numbers come from the run; its author, an AI model, checked the script measures what the claim says, 2026-10-22.
Revised after a check by a second AI model, 2026-10-22.
- ^During a bounce, and on the frame after a brick breaks, the block's cell holds
$23, and every test ofPlayerBGCollisiontakes its solid path for it: the head check's solid range starts at$10in group 0; the foot check's exceptions (climbable from$24, the axe$C5, hidden blocks$5Fand$60) miss it, so it lands Mario or pushes him back; and the side check's exceptions (hidden blocks, climbable, coins$C2and$C3, jumpspring$67and$68, the pipe openings) miss it, so it ends inStopPlayerMove.CodeXkeeper0/smb1revisedHow we know
1611 .db $24, $24, $24, $24 ; blank, used on bricks or blocks that are hitsrc/prg.asm line 1611 at 1cc3c92 · upstream ↗ 11202ChkFootMTile: 11203 JSR CheckForClimbMTiles ; check to see if player landed on climbable metatiles 11204 BCS DoPlayerSideCheck ; if so, branch 11205 LDY Player_Y_Speed ; check player's vertical speed 11206 BMI DoPlayerSideCheck ; if player moving upwards, branch 11207 CMP #$c5 11208 BNE ContChk ; if player did not touch axe, skip ahead 11209 JMP HandleAxeMetatile ; otherwise jump to set modes of operation 11210ContChk: 11211 JSR ChkInvisibleMTiles ; do sub to check for hidden coin or 1-up blocks 11212 BEQ DoPlayerSideCheck ; if either found, branch 11213 LDY JumpspringAnimCtrl ; if jumpspring animating right now, ⋮
src/prg.asm lines 11202–11221 at 1cc3c92 · upstream ↗ 11273CheckSideMTiles: 11274 JSR ChkInvisibleMTiles ; check for hidden or coin 1-up blocks 11275 BEQ ExCSM ; branch to leave if either found 11276 JSR CheckForClimbMTiles ; check for climbable metatiles 11277 BCC ContSChk ; if not found, skip and continue with code 11278 JMP HandleClimbing ; otherwise jump to handle climbing 11279ContSChk: 11280 JSR CheckForCoinMTiles ; check to see if player touched coin 11281 BCS HandleCoinMetatile ; if so, execute code to erase coin and award to player 1 coin 11282 JSR ChkJumpspringMetatiles ; check for jumpspring metatiles 11283 BCC ChkPBtm ; if not found, branch ahead to continue cude ⋮ 11287ChkPBtm: ⋮
src/prg.asm lines 11273–11298 at 1cc3c92 · upstream ↗ 11331StopPlayerMove: 11332 JSR ImpedePlayerMove ; stop player's movement
src/prg.asm lines 11331–11332 at 1cc3c92 · upstream ↗ 11461ChkInvisibleMTiles: 11462 CMP #$5f ; check for hidden coin block 11463 BEQ ExCInvT ; branch to leave if found 11464 CMP #$60 ; check for hidden 1-up block
src/prg.asm lines 11461–11464 at 1cc3c92 · upstream ↗ 11486ChkJumpspringMetatiles: 11487 CMP #$67 ; check for top jumpspring metatile 11488 BEQ JSFnd ; branch to set carry if found 11489 CMP #$68 ; check for bottom jumpspring metatile
src/prg.asm lines 11486–11489 at 1cc3c92 · upstream ↗ 11596ClimbMTileUpperExt: 11597 .db $24, $6d, $8a, $c6
src/prg.asm lines 11596–11597 at 1cc3c92 · 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.
- ^ ab
SpawnBrickChunksmakes the debris from two block objects at the block's place, the upper starting up at 6 px/frame and the lower, 8 px down, at 4 px/frame, both with horizontal speed$F0.BlockObjectsCoremoves each underImposeGravityBlock($50/256 px/frame², fall cap 8) and draws them withDrawBrickChunks, which puts each object's two sprites at its own X and at the original X mirrored across it, plus 6, so four chunks fly apart.CodeXkeeper0/smb1revisedHow we know
6362SpawnBrickChunks: ⋮ 6365 LDA #$f0 6366 STA Block_X_Speed,x ; set horizontal speed for brick chunk objects 6367 STA Block_X_Speed+2,x 6368 LDA #$fa 6369 STA Block_Y_Speed,x ; set vertical speed for one 6370 LDA #$fc 6371 STA Block_Y_Speed+2,x ; set lower vertical speed for the other ⋮ 6381 ADC #$08 ; and save as vertical coordinate for one of them ⋮ 6383 LDA #$fa
src/prg.asm lines 6362–6386 at 1cc3c92 · upstream ↗ 6400 BEQ BouncingBlockHandler ; branch if found, otherwise continue for brick chunks 6401 JSR ImposeGravityBlock ; do sub to impose gravity on one block object object 6402 JSR MoveObjectHorizontally ; do another sub to move horizontally ⋮ 6407 JSR ImposeGravityBlock ; do sub to impose gravity on other block object 6408 JSR MoveObjectHorizontally ; do another sub to move horizontally ⋮ 6412 JSR DrawBrickChunks ; draw the brick chunks
src/prg.asm lines 6400–6412 at 1cc3c92 · upstream ↗ 6612MaxSpdBlockData: 6613 .db $06, $08 ⋮ 6619ImposeGravityBlock: 6620 LDY #$01 ; set offset for maximum speed 6621 LDA #$50 ; set movement amount here
src/prg.asm lines 6612–6623 at 1cc3c92 · upstream ↗ 13501 LDA Block_Rel_XPos ; get first block object's relative horizontal coordinate 13502 STA Sprite_X_Position,y ; save into X coordinate of first sprite 13503 LDA Block_Orig_XPos,x ; get original horizontal coordinate ⋮ 13508 SBC Block_Rel_XPos ; get difference of relative positions of original - current 13509 ADC $00 ; add original relative position to result 13510 ADC #$06 ; plus 6 pixels to position second brick chunk correctly 13511 STA Sprite_X_Position+4,y ; save into X coordinate of second sprite ⋮ 13516 STA Sprite_X_Position+8,y ; save into X coordinate of third sprite ⋮ 13520 ADC $00 ; add original relative position to result 13521 ADC #$06 ; plus 6 pixels to position fourth brick chunk correctly 13522 STA Sprite_X_Position+12,y ; save into X coordinate of fourth sprite
src/prg.asm lines 13501–13522 at 1cc3c92 · 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.
- ^A brick with coins (
$58,$5D) startsBrickCoinTimerat 11 on its first hit. Every bump gives a coin; while the timer runs the brick comes back as itself, and the first bump after it reaches 0 leaves a used block. It is an interval timer, counted down once every 21 frames, so the brick pays out for 11 such ticks, 211 to 231 frames (computed).CodeXkeeper0/smb1revisedHow we know
6177 LDA #$c4 ; load empty block metatile into A for now 6178 LDY $00 ; get metatile from before 6179 CPY #$58 ; is it brick with coins (with line)? 6180 BEQ StartBTmr ; if so, branch 6181 CPY #$5d ; is it brick with coins (without line)? 6182 BNE PutMTileB ; if not, branch ahead to store empty block metatile 6183StartBTmr: 6184 LDA BrickCoinTimerFlag ; check brick coin timer flag 6185 BNE ContBTmr ; if set, timer expired or counting down, thus branch 6186 LDA #$0b 6187 STA BrickCoinTimer ; if not set, set brick coin timer 6188 INC BrickCoinTimerFlag ; and set flag linked to it ⋮
src/prg.asm lines 6177–6194 at 1cc3c92 · upstream ↗ 6259 LDA $05 ; get original metatile from stack 6260 JSR BlockBumpedChk ; do a sub to check which block player bumped head on 6261 BCC ExitBlockChk ; if no match was found, branch to leave 6262 TYA ; move block number to A 6263 CMP #$09 ; if block number was within 0-8 range, 6264 BCC BlockCode ; branch to use current number 6265 SBC #$05 ; otherwise subtract 5 for second set to get proper number 6266BlockCode: 6267 JSR JumpEngine ; run appropriate subroutine depending on block number ⋮ 6270 .dw CoinBlock 6271 .dw CoinBlock 6272 .dw ExtraLifeMushBlock ⋮
src/prg.asm lines 6259–6276 at 1cc3c92 · upstream ↗ 6304BrickQBlockMetatiles: 6305 .db $c1, $c0, $5f, $60 ; used by question blocks ⋮ 6308 .db $55, $56, $57, $58, $59 ; used by ground level types 6309 .db $5a, $5b, $5c, $5d, $5e ; used by other level types
src/prg.asm lines 6304–6309 at 1cc3c92 · upstream ↗ 126DecTimers: 127 LDX #$14 ; load end offset for end of frame timers 128 DEC IntervalTimerControl ; decrement interval timer control, 129 BPL DecTimersLoop ; if not expired, only frame timers will decrement 130 LDA #$14 131 STA IntervalTimerControl ; if control for interval timers expired, 132 LDX #$23 ; interval timers will decrement along with frame timers ⋮ 136 DEC Timers,x ; otherwise decrement the current timer
src/prg.asm lines 126–136 at 1cc3c92 · upstream ↗ 60Timers = $0780 ⋮ 77BrickCoinTimer = $079d
src/ram.asm lines 60–77 at 1cc3c92 · 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.
- ^Jimmy Maher's history of Lode Runner says drilled pits fill in again after ten seconds, and that monks (the guards) climb out of a pit in a few seconds, so a pit that closes while a monk is still inside buries him.WebMaher, The Digital Antiquarian: Lode Runner (2020)
How we know
the pits you drill are automatically filled in again after ten seconds, while monks climb out of pits into which they’ve fallen in just a few seconds.
paragraph opening "There's a deceptive amount of depth" · archived copy ↗ The quote matches our archived copy.
Checked by a second AI model, 2026-10-22.
- ^The Ringer's Ben Lindbergh sets Red Faction's Geo-Mod against the "more primitive environmental mayhem in 2D games like Dig Dug (1982), Rampage (1986), or Worms (1995)", and says Red Faction debuted in May 2001.InterviewLindbergh, Destructible Environments, The Ringer (2024)
How we know
primitive environmental mayhem in 2D games like Dig Dug (1982), Rampage (1986), or Worms (1995)
Red Faction section · archived copy ↗ worked well enough to wow reviewers when Red Faction debuted in May 2001
paragraph opening "Sometimes a deadline does wonders" · archived copy ↗ The quote matches our archived copy.
- ^Andy Davidson, who programmed Worms, told Time Extension it grew from the artillery games he had loved "since the 8-bit days", two tanks trading shots by angle and power, and that what interested him most was generating random landscapes; letting the tanks move was, he says, new for a genre that was "normally very static".InterviewTime Extension, The Making Of: Worms (2024)
How we know
These were where two tanks on each side of the screen had to destroy each other considering angle and power. … the one thing that really interested me was generating random landscapes
section opening "He began developing a new game" · archived copy ↗ This was a new thing for artillery games, which were normally very static
paragraph opening "The Amiga allowed me" · archived copy ↗ The quote matches our archived copy.
Checked by a second AI model, 2026-10-22.
- ^Alan Lawrance says that when Volition set out to make a game with destruction it looked at what was out there, "and there really wasn't anything".InterviewLindbergh, Destructible Environments, The Ringer (2024)
How we know
When we came up with the desire to make a game with destruction in it, we looked to see what was out there, and there really wasn’t anything
Red Faction section · archived copy ↗ The quote matches our archived copy.
Checked by a second AI model, 2026-10-22.
- ^The Ringer reports that John Slagel, Red Faction's lead programmer, wrote a game as a teenager in the mid-1980s on an IBM PCjr in which bombs dropped from an ASCII-art plane left craters in the ground.InterviewLindbergh, Destructible Environments, The Ringer (2024)
How we know
Slagel had designed a game on his IBM PCjr in which the player used the space bar to drop bombs from an ASCII art plane onto targets on the ground, creating craters.
paragraph opening "“It fell on me,” Slagel" · archived copy ↗ The quote matches our archived copy.
Checked by a second AI model, 2026-10-22.
- ^DICE's general manager Karl-Magnus Troedsson told Game Developer that the studio's focus on destruction came out of discussions of how to differentiate itself, and recalled a Battlefield: Bad Company demo in which a tank kept "shooting holes in the houses", forcing a player on foot to move.InterviewNutt and Graft, How DICE fell in love with destruction (2012)revised
How we know
[The concentration on destruction] definitely came out of discussions [about] how we would differentiate ourselves to others
paragraph opening "[The concentration on destruction]" · archived copy ↗ the tank was just going 'boom boom boom,' shooting holes in the houses all the time
paragraph opening "We had one demo I remember" · archived copy ↗ The quote matches our archived copy.
Revised after a check by a second AI model, 2026-10-22.
- ^Alan Kertz, formerly of DICE, told The Ringer that when Battlefield: Bad Company was made "there were a few games doing destruction, but nobody was doing it on the multiplayer front", and that destruction has to leave craters, negative space, and rubble where players can still hide.InterviewLindbergh, Destructible Environments, The Ringer (2024)
How we know
There were a few games doing destruction, but nobody was doing it on the multiplayer front … There’s got to be craters, there’s got to be negative space, there’s got to be rubble leftovers
Bad Company section · archived copy ↗ The quote matches our archived copy.
Checked by a second AI model, 2026-10-22.
- ^The NES Legend of Zelda booklet describes the bomb only as a weapon, a blast against enemies (p. 13); of the invisible doors in caves it says only "That's a secret".ManualLegend of Zelda NES manualrevised
How we know
enemy with the explosive blast.
p. 13, Bomb · archived copy ↗ In the caves where people live are invisible closed doors. How to open them? That's a secret,
p. 18 · archived copy ↗ The quote matches our archived copy.
Revised after a check by a second AI model, 2026-10-22.
Sources
Code
- Cantrell, Christopher. 2026. “Computer Archeology: Space Invaders.” Commit 1adc2a7. topherCantrell/computerarcheology @ 1adc2a7 · licence, all uses
- doppelganger and Xkeeper. 2022. “smb1: Super Mario Bros. disassembly for asm6f (Xkeeper0/smb1).” Commit 1cc3c92. Xkeeper0/smb1 @ 1cc3c92 · licence, all uses
Primary
- Lindbergh, Ben. 2024. “The Destruction (and Reconstruction) of Destructible Environments in Video Games.” The Ringer. original · archived · licence, all uses
- Soft, Hudson and Nintendo of America. 1987. “Lode Runner instruction booklet (NES, North America).” Nintendo of America. original · archived · licence, all uses
- Soft, Hudson and Nintendo of America. 1989. “Bomberman instruction booklet (NES, North America).” Nintendo of America. original · archived · licence, all uses
- Hicken, Wendell. 1995. “Scorched Earth 1.5 documentation (SCORCH.DOC).” Wendell Hicken (shareware). original · archived · licence, all uses
- Team17. 1995. “Worms game manual (PC, US).” Ocean Software. original · archived · licence, all uses
- Nutt, Christian and Kris Graft. 2012. “How DICE fell in love with destruction.” Game Developer. original · archived · licence, all uses
- Johnson, Faith. 2024. “The Making Of: Worms.” Time Extension. original · archived · licence, all uses
- America, Nintendo of. 1987. “The Legend of Zelda instruction booklet (NES, North America).” Nintendo of America. original · archived · licence, all uses
Secondary
- Maher, Jimmy. 2020. “Lode Runner.” The Digital Antiquarian. original · archived · licence, all uses