"Game Development in Eight Bits" by Kevin Zurawel

  Рет қаралды 535,278

Strange Loop Conference

Strange Loop Conference

Күн бұрын

The "8-Bit" era of the late '80s brought video games into the home with systems like the Nintendo Entertainment System (NES). Game developers of the time produced iconic games and introduced genres that are still with us to this day, while working with hardware that had serious limitations. This talk will explore how NES developers created more with less, looking at techniques used in professionally-developed NES games to handle physics, collision detection, randomness, data compression, and more.
Kevin Zurawel
Candid
Kevin has been an NES fan since he first played "Super Mario Bros." in 1989. He learned to program out of a love of video games, and ended up with a career in web development. Kevin is currently an engineering manager at Candid and explores programming for old game consoles in his spare time.
Recorded at Strange Loop 2021
thestrangeloop.com

Пікірлер: 357
@AkihitoKoriyama
@AkihitoKoriyama Жыл бұрын
Ex NES dev here. Our RNG was also stupid, basically just multiplied by 5 and added 1 with an 8-bit value.
@Bunny99s
@Bunny99s Жыл бұрын
It's actually not that stupid. That's how a lot PRNG's are implemented even today. It's called a "Linear congruential generator" (LCG). Look it up on wikipedia. The great thing about multiplying by a "relatively" large number (5 is relatively large for byte values) is that it quickly overflows. The whole sequence of (x*5+1)%256 is: --   0,   1,   6,  31, 156,  13,  66,  75, 120,  89, 190, 183, 148, 229, 122,  99, 240, 177, 118,  79, 140, 189, 178, 123, 104,   9,  46, 231, 132, 149, 234, 147, 224,  97, 230, 127, 124, 109,  34, 171,  88, 185, 158,  23, 116,  69,  90, 195, 208,  17,  86, 175, 108,  29, 146, 219,  72, 105,  14,  71, 100, 245, 202, 243, 192, 193, 198, 223,  92, 205,   2,  11,  56,  25, 126, 119,  84, 165,  58,  35, 176, 113,  54,  15,  76, 125, 114,  59,  40, 201, 238, 167,  68,  85, 170,  83, 160,  33, 166,  63,  60,  45, 226, 107,  24, 121,  94, 215,  52,   5,  26, 131, 144, 209,  22, 111,  44, 221,  82, 155,   8,  41, 206,   7,  36, 181, 138, 179, 128, 129, 134, 159,  28, 141, 194, 203, 248, 217,  62,  55,  20, 101, 250, 227, 112,  49, 246, 207,  12,  61,  50, 251, 232, 137, 174, 103,   4,  21, 106,  19,  96, 225, 102, 255, 252, 237, 162,  43, 216,  57,  30, 151, 244, 197, 218,  67,  80, 145, 214,  47, 236, 157,  18,  91, 200, 233, 142, 199, 228, 117,  74, 115,  64,  65,  70,  95, 220,  77, 130, 139, 184, 153, 254, 247, 212,  37, 186, 163,  48, 241, 182, 143, 204, 253, 242, 187, 168,  73, 110,  39, 196, 213,  42, 211,  32, 161,  38, 191, 188, 173,  98, 235, 152, 249, 222,  87, 180, 133, 154,   3,  16,  81, 150, 239, 172,  93, 210,  27, 136, 169,  78, 135, 164,  53,  10,  51 -- This is a full cycle through all 256 values without repeats. Yes, the distribution is not that perfect. For this the multiplication factor needs to be higher so you get a greater "avalanche effect" between two numbers in the sequence. Though multiplying by 5 is relatively cheap with add and shift (left shift by 2 and add the original value to itself. So in essence multiply by 4 and add one more to get 5). So it's a great compromise between practicality and quality. I've implemented the standard 32 bit turbo pascal LCG (0x8088405) in lua for some simple encryption in computercraft :) of course it's not really secure, but it works quite well. It serves two purposes: obfuscation of wireless modem messages and more resiliance against random malformed messages. My system even used a fix encryption key as well as a random per-message-key. So it makes it harder to reverse engineer or detect patterns ^^.
@auri4061
@auri4061 Жыл бұрын
@@Bunny99s Whoa, I should have expected to see a ComputerCraft mention out here! Do you do this stuff solo or is there some kind of community I'm not aware of?
@alexandarjelenic2880
@alexandarjelenic2880 Жыл бұрын
What games did you develop?
@CelestialHunter-
@CelestialHunter- Жыл бұрын
I don’t get why it’s “stupid” if it works fine. Can you like figure out this RNG pattern and abuse it to your advantage or something?
@yep_2431
@yep_2431 Жыл бұрын
​@@Bunny99s did you tell an actual NES Dev to look it up on Wikipedia?,, 🤭
@KrzysztofGnutek
@KrzysztofGnutek 2 жыл бұрын
I love all those crazy and creative optimizations to make games fit and run on hardware that's so limited that it might seem that a game like that would not be possible :)
@Zalied
@Zalied 2 жыл бұрын
im only halfway in the video so he may mention this. but my favorite optimization in mario is that there are not 32 levels. many levels are the same level and all it does is check is it the hard or easy version of the level. like there are plants in EVERY pipe but it checks "is this 1-1 if so no plants". this is why the castle levels repeat but some have more fire bars or a maze while the other version may not this drastically reduces the number of levels to store
@reddawnstudios2016
@reddawnstudios2016 2 жыл бұрын
It's nice to see the NES's modern descendant , the Switch, doing some similar stuff.
@muslimsrememberapostacyday556
@muslimsrememberapostacyday556 2 жыл бұрын
I like that "random" generator which works on frames. In C64, the timer was located in zeropage which is very fast to access, so you could do the same thing essentially, just reading the timer instead for example. The idea to use the time between title page and start-of-game is also good to get a random number from start.
@amitshukla1495
@amitshukla1495 2 жыл бұрын
Even I really love these cute optimizations , any other similar recommendation in form of book/ video which shows examples of good optimisations...?
@LordHonkInc
@LordHonkInc Жыл бұрын
I love that you could describe the idea of "generating" random numbers from a lookup table as "if you can't make your random numbers from scratch, store-bought is fine, too"
@achtsekundenfurz7876
@achtsekundenfurz7876 Жыл бұрын
Another famous game thaat does it: DOOM. It also advances the index according to certain actions, since those take random numbers, too. For example, any direct attack that hits something with HP queries the random table to give the hit a random amount, from 1/4 to twice the stated power. (Explosives work differently; their damage is power minus the distance to the target, or no hit at all if that's a negative number -- and up/down distance is completely ignored.) At some points, the A.I. running the creatures use random numbers for their decisions, too. But the bottom line is that DOOM gameplay saves (those you can playback to watch what other players did) only work because the starting position is always the same. If you repeat the input in a frame-perfect way, you get the same result. And that's exactly what the playback subroutine does; the file contains user input and timing data only; actual damage figures, shotgun spread, and A.I. decisions are recomputed.
@dijoxx
@dijoxx 5 ай бұрын
@@achtsekundenfurz7876 Doom can generate random numbers using the clock. It doesn't use a lookup table.
@robbymulvany2109
@robbymulvany2109 Жыл бұрын
I love videos like this. I used to develop games in Macromedia Director, and it had a ton of limitations. When I made Mario Paint Composer I couldn't store music the way I wanted to. This is because Director didn't handle arrays very good. You couldn't just jump to the last note in the song - Director had to read every single item in the array before getting there. So the longer the song, the more time it would take to read subsequent notes. So what I did is I saved the songs as image files. I could jump to any pixel and read its RGB value. So I'd store music that way. The R value in a pixel might be the note, the instrument, or the velocity. Then for each new note I'd just read the next horizontal pixel, then the next, then the next.
@RistrayGR
@RistrayGR 2 жыл бұрын
"If it's stupid and it works, it's not stupid." Great talk!
@glurp1er
@glurp1er 4 ай бұрын
The most impressive is that those programmers did all this without internet, only helped by a shitty documentation translated from Japanese. Understanding how the NES worked was already an enigma to solve before you even started coding for it.
@youngzombie6342
@youngzombie6342 2 жыл бұрын
Amazing thing is how Kevin Zurawel explain this on a simple way. This was 34 minuutes, but to me was just like 5. I want more, for sure. Nice work, Kevin!
@thepianomaker6334
@thepianomaker6334 5 ай бұрын
“If it’s stupid and it works, it’s not stupid”
@boredfish80
@boredfish80 2 жыл бұрын
29:25 "...2.5inch disks, here they are with a save icon for size reference" That amused me way more than it probably should have :D
@BenderdickCumbersnatch
@BenderdickCumbersnatch 2 жыл бұрын
Haha it made me go crazy at the realization that we still use floppies as save icons.
@NLPaulus
@NLPaulus 2 жыл бұрын
Same reaction here. Im like "interesting lecture, cool stuff. " then "save icon" XD
@slinkychungus2044
@slinkychungus2044 Жыл бұрын
The ability to explain complex topics to people that aren’t too seasoned in the field is so impressive
@ChrisM541
@ChrisM541 2 жыл бұрын
The very significant restrictions in the 8 bit era led to many incredibly ingenious solutions, all driven by an expert level knowledge of the CPU's instruction optimisations and equally ingenious memory management optimisation. A truly unique, golden era of programming. I miss those days! I still program professionally today and while of course inevitable, my unique historical viewpoint makes me somewhat saddened by how much has been abstracted away today, to the point where so much is provided to the developer - resulting in much of that absolute requirement for critical thinking present in the 80's, quite simply, rapidly heading to a 'not required' status.
@dewaard3301
@dewaard3301 Жыл бұрын
Finally, I understand my childhood. Thank you for building this talk from the ground up, with 0 required knowledge.
@gunhaver12
@gunhaver12 Жыл бұрын
I love the idea of making NES games today, creating within the original hardware limitations as a creative practice. In my experience, creativity thrives under constraints..
@MotiviqueStudio
@MotiviqueStudio 2 жыл бұрын
It's amazing how occupied I stayed with such a small amount of data for so long. Contra collision detection was pretty fascinating.
@GGxEpsilon
@GGxEpsilon 2 жыл бұрын
Agreed. Now we just take the computing power we have for granted.
@Clery75019
@Clery75019 Жыл бұрын
Toshihiko Nakago, that's the guy who programmed Super Mario Bros. And The Legend of Zelda. And the following games of both series. He deserves a lot of praise, yet he doesn't even have his own Wikipedia page in English. 🙁
@timberhoff
@timberhoff Жыл бұрын
pioneer of the game!
@xeridea
@xeridea 2 жыл бұрын
Worth noting on the graphics, each tile was 2 bits per pixel, allowing 4 colors defined for the tile. What 4 colors were used could be changed or "palette swapped", efficiently allowing reuse with minimal space. This is why many enemies, player and background sprites look the same.
@Henrix1998
@Henrix1998 2 жыл бұрын
NES had multiple ways to use tiles and colours, this presentation could spend the whole 30 minutes just on that
@vast634
@vast634 2 жыл бұрын
I used to make very small compressed (4 kilobytes) games for programming competitions. There are a lot of parallels to the optimization and simplification they had to do for those old platforms. Modern games dont really worry about such detailed optimizations much unless it impacts framerate / streaming speed, ending up in those 8 gigabyte patches for a few changes in the gameworld and logic.
@kristianTV1974
@kristianTV1974 2 жыл бұрын
That linear feedback XOR register 'algorithm' is exactly how we generated random noise in our hardware for dithering audio. Super useful.
@THB192
@THB192 2 жыл бұрын
Galois LFSRs are super commonly used everywhere. CRC is built on them, for example. I was first exposed to them when I read Fabien Sanglard's explanation of how the Wolf3D killscreen was drawn.
@Linuxdirk
@Linuxdirk Жыл бұрын
It's impressive how optimized those games were and how clever the devs were able to reduce the size. Nowadays it's "Yeah, sure, 90 Gigabytes are absolutely fine! We have basically unlimited space, so why optimize?"
@eMbry00s
@eMbry00s Жыл бұрын
Should be noted that the average 90GB game's size usually consists of very compressed texture data and model data. Game studios usually buy services or hire consultants to help reduce these sizes. It's very important to them and not at all something they shrug off. This is a standard "gamer doesn't understand the problem complexity and calls game dev lazy" pattern. The reason game devs REALLY care about this is that you need to get this data from CPU to GPU, and for the game to run ok you need to be able to do this very quickly. There are plenty of middleware companies that specialize in exactly this sort of thing. So they're optimizing for CPU->GPU transfer rate, and this leads to complex trade-offs that surprisingly don't always involve making the texture as small in memory as possible. I'm not saying the "who cares" attitude doesn't exist, but there's no room for it if you want to be a successful competitor at the top.
@eMbry00s
@eMbry00s Жыл бұрын
Also consider that textures these days are WAY larger than in the past. You might think a 4096x4096 texture is about four times larger than a 1024x1024 size texture, but it's actually 16 times the number of pixels. Now you might be surprised that we've gone from 10GB games to 120GB games in the last few years, but that's entirely within that 16x multiplier
@matteoquarta2198
@matteoquarta2198 Жыл бұрын
keep in mind that sometimes bigger size is used for performance. As an example, PS1 Crash had random data at the center of the disk so the actual data on the edge would allow for more throughput when the disk spins
@Uradamus
@Uradamus Жыл бұрын
A lot of the data in modern games that make them so big is actually audio in most cases. When you want a ton of voice acting and you need it to play basically instantly without the overhead of decompressing it first, you end up with a crap ton of large audio files. Was a lot easier to keep things small when all conversations were just a series of generated beeps that accompanied the text roll, heh. Even worse if it has been localized for several languages and each get their own set of audio files that end up going out in every copy instead of just for the regions that need them. One of those areas where a lot of studios aren't really taking proper advantage of the modern age of game download services that can technically use a different depot for each language and only download the one that matches the users settings.
@jmason0622
@jmason0622 2 жыл бұрын
As a software developer that is still enamored with video games, this still fills me with admiration for the game devs of old. Hardware limits were there but that just forced devs to optimize like crazy.
@sirgouki6207
@sirgouki6207 2 жыл бұрын
Metroid should have been the dumbest RNG example, it pulls something from the initial state of ram, which is why certain enemies **don't** vary like they should - it only does this once.
@janherfs3063
@janherfs3063 Жыл бұрын
Always amazes me how powerful abstraction is. How much power you can achieve just by dismissing some unnessecary details
@Anteksanteri
@Anteksanteri Жыл бұрын
This is kind of the opposite of how abstraction is usually handled in modern software development. They try to make something complex and then when that's done, provide an interface (java ruined this word) to it for people to use without having to worry about the underlying meticulous construction. I find that any algorithmic problems are usually easiest to solve with as few lines as possible though and just run it. Simple code and only a few lines. It's surprising how often it just works or requires like 1 or 2 small changes. Neurotically checking for null before the program is tested is just bad because it makes writing it a lot more mentally taxing and like half the code will be completely unnecessary.
@1gnore_me.
@1gnore_me. 2 жыл бұрын
wow that bit about contra and how it handles collision detection is actually really ingenious.
@BobbiCodes
@BobbiCodes 2 жыл бұрын
Another noteworthy use of random numbers is for the noise channel of the Audio Processing Unit, used for generating snare drums, cymbals and gunshots, etc. The Linear-Feedback Shift-Register method happens to create a full spectrum of sounds by varying the sample rate, or by reducing the sequence of bits producing a metallic tone as heard in the Megaman games.
@AffidavidDonda
@AffidavidDonda 2 жыл бұрын
this is exactly why atari had random number generator (17 bit shift register). LDA RANDOM is so much easier in atari 8-bit.
@Novous
@Novous Жыл бұрын
Wolfenstein 3D and DOOM both use a hardcoded (the same one in fact) table of 256 values for random numbers. lookup tables were fairly common for everything back when CPUs weren't much faster than RAM. sin/cos tables. fixed point math tables.
@SeppelSquirrel
@SeppelSquirrel 2 жыл бұрын
32:07 I dropped my jaw when I heard how Dragon Warrior saves its games. No wonder my saves on Dragon Warrior outlasted all other saves.
@MtnSmithy
@MtnSmithy Жыл бұрын
I absolutely adore the creative problem-solving that goes into making these old games fit such tiny storage limitations. The example of how Contra handles collision blew my mind. Excellent talk and presentation.
@phookadude
@phookadude Жыл бұрын
Contra's random number system is the best system presented. User feedback and timings are much better than any pseudo random system. The important point about the other two systems presented is what is the seed? Contra's system essentially creates new seeds constantly.
@lonewolfprogrammer8932
@lonewolfprogrammer8932 Жыл бұрын
I was gonna say that it sounded like the most random one
@danevileye
@danevileye 2 жыл бұрын
Regarding ramdomly generated numbers, a great example that uses the RNG Table is Doom, since the developers wanted the player to be able to record its gameplays into demo files and be replayed in any PC that had the same Doom version. By using the RNG table, u could always expect the same results (either them being behaviors, values, etc) when replaying the demos. This ultimately lead to the popularization of speedrunning in general, since now players could record and distribute their playthroughts without using a camcorder or other bulky and expensive solution while also having tiny *.LMP (demo) files.
@SianaGearz
@SianaGearz 2 жыл бұрын
Actually LFSR as shown here for Tetris is also completely deterministic and is easily reset to a known internal state. From that state on, it always reproduces the same sequence. I think random table was merely because it was faster and good enough.
@melanierhianna
@melanierhianna Жыл бұрын
I've been coding since about 1980 and I loved this talk! Some I knew and some I didn't know.
@matthewconte
@matthewconte 2 жыл бұрын
Great talk, Kevin! I wrote a few NES emulators back in the day, and wrote z80 assembly for GameBoy Color professionally for a couple years back in the 1900's, and this presentation was spot on.
@dovedozen
@dovedozen 2 жыл бұрын
the benefits of "embracing the stupid" are so incredibly real; I'm VERY new to game dev and have learned so much from just going "whatever; I'll do it this way for now" and moving on to something else for a while with my technically-functioning solution intact. I've been able to go BACK later with skills I learn doing Other Stuff and make my stupid solutions better / more like the way I wanted them to work originally... & obviously at a certain point, it's reasonable to just say "this is good enough" if your game functions and you don't have anything else to fuss with before you declare it Finished. I love the thing about just writing the save file 8 times especially... sometimes brute force is exactly what you need!
@roop5318
@roop5318 2 жыл бұрын
Slow burn up to 34:00 was worth the like and applies to all of life, not just software. Thank you!
@joshwallace5769
@joshwallace5769 2 жыл бұрын
this is extremely eye opening, thanks for posting!
@scottmarshall1414
@scottmarshall1414 2 жыл бұрын
Great talk! No mention of sound and music, an important feature of the NES. I've been asked how game programs had so many things going on at once. I did it with finite state machines. One racing game I developed needed trig tables, which I precomputed that took up an entire bank of ROM in the cartridge. We called the tiles "characters", which is why they're named chr. Also not mentioned is the 2x2 cells for background characters that specify their palette. We generally used layers of indirection to define large worlds with few bytes, which you call abstraction. Sprite chrs could also be mirrored horizontally and vertically, and we created tools to compress artist's graphics into character maps so they didn't need to be done manually. Music was also compressed with patterns recognition (abstraction) during assembly
@swanofnutella4734
@swanofnutella4734 2 жыл бұрын
Great talk. I had no idea how far they were pushing the limits of the system to provide the games I grew up on. New appreciation.
@Areshiones
@Areshiones 2 жыл бұрын
I completely agree with the "Embrace the Stupid" concept. I often run into people trying to make perfection for stuff that does not require sophistication. If conventional makers understand the concept many things can be accelerated and then, if required, modified for perfection...
@mariorol5376
@mariorol5376 Жыл бұрын
Thanks for this talk! It was really interesting to get an overview of all the struggles developers had to deal with back in the day and the creative solutions they came up with in the end.
@GameplayandTalk
@GameplayandTalk 2 жыл бұрын
Great talk! And I totally agree--As long as something fulfills its purpose, it doesn't matter how dumb you go about it to get there. Classic videogames are so interesting in that regard.
@antonnym214
@antonnym214 2 жыл бұрын
I'm an old-school programmer from the 70s. APL and BASIC had pretty good Random functions. If you wanted to help that a little, you would specify a seed, which is an offset into the random table. One easy way to generate a random seed would be to run a timing loop after requesting an input to see how many cycles it took for the human to answer the question. "Number of Players?" or whatever the question was. When coding in Z-80 Assembly, if you needed a pseudorandom number, the R register came in handy. That was the Ram Refresh register which kept track of which memory address is being refreshed. You could take that value, AND it with however many bits you needed and VIOLA! Good enough for gubment work, as we said.
@ChrisM541
@ChrisM541 Жыл бұрын
Incredible level of ingenuity in the '80s. I was also going to say 'thinking outside the box' was mandatory, however, there really was no box at this time - you literally had to solve many problems yourself i.e. invent solutions. Remember also, no internet here - so no Google for your docs/resources, no stackoverflow/forum, etc, to answer all your questions. It was an incredibly exciting time as the home computer/console era exploded into so many households, with 6502/10, Z80, etc coders busy perfecting those assembly routines. It's equally incredible how far this tech has advanced. There is a real concern, though, in the obvious over-reliance on the internet to increasingly do all our 'thinking' - especially the 'hard thinking'.
@drakedbz
@drakedbz 2 жыл бұрын
As you were describing how devs solved random number generation, I couldn't help but think about how pokemon games handled it (they were also 8-bit, but significantly more hardware to work with). An absolutely perfect example of a dumb solution that works really well (but if you know what's going on in the code you can exploit it in-game) is called DSUM. Basically there were two variables: the first codes for what pokemon will appear in a random encounter, the second for whether or not an encounter is generated on a given check. Those two numbers would be manipulated each frame, in a somewhat predictable manner, such that the cycling of the values could be tracked. Any given in-game area has a set of pokemon that can be encountered there, each with a specified chance, but these "chances" are coded as some range of values out of 255, so you could have a 20% chance to see a pokemon (25/255), a 10% chance (12/255), and so on. The thing is, because you can track the DSUM which cycles roughly every 6.5 seconds, you know which pokemon can appear at any given time. This means you can decide when to take actions in game that can generate an encounter to manipulate which pokemon actually appears (rather than waste time with getting the wrong encounter). You can't really track whether or not the encounter will be generated in the first place, but by only attempting to generate one when the results would be in your favor, you can save a significant amount of time searching. This is particularly relevant in speedruns, where fractions of a second matter. If anyone is curious about this, you can find more by searching "DSUM manipulation" in google, or by watching any generation 1 or 2 pokemon speedrun, especially the ones on the Games Done Quick channel, as those are marathon runs where the runner will explain what they are doing.
@carterash2588
@carterash2588 2 жыл бұрын
Absolutly amazing lecture.
@AtTheVioletHour
@AtTheVioletHour 2 жыл бұрын
I loved this talk! I enjoyed it so much I actually wish it was a series where I could move on to the SNES or Genesis next, then the N64 or PlayStation, and so on to learn about the advancements and new techniques introduced over time!
@johnsams1388
@johnsams1388 2 жыл бұрын
wow that would be awesome, if you ever find a series like that on YT hit me up. I'll do the same :)
@Mostlyharmless1985
@Mostlyharmless1985 Жыл бұрын
19:20 "In real life, we throw bullets at people and see if they hit, in contra, we throw people at bullets and see if they hit, is more efficient!"
@jemakrol
@jemakrol 2 жыл бұрын
Excellent and interesting presentation! It's easy to appreciate the creativity and pragatic problem solving game devs had to use.
@danvilela
@danvilela 2 жыл бұрын
Loved the conclusion! Will take with me for life.
@ryanminer3684
@ryanminer3684 Жыл бұрын
This was a random watch, but sweet jesus this was interesting! I still don’t understand half of it, but it felt like I understood it all due to the great presentation
@feelgoodmusic8722
@feelgoodmusic8722 Жыл бұрын
Same for me. Haven't watched the full thing, but already know it's gonna be guud.
@LorenHelgeson
@LorenHelgeson 9 ай бұрын
Holy smokes! I first saw this video about a year ago, and I just recently went through the entirety of what has published so far on the Famicom Party book without realizing Kevin was the author. It's a great blog series, and I'm looking forward to more parts of it being released. In case Kevin sees this, "Thank you very much for what you have provided."
@gustavo9758
@gustavo9758 5 ай бұрын
Same here! The other way around tho, I started the book a few days ago :)
@antiscian
@antiscian 2 жыл бұрын
This was excellent. It's amazing how elegant the best Solutions are
@john37foldgaming
@john37foldgaming Жыл бұрын
I feel like at times, he was pausing just in case there were a giggle or two. But 100% overall INSANE presentation. I knew the basics of level design and sizing, but how you broke it down was great! I already shared this with my fellow gaming nerds!! Thanks again for posting!
@domagojkobescak6752
@domagojkobescak6752 Жыл бұрын
I have watched so many videos about 8-bits but to be honest this guy explaind it so easly i actualy understand now how it works. !
@NeonShadowsx
@NeonShadowsx 2 жыл бұрын
what a delightful talk
@sonnyjimbod
@sonnyjimbod 2 жыл бұрын
Thanks man, really good video. Your section on graphics has given me a bit more enthusiasm for this Bomber King disassembly I've been doing for the last 3 years. Maybe I'll finally work out how the level data is stored ;)
@ghoshsanjoy
@ghoshsanjoy 2 жыл бұрын
Amazing presentation. Made such a lot of information so easily understandable and interesting. Kudos!
@souhailla10
@souhailla10 2 жыл бұрын
very great conference !! thankyou !!
@MyRealityIsProof
@MyRealityIsProof Жыл бұрын
This is really fascinating!
@dampee6
@dampee6 4 ай бұрын
Great lesson at the end there. I tend to find myself trying to perfect a feature that I'm trying to put in a game rather than dumbing it down.
@philosophiabme
@philosophiabme 2 жыл бұрын
Excellent presentation overall! Clear, thorough, and enjoyable :)
@matthewconte
@matthewconte 2 жыл бұрын
Also, the 2nd pattern table at 06:20 all that garbage in the bottom is actual program code-- they couldn't fit the game's code into PRG-ROM so they put the overflow in CHR-ROM and copied it to RAM and ran it from there to fit into the 32kB + 8kB footprint.
@williamdrum9899
@williamdrum9899 Жыл бұрын
I didn't think you could copy from CHR-ROM to RAM. I was under tge impression that anything on the CHR chip was totally inaccessible by the CPU
@el-chulio
@el-chulio 2 жыл бұрын
Very interesting how problems got solved in the early days. I think we can learn a lot about good abstraction from those programmers :)
@EmielBlom
@EmielBlom 2 жыл бұрын
Great talk, thanks a lot!
@zeropointzer0
@zeropointzer0 2 жыл бұрын
Holy shit...as someone who had just been born when the NES came out, the amount of tedious work necessary to squeeze out every byte of memory and CPU cycle and all sort of tricks the devs had to do back then is just amazing. Today you just take Unity/Godot/etc., throw in a tilemap and some sprites (who cares if mario.png is 2kB or 28kB), hook up the (pre-made) input system and there you go. But then again, making a game is much more complex today and you have to struggle with different shit...so not _that_ much has changed actually. :)
@AnthonyFlack
@AnthonyFlack 2 жыл бұрын
The NES had hardware sprites - luxury.
@SianaGearz
@SianaGearz 2 жыл бұрын
Tedious work? Almost every 8-bit game had between 1 and 3 programmers working on it, usually just one and the art and design team were another 2-3 people, and sound one more person, and the size of code is counted in kilobytes. Each assembler instruction takes a byte + data, and you print all the codebase of a game out nice and legible, you're going to have a fairly thin booklet. Most games were done in mere months. Today, an average production takes a thousand people, around 200 at the head studio and the rest outsourced, and takes around 3 years. Even just clicking a shitty little health overlay in Unity can take you days, they'd be done with that in a couple hours. The scope is completely different. I'd say the work done back then may be seen as unusual from today's point of view, a lot of that basic skill is no longer conveyed and is thus kinda lost, and not everyone was equally successful back then either, but it's not actually all that high up on difficulty scale.
@SeaHorseNSparrow
@SeaHorseNSparrow 2 жыл бұрын
@@SianaGearz Lovely point. I recall when I saw someone finishing the Mario game (just the game) and jaw dropped at the amount of developers on just that one game, by how long it took the credits to scroll all the way.
@UmVtCg
@UmVtCg 2 жыл бұрын
Today you don't just take Unity Unreal etc. Almost every game for Nintendo Switch has careful research management. From Nintendo games like Mario Odyssey to Witcher 3, Doom and Wolfenstein. And late in regular console generations like the PS4 and XboxOne some talented Developers manage to press every drop of performance out of those 2013 weak AMD Jaguar core based APU's in those systems. Which is also quite astonishing in some cases.
@akumaquik
@akumaquik 2 жыл бұрын
This was a fun watch
@KubuntuYou
@KubuntuYou 2 жыл бұрын
A lot of what he talked about coincides the methods that I came up with when I was learning. Excellent presentation.
@inceptional
@inceptional 2 жыл бұрын
What a great talk.
@Egganopolis82
@Egganopolis82 2 жыл бұрын
This is so cool and useful. Thank you!
@dandymcgee
@dandymcgee Жыл бұрын
Wonderful talk, super interesting thanks Kevin!
@DiegoDevPro
@DiegoDevPro 2 жыл бұрын
Amazing conference!!!
@sajibsrs
@sajibsrs 2 жыл бұрын
That was amazing!!!
@tolstoj_
@tolstoj_ Жыл бұрын
Awesome talk! Small correction: the Game Genie does not write to RAM but intercepts the ROM. If the CPU requests a certain address in the ROM data the Game Genie just replaces the value with something predefined. There might also be a check value to make sure that the address points to the correct ROM bank. if(address == X && valueAtAddressX == Y) return Z;
@k0lpA
@k0lpA Жыл бұрын
Yeah the action replay and gameshark do it with RAM instead. Actually.. I wonder how it does it.. the game genie is between the cartridge and the system so it can just act as a middle man and swtich the values up, but the gameshark is also there, how does it intercept the RAM ? I guess it could switch instructions ? Like if there is a LDA for a value it has a cheat for it changes the LDA so it loads from ROM instead of RAM ? But then that wouldn't really work when it's not directly loading the RAM address like if it's using LDA $adr, X because the gameshark doesn't know the value of the X register or if the instruction is loaded from RAM instead of ROM.
@lee1davis1
@lee1davis1 2 жыл бұрын
A wonderful flashback video.
@saifal-badri
@saifal-badri 2 жыл бұрын
This was awesome, watched the whole video!
@Kevint75
@Kevint75 2 жыл бұрын
I'm not into programming, so I have very little knowledge, and I loved that presentation, thanks for making it so easy to understand!
@timhagedorn6890
@timhagedorn6890 2 жыл бұрын
Thanks for the video! The collision part really helped me! I've started making my own NES game, which also requires some sort of RNG. I came up with a different approach that works pretty well for me. I use my key inputs in each frame and add a value to a variable that represents the random number. If I hold down the up key, 1 is added in each frame, if I hold down the right key, 2 is added, if I hold down the down key, 3 is added, etc. Since the number is stored in a byte, it is reset to 0 when it reaches 256. I have a controller that spawns enemies at random positions at a fixed interval. When you play the game, you automatically change the random number that is taken as the spawn position for the enemies.
@SivakD
@SivakD 2 жыл бұрын
Very nice presentation indeed. A lot of the solutions to things made sense.
@jonweinraub
@jonweinraub 2 жыл бұрын
I really appreciate the mantra about stupid ideas. I was developing an algorithm in C++ that I felt was stupid. It was a trivial method to return … random strings. And I just concatenated what was needed and returned the value of random indices to stdout. Fast forward I find an open source program that has a similar function and when reading the code noticed it was done in a more elegant, but in essence, the same way. It made me smile because what I thought was so dumb as an amateur, a paid professional had the same idea. Not such a dumb idea after all. Unless of course the individual copied my code and refactored it 🙄!
@johnwilson3918
@johnwilson3918 Жыл бұрын
Either way, Jonathan - you can still pat yourself on your back!
@thoughtbyte
@thoughtbyte 2 жыл бұрын
Very cool talk!
@ALoonwolf
@ALoonwolf 2 жыл бұрын
With a 6502 processor I usually used the 1/100 seconds value of the timer. So long as the random numbers were required at random times this always produced a genuinely random number from 0 to 99.
@change_profile_n8755
@change_profile_n8755 Жыл бұрын
Awesome talk!
@justinkeys2708
@justinkeys2708 2 жыл бұрын
This was a really fun and comprehensive talk. Makes me kind of wish I was a developer back in those days so I would have to tackle those types of low level challenges. I'd like to try my hand at Game Boy development which, if I'm not mistaken, carries some of similar patterns.
@Idiomatick
@Idiomatick Жыл бұрын
As a kid I remember being impressed that FF1 found a way to avoid people save scumming (resetting the game to get better rng, more favourable battles). Eventually I did guess that they just had one big random number though. So technically I did notice.... but if anything it made the game better that it wasn't really random, rather than worse.
@jeevanpillay
@jeevanpillay 2 жыл бұрын
This was really good. Thanks!
@herrewa2
@herrewa2 2 жыл бұрын
This was awesome!
@sator666666
@sator666666 2 жыл бұрын
Great lecture!
@ruadeil_zabelin
@ruadeil_zabelin 2 жыл бұрын
23:18 The original doom does exactly this. 256 numbers uniquely spread out in an array. Whenever anything needs a random number; pointer + 1 and take it out of the table and roll around. Simple
@damientonkin
@damientonkin 2 жыл бұрын
I was going to say that. It allowes for synchronisation across networks and recording of demos because the randomness is essentially generated by player input. That wouldn't work with Tetris because the player input has to respond to the random element. I suppose that user generated randomness is kind of like an early version of some forms of CAPTCHA.
@xoxmosx
@xoxmosx 2 жыл бұрын
wow! This was awesome. Nice lecture
@bobunnn
@bobunnn Жыл бұрын
what I like is that it's true creativity, that you don't suspect at all
@BradleyAidanJohnson
@BradleyAidanJohnson Жыл бұрын
This is why games like this were awesome. Similar to Star Wars. The original. Limitations breed creativity and passion. Unlimited resources leads to trash. Awesome talk
@firstNamelastName-ho6lv
@firstNamelastName-ho6lv Жыл бұрын
Cyberpunk 2077 moment
@ericwood3709
@ericwood3709 2 жыл бұрын
Awesome talk. I did wonder why the NES had to be reset before being turned off after saving in Final Fantasy.
@goldnutter412
@goldnutter412 2 жыл бұрын
Hi Strange Loop ! you rock.. haha was clapping all the way through this until I stopped and hit download. Thanks, will be back :-)
@jigsound
@jigsound 2 жыл бұрын
Extremely interesting details!
@djfredmiami
@djfredmiami Жыл бұрын
i learned so much from this video. things i have always wondered ....
@simonscott1121
@simonscott1121 Жыл бұрын
To answer the final question, yes. The random function returns a float (from memory everything in JS is a float) between 0 inclusive and 1 *exclusive*, so if you multiplied by 255 youd get a number between 0 and 254, not 0 and 255, given that floor will return the integer portion of the float?
@syntaxed2
@syntaxed2 2 жыл бұрын
This was really interesting and fascinating :D
@stuartthorncraft2948
@stuartthorncraft2948 Жыл бұрын
As a coder from that era , this is great stuff
@Crow4o
@Crow4o Жыл бұрын
The best thing ever happen to this world is the NES home system. Still playing that.
@canman87
@canman87 Жыл бұрын
Played through Mega Man 6 while watching this, myself!
@Eener1000
@Eener1000 Жыл бұрын
"Embrace the stupid" Best advice.
@skilz8098
@skilz8098 2 жыл бұрын
There are some other titles from the NES that are and were legendary classics to play while also being programming masterpieces of their time. The Legend of Zelda, Metroid and The Guardian Legend!
@udeechee
@udeechee 2 жыл бұрын
This entire talk was fascinating! Loved the split between abstract concepts and how they were implemented. hope to see more like it.
NES Graphics Explained
17:23
NesHacker
Рет қаралды 221 М.
NES Architecture Explained
18:28
NesHacker
Рет қаралды 271 М.
когда одна дома // EVA mash
00:51
EVA mash
Рет қаралды 9 МЛН
NO NO NO YES! (40 MLN SUBSCRIBERS CHALLENGE!) #shorts
00:27
PANDA BOI
Рет қаралды 116 МЛН
How To Choose Ramen Date Night 🍜
00:58
Jojo Sim
Рет қаралды 33 МЛН
How NES Games Are STILL Made in 40KB
14:33
Inkbox
Рет қаралды 90 М.
How we fit an NES game into 40 Kilobytes
12:04
Morphcat Games
Рет қаралды 3,5 МЛН
Does the NES Have a Secret Master System Port? | Nostalgia Nerd
12:30
Nostalgia Nerd
Рет қаралды 2 МЛН
Coding NES Loops
17:10
NesHacker
Рет қаралды 26 М.
How Super Mario Bros Was Made Into 40 Kilobytes
9:21
Joseph R Carroll
Рет қаралды 906 М.
How NOT to make an indie game
22:01
Lychee Game Labs
Рет қаралды 1,9 МЛН
NES Scrolling Basics featuring Super Mario Bros. - Behind the Code
17:25
Displaced Gamers
Рет қаралды 115 М.
I Made a 32-bit Computer Inside Terraria
15:26
From Scratch
Рет қаралды 3,1 МЛН
Why Roller Coaster Tycoon is a Game Development Masterpiece
11:59
Tech Stories
Рет қаралды 957 М.
The CIC & 10NES Explained
19:40
NesHacker
Рет қаралды 58 М.
ИГРОВОЙ ПК от DEXP за 37 тысяч рублей из DNS
27:53
Компьютерная мышь за 50 рублей
0:28
dizzi
Рет қаралды 2,1 МЛН
#Shorts Good idea for testing to show.
0:17
RAIN Gadgets
Рет қаралды 808 М.