MAKING 8-BIT ARCADE GAMES IN C An 8bitworkshop Book by Steven Hugg Making 8-Bit Arcade Games in C Copyright©2017byStevenHugg All rights reserved. No part of this book may be reproduced withoutwrittenpermissionfromtheauthor. Firstprinting: April2017 Disclaimer Although every precaution has been taken in the preparation ofthisbook,thepublisherandauthorassumenoresponsibility forerrorsoromissions,norisanyliabilityassumedfordamages resulting from the use of the information contained herein. No warrantiesofanykindareexpressedorimplied. Making 8-Bit Arcade Games in C is an independent publication andhasnotbeenauthorized,sponsored,orotherwiseapproved byanythirdparty. Trademarks Brands and product names mentioned in this work are trade- marks or service marks of their respective companies. Use of a term in this work should not be regarded as affecting the validityofanytrademarkorservicemark. Inquiries [email protected]. Contents Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ix Whyreadthisbook? . . . . . . . . . . . . . . . . . . . . ix Whyfocusonarcadegames? . . . . . . . . . . . . . . ix Whichhardwarewasmostinfluential? . . . . . . . . . x WhyuseConan8-bitplatform? . . . . . . . . . . . . . xi 1 CPUBasics . . . . . . . . . . . . . . . . . . . . . . . . . 1 1.1 Bits,Bytes,andBinary . . . . . . . . . . . . . . . 1 1.2 HexadecimalNotation . . . . . . . . . . . . . . . 2 1.3 Signedvs. UnsignedBytes . . . . . . . . . . . . . 3 1.4 IntegerOverflowandArithmetic . . . . . . . . . . 4 1.5 TheCPUandtheBus . . . . . . . . . . . . . . . . 4 1.6 CPUInstructions . . . . . . . . . . . . . . . . . . . 6 2 TheZ80CPU . . . . . . . . . . . . . . . . . . . . . . . . 8 2.1 Registers . . . . . . . . . . . . . . . . . . . . . . . 9 2.2 ReadingandWritingMemory . . . . . . . . . . . . 11 2.3 FlagsandBranching . . . . . . . . . . . . . . . . 12 2.4 Stack . . . . . . . . . . . . . . . . . . . . . . . . . 15 2.5 LogicalOperations . . . . . . . . . . . . . . . . . 16 3 Hello8-bitCWorld . . . . . . . . . . . . . . . . . . . . . 18 3.1 PreprocessorandCompiler . . . . . . . . . . . . . 18 3.2 Assembler . . . . . . . . . . . . . . . . . . . . . . 21 3.3 Linker . . . . . . . . . . . . . . . . . . . . . . . . . 22 3.4 ROMImage . . . . . . . . . . . . . . . . . . . . . . 24 4 SomeCExamples . . . . . . . . . . . . . . . . . . . . . 25 iii Contents 5 The8bitworkshopCIDE . . . . . . . . . . . . . . . . . . 30 5.1 DebugWindow . . . . . . . . . . . . . . . . . . . . 33 6 TheVICDualHardware . . . . . . . . . . . . . . . . . . 34 6.1 History . . . . . . . . . . . . . . . . . . . . . . . . 34 6.2 MemoryMap . . . . . . . . . . . . . . . . . . . . . 35 6.3 Video . . . . . . . . . . . . . . . . . . . . . . . . . 35 6.4 Colors . . . . . . . . . . . . . . . . . . . . . . . . . 38 6.5 Typedefs . . . . . . . . . . . . . . . . . . . . . . . 40 6.6 AMinimalMainFunction . . . . . . . . . . . . . . 41 6.7 CRoutines . . . . . . . . . . . . . . . . . . . . . . 43 6.8 Controllers . . . . . . . . . . . . . . . . . . . . . . 44 6.9 Z80EntryRoutine . . . . . . . . . . . . . . . . . . 46 7 SiegeGame . . . . . . . . . . . . . . . . . . . . . . . . . 47 7.1 DataStructures . . . . . . . . . . . . . . . . . . . 48 7.2 MainFunction . . . . . . . . . . . . . . . . . . . . 49 8 ShiftandRotate . . . . . . . . . . . . . . . . . . . . . . 57 8.1 ShiftOperations . . . . . . . . . . . . . . . . . . . 57 9 TheProgrammableSoundGenerator . . . . . . . . . . 60 9.1 TheAY-3-8910PSG . . . . . . . . . . . . . . . . . 61 9.2 InlineFunctions . . . . . . . . . . . . . . . . . . . 65 10 Binary-CodedDecimal. . . . . . . . . . . . . . . . . . . 66 11 Pointers . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 11.1 APointerisaTypedMemoryAddress . . . . . . . 68 11.2 APointerisaReferenceToAnotherVariable . . . 69 11.3 APointerisaString . . . . . . . . . . . . . . . . . 69 11.4 APointerisanArray... SortOf . . . . . . . . . . . 70 11.5 APointerisanExtraReturnValue . . . . . . . . . 71 12 TheMidway8080Hardware . . . . . . . . . . . . . . . 72 12.1 History . . . . . . . . . . . . . . . . . . . . . . . . 72 12.2 MemoryMap . . . . . . . . . . . . . . . . . . . . . 73 12.3 Graphics . . . . . . . . . . . . . . . . . . . . . . . 73 12.4 Drawvs. Erasevs. XOR . . . . . . . . . . . . . . . 75 iv Contents 12.5 DrawingText . . . . . . . . . . . . . . . . . . . . . 77 12.6 Pixel-AccurateSpriteShifting . . . . . . . . . . . 78 12.7 WatchdogTimer . . . . . . . . . . . . . . . . . . . 80 13 Game: CosmicImpalas . . . . . . . . . . . . . . . . . . 81 13.1 GameData . . . . . . . . . . . . . . . . . . . . . . 81 13.2 TheGameLoop . . . . . . . . . . . . . . . . . . . 83 13.3 CollisionDetection. . . . . . . . . . . . . . . . . . 86 13.4 AnimatinganExplosion . . . . . . . . . . . . . . . 89 14 Interrupts . . . . . . . . . . . . . . . . . . . . . . . . . . 91 14.1 Interrupts . . . . . . . . . . . . . . . . . . . . . . . 91 15 Randomness . . . . . . . . . . . . . . . . . . . . . . . . 95 15.1 GaloisLFSR . . . . . . . . . . . . . . . . . . . . . . 96 15.2 Entropy . . . . . . . . . . . . . . . . . . . . . . . . 97 16 InitializingMemory . . . . . . . . . . . . . . . . . . . . 98 16.1 Initializedvs. Uninitializedvs. Const . . . . . . . 98 16.2 InitializingMemory . . . . . . . . . . . . . . . . . 100 16.3 InitializingStringsvs. Arrays . . . . . . . . . . . . 101 17 TheGalaxianHardware . . . . . . . . . . . . . . . . . . 102 17.1 History . . . . . . . . . . . . . . . . . . . . . . . . 102 17.2 MemoryMap . . . . . . . . . . . . . . . . . . . . . 104 17.3 OtherSpecialAddresses . . . . . . . . . . . . . . 108 17.4 GraphicsROMs . . . . . . . . . . . . . . . . . . . . 109 17.5 Sound . . . . . . . . . . . . . . . . . . . . . . . . . 109 17.6 WhenNottoUsememset() . . . . . . . . . . . . . 110 18 Game: Solarian . . . . . . . . . . . . . . . . . . . . . . 111 18.1 DrawingTilesvs. Sprites . . . . . . . . . . . . . . 113 18.2 Attack! . . . . . . . . . . . . . . . . . . . . . . . . 115 18.3 DirectionsandTrig . . . . . . . . . . . . . . . . . 117 18.4 AlienBehavior . . . . . . . . . . . . . . . . . . . . 119 18.5 ReturningToFormation . . . . . . . . . . . . . . . 120 18.6 Missiles . . . . . . . . . . . . . . . . . . . . . . . . 121 18.7 BlowingUpAliens . . . . . . . . . . . . . . . . . . 122 18.8 GameSound . . . . . . . . . . . . . . . . . . . . . 123 v Contents 18.9 KeepinginSyncwithInterrupts . . . . . . . . . . 124 19 MakingMusic . . . . . . . . . . . . . . . . . . . . . . . . 126 19.1 HittingtheRightNote . . . . . . . . . . . . . . . . 126 19.2 LayingouttheScore . . . . . . . . . . . . . . . . 127 19.3 SwingingwiththeTempo . . . . . . . . . . . . . . 128 19.4 ComposingtheMusic . . . . . . . . . . . . . . . . 130 19.5 NeedSomeMIDIFiles? . . . . . . . . . . . . . . . 130 19.6 Scramble/FroggerSoundBoard . . . . . . . . . . 131 20 IntegersandYou . . . . . . . . . . . . . . . . . . . . . . 132 20.1 PowersofTwo . . . . . . . . . . . . . . . . . . . . 132 20.2 UnsignedComparisons . . . . . . . . . . . . . . . 134 21 TheAtariVectorHardware . . . . . . . . . . . . . . . . 135 21.1 History . . . . . . . . . . . . . . . . . . . . . . . . 135 21.2 HowVectorMonitorsWork . . . . . . . . . . . . . 136 21.3 AnalogVectorGenerator(AVG) . . . . . . . . . . 137 21.4 Z80MemoryMap . . . . . . . . . . . . . . . . . . 140 21.5 AVGCRoutines. . . . . . . . . . . . . . . . . . . . 141 22 3-DVectors . . . . . . . . . . . . . . . . . . . . . . . . . 144 22.1 3DTypes . . . . . . . . . . . . . . . . . . . . . . . 144 22.2 SineandCosine . . . . . . . . . . . . . . . . . . . 146 22.3 WireframeModels . . . . . . . . . . . . . . . . . . 148 22.4 Transformation . . . . . . . . . . . . . . . . . . . 150 22.5 TheMultBox . . . . . . . . . . . . . . . . . . . . . 150 23 Game: CrowdedOrbit . . . . . . . . . . . . . . . . . . . 152 23.1 ShapePrerendering . . . . . . . . . . . . . . . . . 152 23.2 Actors . . . . . . . . . . . . . . . . . . . . . . . . . 154 23.3 DrawingActors . . . . . . . . . . . . . . . . . . . . 155 23.4 MovingActors . . . . . . . . . . . . . . . . . . . . 156 23.5 AllocatingMemorywithmalloc() . . . . . . . . . . 157 23.6 LinkedLists . . . . . . . . . . . . . . . . . . . . . . 158 23.7 FunctionPointers . . . . . . . . . . . . . . . . . . 160 23.8 DeletingObjects . . . . . . . . . . . . . . . . . . . 161 23.9 CollisionDetection. . . . . . . . . . . . . . . . . . 162 23.10TheMainLoop . . . . . . . . . . . . . . . . . . . . 163 vi Contents 24 ThePOKEYSoundChip . . . . . . . . . . . . . . . . . . 166 24.1 MemoryMap . . . . . . . . . . . . . . . . . . . . . 167 24.2 AUDCTLBitMap . . . . . . . . . . . . . . . . . . . 167 24.3 AUDCxBitMap . . . . . . . . . . . . . . . . . . . . 167 24.4 SettingAUDFFrequency . . . . . . . . . . . . . . 168 24.5 POKEYMusic . . . . . . . . . . . . . . . . . . . . . 169 25 MiscellaneousCTopics . . . . . . . . . . . . . . . . . . 170 25.1 Unions . . . . . . . . . . . . . . . . . . . . . . . . 170 25.2 BigNumbers . . . . . . . . . . . . . . . . . . . . . 171 25.3 AdvancedLoopHandling . . . . . . . . . . . . . . 171 25.4 OperatorPrecedence . . . . . . . . . . . . . . . . 172 26 WilliamsHardware. . . . . . . . . . . . . . . . . . . . . 173 26.1 History . . . . . . . . . . . . . . . . . . . . . . . . 173 26.2 MemoryMap . . . . . . . . . . . . . . . . . . . . . 174 26.3 BankswitchedRAM/ROM . . . . . . . . . . . . . . 175 26.4 VideoFrameBuffer . . . . . . . . . . . . . . . . . 175 26.5 Palette . . . . . . . . . . . . . . . . . . . . . . . . 176 26.6 BitBlitter . . . . . . . . . . . . . . . . . . . . . . . 177 26.7 BlittingtoPixelBoundaries . . . . . . . . . . . . . 182 26.8 OtherHardwareLocations . . . . . . . . . . . . . 182 26.9 WhenNottoUsememset() . . . . . . . . . . . . . 183 27 WilliamsSprites . . . . . . . . . . . . . . . . . . . . . . 184 27.1 KeepingTrackofObjects . . . . . . . . . . . . . . 184 27.2 GettingRidofFlicker . . . . . . . . . . . . . . . . 185 27.3 CollisionDetection. . . . . . . . . . . . . . . . . . 187 27.4 Clipping . . . . . . . . . . . . . . . . . . . . . . . . 189 27.5 GettingByWith8Bits . . . . . . . . . . . . . . . . 189 28 Run-LengthEncoding . . . . . . . . . . . . . . . . . . . 190 29 WilliamsSound. . . . . . . . . . . . . . . . . . . . . . . 193 29.1 TheSWAVESystem . . . . . . . . . . . . . . . . . 194 29.2 TriggeringSoundsfromtheMainCPU . . . . . . 196 30 ImportingAssets . . . . . . . . . . . . . . . . . . . . . . 197 30.1 Installing8bitworkshopTools . . . . . . . . . . . 197 vii Contents 30.2 GraphicsTools . . . . . . . . . . . . . . . . . . . . 200 30.3 SoundTools . . . . . . . . . . . . . . . . . . . . . 201 30.4 Third-PartyTools . . . . . . . . . . . . . . . . . . 201 30.5 FreeArt . . . . . . . . . . . . . . . . . . . . . . . . 201 30.6 Using8bitworkshopOffline . . . . . . . . . . . . . 202 31 DistributingYourGame . . . . . . . . . . . . . . . . . . 203 31.1 MakingROMFiles . . . . . . . . . . . . . . . . . . 203 31.2 PlayingonActualHardware . . . . . . . . . . . . 204 AppendixA:Troubleshooting . . . . . . . . . . . . . . . . . i ProgrammerError . . . . . . . . . . . . . . . . . . . . . i CompilerOddities . . . . . . . . . . . . . . . . . . . . . ii Bibliography . . . . . . . . . . . . . . . . . . . . . . . . . . iii Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . v viii Preface Why read this book? 1. You want to learn about the internals of Golden Age arcadegames. 2. You want to experience what it would have been like to program these games if you had access to an advanced 8- bitCcompiler. 3. You want to learn C on devices with slow CPUs and little RAM. You’ll learn all about the hardware of late 1970s-early 1980s arcade games, and we’ll create a few simple games with the C programminglanguagealongtheway. Why focus on arcade games? The arcade games developed in the late 1970s to early 1980s demonstrate a wide range of capabilities that evolved over a relatively short period of time. Memory and ROM space got bigger, and video hardware got more sophisticated. Sound evolvedtoo,frombleepsandbloopstoFMandspeechsynthesis. These architectures were even more stripped down than per- sonalcomputersofthetime,insomeways. Thingslikeextensi- bility and ease of programming were not design criteria. All of the magic was in the video hardware and sound board, which wereafewyearsaheadoftechnologyavailableforthehome. ix Whichhardwarewasmostinfluential? All of the system architectures described in this book were used for more than one title. Some games were developed by the original manufacturer or their licensees, but some were developed unofficially — “bootlegs,” in other words. Bootleg vendorscouldeasilyduplicatethePCB,madeeasierbythefact that most arcade games included their own schematic in the servicemanual. Thenitwasamatterofreverse-engineeringthe originalROMandadaptingtothenewhardware. Emulator developers have pretty much figured out the hard- ware by now, but with this book you can experience the thrill of writing your own “unauthorized” homebrew game for an obsoletehardwareplatform! Which hardware was most influential? We’re going to focus on five distinct arcade platforms — hard- warethatwasrepurposedforseveraldifferentgames. Eachwas influentualorgroundbreakinginitsownway: Midway 8080 (1975-1980): Developed by Dave Nutting Asso- ciates, this platform’s 7 kilobyte frame buffer not only powered thehugelyinfluentialSpaceInvaders,butalsoacoupleofdozen other games. Credited as the first arcade platform that used a microprocessor. VIC Dual (Sega/Gremlin, 1977-1981): A tile-based Z80 plat- form that drove 20 titles, including some of the first RGB color games. Includedforitssimplicityandhistoricvalue. Galaxianhardware(Namco,1979-1984): Galaxianwasinfluen- tialgameforitsvividRGBcolor, smoothsprites, andsparkling starfield background. It influenced or formed the basis of severalotherhardwaredesigns,includingPac-Man,Frogger,and DonkeyKong. Atarivectorhardware(Atari,1979-1985): Themostsuccessful vector-basedplatformstartedinblack-and-white(LunarLander) andlatermovedtocolor(Tempest,StarWars). ItusedaMotorola 6502 or 6809 CPU with custom hardware to draw vectors and calcuate3Dtransformations. x
Description: