SNES emulators just a few pixels away from absolute perfection


We are so close to creating an emulator that can perfectly recreate all the functions of real hardware and SNES software.

Over the past 15 years, as a coder for the bsnes emulator , I tried to perfect the Super Nintendo emulation, but now we are faced with the last problem: accurate timing of the clock cycles of the SNES video processors. To reach this final stage of emulation accuracy, the help of the entire community is required, and I hope for your support. But first, I’ll tell you what we have already achieved.

Current state


Today, the situation with SNES emulation is very good. Apart from the unusual peripherals that resist emulation (for example, a golf club with a light sensor , a bicycle simulator and a dial-up modem, used in Japan for horse racing betting in Japan), all officially licensed SNES games are fully playable, and no game has obvious problems.

The SNES emulation became so precise that I even had to split the emulator into two versions: higan , which strives for absolute accuracy and consistency with the hardware documentation, and bsnes , which strives for speed, wide capabilities and ease of use.

Recently, in the field of SNES emulation, many interesting achievements have been received, including:


… and much more!

So, is it done? Did everyone work well, bye, and thanks for the fish? Well, not quite.

Today, we have achieved accuracy at the beat level of almost all SNES components. The only exceptions were the PPU (picture processing unit, image processing modules) used to generate video frames transmitted to the screen. We mostly know how PPUs work, but for some functions we have to use guesswork, which leads to imperfect accuracy.

On a general scale, the remaining problems are pretty minor. If you do not strive for the absolutely perfect ideality of emulation for the love of art, then I can not convince you of the need to further improve PPU emulation. As in any field, the closer we are to the ideal, the lower the return.

But I can say why this is important to me : this is the work of my whole life, and I don’t want me to say that I got so close to completion without taking the last step. I am aging and I am not eternal. I want the last piece of the puzzle to be solved, so that, having retired, I was sure that the SNES legacy is reliable and fully preserved thanks to the emulation. I want to say that the problem is solved .

If you are still intrigued then continue reading to get acquainted with a background of a problem and solutions offered by me.

Modeling SNES Architecture


Let's start by listing the components that make up SNES:


Super NES system diagram.

The arrows indicate the directions in which various SNES processors can exchange data with each other, and the dotted lines indicate the connections to the memory chips.

The most important thing for us now is to notice that the output of video and sound is transmitted directly from PPU and DSP. This means that they act as "black boxes", and we can not see what is happening inside them. Later it will become important to us.

Correctness


Imagine that we emulate the CPU command “multiply”, which takes two registers (variables), multiplies them, receives the result and several flags indicating the state of the result (for example, overflow ).

We can write a program that multiplies any possible value from 0 to 255 as a factor and a multiplier. Then we can derive the numerical and flag multiplication results. Thus, we get two tables of 65 536 elements.

By analyzing these tables, we can accurately determine how and where the results of CPU calculations are set in a certain way. Then we can modify the emulators so that when running the same test we get exactly the same tables at the same time.

Now let's say that the CPU can do 16-bit x 16-bit multiplication. When testing every possible value, 4 billion results will be generated, which are almost impossible to test in a reasonable amount of time. If the CPU has multiplications of 32 bits x 32 bits, then in practice it will not be possible to test all combinations of input values ​​before the thermal death of the Universe (at least at the current level of technology).

In such cases, we act more selectively in the tests and try to determine when the flags can exactly change, when the results may overflow, and so on. Otherwise, we would have to run tests that would never end.

Multiplication is a rather trivial operation, but the same principle can be extended to the entire process of reverse engineering, including more complex operations, for example, data transmission via DMA (direct memory access) during the horizontal return of the beam. We create tests that try to determine what happens in borderline cases, and then check whether our emulation behaves identically to the behavior of real SNES.

Signal Generators and Beats


SNES has two signal generators (oscillators): a crystal oscillator operating at a frequency of approximately 21 MHz (it controls the CPU and PPU modules), and a ceramic resonator operating at a frequency of approximately 24 MHz, which controls SMP and DSP. In cartridge coprocessors, sometimes a 21 MHz crystal oscillator is used, and sometimes its own signal generators working with other frequencies.


Recreating this Super Famicom circuit board in code is harder than it sounds.

The clock is the basic element of the timing of any system, and SNES is designed to perform various tasks with certain frequencies and time intervals.

