INL-ROM custom MMC3 hybrid mapper design

Discuss hardware-related topics, such as development cartridges, CopyNES, PowerPak, EPROMs, or whatever.

Moderator: Moderators

User avatar
thefox
Posts: 3134
Joined: Mon Jan 03, 2005 10:36 am
Location: 🇫🇮
Contact:

Re: INL-ROM custom MMC3 hybrid mapper design

Post by thefox »

infiniteneslives wrote:I had only considered storing DPCM samples on the SPI, loading them to RAM and playing.
Remember that DPCM samples can only be played from the $C000-FFFF memory area.
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: fo.aspekt.fi
Grapeshot
Posts: 85
Joined: Thu Apr 14, 2011 9:27 pm
Contact:

Re: INL-ROM custom MMC3 hybrid mapper design

Post by Grapeshot »

1-bit audio at 1.7 mhz would have decent quality (about equivalent to 8-bit at 22 khz) but at that rate you would only get 10 seconds of audio from a 2mb chip. Oversampled audio is not very efficient to store uncompressed.

8-bit audio could be implemented without a latch by zeroing the outputs when shifting new data into the register. For around 44 khz operation, that would mean loading a new byte every 40 cycles, and the DAC would be off 22.5 % of the time. This would require a more aggressive low pass filter to be used for the sound quality to be acceptable, and probably an opamp to amplify the output of a resistor ladder DAC, but it gives 45 seconds of recording time at a higher quality than the 1-bit solution. That's plenty for drum and bass samples and maybe a few voice clips, at a quality about as good as raw PCM with no CPU usage required. Below 44 khz it would become increasingly difficult to filter the waveform.
tepples
Posts: 22759
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: INL-ROM custom MMC3 hybrid mapper design

Post by tepples »

Grapeshot wrote:1-bit audio at 1.7 mhz would have decent quality (about equivalent to 8-bit at 22 khz) but at that rate you would only get 10 seconds of audio from a 2mb chip.
Yeah, you'd be trying to push near SACD quality (SACD is 1-bit audio at 64*44100 Hz = about 2.8 MHz) through an NES. But the overall technique of a delta-sigma DAC remains useful for an output stage.
Grapeshot
Posts: 85
Joined: Thu Apr 14, 2011 9:27 pm
Contact:

Re: INL-ROM custom MMC3 hybrid mapper design

Post by Grapeshot »

Huh, it's possible to get acceptable 1-bit audio quality at a much lower sample rate than I thought. (I was thinking of oversampling on a normal DAC, not a delta sigma bitstream) If 1/8th of the NES clock frequency is acceptable for samples, that gives much more flexibility.
User avatar
infiniteneslives
Posts: 2104
Joined: Mon Apr 04, 2011 11:49 am
Location: WhereverIparkIt, USA
Contact:

Re: INL-ROM custom MMC3 hybrid mapper design

Post by infiniteneslives »

thefox wrote:
infiniteneslives wrote:I had only considered storing DPCM samples on the SPI, loading them to RAM and playing.
Remember that DPCM samples can only be played from the $C000-FFFF memory area.
Good point I forgot about that. Shouldn't be much issue though with the 128KB PRG RAM though, each bank would be fully mappable to $8000-FFFF in normal MMC3 sytle. You'd just have to map the bank to $6000-7FFF while loading from SPI, before placing it in $C000-FFFF. Although a PRG-ROM/WRAM variant would require WRAM to be mapped to $C000-DFFF.
I wrote:The CPLD that's going to handle the SPI flash should have a free pin that could be assigned to the task. Or if you were accepting of a 0-3.3v signal you wouldn't even need a CPLD pin, the SPI could be connected directly to the EXP pin.
Oh I forgot something else though. The CPLD is actually 3.3v supply it's only 5V tolerant. So the output would be 0-3.3v without making use of an output buffer. But I'm guessing that isn't much issue, perhaps even preferred assuming the EXP resistors are properly tuned. If not, a simple 5v inverter would be enough to step it to 0-5v before filtering.
If you're gonna play the Game Boy, you gotta learn to play it right. -Kenny Rogers
lidnariq
Site Admin
Posts: 11523
Joined: Sun Apr 13, 2008 11:12 am

