Designing your discrete logic mapper

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems. See the NESdev wiki for more information.

Moderator: Moderators

Post Reply
User avatar
za909
Posts: 249
Joined: Fri Jan 24, 2014 9:05 am
Location: Mijn hart woont al in Nederland

Designing your discrete logic mapper

Post by za909 »

I've been having some semi-serious thought experiments about designing a cheap and very specific-purpose mapper to be able to create something like UNROM but with a CPU cycle-based IRQ. Having done my old PCM player projects that ran on the DPCM IRQ, I thought that taking it to the next level and not having to compromise on the complexity of the gameplay of any game project using it is just impossible without some kind of external help.

The point is to have a large PRG ROM to draw sampled audio from, and an IRQ that makes streaming it at a reasonable quality easy without too much strain on CPU time (no acknowledgement overhead, no need to write many mapper registers, etc.).

So here's what I'm sure would be needed:
  • 8-bit latch (e.g.:74FCT2573T) for an oversized (4 Megabytes) UNROM bank select register
  • Quad-OR gate (74HC32) as part of the UNROM specification to make $C000-$FFFF fixed to the last ROM bank
  • Double 4-bit binary counter ( to divide the CPU clock by 128 (Obtains a fixed IRQ rate of 13,982 Hz)
  • Appropriate ROM chip(s) to provide 4 MB.
  • RAM chip to act as 8k of CHR-RAM
  • Some singular logic gates on the board to produce the right chip enable signals, etc.
I'm not sure if there needs to be anything else thrown in between the O2 pin of the second counter and /IRQ, possibly some kind of clock that can be driven if the chip doesn't already have a clock output by default. Otherwise I suspect that /IRQ could continuously be held low, resulting in the IRQ being continuously asserted for 64 CPU cycles (O2 of the high counter can be tied to /IRQ to divide by 128 instead of 256). Thankfully there is no need to be able to disable this counter because the CPU can ignore the interrupt with the I flag if needed. At first glance I don't know what else I could be missing, but is this generally how you'd approach trying to design a simplistic custom mapper (before moving on to cost estimation and actually designing the circuit with some tool)?
lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

Re: Designing your discrete logic mapper

Post by lidnariq »

You'll need an extra OR gate if you actually want a fully fixed bank - each OR gate only handles four bits of latch.

The problem with "no IRQ ack" is that there's no such thing - /IRQ on the 6502 is level triggered: at every moment that interrupts are enabled, a new instruction is being fetched, and the /IRQ pin is low, it will jump to the address specified by the IRQ vector.

So you can't "just" give it a ÷128 prescaler unless you can guarantee that you stay in the IRQ handler for 64 cycles. You can make an invisible ack, such as detecting IRQ vector or the instructions in the IRQ handler, or you can shorten the amount of time that /IRQ is asserted.
Joe
Posts: 650
Joined: Mon Apr 01, 2013 11:17 pm

Re: Designing your discrete logic mapper

Post by Joe »

If your latch has tristate outputs, you might be able to use pull-up resistors instead of OR gates to make the fixed bank, like in Family Noraebang. I don't know how reasonable that is from a cost perspective, but it could lower your part count since you can use one resistor array to replace two quad OR gates.
User avatar
za909
Posts: 249
Joined: Fri Jan 24, 2014 9:05 am
Location: Mijn hart woont al in Nederland

Re: Designing your discrete logic mapper

Post by za909 »

lidnariq wrote: Sun Oct 09, 2022 12:23 pm You'll need an extra OR gate if you actually want a fully fixed bank - each OR gate only handles four bits of latch.
Right, I was thinking of the original UxROM boards. I basically need the logic to say if (cpu_R/W & (cpu_A15 & cpu_A14 )) | (latch_O0 & latch_O1 & latch_O2 & latch_O3 & latch_O4 & latch_O5 & latch_O6 & latch_O7) if I'm not mistaken?
lidnariq wrote: Sun Oct 09, 2022 12:23 pm The problem with "no IRQ ack" is that there's no such thing - /IRQ on the 6502 is level triggered: at every moment that interrupts are enabled, a new instruction is being fetched, and the /IRQ pin is low, it will jump to the address specified by the IRQ vector.

So you can't "just" give it a ÷128 prescaler unless you can guarantee that you stay in the IRQ handler for 64 cycles. You can make an invisible ack, such as detecting IRQ vector or the instructions in the IRQ handler, or you can shorten the amount of time that /IRQ is asserted.
I see, that is the idea, if there is some kind of pull up resistor or any other method that is slow enough pulling /IRQ high for the CPU to see the pending IRQ even after the longest instruction, that could work for me. As long as the circuit itself stops asserting on its own both slow and fast enough I'd be happy with that.
lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

Re: Designing your discrete logic mapper

Post by lidnariq »

za909 wrote: Sun Oct 16, 2022 4:31 am Right, I was thinking of the original UxROM boards. I basically need the logic to say if (cpu_R/W & (cpu_A15 & cpu_A14 )) | (latch_O0 & latch_O1 & latch_O2 & latch_O3 & latch_O4 & latch_O5 & latch_O6 & latch_O7) if I'm not mistaken?
In the same way that UNROM looks like this: https://www.nesdev.org/wiki/UxROM#Hardware with one 4-bit register and one chip containing four OR gates, to extend it beyond there you need a total of two chips with four OR gates each for a total of eight OR gates.
I see, that is the idea, if there is some kind of pull up resistor or any other method that is slow enough pulling /IRQ high for the CPU to see the pending IRQ even after the longest instruction, that could work for me. As long as the circuit itself stops asserting on its own both slow and fast enough I'd be happy with that.
There's no great way to do this in analog. You can use a 555, but its timing won't be particularly stable - certainly not enough if you want it to be in tune with the NES-native sound channels.

You can do stupid tricks with making a timer out of something that can be pre-loaded, for example using two 74'161s with a period of 128+(8 or 9) by setting two 74'161s to reload themselves with (256-128-8) and using the msbit out as the IRQ.

Any kind of automatic ack without detecting the 6502 cooperating (e.g. detecting fetching the IRQ vector or the write to $4011) is committing to a certain amount of fragility, which may work or may be a problem - it depends.
Post Reply