If you imagine a 100 hertz clock, it will be a device with a binary output switching to a high logical state of the signal (for example, +5 V), and then to a low state of the signal (0 V, or ground) 100 times per second. That is, every second the voltage at the output will fluctuate 200 times: increasing 100 times and 100 times lowering the front of the clock signal.

A clock cycle is usually considered one complete transition, that is, a 100 Hz cycle will generate 100 clock cycles per second. Some systems require a distinction between rising and falling edges, and for them we break the cycle into half-cycles to indicate each phase (high or low) of the clock signal.

The most important task of an accurate emulator is to complete tasks in exactly the same way and in exactly the same time as on real equipment. However, it is not very important how the tasks are performed. The only thing that is important is that the emulator, receiving the same input signals, generate the same output signals in the same time as on real hardware.

Timings


Sometimes operations take time. Take for example multiplication in the SNES CPU. Instead of pausing and waiting for the multiplication to complete, the SNES CPU calculates the result of the multiplication one bit at a time in the background for eight clock cycles of the CPU opcodes. This potentially allows the code to perform other tasks while waiting for the multiplication to complete.

Most likely, any commercial software will wait for these eight cycles, because if you try to read the result before it is ready, we will get a partially completed result. However, before SNES emulators gave correct results instantly , without waiting for these additional clock cycles.

When fans of consoles began to create and test self-written software in emulators, this discrepancy began to cause certain problems. Part of the software, for example, many of the first Super Mario World ROM hacks , worked correctly only in these old emulators, but not on real SNES hardware. This happened because they were developed taking into account the instant (unreliable from the point of view of real equipment) obtaining of the multiplication results.

In the process of improving emulators, the compatibility of old software was broken, and therefore we had to add compatibility options to the new emulators so as not to lose these programs. Yes, no matter how surreal it sounds, but today emulators must emulate other emulators!

The convenience of this delay of multiplication in the CPU lies in the fact that it is very predictable: eight clock cycles of calculations begin immediately after the request of the multiplication operation. By writing code that reads the results after each cycle, we were able to verify that the SNES CPU uses the Booth algorithm for multiplication .

Clock Sync


Other operations are not easy to model because they are asynchronously executed in the background. One such case is the DRAM update of the central SNES processor.

During the rendering of each raster line, the entire SNES CPU at a certain stage suspends its operation for a short period of time while the contents of the RAM chip are updated. This is necessary because in order to reduce the cost in SNES, dynamic (rather than static) RAM was used as the main memory of the CPU. To save the contents of dynamic RAM, it must be periodically updated.


To create a truly perfect emulator is not enough to ensure the playability of all three and a half thousand SNES games. It is also necessary to achieve simulation of each function of the system with perfect tact accuracy.

The key factor in the analysis of the exact timings of these operations was the possibility of using horizontal and vertical PPU counters. These counters perform increments and are reset after each reverse horizontal and vertical beam travel. However, their accuracy is only a quarter of the frequency of the SNES CPU signal generator; in other words, the horizontal counter increments every four clock cycles.

Reading several times the values ​​of the counters, I was able to determine which quarter of the clock cycle the counter is aligned with. Combining this knowledge with specially created functions that can take a step towards the exact number of clock cycles indicated by the user, I was able to perfectly match the SNES CPU with any exact position of the clock cycle I need.

Thanks to an iterative traversal of many clock cycles, I was able to determine when certain operations are exactly happening (for example, updating DRAM, transmitting HDMA, interrupt polling, etc.). After that, I could exactly recreate all this in emulation.

SMP chipSNES console also has its own timers, and successful reverse engineering was also performed for this processor. I can devote an entire article only to the SMP TEST register, which allows programmers to control the SMP frequency divider and its timer, not to mention other terrible things. It will be enough to say that it was not an easy and quick process, but in the end we won.

We collect coprocessors



The SuperFX chip is just one of many cartridge coprocessors that the SNES emulator can handle.

There are a whole bunch of SNES coprocessors used inside various game cartridges that we also needed to tame. From individual general-purpose CPUs like SuperFX and SA-1 , digital signal processors like DSP-1 and Cx4 to decompression accelerators like S-DD1 and SPC7110, or Sharp and Epson real-time clocks, and much more ...

This means that the SNES emulator must cope with SuperFX instruction and pixel caches; with the SA-1 memory bus conflict resolution scheme (allowing the SNES and SA-1 CPUs to use the same ROM and RAM chips simultaneously); with integrated firmware DSP-1 and Cx4; with prediction-based arithmetic encoders S-DD1 and SPC7110; as well as with odd borderline cases of BCD (binary-coded decimal) in real-time generators. Slowly but surely, using all the techniques for determining correctness and timings described above, we managed to learn how to emulate all these chips almost perfectly.

