Special effects device for games under NES. Part 1

    There are several series of articles about programming for NES, one of them has even been translated into Russian in Habré . However, none of them goes beyond a review of the basic capabilities of the console - it discusses the general architecture of the console, the basics of assembler, briefly describes how to display sprites on the screen, mentions something about music and mappers, and the cycle ends.

    I will try to continue the story about the conclusion of the graphics of games for NES from the place where other tutorials end. It’s quite difficult to figure out how to program animation effects yourself, due to the small amount of information about this, both in Russian and in English. But do not be upset, because as documentation you can use the code from classic games, which are now easily found on the network in the form of ROM files.

    Therefore, before you program something, you have to figure out how these or those effects are arranged for NES, and the article will focus on how to do this. There are many articles from the category " Games, squeezed out of NES maximum", We’ll try to understand how all the main effects in these games are made, and also create tools that can be used to find other games that are no less technologically advanced in effects.

    Disclaimer


    In any descriptions of the iron of the NES prefix or in the use of terms, I can be wrong and, most likely, wrong. In the description of the software part, the information is supposedly more accurate, verified by disassembly and debugging scripts. Links to all the tools used in the article are provided at the end. If the text refers to "emulator" without specifying the name, Fceux is implied . Especially important or interesting, in my opinion, moments are highlighted with exclamation marks.

    Summary of NES Graphics Output Options


    Suppose you read nesdoug 's articles translated from BubaVV , and already know the basic things about programming graphics for NES. I will not write about this in detail, but only describe it briefly and simplistically (you can skip this part and return to it when questions arise why some effect is done this way and not otherwise):

    1. The NES video processor has four screen pages (and several modes of working with them, most often two pages simply copy the contents of the other two), which contain data about the displayed tiles and the attributes of these tiles. A block of 2x2 tiles can be painted in just 3 different colors + use 1 background color.
    2. Also, the video processor can do hardware scrolling of images between multiple screens. This means that part of the first screen page and part of the second can be drawn on the screen. The screens on rendering are “looped” in the order 1-2-1-2-1-2-2 .., i.e. if the video processor has reached the end of one of the pages, it takes data from the beginning of the next. This is easier than it sounds, you can open a game in the emulator and turn on the debug window for displaying screen pages in order to visually see how it works.
      (parsing a scrolling device with pictures here )
    3. The picture on the screen is drawn with tiles from the CHR memory bank, in which at one moment there are 256 memory tiles. The video processor “sees” two such banks, one for rendering sprites and one for rendering the background.

      At the same time, there is a 8x16 sprite rendering mode, in which you can draw sprites with data from both banks at once.

      This memory is located on the cartridge, therefore, depending on the "filling" of the cartridge, banks can be arranged in different ways - software-switched banks with ROM memory (most often in 1, 2 or 4 kilobyte parts), or RAM memory into which you can write data (most often copying data from banks with a code).
    4. Tiles from banks are 8x8 pixels in 2-bit color. Two bits of the color of the tile attribute (common to all pixels of the tile) are added to these two bits. The result is a 4-bit color index in a palette of 16 colors. At one point in time, two palettes are active in the video processor - for background tiles and sprites.
    5. In addition to the background, the video processor draws up to 64 sprites. There is also a limit on the number of sprites displayed on one line, when exceeded, the video processor skips sprites that it does not have time to draw.

    I will not analyze in detail these features of NES, they are “chewed up” in review articles, for example, here . I gave them only to list 5 main ways to create animations and effects on NES - animation by writing to the screen, animation by changing the position of the scroll, animation by changing the contents of the CHR-bank, animation by changing the palette and animation by drawing sprites .

    Perhaps it’s worth highlighting in a separate way the animation by changing the status bit of the video processor , for example, turning on and off the rendering, changing the brightness of color channels, changing the active screen page or alternately changing two active banks between themselves.

    And now, attention,All graphic effects on NES are done in one of these ways or a combination of them !

    Below I will analyze examples of effects of each type and tell how to determine in what way the game creates this or that effect. But before that, a little more theory, which is very important to understand.

    Synchronization of the central processor of the console and the video processor


    The video processor is controlled using the instructions of the central processor of the console, but it works in parallel with it. To create a smooth animation, you need to make changes to the video memory only at the moment when the video processor is not busy rendering the frame, otherwise the user will replace a sharp change in state on the screen! This is in the best case, in the worst, the user will also see a furious “twitching” of the picture, since the change in the state of the video processor is done by writing to its memory, and this leads to a loss of information in its internal registers that control the position of the raster that draws the picture on the screen. So, recording in video memory is possible only when background and sprite rendering is turned off in the video processor.

    Modern graphic systems usually do not allow changing the contents of the current frame, and use double buffering - they draw a picture in an invisible area of ​​memory, which the video card then displays on the whole screen. Older video processors did not have enough speed to prepare an entire frame in time while the previous one is being drawn.

    To give instructions to the video processor, the program has a very short time interval between the end of one frame and the beginning of the next! In order to have time to do this at the right time, the video processor at the end of the frame generates an interrupt. The program must install a handler for this interrupt. It is in this place that the fastest and most optimized code is written, and the most tricky tricks are found.

    However, despite all the difficulties, many games perform operations with changing the video memory not only in this handler (between frames), but also during the rendering of the frame!
    So all effects are further subdivided into interframe (change is made between frames) and midframe (change is made right during the rendering of one frame).

    In this case, several possible options for synchronizing the central and video processor of the console are used.

    • Using a mapper that generates interrupts at the end of rendering each line, by timer or by some other conditions. The interruption tells the central processor "drop everything, only now you can quickly write a few bytes into the video memory, this is more important, you will return to the rest later." A program can set a handler for this interrupt - and execute some code while the beam on the screen goes out to go from one line to another. This is the easiest approach for the developer. The most common of these mappers is MMC3 . The "iron" part of the organization of this is very interesting, think about it - with the help of a chip on CARTRIDGE, a new opportunity was added to use a video processor on CONSOLE.
    • If the mapper does not allow generating interrupts, perversions begin. The program should make an idle cycle, waiting for the appearance of some specially tuned condition, indicating that the video processor has reached drawing a certain place on the screen (for this, sprites or console functions designed to output sound can be used).

      Another way is to measure the number of measures.instructions that have been executed (in this case, the program should ensure that the execution time of the two branches of the conditional statement is equal, and ensure that instructions that work with dynamically composed addresses do not go beyond the boundaries of a 256-byte memory page). But even in this case, the CPU and PPU clock cycles do not coincide exactly, so the developers are trying to do such tricks in those places on the screen where the user does not notice the flickering of pixels. Take a look at the screenshot:



      Pay attention to the width of the strip highlighted in color at the bottom of the screen - while the beam that draws the picture passes in this place, magic happens. As a magician who needs just one instant to fool the viewer, the processor very quickly executes some code in order to have time to update that part of the video memory for which he did not have enough time between frames.

    About both methods of synchronization between the CPU and PPU in the middle of the frame (interruption, and by the condition of checking on the CPU), if there is interest, I will tell in another article with code examples, now it’s enough to understand that changing the memory can be done both between frames (and even developers should do it fast enough!), and even during the rendering of the frame.
    Now we can proceed to the analysis of what can be achieved in one way or another.

    Palette animation


    Interframe


    Changing the palette between frames is one of the easiest effects to implement. There are several varieties of effects that are implemented using palette animations.

    The simplest of these is ordinary flickering, when one color is replaced by another. Another effect is “traveling waves of color”, for example, waves of a waterfall, quicksand or fire. Finally, the third type of effect is the highlighting by one of the colors in the palette of one frame of the image while extinguishing other colors, so you can show a moving particle of rain, snow or another effect with particles. If you carefully read the theory, you can calculate that such an animation will have a maximum of three frames if you do not combine it with the animation by writing to the screen (tiles are limited to two bits of color, of which one is occupied by the background). All three types of such animation can be seen in different levels of the game Duck Tales 2 :

    The video shows the animation in both directions.
    Unfortunately, the rain effect is poorly visible in the video, so here it is on the gif:



    It is very easy to recognize this type of animation, and special tools are not needed for this. We open the PPU Viewer window in the emulator and monitor whether the palette changes or not. For simplicity, the study of "highlighting" frames with raindrops slows down the speed.

    In the middle of the frame (midframe)


    Changing the palette completely in the middle of the frame is difficult, but possible .

    This method is not used for animation in the gameplay, but is rarely used in the static parts of the frame. The obvious effect is to render the interface with a palette different from the level palette.



    Less obvious is to constantly change color from one to another to create a gradient effect.

    How to recognize

    The emulator allows you to see which palette was loaded at the time of drawing any line in the frame. Watch the Indiana Jones and the Last Crusade Intro :


    Indiana Jones and the Gradient Fill

    Please note that the game does not switch the entire palette, but changes only one color. And if she didn’t have time for the time that the beam passes from one line to another.

    Screen Recording Animation


    Interframe


    This is the most common background animation by changing the number of the tile that the video processor will draw, more often it is always performed once for one object. It’s not interesting to analyze such animations, and it’s pointless - almost any ordinary game animation is made like this (but more often the interactive part, for example, the cover of the opening chest, is finished with a sprite). Example - display objects exploded in Contra or the Super the C .


    In this game, when the gun, door or gate explodes, the logical “block” is updated, the size of 4x4 tiles.

    Creating the illusion of tiles smaller than 8x8 is

    well described in the Battle City parsing article.. In short, for each 8x8 tile, several variants of the same type are created with missing 4x4 parts, as a result of software replacement of the tiles, you can create the illusion that the game uses 4x4 pixel tiles:

    image

    In combination with changing the scroll position, a classic screen scrolling effect is created at a large level , which is present in almost any game with levels greater than a couple of screens in width or height (I will only note so far that the update takes place in the invisible part of the screen in advance so that the player sees already drawn part by the time the scroll reaches a new area). I will analyze the types of scrolling in the section of animations created by changing the position of the scrolling.

    Midframe


    It makes no sense to display the change in the screen until the frame is finished, normal people can wait until the next frame 1/24 second.

    Sprite animation


    Interframe


    Character animation . An elementary example, in fact, for what sprites are needed - to move them around the screen, depicting the characters of the game, so that gamers become interested.

    You can also draw particles with sprites , as well as add additional details to the background . Background tiles should be aligned by 8 pixels, sprites can be drawn anywhere on the screen, in addition, they are drawn from the second bank and another palette - due to this, the limits on the number of colors in the picture increase.

    There is also an inappropriate use of sprites - in order to synchronize the processor and the video processor with them (for example, Sprite Zero Hit and Sprite Overflow ).

    It is interesting that it will not be possible to distinguish the effects made by sprites from other effects “by eye”; it is too easy to disguise the background as a sprite and the sprite as a background and fool the player.

    Emulators allow you to disable the sprite and background layer in the settings, but playing in this mode is very inconvenient, so for easier detection of sprites, I wrote a lua script , which when turned on does not interfere much with playing and at the same time clearly emphasizes the sprites on the screen.


    The video may seem a little strange, but if you know the games shown in it well, you will understand what is happening on the screen in the episodes shown. Now you can accurately separate the sprite effects in games from others, and give typical examples.

    Particle

    rendering Rain rendering in Mitsume ga tooru .



    It can be seen that the game uses 8x16 sprites (it is more profitable to use such sprites in terms of the number of graphics displayed on the screen at the same time, because regardless of the size of the sprites - 8x8 or 8x16, you can draw 64 sprites). You can also notice that the game draws raindrops through the frame, because of which the player thinks that there are twice as many drops as there really are - after all, the game also needs sprites to draw the main character, shells and the boss, which also consists of lots of bee particles.

    Rendering through a frame is possible only for small and fast-moving objects (the human brain is designed so that it itself represents the missing frames for fast-moving objects, while the position of the objects is interpolated). In other cases, the player will notice the flickering of an object disappearing and appearing through the frame.

    A similar effect is rendering stars in Galaxian or in Addams Family .



    Shadow Display

    In 2.5-D games, such as Jurassic Park , sprites are used to display shadows under objects - so the player can determine the height at which the object is located.



    Background detailing - often used in screensavers or cut scenes where large and high-quality images are needed.





    Here, I think, comments are superfluous; splash screens without sprites can be just frightening.

    Disguise sprites in the background

    A special trick of designers, one of those for which the game is recorded in the "best graphics for nes." It is difficult to notice it, but with a script for detecting sprites it is not difficult. Most often, developers created the illusion of a separate background layer with sprites (the NES video processor does not support layers, which makes people who are not familiar with the console device think that the game is doing something impossible for the console).

    Examples:


    In Mitsume ga Tooru , in addition to the separate speed of the truck and the background, to enhance the effect, sprites draw a column, as if it were on a separate layer, moving at a slow speed.


    In the famous screensaverMegaman 2 sprites create the effect that the whole house is on a separate layer, although this is not so.


    In Bucky O'Hare there is both a parallax effect (a separate moving layer is highlighted by green lines), and in addition to the illusion of the movement of water, sprites on a fixed layer are added below.


    The big wheel at the beginning of the tower after the first level in Castlevania 3 . It seems like the wheel is spinning, but the moving gears are sprites that drive as if they are a single unit with the base of the wheel. In addition, small gears are also animated by switching memory banks, this effect will be described later in the example with Power Blade 2 .

    There are also reverse effects when the background is disguised as a sprite.(technically, this is NOT sprite animation, although it seems to her). For example, a whole boss can be drawn in the background. This is because 64 sprites would not be enough to draw a huge boss. This effect will be considered in the group of effects by changing the scroll position.

    Separately, I mention games in which sprites go into the background and back invisibly to the player.

    For example, Galaxian . The reason for such a trick of aliens - to render them all with sprites would not work, since there are too many of them.



    This technique is often used in games from Capcom to show interaction with interactive blocks - breaking stones in Duck Tales 1-2 , boxes in Chip and Dale Rescue Rangers 1-2 , shells inLittle Mermaid .


    On the screen are two boxes from Chip & Dale , one of which is painted in the background, and the second is thrown by the player and is a sprite. You can also notice that the colors in the objects palette are slightly different.

    In Prince of Persia, the technique is used more advanced. In those moments (and only in them), when the player runs into the “gate” drawn on the background and needs to pass between two columns, the same column is drawn on top of the character with sprites as in the background that covers the player. So both pillars in the background remain behind the character, but the third pillar temporarily appears in front of the character to preserve the illusion of the correct order of objects.


    Effects of sprite
    translucency The translucency of sprites by a video processor is not supported, so the developers were forced to show not very realistic, but now already known in every way - by drawing a sprite through the frame. As a result, all players knew that if a character or a boss “blinks”, then he is most likely invulnerable at this time.

    The effect of a translucent / opaque background

    But to show the translucency of the background is possible. For each sprite on the screen in the memory of the video processor, the flag " whether to draw a sprite behind the background or in front of it " is assigned . If all the pixels of the background tile are opaque, such a sprite will be completely invisible behind the background. If some of the pixels in the background are transparent and the other does not, then the character behind the background will “shine through”.


    My favorite example of a translucent background is the secret passages in Duck Tales 2 .

    If you exit the aisle in a slowdown frame by frame, you can notice the problem of organizing translucency in this way - the bit “behind the background / in front of the background” is set for the whole 8x8 sprite - therefore, Scrooge fails for a short time for torches in the place where it partially stands in the passage and partially already came out of it.

    The solution to this problem is to close the sprite with a partially different sprite - this will make it possible to increase the display accuracy up to 1 pixel. This effect can be observed in detail in Mystery World Dizzy or Nightshade .


    The character is displayed partially behind the column, and partially in front of the wall, as it should. This effect is discussed in detail here.

    The effect of the Cat Felix bag.
    Finally, the reception from the category of "dirty hacks" from the game Felix the Cat . See how Felix is ​​hiding in a bag - the lower part of the sprite smoothly disappears into the bag, and the upper remains visible in front of the background.



    If you enable the script for displaying sprites, you get the following picture:



    On the left side there are 3 strange sprites (it is worth noting that the script displays sprites a little incorrectly - the game uses 8x16 sprites, and the script draws only 8x8 pixels, so in reality they go one after another vertically continuously).

    If you look a little more in detail, namely, enable logging of the coordinates of the sprites in the script, it will become noticeable that this is not 3 sprites, but 24, with 8 in each line. This is the maximum that a video processor can draw in one line. He does this from left to right, so after 8 sprites are drawn in the invisible area of ​​the screen, the sprites of Felix crawling into his bag do not have time to draw on these lines. In such a cunning way, masking of that part of the sprites that are below the border of the dive was done.

    There are not so few games with such a masking effect (see the Use of excess sprites for masking effects section here )

    I also note a number of sprites on the right, which create a solid line that hides scrolling defects in the game engine. I will return to this “effect” in the next part of the article when I will analyze the effects of scrolling.

    Animations by changing the contents of the CHR bank


    To begin with, it’s worth a little more detailed to consider the differences between cartridges with CHR-ROM and CHR-RAM (there are also those on which both types of memory are present). For the programmer, the difference is that playing with the CHR-ROM allows you to quickly switch entire memory banks. Varieties of mappers have different sizes of “banks” - 1, 2, 4 kilobytes each. This makes it possible to have a common part of the bank and switchable. Switching is carried out by several commands to the mapper, and can be done at a speed several times per frame.

    Cartridges with CHR-RAM require “switching” to directly write the required number of bytes to the memory of the PPU address space (for a program, by writing to a specific CPU address). That is, to change one whole video memory tile, 16 write commands are required.

    In more detail the differences and applications of different types of memory can be studied here . Animation effects are possible with both types of memory, however there are some differences.

    Interframe animation


    The effect of changing the background animation by switching banks. The easiest way is to select several whole CHR-ROM banks for animation and switch them frame by frame. If the mapper supports small banks, they often make the common part of the tiles and switchable to save the number of banks needed.

    An example of such an animation is mechanical objects in factories in Power Blade 2 levels.


    Animated mechanisms.


    Separate frames of animation by banks (the lower half of the bank switches).

    You can study the contents of CHR-ROM banks using any tile editor, for example, TLP . This also allows you to determine the size of the bank switched by the game.

    Animation in CHR-RAM requires the direct writing of tiles to memory and is more difficult to track statically - data can be stored in compressed form or even generated on the fly procedurally. Therefore, to track such effects, I wrote a couple more scripts.

    One of them counts the number of entries in CHR-RAM per frame in order to understand how many tiles the game animates. Another allows you to dump into separate files all the different versions of the contents of CHR-RAM into files - you just need to start the game, go through the right place and study the results of the script. All the results of the study of games in this section were obtained using these scripts.

    One of the most “extreme” games using CHR-RAM animations is Battletoads .
    First, it uses CHR-RAM content modification to animate characters ! Those. only one frame for each toad is stored in memory and it is constantly updated. This effect allows you to store more data in the memory bank.



    Now run the script to count the number of bytes transferred per frame. The script is written for the Mesen emulator , because it is the only one that allows you to track the necessary events of the video processor from lua.


    As you can see, at the 2nd level, the game transfers up to 256 bytes per frame. Moreover, the toad is animated on even frames, and the background is animated on odd frames (The game still needs to perform screen updates when scrolling, they are also written to PPU, as well as the animation of the second player).

    I will talk about background animation later in this section. This is not only interframe animation, but also midframe animation, because developers simply do not have time to transfer so much data in one frame, and quietly transfer the rest, turning off the render for several lines at the beginning of the screen rendering (green zone):



    An example of a procedural change in the memory CHR- RAM is a mirror image of 2x2 tile blocks in Gun Smoke . You can look at the options for the contents of the memory “before” and “after” in the CadEditor level editor :



    This simple technique allows you to increase the number of game elements by almost 2 times. If you look at the contents of the PPU during the passage of the level, you will notice how slowly it works, mirroring the entire memory bank takes several seconds.

    In order for the player to not notice flicker, the game does this at the moment when the character is walking along a long wasteland, on which there are no asymmetric objects. So if the game forces you to go along a long empty corridor (black is best) - most likely this is required in order to quietly switch or load the memory bank. Such a variant of the “huge seamless world without additional loads” of the NES era.

    In more detail, it is worth analyzing the most beautiful animation effect by switching banks (possible with both CHR-ROM and CHR-RAM), achieved in combination with the scrolling effect - parallax simulation (a separate layer moving at a different speed than the main one).

    For the presence of this effect, the game automatically falls into the ratings of "the best graphic games on nes."

    If you have some experience, you can define it visually - a separate layer consists of only a few looped animated blocks. But for reliability, it’s worth running the dump_animated_chr.lua script , which I mentioned above, so as not to be mistaken with the fact that parallax is done in this way (there is another way to implement parallax, with other limitations on its capabilities).

    Distinctive examples of creating a layer in this way are a looped “mosaic” animated background, and also the possibility of “vertical parallax” or “parallax behind the window”, which cannot be achieved in another way.

    Examples of games:


    Bucky O'Hare . Parallax in the windows is an illusion of a separate layer.


    Battletoads . Vertical parallax - the walls of the well move faster than the back wall, as they are closer.


    Mitsume ga Tooru . The wall is separate from the platforms.


    Micro Mashines . Paul "checkers" - with simultaneous horizontal and vertical parallax.

    We will analyze these beautiful effects in more detail.

    Here is a script for the CadEditor editor, which takes all the sampled frames of video memory and draws them in the form of png-pictures. Work Result:



    Then we use the command for ImageMagic to glue the frames together:

    convert -delay 1x24 -loop 0 *.png animation.gif

    It turns out such a gif (for Bucky O'Hare ): Take a



    closer look at the lower right part of the image and you will see that for animation 4 tiles are used (“creeping” and flowing into each other) in 16 different banks, and the banks themselves are used in other places of the game , and only for these 4 tiles was a specially reserved place in each of the banks.

    Similarly, you can calculate that for combat toads in the well, an animation of a wall block of 32 frames is used for the effect of vertical parallax, this is 6 kilobytes of data for 1 block of animation (4x4 tiles) only!



    Here you can see that when using CHR-RAM (in Battle Toads), unlike CHR-ROM (in Bucks), you do not need to allocate a whole bank or carefully plan a place in other banks in advance. However, the fee for this is a more complex code and the inability to animate the entire bank.

    Another way to learn the effects of parallax is to destroy the illusion by placing the animated block in a place where it will not be seamlessly stitched with other blocks. For example, open the level with a well in the CadEditor editor and add a “block indicator”:



    Download the changed level to the emulator and see the result:



    Now the device of this effect should become completely clear, and maybe even try to repeat it in your code in one of the following articles .

    Another “effect” demonstratesJurassic Park immediately after starting the game. It’s just recording beautiful animation in several banks in a row frame by frame and scrolling it without any interactivity. I will not demonstrate it out of resentment towards the developers, because they were so carried away by the demo effects at the start of the game that they did not have a place for a beautiful ending, I think many players were disappointed with this.

    Midframe animation


    Switching banks in the middle of the frame is a great way to expand the number of tiles available for drawing. After all, the upper part of the frame will be drawn in blocks from the old bank and will not change, and the lower part will use the tiles of another bank!

    The obvious use of this is to render the interface with one bank and the game screen with another . You can also select some part of the screen (better separated horizontally from the main part). The Teenage Mutant Ninja Turtles 3 has both these effects - background beach painted tiles of the same bank, the beach - the other, and a beautiful interface with rozhitsami turtles - third.



    A more technological effect is to switch the bank so as to draw one large beautiful picture . Example - Robocop 3.



    For more examples of title screens with switching banks, see the Shiru article.

    The effect is monitored by simply studying the Debug-> Name Table Viewer window in the emulator - this window displays only one of the sets of tiles, the second at that moment looks like a mess.

    Animation by changing the scroll position


    Finally, the last group of effects, perhaps the most interesting and extensive, as well as perfectly combined with other effects. For these effects, I will single out a separate article (along with the effects of changing the state of the PPU).

    The number of examples in it will depend on the results of the survey.

    Using scripts from the article, you can explore the effects of other games, throw up examples of games with beautiful and unusual effects (preferably, which are not yet on this list ), we will figure out their device.

    Used tools


    Fceux is an emulator, you need to take the assembly from the latest versions of the source code of the developers, the public version has not been updated for a long time and it lacks some of the lua functions necessary for debugging.
    render_sprites_numbers.lua - a script for fceux to visually display the number of sprite tiles on the screen, as well as their positions and display flags.

    dump_animated_chr.lua - a script for fceux to save the contents of the unique CHR banks of a video processor into files for analyzing how the animation is composed of them.

    Mesen is an emulator that is best suited for debugging graphics effects; scripts have been written for it that cannot be implemented for fceux.
    mesen_chrRamWriteCounter.lua- a script for mesen to display lines on which the game changes the contents of the video processor memory and counts the number of such changes between frames and during the frame.

    mesen_makeScreensEveryFrame.lua - a script for mesen to save screenshots of each frame, used to create gif animations.

    CadEditor is a universal NES game level editor, it currently contains configs for displaying 1172 different levels for 118 games (the list is periodically expanded).

    Script-ExportAllChrsToPng.cs - a script for CadEditor to build tile images from binary files with the contents of the PPU memory and palette, as NES emulators do.

    Only registered users can participate in the survey. Please come in.

    How many GIFs with examples to add to the article

    • 73.8% Maximum, several for each effect 82
    • 26.1% Usually, one for each effect 29
    • 0% Minimum, a pair of illustrations is enough 0

    Also popular now: