On this page
  1. Related
  2. Games

Tile collision asks the level, not other objects, whether a place is solid. A game looks up the tile under points on an object, such as its feet, head, and sides, and lands it or pushes it back when a point is inside a solid tile. Collisions between objects use hitboxes instead.

  • Felix the Cat (1992). A 512 px ring of 16 px tiles; a blocked step is taken back, but a platform's push isn't.1,2,3

Games

GameYearHowNote
Felix the Cat1992a 512 px ring of 16 px tiles; a blocked step is taken back, but a platform's push isn't
Every claim about this mechanic, by game (8)
Super Mario Bros.: The Lost Levels 1986The collision code (FireballEnemyCollision through BlockBufferCollision) is Super Mario Bros.'s with the upside-down piranha plant, the poison mushroom and the renumbered metatiles added: the fireball, enemy, background and stomp checks treat the upside-down plant like a piranha plant; HandlePowerUpCollision injures the player on power-up type 4; InjurePlayer also does nothing while the star's StarInvincibleTimer runs; HandlePECollisions checks for the cannon's Bullet Bill before the piranha plants and Podoboo, where Super Mario Bros. checks it after them; PlayerEnemyCollision decides a stomp with LDY, DEY, BPL on the vertical speed where Super Mario Bros. uses BMI and BNE (the two disagree only at speed $80); every stomp bounces the player through a new SetBounce, at vertical speed $FA, or $F8 off red paratroopas and flying green paratroopas, where Super Mario Bros. sets $FD after a stomp that defeats an enemy and $FC after one that demotes a paratroopa or knocks an enemy into its shell; HandleClimbing gives a life for grabbing the flagpole when the coin tally's digits and the timer's last digit match; HandlePipeEntry sends the player to the warp zone's one destination whichever pipe they take, where Super Mario Bros. picks by the pipe's x position; HandleCoinMetatile's axe restores Mario's physics; ChkForLandJumpSpring sets VerticalForceDown to $70 as well as VerticalForce; PlayerHammerCollision also skips while the player is off screen; HandleEToBGCollision bounces a power-up on a bumped block without stunning it and never demotes a piranha plant; CheckPlayerVertical drops its test of how far down the screen the player is; one bounding box grows from $14 to $16. The platform collisions, LandEnemyProperly, the side checks and BlockBufferCollision differ only in their addresses, and three regions, PlayerCollisionCore among them, are byte for byte the same.Code
Mega Man 3 1990Both games find the 32-pixel block at a point in the screen's layout and then its 16-pixel quarter, but Mega Man 3's tile check is new code with a new type format. Mega Man 2's _tsa_collision tests one point a call and takes its type from the quarter byte's top two bits, which a per-stage table remaps; Mega Man 3's check_tile_collision tests a list of points from a hitbox table in one call, clamps them to the screen, takes each type from the upper four bits of the tile's entry in a table at $BF00 in the stage bank, and ORs the types together.Code
Mega Man 4 1991Mega Man 4's four routines that push an entity out of a wall, ceiling, or floor after a tile hit are Mega Man 3's snap_x_to_wall_right, snap_x_to_wall_left, snap_y_to_ceil, and snap_y_to_floor instruction for instruction; only the addresses of the entity position arrays differ. Mega Man 3 follows them with two calls into its boss door bank, which Mega Man 4 doesn't have there.Code
Mega Man 4's four routines that move an entity by its speed and stop it at a wall, floor, or ceiling follow Mega Man 3's move_right_collide, move_left_collide, move_down_collide, and move_up_collide step for step. Each saves the player's position before the move, checks for a platform, pushes the player off it, and on a push that crosses a screen retries with the opposite side's tile check. Two things changed. Each tile check is one call, where Mega Man 3 calls its tile check and then update_collision_flags. And when the right mover hits a solid tile, Mega Man 4 first copies $45 to $3F for the player, which its disassembly reads as the ground tile type. Two of the screen-crossing tests also test their two flags in the other order, to the same effect.Code
Felix the Cat 1992Each frame of play, after the mover adds Felix's x speed and push to his x, the fixed bank's $D05F checks him against the screen's edges or the map. With his x's high byte past the bound's, or equal to it with a low byte of $DB or more outside a boss fight (and a few other cases), the game walks him right (the auto-walk) and tests the map. Short of that, an x less than 8 or at least 240 past $B7:$B9 sets his x speed to 1 px a frame back inward, and the map isn't read that frame. Otherwise, moving right, it reads the map 8 px ahead of him, normally at y + 1, y − 8, and y + 13 (moving left, 8 px behind), and if a tile there blocks, it subtracts that frame's x speed from his x again. Then $D191 moves x 1 px toward 7 or 8 px into its 16 px column.Code
The map that Felix's tile tests read is 32 columns of 16 px by 24 rows of 16 px in cartridge RAM at $6000-$63FF, a ring that repeats every 512 px of x. A tile's type is the low nibble of its entry in a table at ($CA). Types 1, 14, and 15 block both ways; type 4 blocks only moving left, and type 5 only moving right. A point above the map reads the top row, and one 384 px down or more reads the bottom row, where any nonzero type counts as 1.Code
Mega Man 5 1992Mega Man 5's four routines that push an object out of a wall, ceiling, or floor after a tile hit are Mega Man 4's, byte for byte but for one instruction: after a ceiling hit, Mega Man 5 clears the carry before adding where Mega Man 4 sets it, so the object ends one pixel higher than in Mega Man 4. Mega Man 5 follows them with four new routines that move an object along X or Y by the amount in $10 or $11 and compare its position with one saved in $02-$03.Code
Mega Man 5's routines that move an object right, left, down, or up and then check tiles, and for the player the platforms it stands on, follow Mega Man 4's with three changes besides addresses. The facing flag they set or clear is bit 5 of the object's flags, where Mega Man 4 uses bit 6. A right-wall hit no longer copies the player's ground tile type from $45 to $3F. And before a vertical move, Mega Man 5 saves the player's vertical screen in $03, where Mega Man 4 saves its horizontal screen.Code