It took a lot of effort and thousands of dollars to remove the chip covers and remove the firmware from the digital signal processors used in different games. In one case, NEC uPD772x emulation alloweduse the code from higan to save the voice of the late Stephen Hawking! .

In another case, we needed to reverse engineer a whole set of instructions for the Hitachi HG51B architecture, because no one had ever published the documentation for this architecture. In another case, it turned out that one game ( Hayazashi Nidan Morita Shougi 2 ) has a powerful 32-bit ARM6 CPU with a frequency of 21 MHz, which accelerates the Japanese shogi game!

Just saving all the SNES coprocessors turned out to be a long-term process, full of difficulties and surprises.

Digital signal processing


The Sony S-DSP (Digital Signal Processor) chip, which should not be confused with the DSP-1 cartridge coprocessor, generated a unique SNES sound. In this chip, eight audio channels with 4-bit ADPCM encoding were connected, which ensured the creation of a 16-bit stereo signal.

Outwardly, and from the system diagram presented above, at first it seems that the DSP is a “black box”: we adjust the sound channels and mixer parameters, after which the chip generates sound transmitted to the speakers.

But one important function allowed the developer under the nickname blargg to perform a complete reverse engineering of this chip: it was an echo buffer. The SNES DSP has a function that mixes the output from previous samples to create an echo effect. This happens at the very end of the sound generation process (apart from the last one sound blocking flag, which can be used to turn off the entire sound output.)

By writing code with the correct timing of the measures and tracking the resulting echo, we were able to determine the exact order of operations performed by the DSP to generate of each sample and creating perfect sound and beat accuracy.

Saving PPU


All this led us to the last part of the SNES architectural scheme: PPU-1 and PPU-2 chips. Thanks to John McMaster, we have scans of the S-PPU1 (revision 1) and S-PPU2 (revision 3) chips with a twenty-fold increase.


Twenty-fold scan of the crystal of the first PPU SNES ...


... and the second PPU.

Both crystal scans let us know that the chips are obviously not general-purpose CPUs, nor are they specialized architectures that execute operation codes from the internal ROM of the firmware program. These are separate logical circuits with hard-coded logic that receive incoming signals from different registers and memory, and create a video signal to the monitor one raster line at a time.

PPUs remain the last obstacle to emulating SNES because, unlike all the components described above, PPUs are actually a black box. We can configure them to any state, but the SNES CPU can’t directly monitor what they generate.

If we use our previous example with multiplication as an analogy, imagine that you requested the result 3 * 7, but instead of the binary answer, you get a fuzzy analog image of the numbers “21” on the screen. Anyone who runs your software will be able to see 21, but you cannot write a test program to automatically check if he sees the correct answer. A person’s manual verification of such results cannot be scaled to more than several thousand tests, and millions will be required to maximize the PPU behavior.

I know what you thought: “But is it easier to use a capture card, perform image processing, approximately compare them with the image on the digital screen of the emulator, and conduct tests based on this?”

Well yes, it is possible! Especially if the test is to check two huge numbers that occupy the entire screen.

But what if testing has many nuances, and we are trying to recognize the color difference of a half-tone of one pixel? What if we want to run a million tests in order, and we don’t always know what we will generate, but still want to compare the result with the output of our emulation?

Nothing beats convenience and accuracy with digital data — an accurate stream of bits that can only match or not match. The analogue nature of a CRT signal cannot provide us with this.

Why is it important?


With the exception of one game ( Air Strike Patrol ), all officially licensed SNES software (should have been) based on raster strings. These games do not try to change the state of PPU rendering in the middle of the current rendered raster line (such a trick by programmers is called the "raster effect"). This means that the execution timings of the vast majority of games do not have to be particularly accurate; if you have time for the next full raster line, then everything is in order.

But this is important for one single game.




This series of images shows a complex emulation effect used in the “Good Luck” message of Air Strike Patrol .

In the images above, you see the frame-by-frame text “Good Luck” from Air Strike Patrol . The game implements it by changing the position of vertically scrolling the background layer 3 (BG3). However, the dashboard display on the left (where you can see that the player has 39 missiles) is also on the same background layer.

