(Yes, I know it was written in ASM).
A Comprehensive Super Mario Bros. Disassembly
41–50 of 87 posts
Re: A Comprehensive Super Mario Bros. Disassembly
#42You might also be interested in the dissambly of the first pokemon games: https://github.com/pret/pokered And some other pokemon games: https://github.com/pret/pokered#see-also
Re: A Comprehensive Super Mario Bros. Disassembly
#43Earlier quoted context omitted.
Lookup tables were indeed a common technique used by games in the past.
And present, too, right? It's not the same reason as it would have been in the 80s, but today in performance critical code it is not uncommon to reduce the number of conditionals for better CPU pipelining, and lookup tables are a very common tool for this.
A lookup table meshes much better with fixed frame rate gameplay, either with one entry per frame, or quantizing countdown timers of how many frames to wait to go to the next state.
Re: A Comprehensive Super Mario Bros. Disassembly
#44Earlier quoted context omitted.
You can also fine-tune the feel of a jump when you're directly editing a handful of values vs trying to find a function that describes your desired results.
How so? "Trying to find a function" is editing a handful of parameters to a polynomial+exponential model -- the same thing
Re: A Comprehensive Super Mario Bros. Disassembly
#45Check out the section under "DemoActionData": this is where it stores (and plays) the demo you see when you don't push Start and Mario runs around on his own volition. It just simulates player input and runs it through the regular game engine. (The alternative, playing a recorded video, would have been laughably data intensive.)
Same thing goes for Super Mario 64. The popular TASer pannenkoek actually explored whether it was possible to manipulate Demo-Mario's starting position in such a way that he collects a star with the demo input (this was for the purposes of special "A-Button Challenge" speedruns, where pressing the A-Button must be kept to a minimum, but since the demo input isn't actual player input it isn't counted) Sadly I think th…
Re: A Comprehensive Super Mario Bros. Disassembly
#46Earlier quoted context omitted.
And present, too, right? It's not the same reason as it would have been in the 80s, but today in performance critical code it is not uncommon to reduce the number of conditionals for better CPU pipelining, and lookup tables are a very common tool for this.
I think the biggest difference is that modern games tend to be written for variable frame rates, stuffing floating point time deltas through equations. A lookup table meshes much better with fixed frame rate gameplay, either with one entry per frame, or quantizing countdown timers of how many frames to wait to go to the next state.
[1] not the full story
Re: A Comprehensive Super Mario Bros. Disassembly
#47Earlier quoted context omitted.
Lookup tables were indeed a common technique used by games in the past.
And present, too, right? It's not the same reason as it would have been in the 80s, but today in performance critical code it is not uncommon to reduce the number of conditionals for better CPU pipelining, and lookup tables are a very common tool for this.
Re: A Comprehensive Super Mario Bros. Disassembly
#48Earlier quoted context omitted.
And present, too, right? It's not the same reason as it would have been in the 80s, but today in performance critical code it is not uncommon to reduce the number of conditionals for better CPU pipelining, and lookup tables are a very common tool for this.
> it is not uncommon to reduce the number of conditionals for better CPU pipelining, and lookup tables are a very common tool for this. On modern CPUs, data dependency, such as lookup tables often cause pipeline stalls — worse pipelining. L1 cache is at a premium as well, you rarely want to waste it to access LUTs. You can compute a lot in 12 cycles caused by L2 hit (L1 miss). In theory up to 32 * 12 = 384 floating p…
What adding a lookup table can do is to add the load-latency to the dependency chain involving the calculation, which seems to be what you are talking about here. For an L1 hit that's usually 4 or 5 cycles, and for L2 hits and beyond it's worse, as you point out. How much that actually matters depends on whether the code is latency-bound and the involved lookup is on the critical path: in many cases where there is enough ILP it won't be (an general rule is that in most code most instructions are not on a critical dependency-chain).
If the involved method isn't that hot then L1 misses (like your example) or worse are definitely a possibility. On the other hand, in that case performance isn't that critical by definition. If the method is really hot, e.g., in a tight(ish) loop, then you are mostly going to be getting L1 hits.
The comparison with 384 FOPs seems a bit off: I guess you are talking about about some 32-FOP per cycle SIMD implementation (AVX512?) - but the assumption of data dependencies kind of rules that out: one would assume it's scalar code here. If it's vectorization, then the whole equation changes!
Re: A Comprehensive Super Mario Bros. Disassembly
#49Re: A Comprehensive Super Mario Bros. Disassembly
#50https://gist.github.com/1wErt3r/4048722#file-smbdis-asm-L601... I think this is where the real gems start. The biggest contribution that SMB had was the "physics engine", to retrofit a modern term. The friction, the jumping, the inertia. If you compare it with the primitive physics in Donkey Kong or Mario Brothers, you can really grasp the groundbreaking novelty that was SMB. You can change direction in mid-air, but…
I once read that the way SMB was able to pull off the physics engine on such limited hardware was that it used lookup tables for physics instead of actually calculating velocity. My assembly-fu is weak but it looks like your link is to the section that contains all the lookup tables. I think JumpMForceData for example is a series of offsets for each successive frame after you hit the jump button. https://gist.github.…