[HN Gopher] Street Fighter II paper trails - allocating sprite s...
       ___________________________________________________________________
        
       Street Fighter II paper trails - allocating sprite space by hand
        
       Author : krajzeg
       Score  : 506 points
       Date   : 2021-12-23 00:36 UTC (22 hours ago)
        
 (HTM) web link (fabiensanglard.net)
 (TXT) w3m dump (fabiensanglard.net)
        
       | HeckFeck wrote:
       | I just wanted to note this website is very well-presented. It
       | mimics the simplicity of a sheet produced by an old typewriter.
       | 
       | Eye pleasing and no distraction from the text, as a web page
       | should be.
        
         | lebaux wrote:
         | No website should use text-align justify and I will die on this
         | hill.
        
           | HeckFeck wrote:
           | You have a point there. It is less noticeable on mobile, but
           | desktop has no call for it.
           | 
           | Though were we in a universe where every choice is a cruel
           | dichotomy, I'd pick understated text-align justify over
           | JavaScript bombardments.
        
         | christophilus wrote:
         | It is really nice. The only thing I'd change is the text
         | justification.
        
       | snarfy wrote:
       | I recall seeing a video of their software setup, where they would
       | use the console controllers instead of a mouse to draw the
       | sprites.
        
       | city41 wrote:
       | I'm currently writing a tool to package up sprite tiles for the
       | Neo Geo[1], which handles graphics in a very similar manner as
       | the CPS1. I can't imagine composing these tiles manually, what a
       | monumental task.
       | 
       | The Neo Geo's hardware offers a few graphical features that work
       | by assuming the tiles are ordered in a certain way. It's an
       | interesting challenge to meet those requirements.
       | 
       | [1] https://github.com/city41/sromcrom
        
       | authed wrote:
       | Street Fighter is one of the the only game that I ever bought...
       | Kali was another one (game related app).
        
       | allenu wrote:
       | I love Fabien Sanglard's work. I've read through his books on
       | Doom and Wolfenstein and never would've imagined he'd start
       | looking at sprites for Street Fighter II.
       | 
       | This is really great stuff and I think important as "developer
       | archaeology". The 80s and 90s don't seem that long ago (to those
       | of us who were around), but it's easy to forget people back then
       | didn't have the sophisticated tools we have today. That said,
       | people _did_ have tools, so it 's awesome to be able to get a
       | glimpse into the workflow of folks back then.
        
         | htkibar wrote:
         | The guy is a legend and makes me question whether or not I
         | should stop working on FE to get into game dev all the time. So
         | cool to see these!
        
       | kingcharles wrote:
       | I was one of the developers on this game in the 90s:
       | 
       | https://www.youtube.com/watch?v=lubyi79e6SY
       | 
       | It was meant to be 100% 2D, and the programming and art went down
       | that path for a few months before it was realized that there just
       | wasn't enough RAM on PCs of the time to store all the possible
       | sprites for the characters in every rotation. The numbers get out
       | of hand very quickly when you have four main characters, each of
       | which can walk in 8 or 16 directions, can also run, walk up
       | stairs, climb ladders, crawl, fire one of 20 different guns etc.
       | The isometric backgrounds are all sheets of 2D tiles, laid out
       | just like in Street Fighter and every other sprite based game.
       | 
       | So, several months into development it was decided to change all
       | the characters to 3D to save RAM. I switched the entire game over
       | in two weeks, including creating all the tooling to convert from
       | 3D Studio to.. whatever the fuck, because there were no rules in
       | those days. When that game was started there were almost no 3D
       | accelerators, and I don't remember if you needed specific SDK for
       | them. I seem to remember our game couldn't use them, perhaps
       | because of the way the 3D and 2D were composited in the frame,
       | which was very unusual - most games were either 2D or 3D, not a
       | combination.
       | 
       | Are there any easter eggs hidden in the sprites for SFII? There
       | were various ones in Abomination, mainly written in the graffiti
       | around the cities.
       | 
       | And then there are ones like this (TFT) that we can't talk about:
       | https://www.reddit.com/r/gaming/comments/3ylmm4/a_staggering...
        
         | rzzzt wrote:
         | Glide for 3Dfx cards maybe?
         | https://en.wikipedia.org/wiki/Glide_(API)
        
       | im_down_w_otp wrote:
       | I absolutely love learning about the clever tricks and their
       | long-tail effects that came out of dealing with incredibly
       | resource constrained computing environments and/or where some
       | quirk of hardware ended up inspiring a lot of fabulous creative
       | misuse.
       | 
       | This is a fantastic article!
        
       | malkia wrote:
       | I could be mistaken, if it was SF II or some other similar game,
       | but for PC (back in the DOS game, the sprites for these were not
       | stored rectangular (with transparency) but rather a run-length of
       | here is a line of pixels that starts from here to here. Hence
       | your code can just "movsb" instead of checking (expensive) for
       | transparency).
       | 
       | ... Could've been another game, but it was fun trying to decode
       | the images :)
       | 
       | (I think it also makes pixel to pixel collision easier to tackle,
       | but don't remember the details - this might've been Star Control
       | II thing, another game we used (as kids) to decode images/mods)
        
         | gmueckl wrote:
         | This reminds me: the Allegro library has a way to compile
         | bitmaps into series of mov instructions to make blitting
         | faster. This was somehow the fastest method on early x86
         | processors. Loops were expensive back then.
         | 
         | See https://liballeg.org/stabledocs/en/alleg016.html
        
         | allenu wrote:
         | Perhaps you were thinking of SFIBM/SF2IBM, aka SFLIU [1], a
         | homebrew version of SF2 for PCs written by a Korean dev. There
         | were specs of the file formats used out on the internet at the
         | time and I remember the image files were stored as run-length
         | encoding.
         | 
         | [1] http://cwcyrix.nsupdate.info/archives/SFLIU/sfliu.html
        
       | Waterluvian wrote:
       | When writing a DMG emulator I thought about how these tiny
       | sprites are often similar. A sprite will be a series of bytes
       | with an address to the beginning.
       | 
       | It got me thinking about a kind of compression algorithm could
       | find byte overlaps and re-pack the sprites, and then adjust the
       | addresses.
       | 
       | This got me thinking: are there any compression algorithms that
       | do not require decompression? You pack them once and then just
       | point at slices.
       | 
       | Then this got me thinking: is that just what unzipping is doing,
       | just eagerly?
        
         | RicoElectrico wrote:
         | Vector quantization, for example. Sound scary, but compression
         | is basically k-means and decompression a table lookup.
        
         | ucyo wrote:
         | Yes. Check out succinct data structures. They are closely
         | related to compression algorithms. The above mentioned
         | compression algorithms (incl. Entropy and all LZ variants) need
         | a decompression step. They might try to improve the
         | decompression speed by chunking and sacrifice storage space,
         | but decompression is needed. This is unrelated to how they
         | remove redundant information from the data (e.g. using
         | pointers). Succinct data structures try to avoid decompression
         | at all. Again, at the cost of storage space but some operations
         | can be done on the succinct data directly as it is on disk.
        
         | marcan_42 wrote:
         | That _is_ how basic Lempel-Ziv compression works, which is one
         | of the two fundamental techniques used in data compression. You
         | keep a history of what you 've already decompressed, and if you
         | find something you already have, you instead encode a pointer
         | to it. Variants of this (LZW, LZ77, LZSS, and a bajillion
         | custom variants, because game developers like to reinvent their
         | own compression) have been used in many, many games.
         | 
         | The other is entropy coding, which means re-writing bytes and
         | pointer codes into variable length values that are optimized by
         | frequency: fewer bits for common codes, more bits for uncommon
         | ones. The most basic approach for this is Huffman coding, which
         | is kind of like variable length binary phone numbers.
         | 
         | Together, these two techniques are how DEFLATE compression
         | works, which is the algorithm used by zip, gzip, and zlib. zlib
         | is then used in many, many formats, like PNG and PDF.
         | 
         | Trivial "look for dupes and subsets and just change pointers"
         | compression is already standard when building C code. If your
         | program has two strings, "foobar" and "bar", the linker will
         | just store "foobar" in the strings section and point 3 bytes
         | into it for "bar", assuming the right compilation/linking
         | options to make it work.
        
         | selcuka wrote:
         | There was a similar trick used for compressing game backgrounds
         | in Commodore 64 games.
         | 
         | The compressor would create a special font (C64 "charsets" are
         | 8x8 pixels), and slice the picture into 8x8 tiles where each
         | block corresponds to an ASCII character. Although C64's hires
         | resolution was 320x200 (160x200 in multicolor mode), because of
         | repeating blocks it would usually end up using less than 256
         | characters. The actual background would then be drawn using
         | those characters with the special font. There is no eager
         | decompression involved.
        
         | ars wrote:
         | Apparently DNA is compressed in this way, it makes studying it
         | very difficult.
         | 
         | https://www.news-medical.net/health/What-is-an-Overlapping-G...
        
         | oceanghost wrote:
         | Many years ago, I implemented an N64 ROM compressor that could
         | work out a rough family tree for variations of a game. It
         | worked something like this:
         | 
         | Brute force compare all the ROMs to each other and find
         | "ancestor" with the least amount of changes as compared to any
         | other.
         | 
         | Pick that as an ancestor, re-brute force check every remaining
         | ROM against that one for changes.
         | 
         | It was silly and wasteful computationally but you could store
         | 40 variations of a cart in 50MB instead of 1GB.
        
           | nightfly wrote:
           | Do you remember what you determined the "ancestor" to be?
        
             | oceanghost wrote:
             | For the n+1 cart, it was always the smallest diff between n
             | and any remaining carts.
             | 
             | Picking the first n, was more difficult. A strong hint was
             | if the ROM name contained a variant of the word Japan.
             | Otherwise, imagine you had 4 images, you could diff them 16
             | ways, but half of those ways are mirror images of each
             | other ie. a diff of ROM 2->4 is the inverse of of a diff of
             | ROM 4->2.
             | 
             | So ideally, the first ancestor would be the image with the
             | most amount of the smallest children.
        
         | willis936 wrote:
         | Iwata famously implemented RLE in Pokemon Gold/Silver. That
         | gains an easy 50% from all the whitespace.
         | 
         | Huffman coding would be the simplest algorithm to compress the
         | repeated patterns in sprites, but I think even loading up the
         | dictionary to decompress would run into memory limitations on
         | these old systems. If nothing else it would cause hitching.
        
       | ggambetta wrote:
       | Another excellent article by Fabien :)
       | 
       | One thing that surprises me is that in such a ROM-constrained
       | context, the artists weren't asked to save some more. There's
       | some tiles that are empty except for a handful of corner or side
       | pixels; I could imagine going to the artists and asking them to
       | tweak the pose a tiny bit to save a tile.
       | 
       | Or maybe what we're seeing in these sheets is the result of doing
       | that _just enough_ to fit their game into the available ROM, at
       | which point they didn 't need to free any more tiles?
        
         | [deleted]
        
         | 0xcde4c3db wrote:
         | My guess is that they preferred bigger optimizations first,
         | such as the given examples of reusing Ryu's body tiles for Ken
         | and mirroring Sagat's legs. If those hit the target, there's no
         | need to go around trying to pick up a tile here and there
         | around the edges.
         | 
         | Also, any given saved tile might not have packed well in the
         | overall sprite sheet, given that they were organizing the ROM
         | by hand.
        
       | thrdbndndn wrote:
       | Fascinating read, one question though:
       | 
       | If they can split an image into multiple tiles at different
       | addresses (as they did in some examples shown in the article),
       | shouldn't they only need to care about the total tile number? Why
       | did they bother to try to fit these postures (more or less) as
       | whole on sheet, or making these sheets at all?
        
         | royjacobs wrote:
         | Because they were manually drawing and designing the sheet
         | layouts. If this was an automated process, as shown for the
         | CPS-2 titles, then they could (and did) automate it.
        
       | ben7799 wrote:
       | Loved this article. SFII was so huge when I was about 13-20...
       | that game had such a long tail. I remember seeing it for the
       | first time and being blown away, it was rather amazing when all
       | you'd seen up to that point was NES and PC games on a 286 or so.
       | 
       | Funny thing is I'm pretty darn sure I have no desire to work in
       | commercial game development these days, but would have loved to
       | back then. The creativity around limitations was amazing back
       | then and it seemed like so much care was put into making games
       | fun. These days it seems like addiction mechanisms, getting
       | people to spend more money, obsessiveness with graphics over
       | gameplay, etc.. are ruining everything.
        
         | Kranar wrote:
         | >These days it seems like addiction mechanisms, getting people
         | to spend more money, obsessiveness with graphics over gameplay,
         | etc.. are ruining everything.
         | 
         | Couldn't be further from the truth, especially when it comes to
         | Street Fighter... People complain about microtransactions today
         | and don't even think to consider that the original
         | microtransaction was the arcade machine. Games back then were
         | specifically designed to extract a certain amount of money per
         | hour from players and their difficulties were adjusted to
         | maintain that rate.
         | 
         | It's never been better to be a game developer then today. The
         | number of platforms available to you, distribution options,
         | variety of studios/publishers are much greater today than ever
         | before.
        
       | teloli wrote:
       | What a game they made out of those 6MiB. Constraints foster
       | creativity rather than limiting it.
        
       | rmetzler wrote:
       | I remember another article where the main developer set aside a
       | big chunk of memory right when they started coding. When they had
       | issues fitting everything in memory shortly before the deadline,
       | he deleted this chunk and had no issue to deliver the project.
       | 
       | I think this is something we should do more today. Defining a
       | memory budget, and staying inside.
        
         | zppln wrote:
         | Maybe this is the article you're thinking of (pretty sure it
         | was first published by Gamasutra):
         | https://www.gamedeveloper.com/programming/dirty-coding-trick...
         | (see The Programming Antihero)
        
           | Scaless wrote:
           | Gamasutra IS Game Developer now, they rebranded recently.
           | 
           | https://www.gamasutra.com/view/news/387227/Gamasutra_is_beco.
           | ..
        
         | eru wrote:
         | > I think this is something we should do more today. Defining a
         | memory budget, and staying inside.
         | 
         | It's fun to think about, but I am not sure if it's the right
         | tradeoff for most projects?
        
         | mensetmanusman wrote:
         | There was a story about a year ago of someone mentioning
         | something similar, where they recommend always having a 10 GB
         | blank file on their server.
         | 
         | This save them multiple times when issues arose later relating
         | to space availability, even for updating things, etc.
        
           | rzzzt wrote:
           | I remember it as being for "disk full" conditions when
           | everything came to a crawl, because log files could no longer
           | be written either.
        
       | tamhero96 wrote:
        
       | ReactiveJelly wrote:
        
         | sodality2 wrote:
         | https://archive.md/lNZ7A
        
           | Keppl8R wrote:
           | https://web.archive.org/web/20211223040849/https://fabiensan.
           | ..
        
           | ReactiveJelly wrote:
           | Thanks! Works after I fill out the CAPTCHA. How strange, I
           | thought I waited long enough on Fabien's page for the SVGs to
           | render. I'll check back if my exit rotates and the IP block
           | goes away.
        
         | fabiensanglard wrote:
         | I use SVG for the drawing but everything else is basic HTML.
        
           | ReactiveJelly wrote:
           | Thanks, Fabien. I know SVG works on the worldometers COVID
           | charts, so I'm not sure what it is.
           | 
           | But now I'm getting "Access denied. Your IP address is
           | blacklisted." so I'll just wait some random weeks and read it
           | over regular Internet.
        
           | jdboyd wrote:
           | Why doesn't pinch-zoom work on mobile?
        
             | ddingus wrote:
             | Hate when that happens, and I switch to desktop view.
             | Annoying. This site prevents it too, and I frequently
             | browse it on mobile the same way.
        
               | fabiensanglard wrote:
               | Sorry, I had no idea. I think I fixed the issue. Let me
               | know if it works now.
        
               | ddingus wrote:
               | No worries. That you took a look at it counts. And
               | please. I love your work and feel an apology is too much!
               | I wrote poorly, with "this site" supposed to mean Hacker
               | News"... Ah well.
               | 
               | Please take my appreciation with you into the holidays!
        
             | fabiensanglard wrote:
             | I had no idea people would want to do this. It turned out
             | it was a simple matter of adding "user-scalable=yes". I
             | regenerated the site and you should be able to zoom in now.
        
               | quakeguy wrote:
               | Thank you!!
        
               | ddingus wrote:
               | I didn't either, until I went through a time when I used
               | mobile as my dominant reading platform. Screen size
               | relative to eyeball acuity and or just a desire for scale
               | drives it, for what that is all worth.
        
         | yuliyp wrote:
         | It looks very basic. It's almost entirely (except for one tiny
         | bit of JS powering a gallery of 4 images about halfway through
         | the article) just html, CSS, text, and images (PNG and SVG)
        
       | mewse-hn wrote:
       | I love that we can dig into rom images from 30 years ago and
       | recreate sprite sheets that were originally hand drawn for
       | something that was an important part of our culture. What more I
       | love that Fabien _actually does it_ and shows us how it 's done.
        
         | christophilus wrote:
         | The fact that later titles are encrypted, so he doesn't have
         | access to them made me a bit sad. The DRM mentality strikes
         | again.
        
           | jonny_eh wrote:
           | Capcom had a hell of a time fighting knock-off SF2 boards. I
           | can understand why they went the DRM route, as sad as it is
           | for preservation. That said, haven't all those roms been
           | decrypted?
        
       | [deleted]
        
       | blondin wrote:
       | would be truly amazing if Fabien can pull it off.
       | 
       | there is so much secrecy surrounding video game development in
       | japan. especially the 8 and 16-bit era. i was very interested in
       | how they did pixel art back then. they supposedly drew them using
       | special keyboards and CRT monitors.
       | 
       | there is one page on the whole internet that briefly mentioned
       | the process.
        
         | fabiensanglard wrote:
         | From what I gathered on Akiman Twitter, they drew on 16x16
         | rectangular grid paper and then manually translated that to
         | pixels with a keyboard using arrows keys and 0-F keys.
         | 
         | That's it.
        
         | bluedino wrote:
         | https://vgdensetsu.tumblr.com/post/179656817318/designing-2d...
        
         | kevin_thibedeau wrote:
         | You can see Nintendo's process for SMB here:
         | 
         | https://www.youtube.com/watch?v=DLoRd6_a1CI
        
           | rzzzt wrote:
           | There is also some footage about digitization/level design in
           | this SMB3 documentary (they might be using the same sources
           | though): https://youtu.be/MxT6IwUtLSU?t=671
           | 
           | The mouse with the crosshair is a nice idea!
        
             | buescher wrote:
             | They still make digitizing tablets, don't they?
        
               | kevin_thibedeau wrote:
               | Wacom has a mouse with a cursor on it.
        
       | phkahler wrote:
       | >> Notice how Ruy's top hair for 0x69/0x6A was placed at
       | 0x6F/0x9F in order to not disturb the layout. Why the hair of the
       | top left pose is offsetted is unknown. Could it be that GFX ROM
       | address 0x0000 could not be used? Analyzing other games also
       | showed that tile 0x0000 was never used.
       | 
       | My guess is that it was easier to encode and use a blank tile
       | than to specify those strange shapes where sprites are non-
       | rectangular. Just tell the hardware the size in tiles and then
       | offer a set of tiles that includes blanks. This could be
       | confirmed or refuted once they find the area in ROM that
       | specifies how to put the tiles together to form a sprite.
       | 
       | It sounds like a complete sprite had to be entirely on one page,
       | so there must be a list of tile numbers to compose a sprite and
       | they would be 1 byte each. since they know the tile layout for
       | some of the poses, they should be able to write down that
       | sequence of bytes and look for it in the ROM, then check if there
       | are zero tiles in there. Or just check the MAME source code since
       | that level of detail was probably all figured out a long time ago
       | for that project :-)
        
         | jonny_eh wrote:
         | > It sounds like a complete sprite had to be entirely on one
         | page
         | 
         | That doesn't seem to be the case. There are pieces of Chun-Li
         | and Blanka on the Dhalsim sheet.
        
       | hariswill wrote:
       | Steet Fighter II, the game I mostly played in my childhood.
       | Always been a big fan of this amazing game.
        
         | ssss11 wrote:
         | Yeah SF2, hyper and turbo were a huge part of my youth too.
         | What an era! I miss playing it
        
         | allenu wrote:
         | It has had such a cultural impact to those of us who grew up
         | with it. I was a teenager when SFII came out and have very fond
         | memories of playing it at arcades and convenience stores with
         | friends. I started learning how to code back then and a lot of
         | my early code was attempts at making a Street Fighter game.
         | (They were usually just attempts at recreating the art and
         | animation in QBasic.)
        
       | aelphssss wrote:
       | Reminded me of this link -
       | https://www.criticalhit.net/gaming/street-fighter-iii-will-a...
        
       | bluedino wrote:
       | The sheer amount of sprites caused it to be the biggest ROM at
       | the time on the Super NES. 16 megabits! That also caused the game
       | to be priced at something ridiculous like $75 US
       | 
       | I wonder if they used this same method on the SNES or not.
        
       ___________________________________________________________________
       (page generated 2021-12-23 23:01 UTC)