Re: INL-ROM custom MMC3 hybrid mapper design

Post by lidnariq »

Sorry for another necropost, but I had a random idea:

What if there were a way to boot out the SPI ROM, so that we don't need a separate parallel flash at all? Two ideas occur: 1- use a fast clock (external RC, crystal, NES's 21/26MHz) so that the CPLD could fetch a byte from SPI at the full instruction fetch rate, or some very simple tiny padding loop that will still allow the use of the 1.7MHz main clock stuffed with some simple or repetitive byte sequence, possibly deliberately using bus conflicts.

Either way, this could load a small (256b?) "boot sector" which would then finish the rest of the game load "correctly".

It could also use way too much CPLD space for the cost savings, I don't know.
User avatar
infiniteneslives
Posts: 2104
Joined: Mon Apr 04, 2011 11:49 am
Location: WhereverIparkIt, USA
Contact:

Re: INL-ROM custom MMC3 hybrid mapper design

Post by infiniteneslives »

oh I don't consider it a necro, the idea is still alive and well in my mind at least :)

I actually had what I thought was a decent idea to ditch the parallel bootrom that just might work. I was holding back from rambling on about may hair brained idea, but since there are people apparently still interested in the idea I'll share.

You're right, with a small cheap 5v tolerant CPLD is would probably consume too much logic to handle starting up from SPI flash. And there is no longer such a thing as small cheap parallel ROMs currently in production. We've discussed the idea of using a micro-controller as ROM before, which I still believe would be prohibitively too low for random access and additional tasks. BUT a bootrom/bootstrap wouldn't have to be random access. You could have the mcu act as a ROM that loaded the bootloader into NES SRAM with LDA/STA's and then jumped to the bootloader. The CPLD would have a 'startup' state which would blanket decode $8000-FFFF (or some subset) to the mcu. The bootloader in SRAM would then turn off the CPLD 'startup' mode and start pumping the SPI flash through the CPLD into (32-128KB) PRG-RAM.

So you could use a cheap little 50cent mcu as the 'boot-ROM' and keep all data on SPI flash. Have a simple CPLD mapper, and 32-128KB of CHR-RAM and PRG-RAM. Thereby completely removing all parallel ROM which thus making parallel ROMs a thing of the past. ;)

There's all kinds of other things you could use the mcu for as well while still keeping it cheap. Things like USB programmability of the SPI flash, IRQ's, and sound to name a few...
If you're gonna play the Game Boy, you gotta learn to play it right. -Kenny Rogers
tepples
Posts: 22759
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: INL-ROM custom MMC3 hybrid mapper design

Post by tepples »

I'd almost recommend loading the first 512 bytes of the volume into $FC00-$FDFF, with some space reserved for the FDC descriptor and other fields in the PC volume boot record, so that a familiar file system can be used when loading files onto the SPI. Then that code can chain-load the game itself. To distinguish it from a boot sector for PCs, it could end with 02 65 instead of 55 AA.
User avatar
infiniteneslives
Posts: 2104
Joined: Mon Apr 04, 2011 11:49 am
Location: WhereverIparkIt, USA
Contact:

Re: INL-ROM custom MMC3 hybrid mapper design

Post by infiniteneslives »

tepples wrote:I'd almost recommend loading the first 512 bytes of the volume into $FC00-$FDFF,
So I understand you're recommendation, you're saying this descriptor would reside in the first 512 bytes of the SPI and describe the SPI volume. The bootloader would put that 512bytes into PRG-RAM @ $FC00-$FDFF so the program can reference it. I'm curious what uses this 512bytes would serve. aside from size all that FDC descriptor stuff seems kind of useless on the NES.
tepples wrote:To distinguish it from a boot sector for PCs, it could end with 02 65 instead of 55 AA.
cute :)

