Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Game Development in Eight Bits (Abstractions II)

Game Development in Eight Bits (Abstractions II)

The "8-Bit" era of the late 1980s brought video games into the home with systems like the Nintendo Entertainment System (NES). Developers of the time produced iconic games and introduced entire genres of video game that are still with us to this day, all while working with limited hardware that required inventive approaches. This talk will explore how NES developers created more with less, looking at techniques and algorithms used in professionally-developed NES games to handle physics, collision detection, randomness, data compression, and more.

Kevin Zurawel

August 21, 2019
Tweet

More Decks by Kevin Zurawel

Other Decks in Programming

Transcript

  1. NES TECH SPECS ➤ MOS Technologies 6502 CPU (1.79MHz) ➤

    Custom Ricoh “Picture Processing Unit”
 (256x240 resolution, 64 colors)
  2. NES TECH SPECS ➤ 2KB work RAM + 2KB video

    RAM ➤ No permanent storage ➤ Read-only cartridges;
 32KB code, 8KB graphics data
  3. Number of bits Possible values 1 2 2 4 3

    8 4 16 5 32 6 64 7 128 8 256
  4. 256 pixels wide
 × 240 pixels tall 61,440 pixels
 per

    screen ÷ 4 pixels per byte 15 KB
 per screen
  5. 256 pixels wide
 × 240 pixels tall 61,440 pixels
 per

    screen ÷ 4 pixels per byte 15 KB
 per screen (!!!)
  6. BACKGROUNDS 32 x 30 grid of tiles 8x8 pixels per

    tile 960 tiles per screen 1 byte per tile 960 bytes per screen
  7. SPRITES 256 bytes of sprite RAM
 ÷ 4 bytes per

    sprite 
 (tile #, x/y, palette #) 64 sprites at a time
  8. PROBLEM #2 How do you show a lot of action


    with only 8 sprites per line?
  9. 14 screens of graphics
 × 960 bytes per screen ~13

    KB graphics data … for World 1-1 alone
  10. 2. MAKE USE OF REPEATED META-OBJECTS Instead of storing 24

    tiles, store “pipe, height 6” and write code that draws pipes
  11. 3. USE BASIC COMPRESSION (RUN-LENGTH ENCODING) Instead of storing 96

    tiles, store “brick tile repeats 32 times” for three rows
  12. { {

  13. ;level 1–1 
 L_GroundArea6: .db $50, $21
 .db $07, $81,

    $47, $24, $57, $00, $63, $01, $77, $01
 .db $c9, $71, $68, $f2, $e7, $73, $97, $fb, $06, $83 
 .db $5c, $01, $d7, $22, $e7, $00, $03, $a7, $6c, $02 
 .db $b3, $22, $e3, $01, $e7, $07, $47, $a0, $57, $06 
 .db $a7, $01, $d3, $00, $d7, $01, $07, $81, $67, $20 
 .db $93, $22, $03, $a3, $1c, $61, $17, $21, $6f, $33 
 .db $c7, $63, $d8, $62, $e9, $61, $fa, $60, $4f, $b3 
 .db $87, $63, $9c, $01, $b7, $63, $c8, $62, $d9, $61 
 .db $ea, $60, $39, $f1, $87, $21, $a7, $01, $b7, $20 
 .db $39, $f1, $5f, $38, $6d, $c1, $af, $26
 .db $fd World 1-1… in 101 bytes! "I AM ERROR", p.131
  14. ;level 1–1 
 L_GroundArea6: .db $50, $21
 .db $07, $81,

    $47, $24, $57, $00, $63, $01, $77, $01
 .db $c9, $71, $68, $f2, $e7, $73, $97, $fb, $06, $83 
 .db $5c, $01, $d7, $22, $e7, $00, $03, $a7, $6c, $02 
 .db $b3, $22, $e3, $01, $e7, $07, $47, $a0, $57, $06 
 .db $a7, $01, $d3, $00, $d7, $01, $07, $81, $67, $20 
 .db $93, $22, $03, $a3, $1c, $61, $17, $21, $6f, $33 
 .db $c7, $63, $d8, $62, $e9, $61, $fa, $60, $4f, $b3 
 .db $87, $63, $9c, $01, $b7, $63, $c8, $62, $d9, $61 
 .db $ea, $60, $39, $f1, $87, $21, $a7, $01, $b7, $20 
 .db $39, $f1, $5f, $38, $6d, $c1, $af, $26
 .db $fd World 1-1… in 101 bytes! Header Footer "I AM ERROR", p.131
  15. ;level 1–1 
 L_GroundArea6: .db $50, $21
 .db $07, $81,

    $47, $24, $57, $00, $63, $01, $77, $01
 .db $c9, $71, $68, $f2, $e7, $73, $97, $fb, $06, $83 
 .db $5c, $01, $d7, $22, $e7, $00, $03, $a7, $6c, $02 
 .db $b3, $22, $e3, $01, $e7, $07, $47, $a0, $57, $06 
 .db $a7, $01, $d3, $00, $d7, $01, $07, $81, $67, $20 
 .db $93, $22, $03, $a3, $1c, $61, $17, $21, $6f, $33 
 .db $c7, $63, $d8, $62, $e9, $61, $fa, $60, $4f, $b3 
 .db $87, $63, $9c, $01, $b7, $63, $c8, $62, $d9, $61 
 .db $ea, $60, $39, $f1, $87, $21, $a7, $01, $b7, $20 
 .db $39, $f1, $5f, $38, $6d, $c1, $af, $26
 .db $fd World 1-1… in 101 bytes! Header Footer Byte pairs (screen location, metatile) "I AM ERROR", p.131
  16. Byte pair Column/Row Description $07, $81 0, 7 (start new

    screen) 
 "?" block w/ coin $47, $24 4, 7 row of bricks, length 4 $57, $00 5, 7 "?" block 
 w/ power-up item $63, $01 6, 3 "?" block w/ coin "I AM ERROR", p.133
  17. THE “STANDARD” 2D JUMP ALGORITHM Height at time t =

    vertical velocity + (acceleration from gravity2 / 2)
  18. MATH ON THE 6502 CPU ADC SBC ASL LSR Add

    (with Carry) Subtract (with Carry) Arithmetic Shift Left (“multiply by 2”) Logical Shift Right (“divide by 2”)
  19. SOLUTION: DON’T USE PHYSICS ➤ When player presses jump button,


    check if player is on the ground ➤ If yes, move player up n pixels per frame ➤ Stop moving up when default jump height reached ➤ Then, move player down n pixels per frame ➤ Check for collision with the ground each frame
  20. THE TETRIS SOLUTION: DO IT WITH MATH 16-bit Fibonacci linear

    feedback shift register (LFSR) (XOR bits 1 and 9, store in bit 16, shift right) https://meatfighter.com/nintendotetrisai/#Picking_Tetriminos
  21. THE FINAL FANTASY SOLUTION: USE A LOOKUP TABLE AE D0

    38 8A ED 60 DB 72 5C 59 27 D8 0A 4A F4 34 08 A9 C3 96 56 3B F1 55 F8 6B 31 EF 6D 28 AC 41 68 1E 2A C1 E5 8F 50 F5 3E 7B B7 4C 14 39 12 CD B2 62 8B 82 3C BA 63 85 3A 17 B8 2E B5 BE 20 CB 46 51 2C CF 03 78 53 97 06 69 EB 77 86 E6 EA 74 0C 21 E2 40 D4 5A 3D C7 2B 94 D5 8C 44 FD EE D2 43 00 BB FA C6 1D 98 A0 D3 54 5F 5E DC A8 00 AF 93 A1 E1 6C 04 DE B6 D7 36 16 C5 C8 C4 E4 0F 02 AB E8 33 99 73 11 6A 09 67 F3 FF A2 DF 32 0E 1F 0D 90 25 64 75 B3 65 2F C9 B0 DA 5D 9F EC 29 CE E3 F0 91 7A 58 45 24 1C 47 A4 89 18 2D CC BD 6F 80 F6 81 22 E9 07 70 FB DD AD 35 A6 61 B4 A3 FE B1 30 4B 15 48 6E 4F 5B 13 9C 83 92 01 C2 19 7F 1A 1B 71 B9 3F 4E 9B BF 9E 87 0B 10 57 F2 26 79 9A 05 C0 E0 F7 4D 7D CA 52 9D F9 BC AA FC 8D 7E D1 A5 42 E7 D6 76 A7 84 8E 66 7C 23 88 37 49 D9
  22. “Contra has a single global 8-bit value that it uses

    as the source of randomness throughout the game. …[T]he next random value is generated by spinning in a tight loop during the time that the game is idle and waiting for the next display frame to begin. -Allan Blomquist THE CONTRA SOLUTION: DO SOME REALLY FAST MATH, ALL THE TIME
  23. SOLUTION: WRITE SAVES MULTIPLE TIMES ➤ Store multiple copies of


    the save data with a 
 CRC code (checksum) ➤ On load, check saves one
 by one until you find one 
 that is intact Dragon Warrior (1989)
  24. NINTENDO / VIDEO GAME HISTORY BOOKS ➤ Altice, Nathan. “I

    AM ERROR”. MIT Press, 2015. ➤ Bogost, Ian and Montfort, Nick. “Racing the Beam: The 
 Atari Video Computer System”. MIT Press, 2009. ➤ Bagnall, Brian. “On the Edge: The spectacular rise and fall of Commodore”. Variant Press, 2005. ➤ Sheff, David. “Game Over: How Nintendo zapped an American industry, captured your dollars, and enslaved your children”. Random House, 1993.