The game manages to perform this separation by changing the position of the BG3 scroll in each raster line after rendering the left dashboard, but before the text “Good Luck” begins to be rendered. This can be done because outside the dashboard and text, BG3 is transparent and there is nothing to draw between these two points, regardless of the value of the vertical scrolling register. This behavior shows us that scrolling registers can be changed at any stage of rendering.


This small shadow under the plane caused a bunch of headaches for the precision-obsessed emulator developer.

The image above shows the infamous shadow of an airplane. This effect is rendered by changing the screen brightness register with short ripples over five raster lines.

During the game, you can see that this shadow is rather chaotic. In the image above, it looks a bit like the letter “c,” but its shape in each raster line changes in length and starting point with each frame. The developers of Air Strike Patrol just roughly outlined where the shadow should appear, and solved this problem directly. In most cases this works.

Correct emulation of such behavior requires perfect timing, which is absolutely extremely difficult to obtain in the emulator .


On the Air Strike Patrol pause screen , raster effects are used that were not intentionally used in any other SNES game.

Now let's talk about the pause screen. It turns on BG3 while drawing a yellow-black border on the left and turns it off again during the same border on the right to draw gray lines on the screen. He also alternately through the frame switches the raster lines in which these gray lines are displayed to create the effect of an overlay jitter.

If you enlarge the emulated image shown above, you will notice that during the pair of raster lines in the left corner of these gray lines there are several missing pixels. It happened because my PPU emulation is 100% imperfect in clock cycles. In this case, it causes the effect of enabling BG3 a little later than it should.

I can very easily change the timings so that this image renders correctly. But such a change is likely to adversely affect other games that change the PPU display registers in the middle of the raster line. Although Air Strike Patrol is the only game that does this on purpose, there are at least a dozen games in which this happens by chance (perhaps IRQ fires in them too sooner or later).

Sometimes this causes brief noticeable damage to the picture, which is not paid attention to during development (for example, in Full Throttle Racingduring the transition between the store and the game). Sometimes recording is performed while rendering the screen that is transparent in the rest, and therefore does not cause visual anomalies (for example, as in the case of displaying HP status in Dai Kaijuu Monogatari II .) But even such “invisible” border cases can cause problems in less accurate rendering of raster lines which are used in the most productive emulators.

Even if you ignore Air Strike Patrol , all of these random (but valid) raster effects in SNES software do not allow you to functionally design a PPU renderer that generates the entire raster line with perfect clock accuracy.

In the case of bsnes over the years of trial and error, we have created a list of such games with “raster effects”. We also created individual rendering positions that allow much faster rendering based on raster lines to correctly display all these games (except for Air Strike Patrol , of course). But in essence, this is a bunch of hacks unpleasant for us, designed for specific games.

I also have a clock-based PPU renderer that doesn’t need all these hacks, but from time to time it creates small (one to four pixels) differences with the rendering of this equipment, as in the screenshot above of Air Strike Patrol .

Internal Latch Registers


The reason for all these small misses comes down to snapping timings.

Let's say SNES renders its famous mode 7 , which is an affine texture transformation with parameter changes in each raster line. To determine any screen pixel, you need to perform similar calculations:

px = a * clip (hoffset - hcenter) + b * clip (voffset - vcenter) +
b * y + (hcenter << 8)

py = c * clip (hoffset - hcenter) + d * clip (voffset - vcenter) +
d * y + (vcenter << 8)

Real SNES will not be able to complete all of these six multiplications fast enough for each pixel that is rendered in the frame. But none of these values ​​changes for each pixel (or, at least, should not change), so we just need to calculate px and py once at the beginning of each raster line. That is, PPU caches static results in latches, which are essentially copies of PPU registers. In the future, they can be transformed, or remain unchanged.

Then the x, y coordinates are transformed by mode 7 as follows:

ox = (px + a * x) >> 8

oy = (py + c * x) >> 8

Although x varies for each pixel, we know that the increment is performed by one each time. Thanks to the storage of internal drives, we can simply add constant values ​​a and c to ox and oy for each pixel, rather than perform two multiplications for each pixel.

Then the question arises before us: in what particular position of the clock cycle does the PPU read the values ​​of a and c from the external PPU registers to which the CPU has access?

If we take them too soon, then this can break some games. If we take it too late, it can break other games.

The easiest way is to wait for bug reports and adjust these positions so as to fix problems in each specific game. But in this case, we will never find the exact positions, only their approximations.

And every time we change one of these variables, it is unrealistic for us to retest all three and a half thousand games from the SNES library to detect the deterioration that our changes could make.