My thought was fairly simple for homebrew use. The bootloader would load the first 8KB of SPI flash into the PRG-RAM's fixed bank at $E000-FFFF and hand over control to the game with the reset vector. Only thing is, the first 512bytes of SPI wouldn't end up in $FC00-$FDFF, they'd probably be at $E000-E1FF. Game data could be arranged however the user chose, they'd just have make sure it was loaded from SPI before making use of it. I figured it'd be nice to put a set of helper routines in there as well to abstract the SPI enough to keep the developer from needing to know much about SPI. They'd only have to specify which address and range of SPI to load where or vice versa for saves and jump to my subroutine.
If you're gonna play the Game Boy, you gotta learn to play it right. -Kenny Rogers
tepples
Posts: 22759
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: INL-ROM custom MMC3 hybrid mapper design

Post by tepples »

infiniteneslives wrote:you're saying this descriptor would reside in the first 512 bytes of the SPI and describe the SPI volume. The bootloader would put that 512bytes into PRG-RAM @ $FC00-$FDFF so the program can reference it. I'm curious what uses this 512bytes would serve.
Same as a PC boot sector: to load the main executable from the root directory (like NTLDR or IO.SYS on a PC or PRODOS on an Apple II) and jump to it. Using the standard size boot sector allows files to be copied on in the usual way.
aside from size all that FDC descriptor stuff seems kind of useless on the NES.
The MCU is exposing the SPI flash to the PC as a mass storage device. The descriptor is so that the computer (which more likely than not runs Windows or Mac OS X) knows what to do with the volume rather than "helpfully" reformat it.
User avatar
infiniteneslives
Posts: 2104
Joined: Mon Apr 04, 2011 11:49 am
Location: WhereverIparkIt, USA
Contact:

Re: INL-ROM custom MMC3 hybrid mapper design

Post by infiniteneslives »

tepples wrote:
infiniteneslives wrote:you're saying this descriptor would reside in the first 512 bytes of the SPI and describe the SPI volume. The bootloader would put that 512bytes into PRG-RAM @ $FC00-$FDFF so the program can reference it. I'm curious what uses this 512bytes would serve.
Same as a PC boot sector: to load the main executable from the root directory (like NTLDR or IO.SYS on a PC or PRODOS on an Apple II) and jump to it. Using the standard size boot sector allows files to be copied on in the usual way.
I'll have to learn up on boot sectors and such so I can figure out how this might work in this case. The bootloader wouldn't actually be in the SPI as I had planned, it'd be in the mcu's rom.
aside from size all that FDC descriptor stuff seems kind of useless on the NES.
The MCU is exposing the SPI flash to the PC as a mass storage device. The descriptor is so that the computer (which more likely than not runs Windows or Mac OS X) knows what to do with the volume rather than "helpfully" reformat it.
I didn't actually plan on making the SPI flash look like a mass storage device. I would set it up like I did the NESDEV1 where the mcu acted as a USB programmer for the SPI flash. So the OS formating the 'drive' isn't a concern. So the only use of the descriptor would be for the host PC's programmer application and for the NES itself. Something more along the lines of a ines header seem more useful than FDC descriptor.
If you're gonna play the Game Boy, you gotta learn to play it right. -Kenny Rogers
tepples
Posts: 22759
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: INL-ROM custom MMC3 hybrid mapper design

Post by tepples »

So what device class would your MCU implement? And who would make drivers for Windows (32-bit), Windows (64-bit), Mac (32-bit), Mac (64-bit), Linux (32-bit), and Linux (64-bit), including the cost of getting the Windows (64-bit) driver signed? Using the mass storage class means the user will already have the driver installed.
User avatar
infiniteneslives
Posts: 2104
Joined: Mon Apr 04, 2011 11:49 am
Location: WhereverIparkIt, USA
Contact:

Re: INL-ROM custom MMC3 hybrid mapper design

Post by infiniteneslives »

It'd use V-USB

The drivers are pretty easy to install, and pretty popular. I've bought several devices that use this library, and made many others including the kazzo. There devices were sucessful using it, and I've been sucessful implementing it myself. I'm no guru on all the details of device classes, signed drivers, etc. It uses libusb drivers and I've never had an issue wth them. Are they signed? I dunno, they just work so I never took the time to dig into such details. As far as I'm concerned it's problem solved. I don't think it's that big of a deal to ask the user to install a driver...

That and I find it a lot easier and user freindly to have a little app that programs the cart. No copy pasting, or finding some input to allow data transfer to occur. After compiling your latest build you just click the program button.
If you're gonna play the Game Boy, you gotta learn to play it right. -Kenny Rogers
tepples
Posts: 22759
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: INL-ROM custom MMC3 hybrid mapper design

Post by tepples »

The MCU would need to feed the CPU enough of a boot loader to read the first sector from flash and execute it. This means it'd need to output on D7-D0 long enough to put a reset vector, a stream of A9 (program byte) 85 (address byte), and finally 4C 00 00 on the data bus before taking itself high-Z. How many inputs and outputs are on such an MCU?
User avatar
infiniteneslives
Posts: 2104
Joined: Mon Apr 04, 2011 11:49 am
Location: WhereverIparkIt, USA
Contact:

Re: INL-ROM custom MMC3 hybrid mapper design

Post by infiniteneslives »

tepples wrote:How many inputs and outputs are on such an MCU?
The beauty of it is you really don't need many i/o to have a mcu act as a non-random access ROM. So all you'd need is 8 i/o for data and 1 i/o for enabling. You don't even bother to decode the address bus because you KNOW what the address will be, you're the ROM after all. You're telling the CPU what the next addresses will be, so you don't need the CPU to tell the same info back to you again. The bootrom doesn't contain any conditional code which is what allows it to be non-random. There would be a fair amount of time needed to do this depending on how long the boot routine was, but this really should be a limit for the mcu. The only limit that really applies is how much ROM the mcu has which is drastically more than necessary.

All the mcu has to do is watch its enable signal which could be as simple as PRG /CE. If it's low output the first byte and retrieve the next. When it goes high release the bus and prepare the next byte. When PRG /CE goes low again output next byte and repeat. You could even cheat and not release the bus when you know the CPU won't be writing to RAM on the following cycle. Shoot you could cheat even further if you wanted and output the same value that the CPU is putting on the data bus since you know what it's going to be. That makes it a little more complex though since you have to do a little more than watch PRG /CE.

The loop the mcu is performing is pretty small especially since it's not conditional aside from enabling to output on the bus. So timing should be pretty easy to satisfy. If I was able to emulate a '161 for bankswitching which had a couple conditional loops with a 12-16Mhz mcu this should be cake in comparison.

The mcu would start off by feeding a reset vector that really doesn't matter as long as it's $8000-FFFF and stays in that range through the bootrom access. Then you just feed a sequence of LDA and STA's copying boot routine from the mcu into RAM. Then jump to RAM and execute the whole bout routine. The routine would SPI access routine fetching the game data and code from the mapper/SPI and dumping it into PRG-RAM.

My initial thought was to use a ATtiny20 with their 12i/o's which is plenty if you ONLY want it to substitute as a bootrom. The only thing you need is 8i/o for data and one i/o for enabling the mcu. This could work for a published cart, but is limited and not easily converted to a devcart with USB programability. You need 4 more i/o for USB two for USB and two for a calibrated clock, which doesn't leave any i/o for enabling the mcu. It's conceivable to multipurpose the USB i/o when running on the NES and disconnected from USB, you'd also have to multipurpose the data lines for SPI interface through the CPLD. That'd be pretty limiting, and it doesn't allow you to move a lot of the logic from the CPLD to the mcu. The more logic that can be moved to the mcu the better, so we can save the CPLD logic for time critical things like bankswitching.

