KrzysioCart Micro SD (Chris' MicroSD Cartridge) - revolution for Famicom players
I would proudly like to present my latest project - KrzysioCart Micro SD - Famiclone cartridge, that should be the last one you'll ever buy - no more carts will you ever need. Cartridge is compatible with 82% of all games that have been ever released for NES / Famicom / Famiclones. Following mappers (chips that extends console's abilities) are supported
Order of | Mapper | Mapper |Amount of|total %
frequency | ID | name | titles |
1 | 1 | MMC1 | 804 | 24,62
2 | 4 | MMC3 | 765 | 23,42
3 | 0 | NROM | 434 | 13,29
4 | 2 | UNROM | 336 | 10,29
5 | 3 | CNROM | 236 | 7,23
6 | 7 | ANROM | 60 | 1,84
17 | 71 | CAMERICA | 14 | 0,43
30 | 232 | CAMERICA Quattro | 8 | 0,24
43 | 15 | 100-in-1/168-in-1 | 4 | 0,12
Moreover, this is the first and only cart that supports famous Famiclone multicart: Contra Function 168-in-1, which is more familiar to Polish and Russian players and every child that had been playing famiclone, cannot imagine his childchood without this cart. Adding support for this cart is my gift to Polish players:
Good news for impatient readers - this cart is available for sale (scroll to end of article for more details). The whole set that I am offering to sale consists of:
- cartridge printed circuit board with plastic shell,
- MicroSD 4 GB memory card
- MicroSD USB reader, which will let you put files on MicroSD card.
This is all you need to begin playing your favourite games.
Cartridge had been tested on most famous Famiclones:
- IQ502 rev2/3
- SP60 (version based on integration circuits),
- RINCO (Thompsonic)
- two blob-top consoles (a'ka NOC = Nes on a Chip).
There were no problems whatsoever. The cartridge has also possibility for firmware update directly from SD cart. No one has ever invented something that in Europe and I am the second person that started works at it in 2012 (NES PowerPak was first).History
My first steps at NES developing scene began in 2012, when I created huge cartridge, that was my Master of Thesis at High School. It was based on Xilinx XC3S400 (Spartan 3) kit. I implemented support for over 95% games, including mappers like MMC5, VRC6. Unfortunately, complex design and huge size and also second faculty made me abandon this project.
Few years later I came up with the idea of creating simpler cartridge - based on Xilinx XC9572XL chip - 72 macrocells (more info here: http://www.elektroda.pl/rtvforum/topic3094839.html
The aim was to support: Contra Function 168-in-1 multicart, Golden 5 / 4 (Camerica's 5-in-1 and 4-in-1 multicarts) - mapper Camerica #71 & #232) and UNROM. The common for all those games is to contain 8 KB CHR-RAM. Later I've included support for NROM games, which in short was just a modification that after selecting game from menu, but before leaving control to it, the cartridge's software preprogrammed CHR-RAM with graphics of this game (NROM games contain 8 kB ROM with graphic data). Later, after updating SRAM from 6264 (8 kB) to 62256 (32 kB) and connecting two highest address lines to FPA, I could support also CNROM games. Next modification was to add MMC1 mapper support (but only for games that use 8 kB CHR-RAM). Later, by adding 8 kB PRG-RAM mapped at $6000-$7FFF I was able to support MMC1 games with additional RAM, like Legends of Zelda, Dyna Blaster. Adding support for MMC1 games with CHR-ROM and MMC3 mapper (which is unfortunately majority of games) was not possible due to insufficient number of macrocells in CPLD and also lack of I/O pins - all of pins has been already used. I had to also do some hacks, like changing obvious multiplexation formula (in VHDL) from: Y <= A when in = '0' else B
to Y <= A when in = '0' else 'Z', with Y being pull-up to B with external resistor.
Unfortunately, my source of XC9572 chips was ended and availability of these chips in Poland in rational price was als limited. I tried to order them FOUR times from aliexpress, each time the seller said the chips were bad or just the parcel did not arrived (buying other things from Aliexpress worked great for me). So I had to search for some kind of alternative.Construction - beginning, first troubles and first milestones
I tried to buy similar CPLS chip from Altera - Max II, which contains more macrocells (192) and around 2 times more I/O pins. Despite fact that Altera's chips have more dense package (TQFP100) than Xilinx (PLCC44), I found soldering Altera easier and faster because I can use flag soldering tip and solder all legs in one phase, instead of soldering them separately like in Xilinx.
After few tries with those chips I had mixed feelings - the same logic structure, that in Xilinx was fitted in 60 makrocel, needed 120 macrocells in Altera. One macrocell is the most basic capacitance unit in CPLD/FPGA circuit that allows storing one bit of information or controlling one output. I had to change my style of describing logic. In Xilinx I was trying to use as less registers as possible - for example by using alias function or shift registers instead of counters. Unfortunately those tricks in Altera lead to weird results - sometimes formula than might seem to be easier, was translated to larger amount of macrocells than more complex formula. I was using Quartus 9 at first, then I migrated to Quartus 13 and some problems were solved, some were still happening - for example slight change in code unrelated to SD card support leaded to compatibility issues with them, but changing `Fitter Seed` to different value canceled these problems.
When I finished MMC1 mapper implementation and was able to support CHR-ROM games and then finished full MMC3 mapper support (CHR-ROM + scanline counter), I was unable to get in limit of the available amount of macrocells. Applying various kind of optimization bring me to success - currently 95% of total chip resources are used. MMC3 mapper - scanline counter
The next milestone problem was to add support to MMC3 scanline counter - some kind of unique add-on that enriched games with possibility to notify CPU using interrupt that rendering scanline (horizontal line of image) with given number has just been started. This is very useful when determining proper time to switch nametables or tile set, for example during status bar display or when more complex screen need to be rendered.
My knowledge about MMC3 specification is gained from nesdev.com - the scanline counter is clocked by rising edge of PPU's A12 signal, however some very quick successive edges need to ignored.
Slight modification of moment in time that the interrupt is fired lead to proper picture displaying. However, there were still issues in some games that resulted in image shaking. Testing on famiclones with integrated circuits gave better result (less shaking) that on those with blob-tops. I think that longest tracks in PCB with DIL chips causes larger capacitances on those tracks with respect to ground and longer capacitances do not allow quick spikes to be propagated. After applying my own-invented analog filter (additional components on cartridge) + digital filter (additional logic in FPGA), the games started to look exactly like in emulator. Comparing my own implementation of MMC3 with the AX5208 chip (this is DIL40 chips that is MMC3 mapper) I can honestly say that my implementation is ideal - image is as good as in emulator.
Left image - AX5202P implementation - should be good, but image is shaking and interrupt is not fired in correct time. Right image - my own implmenetation - ideal gameplay. Micro SD cart support
MicroSD cart support is done by:
- entity in FPGA that is responsible for converting single byte, sent by console's CPU into serial 8 bit communication done via SPI (this block was written in extreme optimal way to be fast and not consume more macrocell - it is clocked by clock from console),
- lots of lines of code written in 6502 assemler, responsible for communication with sd cart (detecting presence and type of cart, sending packets to cart),
- much more lines responsible for detecting partition, listing directories, reading files, traversing FAT entries (full FAT16/32 support, cluster size from 512 bytes to 64 KB), full VFAT Long File Name Entries.
All those elements were written by me from scratch. SD cart support (earlier: MMC cart) were written by me in 2012 during writing my Master of Thesis - at that time I had only MMC cart. Later, when I gathered some SD cards to test (<= 2 GB) I found out that they works fine without any changes in communication. Just after testing larger SDHC >4GB cards I found out they use different addressing mode - block number, instead of 0, 512, 1024 like on MMC is set 0, 1, 2, 3 (which is logical because block number is 32 bit number and the largest cart that can be addressed using old method is 4 GB).
Also, I had couple of 4 GB cards (mainly made by SanDisk company) that were causing troubles in communication, when much larger 32 GB Kingston card worked fine.
Slight protocol modification that consited in adding additional idle clock cycles before each packet bring me to success.Optimalizing loading game time
Initially, game loading time was not satisfacting. For example Contra Function 168-in-1 multicart took 2 minutes to load. During loading game time:
- flash memory is erased (few seconds),
- portion of game program code is being read from selected ROM from SD cart sector-by-secttor and PRG-ROM memory is being programmed with this data,
- portion of game graphics data is being read from selected ROM from SD cart sector-by-secttor and CHR-RAM memory is being written with this data.
Initially, writing algorithm was simple: read single byte, program it and then check if:
- reading next sector is neccessary?,
- switching to next memory bank is neccesary?
- is it end of programming?
If none of above, just read next byte and do another check, et cetera. Those series of checks after each byte reading was not very efficient. I remember spending one of evenings on thinking how to modify that. Replacing byte-by-byte algorithm by block-by-block (where one block is portion of 256 or less bytes to be programmed at once) would increase speed. Hovewer, before each block programming, its size need to be calculated and stored in Y register and then the main programming loop might look like:
;Y <- 256 minus amount of bytes to be programmed
lda (ptr_src), Y
sta (ptr_dst), Y
Even if calculating block size is not trivial and short, this algorithm has the advantage that each iteration of the loop above is very fast. But can it be speed up even more? Yes - because the whole programming routine is placed in RAM (it is impossible to both - program ROM and execute code from it), we can change the long, 5-cycle opcode of indirect read-write by zero-page pointer and Y register `lda (ptr_src), y` into absolute opcode `lda $ffff, y`, where $ffff address will be changed in RAM before each block-program algorithm start. On each loop we gain 1 extra cycle on read and 1 on write, and there are up to 256 read-write cycles, so this will be faster by 512 cycles.
Programming Super Mario Bros 3 game (256 KB PRG-ROM + 128 KB CHR-ROM): 17 seconds:
Zoom showing what parts it consists of:
More zooming showing detailed sector operation:
Comparing with CHR-RAM - writing to CHR-RAM is faster than programming PRG-ROM because it is 1 cycle instruction in contrary to 2 cycle and then polling PRG-ROM. Additional mappers
Adding support for additional mappers is not possible due to insufficient number of macrocells left in FPGA. Although, the cartridge PCB was projected in such manner that all CPU's address lines are wired to CPLD. Maximum granularity of PRG-Bank switching is 8 kB, CHR bank: 1 kB. This can be used to adding support for almost any other mapper in place of one of the currently implemented ones, for example VRC6 could be done instead of mapper 15/232 and maybe some others. Of course MMC5 is out of reach due to the lackness of external 1 kB of dual-port SRAM.Conclussion
After doing prototype that was working 100% as expected I thought of making more units for sale as there is lack of programmable cartridges for famiclone consoles on the market (at least in Poland). Hard to buy and expensive competetive product (everdrive) is not in the reach of many people, so my project might be revolution - I made a lot more PCBs for each of you that is reading that!
Promotion movie - english subtitles available:
------------------------------------------------------------KrzysioCart Micro SD - FAQ
1. How to order:Feel free to send email at: firstname.lastname@example.org
2. What is the price, what is contained in setPrice is 300zl (70€/70$) with included shipping to Poland. Shipping to other European country + 5€/$, overseas shipping needs additional contact with me.
The set contains of: PCB with shell (color can be chosen) + 4 GB micro SD card (random manufacturer) + MicroSD USB cart reader (random manufacturer and design)
3. What games are supported?Mapper #0 (NROM), #1 (MMC1), #2 (UNROM/UOROM), #3 (CNROM), #4 (MMC3), #7 (ANROM/AOROM), #15 (Contra 100/168-in-1), #71 (Camerica), #232 (Camerica Quattro).
Cart contains 1 MB PRG-ROM + 256 kB CHR-RAM/ROM + 8 kB PRG-RAM
No 4 screen mirroring or battery backed up RAM is supported.
4. Will it work on my console??The cartridge was tested on the following console models:
- IQ502 rev2/3
- SP60 (version based on integration circuits),
- RINCO (Thompsonic)
- two blob-top consoles (a'ka NOC = Nes on a Chip).
and no problems were discovered. I cannot guarantee that it will work on every one famiclone on Earth, because manufacturers are using different tricks for cutting-off price, which result in less compatibility, like replacing 7805 voltage regulator with zener diode, bypassing SND-OUT/IT pins from cart connector, bypassing CIRAM-!CE pin from cart connector. It should work on 99% of consoles from market. The cartridge does not draw a lot of current so it should also work on hand-held portable famiclones! After putting it on 60-to-72 pin adapter (with CIC), you can even play in on NES.
5. Is it safe for my console?Yes! The cartridge was made out of 1 mm thickness PCB, so it wont expand the pins on your connector. Well fitted shell holds the cart firmly in the connector. I included voltage translating buffers for converting 5 V logic signals (from cartridge connector) to 3.3 V logic for low-voltage chips (memories, CPLD). It is protecting your console and the cartridge itself and is not driving any additinal current, like for example on cheap ali-express carts, which use 3.3 V memories connected to 5 V using zener diode (or even worse - without it) and driven with 5 V logicw ithout any series resistors limiting clamp diodes current
6. Will any larger memory card be working?All microSD cart up to 32 GB should be working fine, as long as it is formatted as FAT16 or FAT21 with cluster site from 512 bytes to 64 KBs. Larger cards needs to be formatted in different filesystem and they are not supported at the moment. Cart must be capable of communicating over SPI. Some cards (SanDisk) has non-standard SPI mode and might cause troubles, which was taken into account during construction. Most of the card will be working fine
7. Why game XXX is working correctly on emulator, but at this cartridge does not work at all/has garbage graphics/has no graphics at all?Generally, emulators:
i. is trying to idealize the surrounding environment, for example: they fills the whole RAM at startup with zeros,
ii. they block unallowed game operations, like for example blocking game's writes to CHR memory when game declares it uses CHR-ROM memory as graphics,
iii. they try to fix invalid NES headers, like when NES header declares that game uses 128 kB CHR-ROM and game is trying to use graphics past 128 kB bank, it will be wrapped modulo 128.
First case is mainly about unlincensed (homebrew amateur) games, whose creators were not testing them on real hardware. If that happens, please contact game developer for issuing game fixing.
Second case is about games like Doki Doki Amusement Park, Krusty's Fun House - those games might ovevwrite some tiles used in title screens as they try to write to CHR memory despite using CHR-ROM.
Some homebrew games (especially those from Shiru - Alter Ego, Zooming Secretary) have invalid initializing memory function which fills whole CHR memory with zeros. Those games use CHR-ROM, but on real hardware where CHR-RAM is used in place of CHR-ROM, all game graphics will be destroyed and changed to black colour. There are fixes to those games already available at nesdev.com
8. Why there is no progress bar during loading game, just the blinking screen?Console processor, during programming PRG/CHR memory is changing memory banks extensivelly, so trying to display something would lead to the need of reloading tiles to next bank, which would cause slowing programming process. Also when programming CHR, Picture Processing Unit in console cannot display anything.
9. Is that all legal?According to law, game ROMS are copyrighted as other computer programs. It is lawful to have ROM only of those games that you have original cartridges (backup). Micro SD cart, included with this cartridge is blank - the owner is liable for putting only those games on it that he is able according to law. However, except official Nintendo's copyrighted games, there are hundreds of free home-brew games made by fans and enthusiasts of NES.