Using 4 bytes to store a number that is read into 2 bytes, as an ASCII string, in base 10, with no null terminator, is probably the most psychotic method I've ever heard for storing a number. I'm shocked it even works as well as it does.
@@absoluterwahnsinn2389 On its face, it's like if you knew how to write the number "1,000" and what it meant, but you opted to write it as one thousand separate tally marks. Now, there's a good reason why you'd use tally marks in a specific situation (tallying 1,000 objects) and maybe this happened for a good reason too, but that's one analogy.
Me before watching video: "An upside down model usually indicates a negative scale; I bet this is an overflow glitch." After watching video: "Holy crap we're lucky this game ever functioned..."
I've gotta say, I've missed your glitch and in depth game mechanics videos. I'd say you're in my top 5 content creators but I'm not as much into long play vids so I haven't watched as much as I used to but I so make sure to like and comment on all your vids I can. Keep up the good work man.
I'm not sure why you said you miss my in-depth and glitch videos, I just uploaded my biggest In-Depth project ever with the Cloud In-Depth only a few weeks ago, and the next In-Depth is in the works! We have been working on it daily together as a community over on the Twitch channel. At any rate, I really appreciate the love and support you've given me over the years, and it is great to have you around!
Oh you know after reading that comment again, maybe you were talking more about just in-depth mechanic videos in particular? That's really nice to hear, I would like to try to delve more into the mechanical side of games as a separate thing, but to be honest there is only so much FFVII can still give. But whenever it does give, I'll do my best to explain everything I know!
@4-8Productions Awesome. I did watch the Cloud one. I'll make sure to find the rest of them. Tbh TH-cam has been sabotaging my notifications, so I guess they fell through the cracks. And yes, I was talking more about game mechanics like materia interaction, Stat functions, and ways to break games. Keep up the awesome work.
@4-8Productions FF7 is indeed still living and breathing. I actually just started a perfect file run because my old PS mem card got corrupted while playing FFT. So I have to replay all the ps1 FFs, lol what a drag. Take care and keep up the great work.
@@4-8Productions I don't know if its of any interest to you to look into things that aren't speedrun useful, but maybe a video about how chocobo races are handled, or how chocobo breeding actually works in code... I know you're not really the code guy as much as mav and some others, but if you'd like a suggestion for mechanical videos... any of the things that have RNG and _implied_ interactions with items (chocobo breeding and nuts and greens for example) could stand to be demystified for those of us not as many years deep in the speedrun scene.
It’s great to see this figured out after so long; and thanks for explaining it to those of us without backgrounds in computer science or game development in such a concise, understandable manner. All I could think was that those are the materia Scarlet was really looking for. Imagine if they launched that at meteor. Sephiroth would’ve been speechless.
I knew this game was made of chewing gum and string but I didn't realize _any_ of the code was THAT bad. It is actually difficult to find a worse way to store a number, and if you do, its something that's so ridiculous that it is clearly intended to be bad design. That said, I bet this code dates back to the PS1 version, but never happens on that version because the PS1 doesn't have dynamic memory allocation like modern PC games.
There were certainly some decisions made in this game's development. It's honestly a miracle this game runs as well as it does, let alone at all, and proves this is truly the best timeline. I love this game
it was released by being hold together by duck tape. during development they were acutely worried they wouldn't be able to release it. its why the debug room is still in the game because they thought removing it would screw the game over.
@@TheBronfI thought I remembered someone saying the game was held together by duck tape and bubble gum. Honestly I like how old game developers managed to develop solutions to there problems when developing games, but now with modern games the glitches have not only gotten worse but now there just features not problems.
This is not an exotic storage. They just stored the size in a null/zero terminated ascii string. The number in the images from death are actually hexadecimal. And in ascii, 5 is 0x35 (the 0x prefix means hexadecimal), 1 is 0x31 and 2 is 0x32. In C: puts("\x35\x31\x32"); is exactly like: puts("512"); The only strange thing is that they store numbers in ascii string. There are two drawbacks. The first one is that they need to convert the string back to a number to be able to use it. The second one is that it takes more memory. Here they use 4 bytes and they can only store a number from 0 to 999, while a C unsigned short int is usually 2 bytes and can contain a number from 0 to 65,535.
Yeah maybe the wording was not ideal here, it’s not exotic or weird, it’s just the wrong tool for the job. If you need to store a number that will later be used to do math, you should store it as a number, not as an ASCII string, that’s just dumb. And then what’s even dumber is they wrote a custom, botched string to number function that, along with the fact they forgot to add null termination resulted in this bug.
As a software engineer, I agree with the guy who said this is the worst thing he’s ever seen 😂. Idk why they made storing and reading the size so complicated hahaha. Also great explanation, I gotta try this in my current playthrough when I get to Corel lol
8:40 I played through the game for the first time earlier this year and encountered this glitch here. I streamed what was happening to my friends through discord and they had never seen it before so it's cool to know all this now!
As a programmer I love in depth info like this. First ran across your channel when you had just a few subs and were kind of struggling. Happy to see your near 100k now. If you keep making indepth programming vids like this youll fill a much needed niche. I can say for certain ill be watching! Also, I wonder if the algorithm isnt looking for the Null terminator as it iterates over the memory
Nope, it's not just looking for null terminator, it actually has a lookup table of characters to determine whether the current byte is a number, which sounds super complicated for a simple algorithm like this.
So, they store the ASCII digits of the number with a null terminator. It would have saved memory by simply using 2 bytes to store the binary number. Based on what you said about the underflow, the system probably only handles signed 16-bit integers anyway which have a max value of 32,767.
Very cool finally seeing this showcased. I legit had this happen to me once and had NO EARTHLY clue how it happened to me LMAO! Now I know its not that big of a deal and my game file wasnt corrupted or something dire!
They say they left the debug room in the game because the game was so broken right before launch they were afraid that if they took it out, something would break. I think we finally know why. Why on earth did they do it this way and how in the WORLD was the PS1 able to handle such inefficiency?????
Idk doesn't seem like reading/writing 4 bytes of memory (even doing so each cycle) would slow down a room where there's only a handful of character models max on a 2d background. As for why it was done that way, maybe it was a good fit for how they designed the rest of the code? And it was so rare it never came up and as they say, "if it ain't broke don't fix it."
ff7 was kinda groundbreaking in its 3d design; noone had really tried to do what they were doing. Some of the stuff they tried worked, some didnt. The whole thing is held together with stickytape and paper mache.
@@kahlzunEven with all that, it's still one of my most beloved games I've played. Remake is on that list too but it's mostly for the music instead of the gameplay, not to say there's anything necessarily *bad* about it or the direction they took the story.
FF7 is built on top of several game engines. The field module, the battle module, the menu module, the overworld module, and the minigame module are the ones I can think of off hand. If I had to guess, they probably encoded a LOT of information as simple ascii because so much of it would need to be passed back and forth between modules. In the case of the field module, since you can go back and forth between a location and the battle module, you probably have to pass your initial location, rotation and dimensions to the battle module and back again to keep your place on the field module. The game would not be playable if you had to teleport back to the beginning of a large field area every time you battled. As for why you wouldn't just pass a scale value, that would mean that every time you went from battle to field, you'd have to do math just to determine where something was and how big it was supposed to be. Better to just store the raw numbers then.
Because this only works on the PC version, ps1 doesnt have that memory allocation. The ps1 probably only remembers the first 4 numbers because those are the only ones available to it. But of course a PC can hold much more data, also a reason why there were so many terrible PC ports back then. The games were never originally meant to be on PC and why some were buggy messes.
If I may defend the algorithm a bit (I don't mind losing all credibility haha), this seems like a fairly common bug and isn't too egregiously stupid. First of all, as you mentioned, the value is stored as a string in ASCII. I don't know why they store it like that but OK, that's just the format it came in. It's inefficient but there's nothing particularly wrong with that. All ASCII strings are supposed to end with a 00 byte, and it's standard practice to keep reading strings until you hit a 00. They improved this a bit knowing it can only be a number, so they end on anything outside of 30-39 instead of only 00. This is a fairly typical implementation. The only thing that went wrong was a mismatched assumption. Probably the people who built the fields put a 4-byte limit on the model size string, but thought they had room for 4 digits and didn't have to end it with 00. Then the people who wrote the 3D model code assumed it would be a regular ASCII string which always ends with 00 and didn't bother checking the 4-byte limit. Both are reasonable (and common) ways to do it, but the two teams needed to be consistent which they weren't. Finally, this could be something that did work reliably on the PS due to how memory was managed on the console, where the assumption that the string would always end after 4 bytes did hold up. But because memory is allocated differently on PC, and nobody was aware of such an inconspicuous underlying assumption when porting the game, it introduced this new bug.
This video made some simplifications to make it more understandable, in reality the code to convert the string to number is really, really over engineered. It actually uses a lookup table to determine whether it’s looking at a number or not. To me it looks like it was written by a novice programmer who never did such a task and instead of doing any research they just banged together some tools they knew until they had something that kind of worked 😅
@@MaciejTrebacz Ah I see. That's less justifiable lol. I wonder if that was due to the mixture of text encodings used in the game. Maybe some parts are ASCII-esque but not entirely, or it was subject to change, so they used a lookup table to ensure whatever encoding always gets converted correctly.
@@letao12 The PS1 version definitely wasn't standard ASCII, or even Shift-JIS. So that's almost definitely part of why it was programmed this way. I wonder if this is essentially part of a big number implementation? Just because the character field models never go over 1024 in size doesn't mean it's not part of some larger system that requires sizes bigger than you can fit in a uint_32.
Saw m4v3k checking about this on stream, I was wondering if you would make a video about it, I'm glad you did! It was a really interesting glitch to understand!
Going by the memory explanation given, this glitch should also trigger on any map where Cloud's model is defaulted to 2,048. I bet you could trigger this glitch by loading in/out of rooms with the Debug Room. Maybe try this when Cloud is inside the Submarine? I recall the "camera" being zoomed in a bit close there.
The minute you started talking about it I knew it was going to have to do with random memory being used in an unintended way. That's almost always the way these things work.
FF7 OG is nearly 30 years old and people still cherish it and are still finding new things about it. FF7 Remake/Rebirth is only a few years old and it's crickets from all the same people telling you it's a masterpiece and GOTY and better than the original
I think the upside down glitch may also occur early game Midgard Slums, I think before the first church scene or slightly there after. In that case it may have just been the cursor pointer finger upside down because I don't think I could see Cloud due to camera shenanigans. Come to think of it maybe that was just something else, because I see you still have a normal finger cursor while Cloud is massive.
Why would you EVER code that as "grab bytes until you get one that starts with something other than 3"? It's nuts. You KNOW the maximum number for that field and that it will always be a positive number, so you code it normally and simply grab two bytes every time.
Kinda got behind watching twitch, but I never miss a YT vid. Good work on it, man! I absolutely love your content, and you’re by far the best FF7 content creator I know of.
This probably has to do with the field module passing data to the battle module, then the menu module and back again. Timer is constantly changing between battles; so too is Gil count and XP. If you're max level, this should stop. In theory though, shouldn't different party members change the math? I don’t think they all have the same XP values. Could it be step count related? You should reset it after each battle. My last thought is, could it be a fault in the initialization code for the modules?
Just to point out the normal approach when you don't know how many bytes you'll need for your number is to have one or more bytes to keep the size. Basically 512 would be 2(because we need 2 bytes for the size as it's above 255), 2(because 2*256 = 512), 0(for the remainder). This prevents any potential issues because you're always storing how many bytes you need rather than looking at the values of bytes to tell when you end. Also given the game only ever uses powers of two for scaling it may be more efficient to just store the power, 1024 is just 2^10, 512 is 2^9; storing 10 and 9 respectively and just doing a left shift by the number for the scaling would be a lot safer/efficient.
So when I came upon this glitch I thought it was somehow related to the northern crater scene at the end of disk one where cloud is on the ceiling before crystalized sephiroth drops down all being triggered by the extremely wonky code
That's adorable. though all they would have to have done is leave in a trailing 00, but I mean it's an interesting lesson for programming overlooked side effects.
Might be nothing, but could it be related to the demos of the game that were released? The first reactor and Mt Nibel reactor areas were both areas used in demos of the game. I guess that doesn't explain Bugenhagen's observatory though.
No way lmao, I remember getting this glitch like 5 years ago just casually playing the game. It happened at the screen just past the North Corel reactor
The previous FF game FF6 in Japan and FF3 in America, where on the SNES and FF7 might have been started while the negotiations were ongoing with Square, Nintendo, and Sony. Square might not have known what console architecture the game would be released under. The dynamic could have been a way to make it easier to port to multiple systems depending on who would host the game. It was also their first 3D game so there might be some jankie code as a result of not knowing what problems could arise from being in a 3D engine. But even their 2D games had some weird glitches and bugs.
i didnt even know this was a thing. i never encountered it. the only glitch i remember activating was the cut scene in the junon elevator of the fishing village that kept showing cloud giving the black materia to sephiroth.
Hey, thanks for all your videos. I have learnt stuff I never knew existed in my all time favourite game. can I ask, I have the Ochu trainer because I want to speed up FPS, but I can't friggin edit the values like you do. How do you even do that?
Bro you reminded me that i saw this glitch when i first ever played through this game. I was 7 and it happened at bugenhagen. My brother didnt believe me!
Good videos I would love to see you do would be on Important Missable Item Locations/How To Get Them and all the ways Get Each Type of Chocobo, not just the 15 minute way for the speed runners.
I got it to trigger on the avalanche screen with 95% consistency on my casual playthrough, it triggered immediately when i returned to the avalanche screen after the cutscene and was triggered like 1/20 times (the only time it didn't trigger after 1 try is right after a battle cancelled it on the avalanche screen). I got recordings :3
I didn't even understand what you were talking about at first. I immediately understood it as "oh, those are hex numbers. That makes sense they would read numbers there". But when it clicked that they were literally just taking the decimal 30 range and reading the ones digit there, I mean that is just so dumb! I know consoles back in the day did hacky stuff in order to fit more on the disc/cartridge. But I can't imagine that this would even improve anything at all? It's just a weird obfuscated way to read numbers.
16:07 makes sense since that is an ASCII string that represents a number. There are valid scenarios where you want to take a number that is displayed as a text string and pull the displayed number as a real number. The code is likely bog standard code for pulling a number from a string. The way you describe it is how that sort of thing is done, it's a very standard function. parseInt() in JavaScript and int.Parse() in ..NET both work the same as what you described. It's likely the text was typed in by a developer somewhere and it was just dumped into the game as-is. Given it only uses four bytes and they could have saved a whopping two bytes for each model it really isn't a big deal all things considered. Then the game itself had the responsibility to parse out the strings. Of course they failed to protect against buffer overflow, a very basic bug.
Great find! Hey, I revisited Bloodstained again recently and I once again couldn't help but think Zangetsu is your doppelganger. Has anyone else pointed this out? Maybe the character designer is an 4-8 viewer?
i think death broke it lol but yh this was very insightful i didnt know why this happened when i watched one of your stream this was a good watch and explaination
Pokemon Red & Blue are my go-to "this game is gloriously broken" examples, but I love hearing about the madness underlying FF7's polish. That number encoding system just feels wrong to me. It's the sort of thing I'd have done in my late teens when I was first learning c++ coding and didn't know the right ways (bitwise operations come to mind). Considering how many sacrifices the team had to make, how many hoops they had to jump through just to optimize the game to fit and work, it's weird that they'd have such a weirdly inefficient and convoluted way to store 512 at the start of a model.
So my hunch it has to do with bad Memory management, or as i wrote under the part in question of the Pincer Mod play trough, "garbage collection". I thought it was a simple error in handling signed and unsigned integers, wich wouldn't be a surprise. I had never imagined such a bad/warped/inefficient way of storing the value of the model size. It hasn't even a advantage over the standard way of storing values and will use more time/resources. Please correct me if i am mistaken. Thank you for telling us how and why this happens. This question bugged me for years.
Yeah there’s absolutely zero reason to store the model size as string given this is meant to be used to do math later. They blew it on several different layers.
Based on the way the memory is stored, when the model size is 512 it'll always still write the 4 bytes so [35][31][32][00] so the code extract numbers from memory would always stop at [00] That is assuming that it does in fact always write the 4 bytes of memory even for numbers that only require the 3.
I suppose you can get this glitch when playing as Tifa or Cid as well, and given how short those sections are, there's a good chance no one's ever seen them yet.
I am a very novice programmer. My code is horrible. But my jaw dropped when I saw how they coded this. That is insanity. What materia were they smoking?
Given this explanation, wouldn't we occasionally see only a single number starting with 3 added to the end, resulting in a roughly 10x scaled model that isn't too high to underflow? or is the max value small enough that even one extra digit is enough?
So the 3 junk slots after 1024 are always the same when this happens? Or does any number over 1024 cause max underflow, therefore, no variations? Also, why doesn't this happen on other platforms?
On PS there is no dynamically allocated memory AFAIK, since the console has a well-known memory capacity and they can pre-allocate everything in the right place. Dynamic allocation is only used on PC because the amount of available memory can't be predicted. I would think it's possible to get other random values that overflow to different amounts. Realistically it depends on what the memory was previously used for, and that might have some patterns that force it to be always a similar size.
They can be different, but I think the underflow always ends up in about the same amount. So I don't think you'll be getting drastically different sizes of Cloud.
@@4-8Productions Is the underflow point at 65536? Like if you generated just a single "3X" value in the 5th column, you could end up with a value like 10249, so wouldn't that give you a big cloud that isn't upside down?
Pretty sure PS4 & PS5 are the same version, and they're based on the Steam version so it makes sense that the bug happens there as well, although I personally never seen it. Thanks for the report!
Hmm. Thats just standard buffer overflow problem. I would say taht the issue was not stetting 00 as the 5th byte. (ofcourse depending on the other API)
yeah if they've just been more careful and made sure the last byte was always 00 when they loaded that value it wouldn't be a problem. Or if they just stored this number as a proper short/integer depending on their needs. But they did neither and here we are.
Storing numbers as ASCII might seem strange, but the last month I've had to work with that and bytes being stored as base 16 (hex) in ASCII too. Is this the case for the PS1 version too? Otherwise, it might just be to avoid any endianness issues when porting to PC. In my case it was for sending data blocks over a network (I had nothing to do with the implementation of the server, lol).
If you want an explanation: Endianness affects the order of bytes (not bits, usually) in a value. If you have a number that is more than 127 (or 255, if no negative requirements), then you'd need more than one byte to represent it. binary: 00000001 00000000 (2 bytes) = decimal: 256, right? Maybe! It depends on what order the bytes are stored in! Is it the way I just represented it or is it 00000000 00000001? In other words, the answer could be 256 or just 1. If PS1 uses a different endianness than PC, this could cause big issues if not properly considered. Why does the ASCII version fix this issue? Character arrays (strings), if ASCII, are arrays where each value is just one byte at a time, no endianness issues!
The problem with that explanation is that FF7 uses thousands of different number values for many different things and they are all mostly stored as little endian integers or shorts. So they obviously knew how to do it and endianness wasn't an issue for them. This model size/scale value is one of very few that are stored as ASCII (I'm not even sure if there are more, but they might be).
Using 4 bytes to store a number that is read into 2 bytes, as an ASCII string, in base 10, with no null terminator, is probably the most psychotic method I've ever heard for storing a number. I'm shocked it even works as well as it does.
Lmaooo this
It honestly hurt my brain. I just have no idea why they'd do something like this. It doesn't make sense. It's so strange.
It is the Rube-Goldberg machine of data storage. There is something beautiful about it.
Pls explain in non-nerd terms
@@absoluterwahnsinn2389 On its face, it's like if you knew how to write the number "1,000" and what it meant, but you opted to write it as one thousand separate tally marks. Now, there's a good reason why you'd use tally marks in a specific situation (tallying 1,000 objects) and maybe this happened for a good reason too, but that's one analogy.
Me before watching video: "An upside down model usually indicates a negative scale; I bet this is an overflow glitch."
After watching video: "Holy crap we're lucky this game ever functioned..."
I thought SM64 was jank.
its the same feeling I get when I play The Sims 2. That game was built on hope and payer type coding lmao
Pokémon Red/Blue: "First time?"
I've gotta say, I've missed your glitch and in depth game mechanics videos. I'd say you're in my top 5 content creators but I'm not as much into long play vids so I haven't watched as much as I used to but I so make sure to like and comment on all your vids I can. Keep up the good work man.
I'm not sure why you said you miss my in-depth and glitch videos, I just uploaded my biggest In-Depth project ever with the Cloud In-Depth only a few weeks ago, and the next In-Depth is in the works! We have been working on it daily together as a community over on the Twitch channel. At any rate, I really appreciate the love and support you've given me over the years, and it is great to have you around!
Oh you know after reading that comment again, maybe you were talking more about just in-depth mechanic videos in particular? That's really nice to hear, I would like to try to delve more into the mechanical side of games as a separate thing, but to be honest there is only so much FFVII can still give. But whenever it does give, I'll do my best to explain everything I know!
@4-8Productions Awesome. I did watch the Cloud one. I'll make sure to find the rest of them. Tbh TH-cam has been sabotaging my notifications, so I guess they fell through the cracks. And yes, I was talking more about game mechanics like materia interaction, Stat functions, and ways to break games. Keep up the awesome work.
@4-8Productions FF7 is indeed still living and breathing. I actually just started a perfect file run because my old PS mem card got corrupted while playing FFT. So I have to replay all the ps1 FFs, lol what a drag. Take care and keep up the great work.
@@4-8Productions I don't know if its of any interest to you to look into things that aren't speedrun useful, but maybe a video about how chocobo races are handled, or how chocobo breeding actually works in code... I know you're not really the code guy as much as mav and some others, but if you'd like a suggestion for mechanical videos... any of the things that have RNG and _implied_ interactions with items (chocobo breeding and nuts and greens for example) could stand to be demystified for those of us not as many years deep in the speedrun scene.
Not only upside down, he's probably inside out as well, sm64 has a pretty similar glitch with the fly guy.
He's just inverted along all three axes.
It’s great to see this figured out after so long; and thanks for explaining it to those of us without backgrounds in computer science or game development in such a concise, understandable manner.
All I could think was that those are the materia Scarlet was really looking for. Imagine if they launched that at meteor. Sephiroth would’ve been speechless.
This is exactly the reason I subscribed to you death, other than the awesome mod play throughs that is. Thanks for everything.
Thanks!
@@4-8Productions the least I can do with all the amazing content you've given us.
I knew this game was made of chewing gum and string but I didn't realize _any_ of the code was THAT bad. It is actually difficult to find a worse way to store a number, and if you do, its something that's so ridiculous that it is clearly intended to be bad design.
That said, I bet this code dates back to the PS1 version, but never happens on that version because the PS1 doesn't have dynamic memory allocation like modern PC games.
you know a FF game gonna be GOAT'd when it's glitchy af
@@GrantedBunion True dis
wait WHAT
this game came out b4 u were born ugh
There were certainly some decisions made in this game's development. It's honestly a miracle this game runs as well as it does, let alone at all, and proves this is truly the best timeline. I love this game
it was released by being hold together by duck tape. during development they were acutely worried they wouldn't be able to release it. its why the debug room is still in the game because they thought removing it would screw the game over.
I'm thinking, if this is only present in the PC version, that it's a porting issue, and is related to avoid issues with endianness.
@@MMasterDEProbably because of how differently PCs store memory compared to a PS1
@@TheBronfI thought I remembered someone saying the game was held together by duck tape and bubble gum. Honestly I like how old game developers managed to develop solutions to there problems when developing games, but now with modern games the glitches have not only gotten worse but now there just features not problems.
FFVII, the gift that keeps on giving, hopfuly one day I am blessed and found worthy of viewing big Cloud.
Thank you and m4v3k for continuing to breathe new life into this classic! So grateful to have fans like you who keep making FFVII content.
This is not an exotic storage. They just stored the size in a null/zero terminated ascii string. The number in the images from death are actually hexadecimal. And in ascii, 5 is 0x35 (the 0x prefix means hexadecimal), 1 is 0x31 and 2 is 0x32.
In C:
puts("\x35\x31\x32");
is exactly like:
puts("512");
The only strange thing is that they store numbers in ascii string. There are two drawbacks.
The first one is that they need to convert the string back to a number to be able to use it.
The second one is that it takes more memory. Here they use 4 bytes and they can only store a number from 0 to 999, while a C unsigned short int is usually 2 bytes and can contain a number from 0 to 65,535.
Yeah maybe the wording was not ideal here, it’s not exotic or weird, it’s just the wrong tool for the job. If you need to store a number that will later be used to do math, you should store it as a number, not as an ASCII string, that’s just dumb. And then what’s even dumber is they wrote a custom, botched string to number function that, along with the fact they forgot to add null termination resulted in this bug.
As a software engineer, I agree with the guy who said this is the worst thing he’s ever seen 😂. Idk why they made storing and reading the size so complicated hahaha. Also great explanation, I gotta try this in my current playthrough when I get to Corel lol
This was probably due to a bad porting job, and it exists to avoid endianness issues. However, the algorithm to read the numbers is just dumb.
Thank you so much! This happened to me once and I was so confused and I couldn’t find anyone explaining how it happened
8:40 I played through the game for the first time earlier this year and encountered this glitch here. I streamed what was happening to my friends through discord and they had never seen it before so it's cool to know all this now!
As a programmer I love in depth info like this. First ran across your channel when you had just a few subs and were kind of struggling. Happy to see your near 100k now. If you keep making indepth programming vids like this youll fill a much needed niche. I can say for certain ill be watching! Also, I wonder if the algorithm isnt looking for the Null terminator as it iterates over the memory
Nope, it's not just looking for null terminator, it actually has a lookup table of characters to determine whether the current byte is a number, which sounds super complicated for a simple algorithm like this.
I had this happen to me in Corel on my first playthrough and have been curious about it ever since. Interesting stuff!
So, they store the ASCII digits of the number with a null terminator. It would have saved memory by simply using 2 bytes to store the binary number. Based on what you said about the underflow, the system probably only handles signed 16-bit integers anyway which have a max value of 32,767.
I love how after so long, you all are still finding out stuff about this game
Very cool finally seeing this showcased. I legit had this happen to me once and had NO EARTHLY clue how it happened to me LMAO! Now I know its not that big of a deal and my game file wasnt corrupted or something dire!
the fact this game works at all is a genuine miracle
FF7 is my favorite game and I love these videos. It's interesting to see under the hood of this bizarrely programmed game.
Thanks!
They say they left the debug room in the game because the game was so broken right before launch they were afraid that if they took it out, something would break. I think we finally know why. Why on earth did they do it this way and how in the WORLD was the PS1 able to handle such inefficiency?????
Idk doesn't seem like reading/writing 4 bytes of memory (even doing so each cycle) would slow down a room where there's only a handful of character models max on a 2d background.
As for why it was done that way, maybe it was a good fit for how they designed the rest of the code? And it was so rare it never came up and as they say, "if it ain't broke don't fix it."
ff7 was kinda groundbreaking in its 3d design; noone had really tried to do what they were doing. Some of the stuff they tried worked, some didnt. The whole thing is held together with stickytape and paper mache.
@@kahlzunEven with all that, it's still one of my most beloved games I've played. Remake is on that list too but it's mostly for the music instead of the gameplay, not to say there's anything necessarily *bad* about it or the direction they took the story.
FF7 is built on top of several game engines. The field module, the battle module, the menu module, the overworld module, and the minigame module are the ones I can think of off hand. If I had to guess, they probably encoded a LOT of information as simple ascii because so much of it would need to be passed back and forth between modules. In the case of the field module, since you can go back and forth between a location and the battle module, you probably have to pass your initial location, rotation and dimensions to the battle module and back again to keep your place on the field module. The game would not be playable if you had to teleport back to the beginning of a large field area every time you battled. As for why you wouldn't just pass a scale value, that would mean that every time you went from battle to field, you'd have to do math just to determine where something was and how big it was supposed to be. Better to just store the raw numbers then.
Because this only works on the PC version, ps1 doesnt have that memory allocation. The ps1 probably only remembers the first 4 numbers because those are the only ones available to it. But of course a PC can hold much more data, also a reason why there were so many terrible PC ports back then. The games were never originally meant to be on PC and why some were buggy messes.
If I may defend the algorithm a bit (I don't mind losing all credibility haha), this seems like a fairly common bug and isn't too egregiously stupid.
First of all, as you mentioned, the value is stored as a string in ASCII. I don't know why they store it like that but OK, that's just the format it came in. It's inefficient but there's nothing particularly wrong with that.
All ASCII strings are supposed to end with a 00 byte, and it's standard practice to keep reading strings until you hit a 00. They improved this a bit knowing it can only be a number, so they end on anything outside of 30-39 instead of only 00. This is a fairly typical implementation.
The only thing that went wrong was a mismatched assumption. Probably the people who built the fields put a 4-byte limit on the model size string, but thought they had room for 4 digits and didn't have to end it with 00. Then the people who wrote the 3D model code assumed it would be a regular ASCII string which always ends with 00 and didn't bother checking the 4-byte limit. Both are reasonable (and common) ways to do it, but the two teams needed to be consistent which they weren't.
Finally, this could be something that did work reliably on the PS due to how memory was managed on the console, where the assumption that the string would always end after 4 bytes did hold up. But because memory is allocated differently on PC, and nobody was aware of such an inconspicuous underlying assumption when porting the game, it introduced this new bug.
This video made some simplifications to make it more understandable, in reality the code to convert the string to number is really, really over engineered. It actually uses a lookup table to determine whether it’s looking at a number or not. To me it looks like it was written by a novice programmer who never did such a task and instead of doing any research they just banged together some tools they knew until they had something that kind of worked 😅
@@MaciejTrebacz Ah I see. That's less justifiable lol. I wonder if that was due to the mixture of text encodings used in the game. Maybe some parts are ASCII-esque but not entirely, or it was subject to change, so they used a lookup table to ensure whatever encoding always gets converted correctly.
@@letao12 The PS1 version definitely wasn't standard ASCII, or even Shift-JIS. So that's almost definitely part of why it was programmed this way.
I wonder if this is essentially part of a big number implementation? Just because the character field models never go over 1024 in size doesn't mean it's not part of some larger system that requires sizes bigger than you can fit in a uint_32.
Saw m4v3k checking about this on stream, I was wondering if you would make a video about it, I'm glad you did! It was a really interesting glitch to understand!
Finally, an explanation. I had this happen to my playthrough once and never understood it. Now it makes sense.
Going by the memory explanation given, this glitch should also trigger on any map where Cloud's model is defaulted to 2,048.
I bet you could trigger this glitch by loading in/out of rooms with the Debug Room.
Maybe try this when Cloud is inside the Submarine? I recall the "camera" being zoomed in a bit close there.
The minute you started talking about it I knew it was going to have to do with random memory being used in an unintended way. That's almost always the way these things work.
Rumor has it the guy who made this code went on to number the kingdom hearts games
I think I've only ever heard you mention this, never seen it!
Great vid dude
Always learning something new about FF7. Amazing. Thanks Death
I've never even heard of this glitch before. Very interesting...
ff7 will never give up all it secrets in over 25 years.
FF7 OG is nearly 30 years old and people still cherish it and are still finding new things about it. FF7 Remake/Rebirth is only a few years old and it's crickets from all the same people telling you it's a masterpiece and GOTY and better than the original
I get so much joy out of you sharing your love of this game.
Thanks!
Oh wow, It's not everyday I see something new in FF7.
I’m so glad I’m not the only person who ever noticed this. I remember taking a screenshot back in 2015 but somehow I lost it 😂
For real this is probably the best and most reliable FF7 content in recent years
I think the upside down glitch may also occur early game Midgard Slums, I think before the first church scene or slightly there after. In that case it may have just been the cursor pointer finger upside down because I don't think I could see Cloud due to camera shenanigans. Come to think of it maybe that was just something else, because I see you still have a normal finger cursor while Cloud is massive.
This is one of the funniest things I've seen in a long time. I literally burst out laughing when I realized how bad the algorithm is!
Videos like this are always a fun watch for a CS student :)
11:15 "Trying everything on everything".
Ah, the Broken Sword method.
It's the best method, it never fails.
Why would you EVER code that as "grab bytes until you get one that starts with something other than 3"?
It's nuts. You KNOW the maximum number for that field and that it will always be a positive number, so you code it normally and simply grab two bytes every time.
this happened to me! changing the resolution worked at the time - and it was always on the same room (the one from your ss)
Kinda got behind watching twitch, but I never miss a YT vid. Good work on it, man! I absolutely love your content, and you’re by far the best FF7 content creator I know of.
This game has endless secrets and quirks and I am here for all of them
This probably has to do with the field module passing data to the battle module, then the menu module and back again. Timer is constantly changing between battles; so too is Gil count and XP. If you're max level, this should stop. In theory though, shouldn't different party members change the math? I don’t think they all have the same XP values. Could it be step count related? You should reset it after each battle.
My last thought is, could it be a fault in the initialization code for the modules?
almost 100k subs that's insane i'm glad that i am able to be subbed before it
Just to point out the normal approach when you don't know how many bytes you'll need for your number is to have one or more bytes to keep the size.
Basically 512 would be 2(because we need 2 bytes for the size as it's above 255), 2(because 2*256 = 512), 0(for the remainder).
This prevents any potential issues because you're always storing how many bytes you need rather than looking at the values of bytes to tell when you end.
Also given the game only ever uses powers of two for scaling it may be more efficient to just store the power, 1024 is just 2^10, 512 is 2^9; storing 10 and 9 respectively and just doing a left shift by the number for the scaling would be a lot safer/efficient.
math with Death is the best. Got my geek on for sure 1024 bits man!!!
So when I came upon this glitch I thought it was somehow related to the northern crater scene at the end of disk one where cloud is on the ceiling before crystalized sephiroth drops down all being triggered by the extremely wonky code
this is beautiful
This glitch happened to me before, I have it clipped but it happened with no back and forth. In the Coral spot.
That's adorable. though all they would have to have done is leave in a trailing 00, but I mean it's an interesting lesson for programming overlooked side effects.
My FMVs used to play upside down in this game for some reason - way back in the day on PC
Might be nothing, but could it be related to the demos of the game that were released? The first reactor and Mt Nibel reactor areas were both areas used in demos of the game.
I guess that doesn't explain Bugenhagen's observatory though.
Interesting thought!
Yea mate I had that trigger in Bugenhagen's observatory once, confused the heck out of me!
No way lmao, I remember getting this glitch like 5 years ago just casually playing the game. It happened at the screen just past the North Corel reactor
The previous FF game FF6 in Japan and FF3 in America, where on the SNES and FF7 might have been started while the negotiations were ongoing with Square, Nintendo, and Sony. Square might not have known what console architecture the game would be released under. The dynamic could have been a way to make it easier to port to multiple systems depending on who would host the game. It was also their first 3D game so there might be some jankie code as a result of not knowing what problems could arise from being in a 3D engine. But even their 2D games had some weird glitches and bugs.
i didnt even know this was a thing. i never encountered it. the only glitch i remember activating was the cut scene in the junon elevator of the fishing village that kept showing cloud giving the black materia to sephiroth.
Hey, thanks for all your videos. I have learnt stuff I never knew existed in my all time favourite game. can I ask, I have the Ochu trainer because I want to speed up FPS, but I can't friggin edit the values like you do. How do you even do that?
Hit F1, then the numbers should be green, type in the new number, right click, update. 👍
want to know if this work with cid amd tifa besides just cloud?
This happened to me the first time I played FFVII Steam version, I had no idea it was considered a “rare” glitch lol :D
I'd completely forgotten about this happened to me until this video
Why does FF7 years later still shrouded in mystery..... This game will always feel like there's something else to discover
Bro you reminded me that i saw this glitch when i first ever played through this game. I was 7 and it happened at bugenhagen. My brother didnt believe me!
Good videos I would love to see you do would be on Important Missable Item Locations/How To Get Them and all the ways Get Each Type of Chocobo, not just the 15 minute way for the speed runners.
I’ve experienced this glitch before. I believe I was playing on the steam version. It was on the screen behind Coral where Barret looses his hand.
Lol, as I wrote that I looked up and you were already demonstrating that screen in video.
I got it to trigger on the avalanche screen with 95% consistency on my casual playthrough, it triggered immediately when i returned to the avalanche screen after the cutscene and was triggered like 1/20 times (the only time it didn't trigger after 1 try is right after a battle cancelled it on the avalanche screen). I got recordings :3
sorry i typoed it triggered 19/20 times, 1/20 times it didnt trigger ^^
Alternate timeline confirmed, Aeris Aerith / Cloud Upside Down Massive Cloud
I didn't even understand what you were talking about at first. I immediately understood it as "oh, those are hex numbers. That makes sense they would read numbers there". But when it clicked that they were literally just taking the decimal 30 range and reading the ones digit there, I mean that is just so dumb! I know consoles back in the day did hacky stuff in order to fit more on the disc/cartridge. But I can't imagine that this would even improve anything at all? It's just a weird obfuscated way to read numbers.
This is great! A very fun glitch.
Great work!
16:07 makes sense since that is an ASCII string that represents a number. There are valid scenarios where you want to take a number that is displayed as a text string and pull the displayed number as a real number.
The code is likely bog standard code for pulling a number from a string. The way you describe it is how that sort of thing is done, it's a very standard function. parseInt() in JavaScript and int.Parse() in ..NET both work the same as what you described.
It's likely the text was typed in by a developer somewhere and it was just dumped into the game as-is. Given it only uses four bytes and they could have saved a whopping two bytes for each model it really isn't a big deal all things considered. Then the game itself had the responsibility to parse out the strings. Of course they failed to protect against buffer overflow, a very basic bug.
Great find! Hey, I revisited Bloodstained again recently and I once again couldn't help but think Zangetsu is your doppelganger. Has anyone else pointed this out? Maybe the character designer is an 4-8 viewer?
Cloud must have taken a super mushroom from the super smash Bros game back with him into FF7
loved this, bro - more please
I never get tired of this game
Sooo, upside down gigantimax cloud% when 😅 So goofy glitch and good that we have now more details in this.
Keep up the good work.
It'll be 2050 and we'll still be making discoveries about this game.
i think death broke it lol but yh this was very insightful i didnt know why this happened when i watched one of your stream this was a good watch and explaination
Pokemon Red & Blue are my go-to "this game is gloriously broken" examples, but I love hearing about the madness underlying FF7's polish. That number encoding system just feels wrong to me. It's the sort of thing I'd have done in my late teens when I was first learning c++ coding and didn't know the right ways (bitwise operations come to mind). Considering how many sacrifices the team had to make, how many hoops they had to jump through just to optimize the game to fit and work, it's weird that they'd have such a weirdly inefficient and convoluted way to store 512 at the start of a model.
Missed it live but I’m here now
So my hunch it has to do with bad Memory management, or as i wrote under the part in question of the Pincer Mod play trough, "garbage collection". I thought it was a simple error in handling signed and unsigned integers, wich wouldn't be a surprise. I had never imagined such a bad/warped/inefficient way of storing the value of the model size. It hasn't even a advantage over the standard way of storing values and will use more time/resources. Please correct me if i am mistaken.
Thank you for telling us how and why this happens.
This question bugged me for years.
Yeah there’s absolutely zero reason to store the model size as string given this is meant to be used to do math later. They blew it on several different layers.
I love this game so much.
Very cool! Does this happen with Tifa/Cid, and can it work on any other versions?
This makes me think that the glitch could also happen in the Lifestream, unless the multiple Clouds are handled differently from normal Cloud.
Based on the way the memory is stored, when the model size is 512 it'll always still write the 4 bytes so [35][31][32][00] so the code extract numbers from memory would always stop at [00]
That is assuming that it does in fact always write the 4 bytes of memory even for numbers that only require the 3.
I wonder if the same can be done to Cid when he temporarily becomes leader?
I suppose you can get this glitch when playing as Tifa or Cid as well, and given how short those sections are, there's a good chance no one's ever seen them yet.
You know what they say about big, upside down Cloud? Big Shoes!
so only a few different model sizes, I really thought there would be more considering all the scale and angles in this game.
I am a very novice programmer. My code is horrible.
But my jaw dropped when I saw how they coded this. That is insanity. What materia were they smoking?
Given this explanation, wouldn't we occasionally see only a single number starting with 3 added to the end, resulting in a roughly 10x scaled model that isn't too high to underflow? or is the max value small enough that even one extra digit is enough?
So the 3 junk slots after 1024 are always the same when this happens? Or does any number over 1024 cause max underflow, therefore, no variations?
Also, why doesn't this happen on other platforms?
On PS there is no dynamically allocated memory AFAIK, since the console has a well-known memory capacity and they can pre-allocate everything in the right place. Dynamic allocation is only used on PC because the amount of available memory can't be predicted.
I would think it's possible to get other random values that overflow to different amounts. Realistically it depends on what the memory was previously used for, and that might have some patterns that force it to be always a similar size.
They can be different, but I think the underflow always ends up in about the same amount. So I don't think you'll be getting drastically different sizes of Cloud.
@@4-8Productions
Is the underflow point at 65536? Like if you generated just a single "3X" value in the 5th column, you could end up with a value like 10249, so wouldn't that give you a big cloud that isn't upside down?
@@4-8Productions Appreciate the response, thanks!
Never happened to me...
Cheers to super good nerding, all the same! Major nerd cred to y'all!
The Bugenhagen one happened to me on Playstation 4 (?) I played on PS5. Is there a PS5 version, or was it the same as for PS4?
Pretty sure PS4 & PS5 are the same version, and they're based on the Steam version so it makes sense that the bug happens there as well, although I personally never seen it. Thanks for the report!
Cloud working on them squats
Hmm. Thats just standard buffer overflow problem. I would say taht the issue was not stetting 00 as the 5th byte.
(ofcourse depending on the other API)
yeah if they've just been more careful and made sure the last byte was always 00 when they loaded that value it wouldn't be a problem. Or if they just stored this number as a proper short/integer depending on their needs. But they did neither and here we are.
Storing numbers as ASCII might seem strange, but the last month I've had to work with that and bytes being stored as base 16 (hex) in ASCII too. Is this the case for the PS1 version too? Otherwise, it might just be to avoid any endianness issues when porting to PC. In my case it was for sending data blocks over a network (I had nothing to do with the implementation of the server, lol).
If you want an explanation:
Endianness affects the order of bytes (not bits, usually) in a value. If you have a number that is more than 127 (or 255, if no negative requirements), then you'd need more than one byte to represent it. binary: 00000001 00000000 (2 bytes) = decimal: 256, right? Maybe! It depends on what order the bytes are stored in! Is it the way I just represented it or is it 00000000 00000001? In other words, the answer could be 256 or just 1. If PS1 uses a different endianness than PC, this could cause big issues if not properly considered. Why does the ASCII version fix this issue? Character arrays (strings), if ASCII, are arrays where each value is just one byte at a time, no endianness issues!
The problem with that explanation is that FF7 uses thousands of different number values for many different things and they are all mostly stored as little endian integers or shorts. So they obviously knew how to do it and endianness wasn't an issue for them. This model size/scale value is one of very few that are stored as ASCII (I'm not even sure if there are more, but they might be).
Cool never seen that
if one number is stored cloud becomes very big but the right way up?