Out of the frying pan into the fire



Artistic interpretation of the process of eliminating emulation errors.

A similar style of testing methodology, “we’ll just make the game we are interested in working at any cost” led to the phenomenon, which I call emulation “from the fire, but into the fire”.

At the very beginning of the development of SNES emulation, when problems arose in the game, then any correction in this game that allowed it to work was accepted and added to the emulator. This fix necessarily broke some other game. And then they corrected this game, after which the third one broke. Fixing the third game again broke the first. This went on for many years.

The mistake here was that the developers tried to take into account only one variable at a time. Suppose we have a game, and for it to work, events must occur between measures 20 and 120. We do not know the exact measure, so just choose 70, exactly in the middle.

Later we get a bug report in another game, and determine that for this game to work , the measure value should be between 10 and 60. So now we change it to 40, which works for both games. Sounds logical!

But then the third game appears , in which the event should work between measures 80 and 160! Now we can’t make all three games work at the same time with the same value.

This forced emulator developers to create hacks for specific games. Coders do not want to release an emulator in which you can not run Mario , Zelda or Metroid . Therefore, for the general case, clock cycle 40 is used, but when loading Metroid, we force the timing value to 100.

How is this possible, why do two games need different values? This happens because not only one variable is involved here. The timing that you previously used to trigger another event may affect the timing value that is required for the next event.

Imagine this in the form of a simple algebraic expression:

2x + y = 120

You can solve it by taking x = 10, y = 100. Or x = 20, y = 80. Or x = 30, y = 60. If we only think about the value of x, which allows you to simultaneously run one set of games, then we miss the fact that in fact the problem may be in the wrong y!

The first versions of emulators to increase compatibility simply redefined the value of x depending on the running game. Such individual game hacks persisted, even if the correct, single value of x was later discovered. So the y problem would never be solved!

However, in the case of SNES, not one or two variables are involved simultaneously. The SNES console PPU alone has 52 external registers, which is approximately 130 parameters. In the process of rendering a single raster line, all 130 of these parameters and an unknown number of internal registers and latches are involved. This is too much information for someone outside to be able to realize the full state of the PPU at a particular point in time.

This aspect of emulation is not obvious to the uninitiated, but it is very fair: accuracy is not equal to compatibility. We can create an emulator with 99 percent accuracy, capable of running 10% of games. And you can write an 80% accurate emulator that runs 98% of games. Sometimes a correct implementation in the short term breaks popular games. This is a necessary sacrifice if you are trying to achieve both 100% accuracy and 100% compatibility.

Solve the problem


We got to the current stage of PPU emulation thanks to deductive reasoning and results in the real world.

We know that two PPUs have access to two VRAM chips. We know that they can read from each chip a known number of data bytes per raster line. We know the rough details of how each of the SNES video modes works. And based on this, we can outline a generalized pattern of how architecture might look. For example, here is a brief example of how the first three SNES video modes can work:

if (io.bgMode == 0) {

bg4.fetchNameTable ();

bg3.fetchNameTable ();

bg2.fetchNameTable ();

bg1.fetchNameTable ();

bg4.fetchCharacter (0);

bg3.fetchCharacter (0);

bg2.fetchCharacter (0);

bg1.fetchCharacter (0);

}

if (io.bgMode == 1) {

bg3.fetchNameTable ();

bg2.fetchNameTable ();

bg1.fetchNameTable ();

bg3.fetchCharacter (0);

bg2.fetchCharacter (0);

bg2.fetchCharacter (1);

bg1.fetchCharacter (0);

bg1.fetchCharacter (1);

}

if (io.bgMode == 2) {

bg2.fetchNameTable ();

bg1.fetchNameTable ();

bg3.fetchOffset(0);

bg3.fetchOffset(8);

bg2.fetchCharacter(0);

bg2.fetchCharacter(1);

bg1.fetchCharacter(0);

bg1.fetchCharacter(1);

}


PPU reveals to a third-party observer only a small part of its state: horizontal and vertical backward (horizontal / vertical blanking) flags, horizontal and vertical pixel counts, and tile overlay flags in the interval for sprites. This is not so much, but I repeat - every tiny element of the state accessible to the observer helps us.

The VRAM (video RAM, video memory) of the PPU chip during rendering is closed to SNES CPUs, even for reading. But as it turned out, OAM (sprite memory) and CGRAM (palette memory) are open. The trick is that at this time, the PPU controls the address bus. Therefore, reading OAM and CGRAM during screen rendering, I can observe what the PPU gets from these two memory blocks at such a critical time.

