It's not specific to level 235 but rather depends on what level you start on. The bug happens at 2190 lines and lasts 800 lines, and this happens every 2900 lines thereafter (so the second period is from 5090 to 5890 lines). It's an overflow error when comparing bytes. Basically, the upper digit of the lines counter can have any value from 0 to 255. A CMP (compare) instruction essentially subtracts this from ten times the starting level plus one to decide if it should increment the level. That's how it knows that, for instance, if you started on level 5, you shouldn't increment the level unless you have cleared at least 60 lines. But if you subtract a very large value, say 200 from 20, you will not really get -180, because that's out of bounds. Signed 8-bit ints only range from -128 to +127, so -180 is actually treated as a positive number. As a result, the comparison fails, and the level is not incremented. Meatfighter has a good detailed explanation of it: meatfighter dot com/nintendotetrisai/#Lines_and_Statistics.
I see this comment is getting a lot of likes so for those of you who seem to not have noticed I already made a video on that: ua-cam.com/video/akTKMNvi97A/v-deo.html (didn't exist at the time of this commenter asking, but it does now)
ACE can be a wild thing. I still remember that time at Games Done Quick where they used TASbot to basically mess with Ocarina of Time in real time, turning a still running game into a canvas on which to paint. It somehow feels like the software version of playing god, the way one can theoretically mess with a game’s “world” in real time ignoring its ROM completely as desired
I'm here because of the aGameScout video and it absolutely blows my mind how your approach with amazing doodles and good explanations didn't kick off. This would be so interesting to see for more game related bugs and how they are actually created and happen. Love the videos!
Thank you! I mostly created them as a reference for the community, so I wouldn't expect them to ever take off, as they are pretty much pure information; it's not the kind of video that goes viral. Scout on the other hand makes that kind of video, and has blessed me with a shoutout that has literally boosted the views on these by like 800% at the time of writing here.
@@hydrantdude3642I came from that video as well! I don’t even play Tetris but I love how you broke the information down into something much easier to understand, and the visuals here are super cute and helpful as well. I wish videos like these took off more because they’re really interesting!
@@hydrantdude3642 For someone with an introductory level experience using assembly code, you explain this amazingly well - love the analogies with the mathematician, artist, whiteboard.
Same here, watched Scout's video to learn about the killscreen and followed the description to here. It's so cool sometimes to discover a little niche on UA-cam where someone is making videos on a super-specific subject with incredible quality. I didn't expect to find videos explaining NES assembly code with timelapse drawings and a little 👀T-piece, and yet here I am spending my Friday night watching all of them. This is amazing
Just found this while surfing the web while doing college homework. This is probably the coolest thing I've watched all day. Thanks for explaining it so well!
As a long time gamer of 35 years I hope you are using the intellectual freedom which comes with being an indie developer to push gaming forward. I am a failed artist so I understand design. I do not understand code.
Love the audio, love the visuals, love the timing, and of course, the content has recently become more relevant than ever. Definitely pressing all the good buttons! (that don't cost money to press. Those will have to wait until I watch everything else you have made.)
Very nicely made video! I would be so giddy if this turned out to be fully exploitable :) Do you think that might be possible? I don't know any Tetris internals whatsoever but I just took a quick peek at RAM while the game was playing and it looks like even if you could get the instruction pointer into the board area, you'd only get to arrange 4 different opcodes (which all seem difficult to work with at a glance). But maybe you could manipulate up to 6 of the piece frequency counters to form some useful instructions? Control over memory seems pretty constrained. But if it were possible, this would make such a funny ACE TAS given the unavoidable 30+ minute setup time
We have a working bootstrapper; it takes about 30 minutes of gameplay to setup the scoreboard and another hour to crash it properly. We use the LFSR's value plus the piece in the next box to tell the PC to jump to the place where high score names, levels, and scores are stored, where there is enough room to get something going.
@HydrantDue the reason only singles crash at this level is that they need extra carries in the lower byte of the score unlike all other linee clears. This make the crash avoidable.
Fun fact, we actually don't know who the developers are for this game. it was probably Nintendo R&D 1 in the late 80s, but who was on that team is pretty much unknown. Also pretty hard to find out now since the lead at that point in time passed away a few years ago, 2018 or 2019? Having trouble tracking down where I heard that though.
Scoring a different type of line clear would result in no crash due to the different particulars involved in the math. The score is stored in 3 seperate bytes, each one covering 2 decimal digits of the score. Here's the process written in pseudocode: for i from 1 to current level+1 score(1) = score(1)+lineclearpoints(1) if score(1) & 0F >= 0A: score(1) = score(1)+6 if score(1) >=A0 score(1) = score(1)-A0 score(2) = score(2)+1 repeat this for 2 (it's not written as a loop) for 3 replace the last line with score(3) = 99 score(2) = 99 score(1) = 99 the single happens to be the only line clear which involves the lowest byte of the score; all others only directly add to the middle byte, so singles are the first type of clear to be able to cause the crash.
I was going "oh no, I know what's going to happen next" and "this looks familiar" all through it, and then hit the comments - I did a bit of low-level Apple][ (6502) coding back in the day, so yes, it *was* familiar.
Interestingly, one of the flags in the 6502 CPU causes decimal math to be done in hardware, which means that the Atari 2600, for example, doesn't have to do it in code. But the NES processor, despite being based on the 6502, doesn't have that feature.
That's because MOS/Commodore had a patent on their decimal mode and Ricoh/Nintendo didn't want to pay royalties... so they cut out 5 transistors instead
0:53 But what IS a "maxout"? 3:08 What's the difference between the "book page" and the program counter? 3:50 But... WHY? The code knows to store the "book page" at that RAM address, so what other code path would write other data (and WHAT other data, other than the registers, would it even want to store?) to that RAM address? Edit: Okay, after rewatching several times, the overwrite happens during the graphics update phase, which ALSO used the left side of the whiteboard (something not really made clear - the earlier part of the video implies that ONLY the right side of the whiteboard is used for graphic updates). But if that book page is overwritten, then why not everything else the CPU stored, including register values like the program counter? Why is the book page vulnerable but not anything else?
1. A maxout is how we refer to the score of 999,999. The game caps the score at that number. 2. The program counter is a register held internally by the processor which does not have a memory address. The "book page" as I refer to it is something that would be written into the program counter through a jump command. 3. The addresses at the beginning of ram, $0000-0001 are used as temporary working variables for more complex operations which can't be done using just the accumulator register. The routine to read the controller, which happens during the graphics interrupt, uses those addresses and overwrites them. Therefore, if the interrupt happens at the wrong time, those ram addresses are not preserved and the wrong thing ends up in the program counter when the jump command eventually happens.
While it’s true the CPU has no multiplication function so it has to go through several iterations of addition in order to multiply, it does not have to “convert to base 10” for every step of the way. Remember, hexadecimal is just another useful tool the programmer uses to make the machine code instructions easier to deal with (ff is a whole lot easier to read than 11111111, but the compiler automatically converts it to machine code for you). So it’s not even doing the math in hex, it does it in binary. It’s true that you do have to deal with the carry flag every time though, but that’s just standard practice when performing addition on a 6502 instruction set.
Yeah, they could've done the conversion to decimal for on-screen display in a separate step and do all the math in binary/hex, but that is not how it's programmed. github.com/CelestialAmber/TetrisNESDisasm/blob/2bd894105206976edb6372e18b8f2b949a8dde31/main.asm#L3336 if you'd like to read it yourself to confirm I've described it accurately.
@@hydrantdude3642 I think you misunderstand the job of the compiler. Yes, those numbers are coded in decimal notation but that doesn’t result in extra “conversion” steps for the CPU at runtime. The CPU doesn’t understand anything other than binary which is why it needs to be compiled into a binary executable. All of that (including any conversion) is done by the compiler on the programmer’s computer. The NES CPU only ever runs machine code not source code.
>The NES CPU only ever runs machine code not source code I just gave you the machine code. lda #$00 sta holdDownPoints lda levelNumber sta generalCounter inc generalCounter maybe you're expecting it to be bytes? the exact same code in that format is A9 00 85 4F A5 44 85 A8 E6 A8 also most nes games to my knowledge were coded directly in assembly, not in a higher level language using a compiler.
@@hydrantdude3642 That's not machine code. While assembly is a close approximation, its not the same thing. The NES CPU can't read that. Assembly still has to be compiled. Look at the format of the file (main.asm). The NES is expecting a .ROM file (or a .NES which is basically the same thing). There's still 2 steps that need to be performed to compile this. Using modern tools it would be this: 1. ca65 main.asm -o main.o 2. ld65 main.o -o main.nes Regardless of what tools you use, these steps are necessary because pure assembly is too high-level for the CPU. It can literally only read ones and zeroes. Thus, no run-time base ten conversion is necessary. Where the CPU is really getting bogged down is trying to handle the fact that the score needs 3 bytes and the processor can only handle one byte at a time, leading to a lot of carries per iteration of addition and drastically increasing the number of processor cycles required to complete the multiplication operation. When multiplying smaller scores, which were previously all in the realm of what we thought to be humanly possible, this was fine.
@@guitarmanlevi97 I'm having a hard time figuring out where you're getting stuck here. These are the exact instructions the processor is following, like you can run the rom in an emulator and watch it do these instructions. You can see the clock ticking up with each one that runs. I don't know what you think a compiler does to assembly, but it's just translating "lda #$00" to A9 00 / 1010100100000000 since you seem to be so interested in the processor reading binary. I have done this by hand before and copy-pasted binary code into roms to create romhacks. I know what machine code looks like. The commands are all exactly as written, saying it needs to be compiled is irrelevant to what the processor is actually doing.
the high score leaderboard the game stores for A-type and B-type is enough to write a bootstrapper. gives us 60 bytes with pretty heavy restrictions on their values, but we got it working.
We don't have a finished tas because we all were super excited that it was possible and then put together the bootstrapper and got it working, and then none of us knew what to do with the power we'd attained. Would be great if we got the TAS community involved to come up with a cool payload for us.
no. given that the score counter maxes out at 999,999. the concept of "giving yourself the highest score possible" doesn't really make any sense. ACE would only be used as a stunt because the setup for it requires hours, unlike ACE in games that have credits warps and the like. a human-viable route was planned a while ago that activates 2-player mode.
Imagine playing 155 levels and _then_ having to set up an ACE payload while also not losing the game or triggering a crash. It would never be viable, but it's a ceazy thought at least.
we setup the payload by getting specific scores and names into the highscore table, so there isn't an "and then" part. it comes first. of course that's pretty limiting but for TAS we can build a bootstrapper with it, and for humans we can do something simple like enable 2-player.
if single line clears at level 155 crash the game because too much time is taken on scoring, then why are they safe from 159 onwards? shouldn't the score calculations for those levels take even longer than in 155?
the crash results from the end of frame graphics call interrupting the switch routine, which is only 30 cycles long. it has 8 opportunities to be interrupted, but once you get past that window a crash is no longer possible.
the glitch when it comes to invalid numbers (such as non-decimal digits (A-F) or simply too large reminds me of the ZZAZZ glitch in pokemon on its prize money glitch.
So a single into 155 crashes, a single at 157 also crashes. What are the others? I saw Eric's video reference some spreadsheet with all the known triggers, where's that sheet?
link #1 in that video description (HD's notes RE nextbox/pushdown survival are fascinating), docs.google.com/spreadsheets/d/1zAQIo_mnkk0c9e4-hpeDvVxrl9r_HvLSx8V4h4ttmrs/edit#gid=1013692687
@@hydrantdude3642 even if I mostly only use r12, r3 and r0 when working with power oc (I mod wii games), the other registers always come in handy. Working with just 3 registers sounds like a pain.
I’d’ve said ONE “general purpose” register , the accumulator “A”, with the X & Y “index” registers (as I recall them being called back in the 80s when I tried teaching myself 6502 assembly .. from whatever the local book store was kind enough to carry.. in the early 80s we had no “real” local book store and I felt like a deprived child). Translation: x and y not “general purpose”. But I won’t argue it. You can imagine my surprise when I learned about the 8088/8086 registers😮 and 68000 registers!The x86 stuff was earlier college classes and then in a microprocessor design class we looked at RISC with MIPS (I still got my copy of Computer Organization and Design by Patterson & Hennessy sitting on the book case next to the fire place all these decades later!). 😮😮 I wish I had more context back then. I couldn’t have been the only student going “uh huh” but not really seeing the big picture, not that we needed it for the test. But in high school in the Pascal based CimpSci classes I didn’t understand what an ALU was in the younger days of my teacher. And a “cpu” to my college professor. When you see an 1970s/1980s “ microprocessor in a 40-pin DIP (or even larger ones by late 80s) and that’s ALL you are familiar with, the notion that an ALU is a subsection of a CPU doesn’t come into focus without understanding the history… that a CPU was literally a unit of a minicomputer or mainframe that did processing and it’s many parts were centralized. Imagine, a “cpu” came in several circuit boards. Seriously? All discrete logic chips. And some did arithmetic and logic - the ALU portion! Glad I finally got that background so I can better understand the videos here by “Usagi Electric” and the Centurion computers with their custom CPU5 or CPU6 logic boards. Fascinating.
I'm not sure I'm understanding the question correctly, if you're asking if it's possible to clear 5 or more lines at a time, no, it isn't. Tetris pieces only have 4 blocks so you can only complete 4 rows at a time.
@@hydrantdude3642 So, can the game take soooooo long to process one line clear that you can clear another line, presumably if you removed the maxout counter?
@@fireyfan25 No. Firstly, removing the maxout prevents the game crash by making the calculations much faster. Secondly, the game works through steps in order. If one is taking forever, it's not just gonna start running other ones at the same time, the processor is single-threaded. Even if the game was stuck on the score calculation for 5 minutes you couldn't place another piece on the board.
those aren't mutually exclusive but yes we have a working ACE tas that can do anything and yes we have a theorized human route to do limited ACE to enable 2-player mode.
Players tend to use codes which remove the 999999 cap, and because this removes the part of the code that spends lots of extra time setting the score to all 9s, eric was actually not very close to the crash. The earliest documented crashes on those codes are around level 230. However this is all moot since eric was playing on the tetris gym ROM which entirely patches out the crash. But yes, if he was playing on a completely unmodified game (which nobody of his caliber plays on) he was pretty close to the crash.
So far I couldn't even imagine a system where the code and dynamic data are equal and "accidentally" switchable. :O Thanks to Scuti, I found this video. And thanks to HydrantDude, of course.
A few months ago I watched a video on the 8-Bit Show And Tell channel here on UA-cam, called “ One Bad Byte Broke This Game: Commodore 64's "Livingstone, I Presume?" “. I encourage you (everyone really) to watch it. This Tetris / NES explainer reminded me of it. Different issue and circumstances but it shows how one little innocuous byte change can throw a big monkey wrench in the works. It’s not a quick video like this but if you want some quick tech dirt with limited background (although mention of a cheat code and a patch to remove it IIRC between English language version and Spanish version is enough to get an idea) then skip to 27 minutes mark and watch for a few minutes.
From what I remember from operating systems, the way a typical, standard OS runs basically locks you out from modifying program code, while not allowing arbitrary execution on the "ram" part of your memory (stack, heap, data segment, etc).
@@bobbobbob321 you show your age :-) either : (1) you are old enough to be of the mainframe days (before my time) Or (2) you are young enough to be accustomed to a baseline interaction consisting of a mouse and high resolution graphics with millions of colors and a WIMP (window, icon, mouse, pointer) interface. And “95” was a long time ago. If you were born then you were still too young to be watching a white Bronco driving slowly down an LA freeway followed by police in a non-high-speed chase … and you missed out on “you’ve got mail!” (Which one day preceded that software crashing and taking down my entire computer - crashed OS since the buggy software Steve Case put out wrote to wrong part of memory - no protection - AND damaged my file system) There was this glorious time in the late 70s to late 90s where home computers (let’s not call them personal computers since that leads to “pc” and that eventually became synonymous with DOS and later Wintel) came in many sizes and colors and so many different platforms and abilities. Computer stores were like candy stores. And they all crashed! There were no guardrails. Even IF the cpu offered some protection it might be in an additional chip from the chipset family and YOU KNOW that was left out to save money. And even if it were there then the OS’s of the time didn’t use it. And by the later 90s there were more and more exploits targeting the “586” (as it were) with web sites delivering finely crafted files that overran buffers so data corrupted code and in a way that was intended to gain system control. Windows 2000 (aka NT5 and XP aka NT5.1) and Mac OS X didn’t come until the cusp of the new millennium and Linux … I played with it but only people I knew back in college and come colleagues at work were into it to any sort of degree (and not primarily using it). Oh and then there was this twerp working at Radio Shack saying the only reason he’d get an iBook was to put Linux on it. Really? How secure is your job as a glorified sales agent of cell phones and plans and equipment by the “brand” RCA (since they, as a real and serious company, had flipped)? Enough ranting about somebody barely old enough to shave working a “tech” job telling me about Linux. Fanboy-isn on any side bothers me. I don’t want to come across as old and cranky but I do miss the Wild West days. It was fun and charming. Pac Man and Rubik’s cube on Saturday morning cartoons back when Reagan let cartoons have no redeeming value other than commercialism 🤑 ! I find myself irritated at all the platforms today. So here I am with far too many web browser tabs open (but typical I hear) and my browser crashed. But that’s all that crashed. The system and other applications stayed open. Yay! But it still sucks. I finally bought a smart TV. Not sure if I want to allow it to connect to my router and thus keep it dumb or put it on a VPN. My old HDTV has a corner that flickers - backlight going. And it cost more over a decade ago than my new 4K UHD tv (btw its still in box - gotta get off my butt watching UA-cam and spending time in comments 🙄) i.e. not worth fixing. BUT .. I vividly recall smart TVs getting bricked by ransomware in the recent times. That ties it into code and data spill over. Is a 2023 model TV safe enough? Ughhh… I wish the ideals of data not spoiling code were actually a thing but you see it still is and probably will be for some time. To nail it down takes time and time is money and moneys for the capitalists. My teenager even knows that thanks to the AP history courses taken these past few years of high school. What isn’t taught is how I used to just turn on a CRT and play a LaserDisc and had no menu and no restrictions and no ransoms etc etc. So maybe there was little protection then but I was never inundated with attacks and DRM restrictions. Maybe it was better ?
This does nothing to explain why a single line crashes the game at 155 but not a double. Or why on later levels, a single line does NOT crash the game.
crashing the game requires the v-blank interruption to happen during a very short window of time during the switch routine. there are 8 separate instances of the switch routine and therefore 8 opportunities for the game to crash. if you level up above the range where v-blank happens during the switch routines, then it is no longer possible for the game to crash. singles take longer to calculate than other line clears because they are the only line clear which involves the lowest byte of the score (adding 40 uses the 10s digit but all others only use the 100s digit and above, adding 100 300 or 1200). in addition, doubles, triples, and tetrises take different amounts of time from each other because of the part of code that deals with adding the lines to the line counter.
@@hydrantdude3642 Oh weird, didn't think it would be a narrow window that crashes things and not just "Here be dragons" past a certain lag amount. Thanks for the explanation!
Maybe you could do a video why level 235 takes 800 lines to clear
It's not specific to level 235 but rather depends on what level you start on. The bug happens at 2190 lines and lasts 800 lines, and this happens every 2900 lines thereafter (so the second period is from 5090 to 5890 lines). It's an overflow error when comparing bytes. Basically, the upper digit of the lines counter can have any value from 0 to 255. A CMP (compare) instruction essentially subtracts this from ten times the starting level plus one to decide if it should increment the level. That's how it knows that, for instance, if you started on level 5, you shouldn't increment the level unless you have cleared at least 60 lines. But if you subtract a very large value, say 200 from 20, you will not really get -180, because that's out of bounds. Signed 8-bit ints only range from -128 to +127, so -180 is actually treated as a positive number. As a result, the comparison fails, and the level is not incremented. Meatfighter has a good detailed explanation of it: meatfighter dot com/nintendotetrisai/#Lines_and_Statistics.
ua-cam.com/video/akTKMNvi97A/v-deo.html
I see this comment is getting a lot of likes so for those of you who seem to not have noticed I already made a video on that: ua-cam.com/video/akTKMNvi97A/v-deo.html (didn't exist at the time of this commenter asking, but it does now)
Or a video on how many toes on each foot is normal
i thought the game was possessed lmao ty this helped me a lot
I would die for Little Doodle T-Piece it's doing its best and working SO hard
this comment is making me smile so hard you have no idea
The Tetris block with the huge eyes is SO cute I can’t stop staring at him
ACE can be a wild thing. I still remember that time at Games Done Quick where they used TASbot to basically mess with Ocarina of Time in real time, turning a still running game into a canvas on which to paint. It somehow feels like the software version of playing god, the way one can theoretically mess with a game’s “world” in real time ignoring its ROM completely as desired
aka Triforce Percent
I'm here because of the aGameScout video and it absolutely blows my mind how your approach with amazing doodles and good explanations didn't kick off. This would be so interesting to see for more game related bugs and how they are actually created and happen. Love the videos!
Thank you! I mostly created them as a reference for the community, so I wouldn't expect them to ever take off, as they are pretty much pure information; it's not the kind of video that goes viral. Scout on the other hand makes that kind of video, and has blessed me with a shoutout that has literally boosted the views on these by like 800% at the time of writing here.
@@hydrantdude3642I came from that video as well! I don’t even play Tetris but I love how you broke the information down into something much easier to understand, and the visuals here are super cute and helpful as well. I wish videos like these took off more because they’re really interesting!
@@hydrantdude3642 For someone with an introductory level experience using assembly code, you explain this amazingly well - love the analogies with the mathematician, artist, whiteboard.
Same here, watched Scout's video to learn about the killscreen and followed the description to here. It's so cool sometimes to discover a little niche on UA-cam where someone is making videos on a super-specific subject with incredible quality. I didn't expect to find videos explaining NES assembly code with timelapse drawings and a little 👀T-piece, and yet here I am spending my Friday night watching all of them. This is amazing
This old programming blows my mind. Let alone what new computers are capable of. Unreal.
Just found this while surfing the web while doing college homework. This is probably the coolest thing I've watched all day. Thanks for explaining it so well!
this brings me back to the days of "draw my life" in youtube. love the presentation, love the information. gj!
the byte of '87
The goat is still responding to comments and answering questions. Great video!
As an indie developer, some great analogies in this video. Good work.
As a long time gamer of 35 years I hope you are using the intellectual freedom which comes with being an indie developer to push gaming forward. I am a failed artist so I understand design. I do not understand code.
incredible break down and knowledge bomb dude, thank you for making this, thoroughly appreciated 🤘🤘
I enjoy watching this explanation just for the great concerned faces of the Tetris pieces.
Love the audio, love the visuals, love the timing, and of course, the content has recently become more relevant than ever. Definitely pressing all the good buttons! (that don't cost money to press. Those will have to wait until I watch everything else you have made.)
Awesome stuff! Really get to learn more about tetris through these :)
those 2 little guys have a pretty hard job
Here after Blue Scuti crashed the game... wow, great video!
Very nicely made video! I would be so giddy if this turned out to be fully exploitable :) Do you think that might be possible? I don't know any Tetris internals whatsoever but I just took a quick peek at RAM while the game was playing and it looks like even if you could get the instruction pointer into the board area, you'd only get to arrange 4 different opcodes (which all seem difficult to work with at a glance). But maybe you could manipulate up to 6 of the piece frequency counters to form some useful instructions? Control over memory seems pretty constrained. But if it were possible, this would make such a funny ACE TAS given the unavoidable 30+ minute setup time
We have a working bootstrapper; it takes about 30 minutes of gameplay to setup the scoreboard and another hour to crash it properly.
We use the LFSR's value plus the piece in the next box to tell the PC to jump to the place where high score names, levels, and scores are stored, where there is enough room to get something going.
@@hydrantdude3642 Oooh, the high score table is a great idea! That's so awesome, congrats on getting that working! :D
@HydrantDue the reason only singles crash at this level is that they need extra carries in the lower byte of the score unlike all other linee clears. This make the crash avoidable.
i've been seeing a lot of well made videos from very small content creators recently
good job making this video
I would have loved for ACE to be explained to me this way like 4 years ago
0:57 tspin naughty finger towards 999,999 momen
Surprising that there is no expectation of a lag frame. I didn't know the NES didn't have multiplication and division. SNES has me so spoiled :)
Thanks I've been wondering why the crash happens. This is super helpful.
This kinda reminds me of 12tone's videos. Great work! 👍
Great demo. Love to know who the Test Lead was 🙂 A great example of an edge-case not getting tested.... lol
Fun fact, we actually don't know who the developers are for this game. it was probably Nintendo R&D 1 in the late 80s, but who was on that team is pretty much unknown. Also pretty hard to find out now since the lead at that point in time passed away a few years ago, 2018 or 2019? Having trouble tracking down where I heard that though.
Excellent explanation and visuals.
And we are now there that 3 humans have expoited this "bug"… after 35 years of creation (Nes Tetris)
1:00 so it does something like
for (SIGNED BYTE ii = 0; ii
Scoring a different type of line clear would result in no crash due to the different particulars involved in the math.
The score is stored in 3 seperate bytes, each one covering 2 decimal digits of the score. Here's the process written in pseudocode:
for i from 1 to current level+1
score(1) = score(1)+lineclearpoints(1)
if score(1) & 0F >= 0A:
score(1) = score(1)+6
if score(1) >=A0
score(1) = score(1)-A0
score(2) = score(2)+1
repeat this for 2 (it's not written as a loop)
for 3 replace the last line with
score(3) = 99
score(2) = 99
score(1) = 99
the single happens to be the only line clear which involves the lowest byte of the score; all others only directly add to the middle byte, so singles are the first type of clear to be able to cause the crash.
oh i see you're THE hydrant dudddddedude
I was going "oh no, I know what's going to happen next" and "this looks familiar" all through it, and then hit the comments - I did a bit of low-level Apple][ (6502) coding back in the day, so yes, it *was* familiar.
strong vi hart vibes
The drawing’s cute :)
Interestingly, one of the flags in the 6502 CPU causes decimal math to be done in hardware, which means that the Atari 2600, for example, doesn't have to do it in code. But the NES processor, despite being based on the 6502, doesn't have that feature.
That's because MOS/Commodore had a patent on their decimal mode and Ricoh/Nintendo didn't want to pay royalties... so they cut out 5 transistors instead
History was made a few days ago
0:53 But what IS a "maxout"?
3:08 What's the difference between the "book page" and the program counter?
3:50 But... WHY? The code knows to store the "book page" at that RAM address, so what other code path would write other data (and WHAT other data, other than the registers, would it even want to store?) to that RAM address?
Edit: Okay, after rewatching several times, the overwrite happens during the graphics update phase, which ALSO used the left side of the whiteboard (something not really made clear - the earlier part of the video implies that ONLY the right side of the whiteboard is used for graphic updates). But if that book page is overwritten, then why not everything else the CPU stored, including register values like the program counter? Why is the book page vulnerable but not anything else?
1. A maxout is how we refer to the score of 999,999. The game caps the score at that number.
2. The program counter is a register held internally by the processor which does not have a memory address. The "book page" as I refer to it is something that would be written into the program counter through a jump command.
3. The addresses at the beginning of ram, $0000-0001 are used as temporary working variables for more complex operations which can't be done using just the accumulator register. The routine to read the controller, which happens during the graphics interrupt, uses those addresses and overwrites them. Therefore, if the interrupt happens at the wrong time, those ram addresses are not preserved and the wrong thing ends up in the program counter when the jump command eventually happens.
These vids are amazing! Just found them and i’m watching them all 😍
i wonder if its possible to somehow massage the part of RAM it executes into returning back into the main game loop without crashing
benevolent ACE
we have a working ACE TAS, yes. we redirect the processor to the highscore table and use that to build a bootstrapper.
Blue Scuti has entered the chat.
These videos are SO good!!
While it’s true the CPU has no multiplication function so it has to go through several iterations of addition in order to multiply, it does not have to “convert to base 10” for every step of the way. Remember, hexadecimal is just another useful tool the programmer uses to make the machine code instructions easier to deal with (ff is a whole lot easier to read than 11111111, but the compiler automatically converts it to machine code for you). So it’s not even doing the math in hex, it does it in binary. It’s true that you do have to deal with the carry flag every time though, but that’s just standard practice when performing addition on a 6502 instruction set.
Yeah, they could've done the conversion to decimal for on-screen display in a separate step and do all the math in binary/hex, but that is not how it's programmed. github.com/CelestialAmber/TetrisNESDisasm/blob/2bd894105206976edb6372e18b8f2b949a8dde31/main.asm#L3336 if you'd like to read it yourself to confirm I've described it accurately.
@@hydrantdude3642 I think you misunderstand the job of the compiler. Yes, those numbers are coded in decimal notation but that doesn’t result in extra “conversion” steps for the CPU at runtime. The CPU doesn’t understand anything other than binary which is why it needs to be compiled into a binary executable. All of that (including any conversion) is done by the compiler on the programmer’s computer. The NES CPU only ever runs machine code not source code.
>The NES CPU only ever runs machine code not source code
I just gave you the machine code.
lda #$00
sta holdDownPoints
lda levelNumber
sta generalCounter
inc generalCounter
maybe you're expecting it to be bytes? the exact same code in that format is A9 00 85 4F A5 44 85 A8 E6 A8
also most nes games to my knowledge were coded directly in assembly, not in a higher level language using a compiler.
@@hydrantdude3642 That's not machine code. While assembly is a close approximation, its not the same thing. The NES CPU can't read that. Assembly still has to be compiled. Look at the format of the file (main.asm). The NES is expecting a .ROM file (or a .NES which is basically the same thing). There's still 2 steps that need to be performed to compile this. Using modern tools it would be this:
1. ca65 main.asm -o main.o
2. ld65 main.o -o main.nes
Regardless of what tools you use, these steps are necessary because pure assembly is too high-level for the CPU. It can literally only read ones and zeroes. Thus, no run-time base ten conversion is necessary.
Where the CPU is really getting bogged down is trying to handle the fact that the score needs 3 bytes and the processor can only handle one byte at a time, leading to a lot of carries per iteration of addition and drastically increasing the number of processor cycles required to complete the multiplication operation. When multiplying smaller scores, which were previously all in the realm of what we thought to be humanly possible, this was fine.
@@guitarmanlevi97 I'm having a hard time figuring out where you're getting stuck here. These are the exact instructions the processor is following, like you can run the rom in an emulator and watch it do these instructions. You can see the clock ticking up with each one that runs. I don't know what you think a compiler does to assembly, but it's just translating "lda #$00" to A9 00 / 1010100100000000 since you seem to be so interested in the processor reading binary. I have done this by hand before and copy-pasted binary code into roms to create romhacks. I know what machine code looks like. The commands are all exactly as written, saying it needs to be compiled is irrelevant to what the processor is actually doing.
They'll do why tLfH ( levels 249-255) Crash the game when you SIMPLY PLACE A PIECE IN THE WRONG SPOT
The issue is that there is no good way to "spray the heap". Yes, there is the game board, but there is hardly enough entropy there to do much.
the high score leaderboard the game stores for A-type and B-type is enough to write a bootstrapper. gives us 60 bytes with pretty heavy restrictions on their values, but we got it working.
@@hydrantdude3642 Damn, there was enough entropy for that? Impressive!
u explain so awesome, thankyouuuuuuuuuuuuu
Imagine if people find a way to abuse arbitrary code in Tetris.
hehe smol tetrimino
ACE is possible in NES Tetris? Sounds like a new category for @tasbot: "Tetris, Triforce %"
@dwangoAC
We don't have a finished tas because we all were super excited that it was possible and then put together the bootstrapper and got it working, and then none of us knew what to do with the power we'd attained. Would be great if we got the TAS community involved to come up with a cool payload for us.
So if someone where to use ACE to give themselves the highest score possible would it be a world record?
no. given that the score counter maxes out at 999,999. the concept of "giving yourself the highest score possible" doesn't really make any sense. ACE would only be used as a stunt because the setup for it requires hours, unlike ACE in games that have credits warps and the like. a human-viable route was planned a while ago that activates 2-player mode.
Wow@@hydrantdude3642
Imagine playing 155 levels and _then_ having to set up an ACE payload while also not losing the game or triggering a crash. It would never be viable, but it's a ceazy thought at least.
we setup the payload by getting specific scores and names into the highscore table, so there isn't an "and then" part. it comes first. of course that's pretty limiting but for TAS we can build a bootstrapper with it, and for humans we can do something simple like enable 2-player.
@@hydrantdude3642 oooh, that's... much more sensible than what I was saying.
if single line clears at level 155 crash the game because too much time is taken on scoring, then why are they safe from 159 onwards? shouldn't the score calculations for those levels take even longer than in 155?
the crash results from the end of frame graphics call interrupting the switch routine, which is only 30 cycles long. it has 8 opportunities to be interrupted, but once you get past that window a crash is no longer possible.
RCE with playing tetris? Sounds great
little silly fella :3
Well explained.
ok
sooo if the code to calculate the score would be erased, the game would go as normal?
yeah but then there's no score lol. you can patch out the crash by skipping the part that checks for a maxout.
@@hydrantdude3642 kinda dont know programing enough to know what a maxout really is, i just know the start of the start
0:50 binary coded decimal or “decimal mode”
the glitch when it comes to invalid numbers (such as non-decimal digits (A-F) or simply too large reminds me of the ZZAZZ glitch in pokemon on its prize money glitch.
which was left out of the NES to avoid patent fees
So a single into 155 crashes, a single at 157 also crashes. What are the others? I saw Eric's video reference some spreadsheet with all the known triggers, where's that sheet?
link #1 in that video description (HD's notes RE nextbox/pushdown survival are fascinating), docs.google.com/spreadsheets/d/1zAQIo_mnkk0c9e4-hpeDvVxrl9r_HvLSx8V4h4ttmrs/edit#gid=1013692687
is the HEY! YOU MESSED ME UP supposed to be a reference to sam and max or am i just insane
well it wasn't when I wrote it, but sure, why not? it can be a reference to sam and max.
Do I detect some 12tone influence ;)?
If I'm crazy and I'm wrong then you should check his videos, very similar presentation.
Anyways, great video!
I've watched a handful of his videos. It's not unique to him to do this, I'd also cite minutephysics and vi hart as influences.
The nes only has 3 general purpose registers?
Yep, A, X, and Y are all you have. Most opcodes only work for A.
@@hydrantdude3642 even if I mostly only use r12, r3 and r0 when working with power oc (I mod wii games), the other registers always come in handy.
Working with just 3 registers sounds like a pain.
I’d’ve said ONE “general purpose” register , the accumulator “A”, with the X & Y “index” registers (as I recall them being called back in the 80s when I tried teaching myself 6502 assembly .. from whatever the local book store was kind enough to carry.. in the early 80s we had no “real” local book store and I felt like a deprived child). Translation: x and y not “general purpose”. But I won’t argue it.
You can imagine my surprise when I learned about the 8088/8086 registers😮 and 68000 registers!The x86 stuff was earlier college classes and then in a microprocessor design class we looked at RISC with MIPS (I still got my copy of Computer Organization and Design by Patterson & Hennessy sitting on the book case next to the fire place all these decades later!). 😮😮
I wish I had more context back then. I couldn’t have been the only student going “uh huh” but not really seeing the big picture, not that we needed it for the test. But in high school in the Pascal based CimpSci classes I didn’t understand what an ALU was in the younger days of my teacher. And a “cpu” to my college professor. When you see an 1970s/1980s “ microprocessor in a 40-pin DIP (or even larger ones by late 80s) and that’s ALL you are familiar with, the notion that an ALU is a subsection of a CPU doesn’t come into focus without understanding the history… that a CPU was literally a unit of a minicomputer or mainframe that did processing and it’s many parts were centralized. Imagine, a “cpu” came in several circuit boards. Seriously? All discrete logic chips. And some did arithmetic and logic - the ALU portion! Glad I finally got that background so I can better understand the videos here by “Usagi Electric” and the Centurion computers with their custom CPU5 or CPU6 logic boards. Fascinating.
Wow, great video
So, if one removed the maxout counter, crashes would never happen? But can the game have to process more than four lines being cleared at once?
I'm not sure I'm understanding the question correctly, if you're asking if it's possible to clear 5 or more lines at a time, no, it isn't. Tetris pieces only have 4 blocks so you can only complete 4 rows at a time.
@@hydrantdude3642 So, can the game take soooooo long to process one line clear that you can clear another line, presumably if you removed the maxout counter?
@@fireyfan25 No. Firstly, removing the maxout prevents the game crash by making the calculations much faster. Secondly, the game works through steps in order. If one is taking forever, it's not just gonna start running other ones at the same time, the processor is single-threaded. Even if the game was stuck on the score calculation for 5 minutes you couldn't place another piece on the board.
Who's gonna tell him?
Can this bug be ACE'd or is it frame perfect bs
those aren't mutually exclusive but yes we have a working ACE tas that can do anything and yes we have a theorized human route to do limited ACE to enable 2-player mode.
@@hydrantdude3642 very cool work, yeah I just meant human route ACE lol
Wait so eric was potentially 14 levels off
Players tend to use codes which remove the 999999 cap, and because this removes the part of the code that spends lots of extra time setting the score to all 9s, eric was actually not very close to the crash. The earliest documented crashes on those codes are around level 230.
However this is all moot since eric was playing on the tetris gym ROM which entirely patches out the crash.
But yes, if he was playing on a completely unmodified game (which nobody of his caliber plays on) he was pretty close to the crash.
is there a way to fix the crash?
yeah it's very easy, you just remove the part that checks for maxout and the calculation fits within the allotted time on every level.
HydrantDude, that's not true cause Scuti crashed the game on level 157.
So in other words, an unexpected ordering of events results in the call stack getting trampled, or something analogous to that.
nothing problematic happens to the stack, it's just a variable on the zero page which is used temporarily for calculations that gets overwritten.
So far I couldn't even imagine a system where the code and dynamic data are equal and "accidentally" switchable. :O
Thanks to Scuti, I found this video. And thanks to HydrantDude, of course.
A few months ago I watched a video on the 8-Bit Show And Tell channel here on UA-cam, called “ One Bad Byte Broke This Game: Commodore 64's "Livingstone, I Presume?" “. I encourage you (everyone really) to watch it. This Tetris / NES explainer reminded me of it. Different issue and circumstances but it shows how one little innocuous byte change can throw a big monkey wrench in the works. It’s not a quick video like this but if you want some quick tech dirt with limited background (although mention of a cheat code and a patch to remove it IIRC between English language version and Spanish version is enough to get an idea) then skip to 27 minutes mark and watch for a few minutes.
m.ua-cam.com/video/c4OQPojiEOo/v-deo.html
This is called a von Neumann architecture and is how nearly every modern computer works. Having them separate is Harvard architecture.
From what I remember from operating systems, the way a typical, standard OS runs basically locks you out from modifying program code, while not allowing arbitrary execution on the "ram" part of your memory (stack, heap, data segment, etc).
@@bobbobbob321 you show your age :-) either :
(1) you are old enough to be of the mainframe days (before my time)
Or
(2) you are young enough to be accustomed to a baseline interaction consisting of a mouse and high resolution graphics with millions of colors and a WIMP (window, icon, mouse, pointer) interface. And “95” was a long time ago. If you were born then you were still too young to be watching a white Bronco driving slowly down an LA freeway followed by police in a non-high-speed chase … and you missed out on “you’ve got mail!” (Which one day preceded that software crashing and taking down my entire computer - crashed OS since the buggy software Steve Case put out wrote to wrong part of memory - no protection - AND damaged my file system)
There was this glorious time in the late 70s to late 90s where home computers (let’s not call them personal computers since that leads to “pc” and that eventually became synonymous with DOS and later Wintel) came in many sizes and colors and so many different platforms and abilities. Computer stores were like candy stores. And they all crashed! There were no guardrails. Even IF the cpu offered some protection it might be in an additional chip from the chipset family and YOU KNOW that was left out to save money. And even if it were there then the OS’s of the time didn’t use it. And by the later 90s there were more and more exploits targeting the “586” (as it were) with web sites delivering finely crafted files that overran buffers so data corrupted code and in a way that was intended to gain system control.
Windows 2000 (aka NT5 and XP aka NT5.1) and Mac OS X didn’t come until the cusp of the new millennium and Linux … I played with it but only people I knew back in college and come colleagues at work were into it to any sort of degree (and not primarily using it). Oh and then there was this twerp working at Radio Shack saying the only reason he’d get an iBook was to put Linux on it. Really? How secure is your job as a glorified sales agent of cell phones and plans and equipment by the “brand” RCA (since they, as a real and serious company, had flipped)? Enough ranting about somebody barely old enough to shave working a “tech” job telling me about Linux. Fanboy-isn on any side bothers me. I don’t want to come across as old and cranky but I do miss the Wild West days. It was fun and charming. Pac Man and Rubik’s cube on Saturday morning cartoons back when Reagan let cartoons have no redeeming value other than commercialism 🤑 ! I find myself irritated at all the platforms today.
So here I am with far too many web browser tabs open (but typical I hear) and my browser crashed. But that’s all that crashed. The system and other applications stayed open. Yay! But it still sucks. I finally bought a smart TV. Not sure if I want to allow it to connect to my router and thus keep it dumb or put it on a VPN. My old HDTV has a corner that flickers - backlight going. And it cost more over a decade ago than my new 4K UHD tv (btw its still in box - gotta get off my butt watching UA-cam and spending time in comments 🙄) i.e. not worth fixing. BUT .. I vividly recall smart TVs getting bricked by ransomware in the recent times. That ties it into code and data spill over. Is a 2023 model TV safe enough? Ughhh… I wish the ideals of data not spoiling code were actually a thing but you see it still is and probably will be for some time. To nail it down takes time and time is money and moneys for the capitalists. My teenager even knows that thanks to the AP history courses taken these past few years of high school. What isn’t taught is how I used to just turn on a CRT and play a LaserDisc and had no menu and no restrictions and no ransoms etc etc. So maybe there was little protection then but I was never inundated with attacks and DRM restrictions. Maybe it was better ?
Thank you, next is why Bugged Colors happened after 137?
he alrdy made a video for that
@@33Pokenerd Thanks!
This does nothing to explain why a single line crashes the game at 155 but not a double. Or why on later levels, a single line does NOT crash the game.
crashing the game requires the v-blank interruption to happen during a very short window of time during the switch routine. there are 8 separate instances of the switch routine and therefore 8 opportunities for the game to crash. if you level up above the range where v-blank happens during the switch routines, then it is no longer possible for the game to crash. singles take longer to calculate than other line clears because they are the only line clear which involves the lowest byte of the score (adding 40 uses the 10s digit but all others only use the 100s digit and above, adding 100 300 or 1200). in addition, doubles, triples, and tetrises take different amounts of time from each other because of the part of code that deals with adding the lines to the line counter.
@@hydrantdude3642 Oh weird, didn't think it would be a narrow window that crashes things and not just "Here be dragons" past a certain lag amount. Thanks for the explanation!
While the nerds are doing the calculations, ordinary guys go through all the levels in this tetris
Stopped watching at "the processor natively runs in hexadecimal".
I wondered about that vs “binary” but I kept watching.
So this means you can't beat Tetris.