INES Mapper 096: Difference between revisions

From NESdev Wiki
Jump to navigationJump to search
m (refile, add cat:nescartdb)
No edit summary
 
(13 intermediate revisions by 6 users not shown)
Line 1: Line 1:
[[Category:iNES Mappers|096]][[Category:Discrete logic mappers|096]][[Category:in NesCartDB|096]]
{{DEFAULTSORT:096}}[[Category:iNES Mappers]][[Category:Discrete logic mappers]][[Category:in NesCartDB]][[Category:Mappers with CHR RAM]]
  Here are Disch's original notes:
[[iNES Mapper 096]] was used with the two games that use the [[Oeka Kids tablet]]. It is specifically designed to turn the PPU into an all-points-addressable 2bpp bitmap without needing timed code, a scanline counter, or [[APU DMC#Usage of DMC for syncing to video|audio channel abuse]].
  ========================
 
  =  Mapper 096         =
Games:
  ========================
* ''Oeka Kids: Anpanman no Hiragana Daisuki''
 
* ''Oeka Kids: Anpanman to Oekaki Shiyou!!''
 
 
  Example Games:
== Overview ==
  --------------------------
* PRG ROM size: 128 KiB
  Oeka Kids - Anpanman no Hiragana Daisuki
* PRG ROM bank size: 32 KiB
  Oeka Kids - Anpanman to Oekaki Shiyou!!
* PRG RAM: No
 
* CHR capacity: 32 KiB RAM
 
* CHR bank size: 4 KiB inner / 16 KiB outer
  Notes:
* Nametable [[mirroring]]: Hardwired Vertical mirroring
  ---------------------------
* Subject to [[bus conflict]]s: partly
  These games use the [[Oeka Kids tablet]] -- so you'll need to add support for that if you really want to test
 
  these.
== Banks ==
 
* CPU $8000-$FFFF: 32 KiB switchable PRG ROM bank
  These games use 32k of CHR-RAM, which is swappable in a very unique fashion.  Be sure to read the CHR Setup
* PPU $0000-$0FFF: 4 KiB switchable CHR RAM bank
  section in detail.
* PPU $1000-$1FFF: 4 KiB semi-fixed CHR RAM bank (banks 3 or 7 only)
 
 
 
== Registers ==
  Registers:
=== Outer Bank Control (CPU $8000-$FFFF), bus conflicts ===
  ---------------------------
7  bit  0
  I'm unsure whether or not this mapper suffers from bus conflicts.  Use caution!
xxxx xCPP
 
      |||
 
      |++- Select 32KiB PRG bank
    $8000-FFFF: [.... .CPP]
      +--- Select 16KiB outer CHR bank
      C = CHR Block select (see CHR Setup)
 
      P = PRG Page select (32k @ $8000)
=== Inner Bank Control (PPU $2000-$2FFF) ===
 
No bus conflicts:
 
<pre>
 
13  PPU address  0
  CHR Setup:
DD xxCC xxxx xxxx
  ---------------------------
||   ||
 
||  ++---------- Select 4 KiB inner CHR RAM bank for PPU $0000-$0FFF
  This mapper is tricky!!!
++--------------- Latch CC bits when 'DD' changes from anything else to '10'
 
</pre>
  Firstly, this mapper divides the 32k CHR-RAM into two 16k blocks (above 'C' bit selects which block is used).
Note that this effect does not pay attention to the PPU read or write strobes; it reacts continuously to all changes of the PPU's address bus.
  The selected pages (including the fixed page) are taken from only the currently selected 16k block.
 
 
Sprites fetched from PPU $0000-$0FFF will always come from banks 0 or 4 because the CC bits are clear for the sprite dummy nametable fetches.
        $0000  $0400  $0800  $0C00  $1000  $1400  $1800  $1C00
 
      +-------------------------------+-------------------------------+
== Hardware ==
      |         **See below**        |             { 3 }            |
 
      +-------------------------------+-------------------------------+
The game uses a [[74161]], [[7402]], and [[7474]]. The 74161 is wired exactly the same as in all of Nintendo's discrete logic mappers, complete with bus conflicts.
 
 
 
The 7402 generates the clock signal for the 7474 by calculating <tt>(PPU /A13) NOR (PPU A12)</tt>, which is equivalent to <tt>(PPU A13) AND (PPU /A12)</tt>. On a rising edge of this signal, the 7474 latches the value of <tt>PPU A9</tt> and <tt>PPU A8</tt>, i.e. when the PPU fetches the nametable after having fetched from the pattern tables. Because <tt>PPU /RD</tt> isn't involved and attribute fetches are immediately after nametable fetches, attribute fetches are ignored. Another two NOR gates take these two latched values and produce 4+4F CHR banking.
  But that's the easy part. This mapper does a very, very cool trick which watches the PPU address lines to
 
  effectively "split" the nametable into 4 smaller sections -- thereby assigning a different CHR-RAM page to
Technically, this banking is NOR logic, not OR logic. This difference is invisible to the software, however. (This means that the fixed bank is actually bank 0 or 4, and that reading from $2000 actually selects bank 3 or 7. The outer bank is not inverted: mapping the 3 C bits above to what actually appears on the RAM's address lines provides the order 3,2,1,0,7,6,5,4)
  each section. This allows **every single tile in the NT** to have a unique tile graphic!
 
    
To rephrase: it is the act of changing the PPU address from $0xxx, $1xxx, or $3xxx ''to'' $2xxx that latches A9 and A8. There is no special logic that guarantees attribute fetches don't cause bankswitching, and Y scroll values greater than 240 will choose the same bank as reads from any of the rest of $23xx. It is only because of the PPU's fetch pattern that attribute fetches have no impact.
 
 
==Disch's Notes==
   Subset of Disch's original notes: 
 
   Long story short:
   Long story short:
    
    
Line 73: Line 76:
   appropriate CHR page in.
   appropriate CHR page in.
    
    
     It will only swap CHR when the address falls between $2000-2FFF (or mirrored regions like $6000-6FFF,
     It will only swap CHR when the address falls between $2000-2FFF.  $3xxx will not trigger a swap.
  $A000-AFFF, $E000-EFFF).  $3xxx will not trigger a swap.
 
    When in that range, it checks to make sure the address is not attribute tables ((Addr AND $03FF) < $03C0).
  Note I'm not 100% sure if the mapper really does this or not.  It's very possible that attribute fetches will
  also swap CHR... this would not really disrupt anything other than making the game be more careful about its
  PPU writes.
    
    
     When all that checks out, bits 8 and 9 (Addr AND $0300) select the 4k CHR page to swap in to $0000.
     When all that checks out, bits 8 and 9 (Addr AND $0300) select the 4k CHR page to swap in to $0000.
 
    
    
     Note that the mapper does not distinguish between PPU driven line changes and game driven line changes.
     Note that the mapper does not distinguish between PPU driven line changes and game driven line changes.
   This means that games can manually swap the CHR page by doing specific writes to $2006:
   This means that games can manually swap the CHR page by doing specific writes to $2006:
 
    
    
   LDA #$20
   LDA #$20
Line 98: Line 93:
     And in fact, games would HAVE to do that to select CHR, since that's the only way to fill CHR RAM with the
     And in fact, games would HAVE to do that to select CHR, since that's the only way to fill CHR RAM with the
   desired data.  So make sure your emu supports this.
   desired data.  So make sure your emu supports this.
== See Also ==
* NES Mapper list by Disch [http://www.romhacking.net/documents/362/]

Latest revision as of 16:39, 24 April 2020

iNES Mapper 096 was used with the two games that use the Oeka Kids tablet. It is specifically designed to turn the PPU into an all-points-addressable 2bpp bitmap without needing timed code, a scanline counter, or audio channel abuse.

Games:

  • Oeka Kids: Anpanman no Hiragana Daisuki
  • Oeka Kids: Anpanman to Oekaki Shiyou!!

Overview

  • PRG ROM size: 128 KiB
  • PRG ROM bank size: 32 KiB
  • PRG RAM: No
  • CHR capacity: 32 KiB RAM
  • CHR bank size: 4 KiB inner / 16 KiB outer
  • Nametable mirroring: Hardwired Vertical mirroring
  • Subject to bus conflicts: partly

Banks

  • CPU $8000-$FFFF: 32 KiB switchable PRG ROM bank
  • PPU $0000-$0FFF: 4 KiB switchable CHR RAM bank
  • PPU $1000-$1FFF: 4 KiB semi-fixed CHR RAM bank (banks 3 or 7 only)

Registers

Outer Bank Control (CPU $8000-$FFFF), bus conflicts

7  bit  0
xxxx xCPP
      |||
      |++- Select 32KiB PRG bank
      +--- Select 16KiB outer CHR bank

Inner Bank Control (PPU $2000-$2FFF)

No bus conflicts:

13  PPU address  0
 DD xxCC xxxx xxxx
 ||   ||
 ||   ++---------- Select 4 KiB inner CHR RAM bank for PPU $0000-$0FFF
 ++--------------- Latch CC bits when 'DD' changes from anything else to '10'

Note that this effect does not pay attention to the PPU read or write strobes; it reacts continuously to all changes of the PPU's address bus.

Sprites fetched from PPU $0000-$0FFF will always come from banks 0 or 4 because the CC bits are clear for the sprite dummy nametable fetches.

Hardware

The game uses a 74161, 7402, and 7474. The 74161 is wired exactly the same as in all of Nintendo's discrete logic mappers, complete with bus conflicts.

The 7402 generates the clock signal for the 7474 by calculating (PPU /A13) NOR (PPU A12), which is equivalent to (PPU A13) AND (PPU /A12). On a rising edge of this signal, the 7474 latches the value of PPU A9 and PPU A8, i.e. when the PPU fetches the nametable after having fetched from the pattern tables. Because PPU /RD isn't involved and attribute fetches are immediately after nametable fetches, attribute fetches are ignored. Another two NOR gates take these two latched values and produce 4+4F CHR banking.

Technically, this banking is NOR logic, not OR logic. This difference is invisible to the software, however. (This means that the fixed bank is actually bank 0 or 4, and that reading from $2000 actually selects bank 3 or 7. The outer bank is not inverted: mapping the 3 C bits above to what actually appears on the RAM's address lines provides the order 3,2,1,0,7,6,5,4)

To rephrase: it is the act of changing the PPU address from $0xxx, $1xxx, or $3xxx to $2xxx that latches A9 and A8. There is no special logic that guarantees attribute fetches don't cause bankswitching, and Y scroll values greater than 240 will choose the same bank as reads from any of the rest of $23xx. It is only because of the PPU's fetch pattern that attribute fetches have no impact.

Disch's Notes

 Subset of Disch's original notes:  
 Long story short:
 
   A nametable spans from $2000-$23BF   ($23C0-$23FF are the attribute table).
   The mapper breaks the NT up like so:
 
      $2000-20FF = use CHR page 0
      $2100-21FF = use CHR page 1
      $2200-22FF = use CHR page 2
      $2300-23BF = use CHR page 3
 
   the other nametables at $2400, $2800, $2C00 are broken up in the same fashion.
 
 
 
 
 Long story long:
 
   PPU Address lines are modified as the PPU fetches tiles, and also when the game manually changes the PPU
 address (via the second write to $2006 --- or by the increment after read/writing $2007).  The mapper
 monitors every change to the PPU Address lines, and when it lies within a certain range, it swaps the
 appropriate CHR page in.
 
   It will only swap CHR when the address falls between $2000-2FFF.  $3xxx will not trigger a swap.
 
   When all that checks out, bits 8 and 9 (Addr AND $0300) select the 4k CHR page to swap in to $0000.
 
   Note that the mapper does not distinguish between PPU driven line changes and game driven line changes.
 This means that games can manually swap the CHR page by doing specific writes to $2006:
 
 LDA #$20
 STA $2006
 STA $2006   ; Addr set to $20xx -- CHR page 0 selected
 
 LDA #$21
 STA $2006
 STA $2006   ; Addr set to $21xx -- CHR page 1 selected
 
   And in fact, games would HAVE to do that to select CHR, since that's the only way to fill CHR RAM with the
 desired data.  So make sure your emu supports this.

See Also

  • NES Mapper list by Disch [1]