Developing games under the NES on C. Chapters 22-23. Appendix 1 - Mappers and Digital Sound
Here there will be information not included in the main loop, but too valuable to ignore.
From our discussion, the topic of coprocessors - coprocessors in a cartridge almost completely fell out. If you need to make a game larger than 0x8000 bytes, then the standard capabilities of the console for this is not enough. Mapper allows you to switch memory banks in the game, and cc65 can work with it. The most popular mapper is MMC3. In addition to switching memory banks, it has a row counter.
I strongly recommend that you do not mess with all this, it is slow even in comparison with the C code, where memory is allocated static. Another interesting function in the library is rand and srand for pseudo-random numbers and qsort for sorting
So cc65_sin is imported and cc65_cos is the sine and cosine of
And so - work with compression. Did not feel at all.
Interrupts - IRQ
The principle of operation is the same as with NMI: when it is triggered, control is transferred to the interrupt handler. The pointer to the handler is located in the interrupt vector at the addresses $ FFFE- $ FFFF. There are three ways to call an interrupt:
- instruction BRK in the code, opcode # 00
- the interruption of the DMC audio channel is enabled, it is triggered when the sample ends.
- an interrupt can be invoked by a mapper, for example MMC3 knows how to handle the counter of strings
Only the third way looks useful, it really allows you to change the PPU settings in the process of drawing the frame - you can combine the background and all that.
Some emulators are cut at 8 pixels from the top and bottom of the screen. NES issues 240 lines, but the TVs of that era often lost the edges of the screen. In short, do not put in this area is something critical for the game.
Reading and writing PPU data works roughly the same way. We write the high byte of the address in $ 200? then the lower byte there, and we READ from $ 2007 (LDA $ 2007). But we must remember that the first reading from the PPU always gives the garbage. In addition to working with palettes at the addresses $ 3F00- $ 3FFF, there the first reading gives the correct data. So it is necessary to read two times. I'm not an NES developer and do not have the faintest idea why this works. Once again, I remind you that all PPU work should be done during V-blank.
Working with DMC
A little more detail on how to use Famitone2 and Famitracker to add music to the game. If you want to do without libraries, then the sequence of actions is something like this:
* ((unsigned char *) 0x4015) = 0x0f; //turn off the DMC
//the register controls the channel enable, DMC is controlled by bit 0x10
* ((unsigned char *) 0x4010) = 0x0f; //sampling frequency, 0x0f - maximum
ADDRESS = 0xf000; //address of the DMC sample in ROM
//samples should be in the address range $ C000- $ FFFF in ROM
* ((unsigned char *) 0x4012) = (ADDRESS & 0x3fff) 6; //0xf000 => 0xc0
LENGTH = 0x0101; //the sample length is
* ((unsigned char *) 0x4013) = LENGTH 4; //0x0101 => 0x10
* ((unsigned char *) 0x4015) = 0x1f; //enable DMC
again. //when the channel starts, the sample starts to play
Famitone2 does it all by himself. In any case, the samples should be short - I usually use 0.1-0.5 seconds. If you need to increase the length, you have to reduce the frequency, and this spoils the quality. Still it is necessary to consider, that the channel DMC plays approximately twice more silently other channels.
Let's try to add it all to the game. I will use samples licensed for non-commercial use from some old collection. I cut them in length and imported them into Famitracker:
Then you need to save them as DMC files. Each sample is attached to the instrument key, and you can arrange them in a track in the DPCM column. Then it must be exported to .txt. The program text2data from Famitone2 /tools converts it into .s and .dmc files.
text2data DMCmusic.txt -ca65
Next, you need to enable DMC and SoundFx channels in Famitone2. This is in the .define section of the reset.s file. The samples will be stored in memory starting at $ F00? this is the option FT_DPCM_OFF. The samples themselves are located at the end of the file reset.s, in the .segment "SAMPLES". Its address should also be specified in .CFG. Next Famitone2 manages on its own and switches samples from the file famitone.s. I also added non-DMC effects for the voiceover of the jump and converted them through famitone2 /tools /nsf2data - this technique has already been considered before.
And now you can add DMC effects. I leave the same track, but I transfer the percussion to the noise channel - it will not be interrupted by the effects. In Famitone? this is done about the same.
To call these effects from the code, you need to call procedures from famitone2.s on labels, fastcall:
void __fastcall__ DMC_PLAY (unsigned char effect);
The effect number must be embedded in one byte and correspond to the number of the DMC sample. They need to be checked with the generated file DMCmusic2.s, there may be surprises:
25 and 27 turned out, because the samples are tied to the 25 and 27 notes of the series.
And then it's very simple:
One plays when jumping, and the second when you press Start.
It may be interesting
Situs QQ Online
Situs QQ Online