Kevin Zurawel
August 21, 2019
210

# 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.

August 21, 2019

## Transcript

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

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

RAM ➤ No permanent storage ➤ Read-only cartridges;  32KB code, 8KB graphics data

1.
15. ### Number of bits Possible values 1 2 2 4 3

8 4 16 5 32 6 64 7 128 8 256
16. ### As far as the NES is concerned, everything is a

number between zero and 255.

screen
21. ### 256 pixels wide  × 240 pixels tall 61,440 pixels  per

screen ÷ 4 pixels per byte
22. ### 256 pixels wide  × 240 pixels tall 61,440 pixels  per

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

screen ÷ 4 pixels per byte 15 KB  per screen (!!!)
24. ### PROBLEM #1 How do you draw a screen of graphics

in less than 2KB?

28. ### BACKGROUNDS 32 x 30 grid of tiles 8x8 pixels per

tile 960 tiles per screen 1 byte per tile 960 bytes per screen

32. ### SPRITES 256 bytes of sprite RAM  ÷ 4 bytes per

sprite   (tile #, x/y, palette #) 64 sprites at a time

per scanline
34. ### PROBLEM #2 How do you show a lot of action

with only 8 sprites per line?

38. ### 14 screens of graphics  × 960 bytes per screen ~13

KB graphics data
39. ### 14 screens of graphics  × 960 bytes per screen ~13

KB graphics data … for World 1-1 alone

41. ### PROBLEM #3 How do you store a big game  in

32KB or less?
42. ### 1. MAKE USE OF DEFAULT COLOR 228  non-default   tiles

(23.75% of  the screen)
43. ### 2. MAKE USE OF REPEATED META-OBJECTS Instead of storing 24

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

tiles, store “brick tile repeats 32 times” for three rows
45. ### SUPER MARIO BROS.: GET EVEN MORE ABSTRACT "set decoration” (3

screens wide)

47. ### ;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
48. ### ;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
49. ### ;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
50. ### 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

52. ### THE “STANDARD” 2D JUMP ALGORITHM Height at time t =

vertical velocity + (acceleration from gravity2 / 2)
53. ### 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”)

55. ### 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

59. ### PROBLEM #5 How do you handle collisions between  lots of

objects in real-time?

64. ### PROBLEM #6 How do you make random numbers  without a

system-wide RNG?
65. ### 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

67. ### 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
68. ### “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

79. ### PROBLEM #8 How do you make writable game media  that

users can’t easily copy?

82. ### PROBLEM #9 How do you ensure that save data  hasn’t

been corrupted?
83. ### 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 ﬁnd one   that is intact Dragon Warrior (1989)

86. ### 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. ➤ Sheﬀ, David. “Game Over: How Nintendo zapped an American industry, captured your dollars, and enslaved your children”. Random House, 1993.