Because of that I've pretty much settled on the ATmega48/88/168/328 family, size depending upon how much ram/rom I need/want on the mcu. The ATmega88 should be plenty of space when running USB as well.

Here's my current i/o plan:

Code: Select all

Port B: 
(2x) USB
(4x) SPI
(2x) crystal/resonator

Port C: 
(1x) enable signal from mapper
(1x) PRG R/W
(1x) Sound out to EXP6
(1x) IRQ
(1-2x) JTAG TCK for 1-2 CPLDs?
(1x) spare for mcu boot loader select perhaps?

Port D:
(8x) PRG Data
JTAG TDI, TDO, TMS connected to the data bus D0-2 to allow for reprogramming the CPLD(s) when the cart is disconnected from the NES which would multi-purpose these i/o. (EDIT:verified possible)
So this would take utilizing the mcu to another level. Pairing the CPLD(s) and mcu together should allow for some pretty sophisticated mapper features with a small amount of low cost hardware in comparision to my NESDEV1 project. Something like this would actually be cost effective enough to produce hardcopies for a homebrew game. And if the sophisticated mapper wasn't desired because something closer to a discrete mapper was enough you could cut back to the ATtiny20 as a bootrom. While the mapper does cost more in comparison to a cheap little discrete mapper, something like this allows you to have HUGE amounts of ROM giving you a lower total cost when you consider how expensive large parallel 5v ROMs are in comparison to SPI flash.

Some of the features like USB programability, mapper JTAG reflashing, and such are more tailored towards a devcart version. But having the mcu at the ready could really open up a large amount of features to a homebrew game. The CPLD would address decode for the mcu simply sending it a mcu enable signal and the mcu could sense PRG R/W. So my plan is to implement a set of opcodes for the mcu which would be accessed at $5000/5001.

I've still got some details to iron out but there's a ton of potential here. Moving SPI access to the mcu will be a little more tricky but frees up logic in the CPLD quite a bit. Aside from tossing a synth in mcu you could also put things in there like IRQs, hardware multiplier, etc. Anything that fits well in an opcode-operand format and doesn't require immediate processing should be feasible. You'd probably have to leave the mcu alone for a while while it goes and performs whatever operation you just asked of it. For longer operations like fetching SPI data it might be fitting to just have it fire an IRQ when it's ready to pump out data. That way the CPU can perform other stuff at the same time truly making it a co-processor. :D While all this is going on you'd still have the CPLD handling bankswitching, scanline/cycle counter, etc which is all the stuff the mcu doesn't have the time, i/o, or speed to take care of.

Here's the best part about this is the cost of the hardware is actually reasonable, one might even consider it free when compared to a comparable setup. Consider having a MMC3 with 32KB CHR RAM, battery backed WRAM, and 512KB PRG-ROM. Swap the parallel PRG ROM and battery backing for the mcu, 128KB PRG-RAM, and 1MB of SPI flash for around same cost. Basically you get twice the ROM space, hassle free saves, and all the complex mapper features for FREE. Want more ROM space? You don't have to worry about supporting a bigger mapper, just buy larger SPI flash. Double it (2MB) for less than 50cents. Quadruple it (4MB) for less than 75cents.

Even if you didn't care for all the complex mapper stuff and just wanted to use a ATtiny20 as a boot rom and have comparable to discrete mapper function from a small CPLD. Comparing it to UOROM, the hardware difference is less than $2 to get 1MB flash, 128KB PRG-RAM, and saves. You'd probably pay the same amount to add battery backed WRAM to a UOROM style mapper...

Now I'm really starting to get excited about the potential 8-)
Last edited by infiniteneslives on Sun Mar 10, 2013 3:24 am, edited 1 time in total.
If you're gonna play the Game Boy, you gotta learn to play it right. -Kenny Rogers
Post Reply