I recently watched some cool anime-style intro sequences on old games, like Astal, Silhouette Mirage and even Sonic CD (one of my favorite intro sequences since forever), and started thinking of a way to do something remotely similar to that on the NES.
Due to the limited memory and PPU bandwidth, the first thing I decided is that the pictures would be created with NT/AT updates only, instead of expensive pattern table manipulations, which are also impossible with CHR-ROM. Keeping things compatible with all the different mappers and types of CHR memory meant using only 512 tiles all the way through. The problem is that packing color combinations in so few tiles usually results in extremely chunky pixels.
Being impressed at how decent rgb121 alternating color components every scanline looked, I started thinking of how to do something similar. Based on the fact that many video codecs encode lightness with more resolution than color, due to the fact that the human eye is more sensitive to lightness, I decided to make that same separation. At 2 levels of brightness, I can pack 8 pixels in a tile, for a total of 256 combinations. If I arrange them in a 4x2 pattern, I can get a monochrome 128x60-pixel picture out of a single name table. As for the colors, 4 colors arranged in a 2x2 pattern (using the remaining 256 tiles) can represent a 64x30-pixel image.
Basically, the name tables would look like this (please don't mind the image I used for testing, it's just some cartoon looking thing I found on Google):
fmv-nt.png [ 1.85 KiB | Viewed 4752 times ]
The interesting thing about having the color image use only half of its name table is that at least that part of the image can be double buffered, reducing the amount of bytes to update at a time every time the picture changes. Anyway, since the vertical resolution is not that good and the display will need constant scroll manipulation and pattern table switching, we need borders. The most straightforward thing to do is to squeeze the image to half of its height. Unfortunately that means that half of the screen is occupied by borders, and the video ends up looking very, very wide. This invokes a certain cinematic vibe so I don't think it's so terrible. Anyway, here's the result after combining the two pictures:
fmv-still.png [ 1.18 KiB | Viewed 4752 times ]
Yes, it's stripy and washed out, but it looks much more detailed than the color image alone could. The higher resolution lightness image adds a lot of detail, and allows for light and dark variations of each color in the color image.
Since one palette is used for the lightness image, 3 are free for the color image. Each 4x2-pixel area (area affected by a pair of attribute bits) in that image can have only 4 colors, and the 3 palettes must share 1 color (color 0), because of how the PPU works. Color 0 is not hardcoded to black (or any other color), which means that the palette has to be changed mid-frame because of the border. There is one free color in the lightness palette that could be permanently set to black and pointed to with rendering disabled, but in order to update the name table for the next frame the PPU address register will have to point away from it at some point, so a palette change would be needed anyway.
The frame rate would be only 12fps (which is fairly standard for hand-drawn animation, although they frequently use motion and compositing to make it look more fluid), to save memory and provide more time for processing each image. Here's a little test featuring scaling and rotation (I didn't have time to draw/rip a proper animation):
fmv-test.gif [ 66.24 KiB | Viewed 4752 times ]
Obviously, images have to be drawn with this specific format in mind. If you simply take an existing video and try to convert it to this format it will surely look like crap. Ideal images should have thick outlines, few colors in localized areas, and very simplistic backgrounds. Zoomed out scenes should also be avoided, in favor of close-up shots.
I haven't given much thought to the final (and really important) step, which is compression. Each uncompressed frame is nearly 1.5 KB, so there's definitely room for improvement.
Any comments, suggestions, opinions?
P.S.: Bregalad, I won't be offended if you say it looks like crap.
Due to the limited memory and PPU bandwidth, the first thing I decided is that the pictures would be created with NT/AT updates only, instead of expensive pattern table manipulations, which are also impossible with CHR-ROM. Keeping things compatible with all the different mappers and types of CHR memory meant using only 512 tiles all the way through. The problem is that packing color combinations in so few tiles usually results in extremely chunky pixels.
Being impressed at how decent rgb121 alternating color components every scanline looked, I started thinking of how to do something similar. Based on the fact that many video codecs encode lightness with more resolution than color, due to the fact that the human eye is more sensitive to lightness, I decided to make that same separation. At 2 levels of brightness, I can pack 8 pixels in a tile, for a total of 256 combinations. If I arrange them in a 4x2 pattern, I can get a monochrome 128x60-pixel picture out of a single name table. As for the colors, 4 colors arranged in a 2x2 pattern (using the remaining 256 tiles) can represent a 64x30-pixel image.
Basically, the name tables would look like this (please don't mind the image I used for testing, it's just some cartoon looking thing I found on Google):
Attachment:
fmv-nt.png [ 1.85 KiB | Viewed 4752 times ]
The interesting thing about having the color image use only half of its name table is that at least that part of the image can be double buffered, reducing the amount of bytes to update at a time every time the picture changes. Anyway, since the vertical resolution is not that good and the display will need constant scroll manipulation and pattern table switching, we need borders. The most straightforward thing to do is to squeeze the image to half of its height. Unfortunately that means that half of the screen is occupied by borders, and the video ends up looking very, very wide. This invokes a certain cinematic vibe so I don't think it's so terrible. Anyway, here's the result after combining the two pictures:
Attachment:
fmv-still.png [ 1.18 KiB | Viewed 4752 times ]
Yes, it's stripy and washed out, but it looks much more detailed than the color image alone could. The higher resolution lightness image adds a lot of detail, and allows for light and dark variations of each color in the color image.
Since one palette is used for the lightness image, 3 are free for the color image. Each 4x2-pixel area (area affected by a pair of attribute bits) in that image can have only 4 colors, and the 3 palettes must share 1 color (color 0), because of how the PPU works. Color 0 is not hardcoded to black (or any other color), which means that the palette has to be changed mid-frame because of the border. There is one free color in the lightness palette that could be permanently set to black and pointed to with rendering disabled, but in order to update the name table for the next frame the PPU address register will have to point away from it at some point, so a palette change would be needed anyway.
The frame rate would be only 12fps (which is fairly standard for hand-drawn animation, although they frequently use motion and compositing to make it look more fluid), to save memory and provide more time for processing each image. Here's a little test featuring scaling and rotation (I didn't have time to draw/rip a proper animation):
Attachment:
fmv-test.gif [ 66.24 KiB | Viewed 4752 times ]
Obviously, images have to be drawn with this specific format in mind. If you simply take an existing video and try to convert it to this format it will surely look like crap. Ideal images should have thick outlines, few colors in localized areas, and very simplistic backgrounds. Zoomed out scenes should also be avoided, in favor of close-up shots.
I haven't given much thought to the final (and really important) step, which is compression. Each uncompressed frame is nearly 1.5 KB, so there's definitely room for improvement.
Any comments, suggestions, opinions?
P.S.: Bregalad, I won't be offended if you say it looks like crap.