References

  1. ^Each frame of play, after the mover adds Felix's x speed and push to his x, the fixed bank's $D05F checks him against the screen's edges or the map. With his x's high byte past the bound's, or equal to it with a low byte of $DB or more outside a boss fight (and a few other cases), the game walks him right (the auto-walk) and tests the map. Short of that, an x less than 8 or at least 240 past $B7:$B9 sets his x speed to 1 px a frame back inward, and the map isn't read that frame. Otherwise, moving right, it reads the map 8 px ahead of him, normally at y + 1, y − 8, and y + 13 (moving left, 8 px behind), and if a tile there blocks, it subtracts that frame's x speed from his x again. Then $D191 moves x 1 px toward 7 or 8 px into its 16 px column.Code“Felix the Cat (USA)”revised
    How we know

    In the cartridge (“Felix the Cat (USA)”): fixed bank $D023-$D02B, in Felix's update: JSR $D87E, JSR $D90F (the mover), JSR $D05F; fixed bank $D049-$D0EA: past the bound's page, or in it at x low byte $DB or more unless $040D is 1, $040D + $0411 is 8 (a boss fight), or the stage index is $17, hold Right and accelerate (the auto-walk), then the map test; otherwise x - $B7:$B9 below 8 sets the x speed to $0100, at $F0 or more to $FF00, and returns; fixed bank $D0EB-$D15F: with the x speed at 0, test both sides; positive, the tile at x + 8 (mask $FD); negative, x - 8 (mask $FB); on a hit, subtract the x speed from the fraction and x, then $D191; fixed bank $D191-$D1BD: fraction to $80; x's low nibble 7 or 8 stays, below 7 gains 1, above 8 loses 1; fixed bank $D1BE-$D213: the tile at y + 1; then y - 8 unless $03C3 is 7; then y + 13 unless $03B0 is set; nonzero when one blocks. We don't reproduce the bytes.

    Checked against the evidence by its author, an AI model, 2026-10-25.

    Revised after a check by a second AI model, 2026-10-25.

    In the claim ledger

  2. ^The map that Felix's tile tests read is 32 columns of 16 px by 24 rows of 16 px in cartridge RAM at $6000-$63FF, a ring that repeats every 512 px of x. A tile's type is the low nibble of its entry in a table at ($CA). Types 1, 14, and 15 block both ways; type 4 blocks only moving left, and type 5 only moving right. A point above the map reads the top row, and one 384 px down or more reads the bottom row, where any nonzero type counts as 1.Code“Felix the Cat (USA)”
    How we know

    In the cartridge (“Felix the Cat (USA)”): fixed bank $F251-$F290: row from y ($07:$06): negative, row 0; below 256, y / 16; 256-383, 16 + (y - 256) / 16; else row 23 with a nonzero type as 1; address $6000 + (x high bit 0) * $200 + (x low / 16) * $20 + row; type = ($CA),tile AND $0F; fixed bank $CF81-$CF90, the blocking bits by type: 00 01 00 00 02 04 00 00 00 00 00 00 00 00 01 01; moving right tests them with $FD, left with $FB. We don't reproduce the bytes.

    Checked against the evidence by its author, an AI model, 2026-10-25.

    Checked by a second AI model, 2026-10-25.

    In the claim ledger

  3. ^Felix's push $041D comes from one routine, in PRG bank 12: a platform whose x swings with the frame counter sets it, while Felix rides, to the change in its x that frame, and the object pass clears it again afterward. The mover adds it to Felix's x, and the wall test never takes it back (felix-the-cat/wall-test). In FCEUX's replay of the 1625M movie the push was 1 px either way, and it came only in the main areas of stage indices 1, 2, 7, 9, 10, 12, 18, and 22, never in a boss room.Code“Felix the Cat (USA)” · 1625M, replayed in FCEUX
    How we know

    In the cartridge (“Felix the Cat (USA)”): bank 12 $9165-$91B2: save the x low byte in $01; x = the base $06F2:$06DC + ($37 / 2, mirrored by $37 bit 6) AND $1F; with $0708 bit 4 set and x moved, $041D = x - $01; fixed bank $E12B-$E155: update slots 6 to 21, then 0 to 5, then zero $0420-$0423 and $041D; fixed bank $D90F-$D93D: the mover adds $06C6 + $041D to Felix's x. We don't reproduce the bytes.

    every nonzero write to $041D

    Checked against the evidence by its author, an AI model, 2026-10-25.

    Checked by a second AI model, 2026-10-25.

    In the claim ledger