There will be information that is not included in the main cycle, but too valuable to ignore.
From our discussion almost completely dropped the topic of mappers - co-processors in the cartridge. If you need to make a game larger than 0x8000 bytes in size, then the standard console capabilities are not enough for this. Mapper allows you to switch memory banks in the game, and the cc65 can work with it. The most popular mapper is MMC3. In addition to switching memory banks, it has a row counter.
To play your own game on this console, you can use a flash cartridge like Everdrive or PowerPak. You can also flash the EPROM chip and make your own board for it or sacrifice another cartridge, but this requires specific skills, and I’m not available right now.
The 3 high bits in the $ 2001 register include the luminance enhancement of the color channels. Bits are inverted - setting all the bits will evenly reduce the brightness of the entire screen. All versions of the palette in the picture.
Ulrich von Bassewitz (Ullrich von Bassewitz) ported to cc65 all the standard C library and something else. Now there is a division and multiplication of numbers, albeit a very slow one. Perhaps tabular computing will be faster.#include “..\include\stdlib.h”
Now you can use the work with memory: calloc, malloc, free and realloc. When testing these features, some difficulties were discovered - it is necessary to define both __STACK_SIZE__ and __STACKSIZE__ in the config file. Very similar to a typo in the library, but both options are found in the documentation. To work with the allocator, HEAP must also be defined .
I strongly recommend not contacting all of this, it is slow even in comparison with the C code, where the memory is statically allocated. Another interesting feature in the library is the rand and srand functions for pseudorandom numbers and qsort for sorting#include “..\include\cc65.h”
So are imported cc65_sin and cc65_cos - sine and cosine#include “..\include\zlib.h”
And so - work with compression. Not experienced at all.
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 in the interrupt vector at the addresses $ FFFE- $ FFFF. There are three ways to cause an interrupt:
Only the third method looks useful, it really allows you to change the PPU settings in the frame drawing process - you can combine the background and all that.
Some emulators cut by 8 pixels above and below the screen. NES produces 240 lines, but TVs of that era often lost the edges of the screen. In short, you should not put something critical to the game in this area.
Reading and writing PPU data works about the same. We write the high byte of the address in $ 2006, then the low byte to the same, and READ from $ 2007 (LDA $ 2007). But we must remember that the first reading from PPU always gives garbage. In addition to working with palettes at addresses $ 3F00- $ 3FFF, there the first reading gives the correct data. So you have to read two times. I am not a developer of NES and I have no idea why it works that way. Let me remind you once again that all PPU work should be done during V-blank.
A bit more about how to add music to the game using Famitone2 and Famitracker. If you want to do without libraries, then the sequence of actions is approximately as follows:
*((unsigned char*)0x4015) = 0x0f; // DMC // , DMC 0x10 *((unsigned char*)0x4010) = 0x0f; // , 0x0f - ADDRESS = 0xf000; // DMC- ROM // $C000-$FFFF ROM *((unsigned char*)0x4012) = (ADDRESS & 0x3fff) >> 6; // 0xf000 => 0xc0 LENGTH = 0x0101; // *((unsigned char*)0x4013) = LENGTH >> 4; // 0x0101 => 0x10 *((unsigned char*)0x4015) = 0x1f; // DMC //
Famitone2 does it all by itself. In any case, the samples should be short - I usually use 0.1-0.5 seconds. If you need to increase the length, you will have to reduce the frequency, and this dramatically spoils the quality. Still it is necessary to take into account that the DMC channel plays about twice as quieter than other channels.
Let's try to add all this to the game. I will use samples from some old collection that are licensed for non-commercial use. I cut them in length and imported into Famitracker:
Next you need to save them as DMC files. Each sample is tied to the instrument key, and you can compose them into a track in the DPCM column. Then it must be exported to .txt. The text2data program 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. Samples will be located in memory starting at $ F000, this is the FT_DPCM_OFF option. The samples themselves are located at the end of the reset.s file, in the “SAMPLES” .segment. His address must also be specified in .CFG. Next, Famitone2 does it on its own and switches the samples from the famitone.s file. I also added non-DMC effects for the voice of the jump and converted them via 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 drums to the noise channel - it will not be interrupted by the effects. In Famitone2, it's about the same.
To call these effects from the code, you need to call the procedures from famitone2.s by tags, the fastcall function:void __fastcall__ DMC_PLAY(unsigned char effect);
The effect number must be enclosed in one byte and correspond to the DMC sample number. They should be checked with the generated DMCmusic2.s file, there may be surprises:
25 and 27 turned out, because the samples are tied to the 25 and 27 note of the series.
And then it's very simple:DMC_PLAY(27);
One plays when jumping, and the second when you press Start.
Source: https://habr.com/ru/post/351034/
All Articles