These are not all pieces of the puzzle, but they are enough for me to be able to implement the practically correct patterns for obtaining sprites.

Using access patterns for open OAM and CGRAM, PPU flags, general observations (i.e. guesses) from error reports for different games, and deductive reasoning, we were able to create clock-based PPU renderers that can almost perfectly launch all released games.

But the situation is still precarious: if someone starts creating homebrew games using accurate timing of ticks and raster effects, then all of our modern emulators will not be able to handle this. Including software and hardware implementations based on FPGA.

I must say clearly: today everythingthey are only aware of the internal order of operations and snap behavior in the PPU chips of the SNES console. No one knows how to emulate them perfectly. At least for now.

Possible solutions


What shall we do with this? How to determine the exact order of operations in a PPU if, from the point of view of the SNES CPU, it is a "black box"?

I see four possible options: logic analyzers, digital video output in test mode, risers and removing covers from chips.

Logic analyzers


If you look at the scans of PPU crystals shown above, you will notice black areas at the edges of the chip. These are the platforms connecting to the contacts of the chips.

These pins store the state of the PPU chips during each clock cycle. Here you can find the current address to which the chips access the video memory chip, the values ​​of the data transferred from one PPU to the second, and much more.

This information is not available for code running on the SNES CPU, but it provides valuable observations about the internal order of PPU operations.


Connecting Super NES console PPUs to a similar logic analyzer can be the key to the black box.

The critical problem of logic analyzers is that they are not very convenient to manage: if you try to sample live data from a working system, we will get a stream of results that is rather difficult to decipher. You will encounter the same problem if you try to analyze the analog RGB output of the system: to capture this data, you will have to manually perform each of the tests. Such a system is not very good for creating reproducible automated regression tests.

Digital video output in test mode


Recently, through a scan of crystal slices with a 20x magnification, a secret test mode has been discovered in the SNES console PPU chips. If you make a small hardware modification, then the PPU will begin to output a 15-bit digital RGB signal !

This is almost what we need! However, this mode has problems, because the famous mode 7 cannot display the correct picture in it. It seems that this function has not been fully completed.

In addition, to implement this method, manual modification of SNES consoles and an appropriate mechanism for capturing and analyzing output in test mode are still required. Nevertheless, unlike the solution with capturing an analog RGB signal, such a digital signal can be subjected to automatic testing, which can allow us to quickly complete a large amount of work on PPU reverse engineering.

Risers


Given that the PPUs are static, we could remove the PPU chips from a working SNES console and connect them to a prototyping board or a custom made circuit board along with two VRAM chips. After that, you can place a microcontroller between the PPU and the USB interface, and connect the interface to the PC, which will allow the encoder to program all external video memory registers and PPUs. In addition, the encoder will be able to manually control the PPU clock cycles and read the resulting signals on the I / O connectors, registers and in the PPU memory in each clock cycle.

By modifying the software emulator so that it generates the same internal values ​​of the I / O connectors, we could directly compare real hardware with emulation, even in real time. However, this will be very hard work because we cannot yet see the internal PPU operations.

Cover removal


Last, the most extreme solution is to further study the crystal by removing the chip cover. We already have crystal scans with a 20x magnification, but their resolution is not enough to analyze and recreate individual logic circuits, as was done in the Visual 6502 project . If we can get the crystal scans of both PPUs with a 100x magnification, then we can begin the hard work of compiling PPU circuits and converting them to connection tables or VHDL code. Then they can be used directly in FPGA, as well as ported to C ++ or another programming language, applicable for creating software emulators.

One specialist who had done this before gave me a rough estimate: it would take about 600 hours to map both PPUs. This task is much higher than the level of “let's collect money by fundraising and pay someone”, and ideally falls into the category “let's hope that someone very talented with a unique set of skills will want to help us voluntarily”.

Of course, this does not mean that I would not be happy to financially reward someone for their help, I can pay for the necessary details and work.

Request for help


To summarize: I went as far as possible in my SNES emulator project, and I need help to complete this final task. If you have read to the end, then you might want to help! Any support, including participation in the bsnes project on GitHub , or any research documentation on the internal workings of PPU chips, will prove invaluable to us!

Thank you for reading and for your support! It has been an honor for me for fifteen years to be a member of the SNES emulation community.

All Articles