It is currently Wed May 22, 2019 3:37 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 6 posts ] 
Author Message
 Post subject: Mapper 340
PostPosted: Sat Apr 06, 2019 11:57 am 
Offline
User avatar

Joined: Mon Dec 29, 2014 1:46 pm
Posts: 911
Location: New York, NY
Mapper 340 appears to be a very simple multi-cart mapper. The implementation in NintendulatorNRS matches the description in the wiki. And I attempted a similar implementation in my emulator. However, I found several of the games do not function in my implementation. Contra, Life Force, Rushn Attack and Galaxian all work fine. But the remainder has garbled graphics (wrong tiles). Some of those are playable and some of them crash on start up (KIL instructions encountered).

I checked over my implementation several times and I can't locate a bug. Interestingly, I noticed that the initial RAM state affects which games work. What does NintendulatorNRS set RAM to on startup? Maybe it's expecting some initial value set.


Top
 Profile  
 
 Post subject: Re: Mapper 340
PostPosted: Sat Apr 06, 2019 12:09 pm 
Offline

Joined: Thu May 19, 2005 11:30 am
Posts: 923
The initial RAM value can be chosen from the menu: CPU->RAM Initialization. That being said, that does not seem to make any difference for me. Maybe you can post your implementation, so I can have a look at it.


Top
 Profile  
 
 Post subject: Re: Mapper 340
PostPosted: Sat Apr 06, 2019 12:24 pm 
Offline
User avatar

Joined: Mon Dec 29, 2014 1:46 pm
Posts: 911
Location: New York, NY
Here's my implementation:

Code:
public class BMCK3036 extends Mapper {
 
  public BMCK3036(final CartFile cartFile) {
    super(cartFile, 4, 1);
  }
 
  @Override public void writeRegister(final int address, int value) {
    final int outer = address & 0x0018;
    value &= 7;
    setPrgBank(2, outer | value);
    setPrgBank(3, outer | (getBitBool(address, 5) ? value : 7));
    setNametableMirroring(((address & 0x25) == 0x25) ? HORIZONTAL : VERTICAL);
  }
}


That line in the constructor partitions PRG address space into 4 segments. And PRG banks 2 and 3 refer to the address ranges $8000--$BFFF and $C000-$FFFF, respectively. writeRegister() is called when address >= $8000.

I noticed that in the NintendulatorNRS implementation that the address and data values are not masked:

Code:
void   Sync (void) {
   if (Latch::Addr.b0 &0x20) {
      EMU->SetPRG_ROM16(0x8, Latch::Addr.b0 | Latch::Data);
      EMU->SetPRG_ROM16(0xC, Latch::Addr.b0 | Latch::Data);
   } else {
      EMU->SetPRG_ROM16(0x8, Latch::Addr.b0 | Latch::Data);
      EMU->SetPRG_ROM16(0xC, Latch::Addr.b0 | 7);
   }
   EMU->SetCHR_RAM8(0, 0);
   if ((Latch::Addr.b0 &0x25) ==0x25)
      EMU->Mirror_H();
   else
      EMU->Mirror_V();
}


Logging indicates that the data value is not necessarily confined to <= 7. Though that my be a problem on my end if my emulator is executing code that it shouldn't be.

I also noticed that the cart reads from values in the range $4000--$400F. It never writes into that range. This might suggest that the cart has DIP switches. Or it could just be some other strange issue on my end.


Top
 Profile  
 
 Post subject: Re: Mapper 340
PostPosted: Sat Apr 06, 2019 12:33 pm 
Offline

Joined: Thu May 19, 2005 11:30 am
Posts: 923
The cart sets the bank from which to copy CHR data from PRG-ROM to CHR-RAM using STA $9000,X with A=$80. That means that the inner bank is set via the address as well, which is why you must use unmasked bank numbers, only masking bits that would exceed the total PRG-ROM size.

The code does not read directly from $4000-$400F. The 6502 however performs a dummy read during the menu code's "STA $4000.X" initialization, maybe that is what you are seeing.

Edit: After checking the "Super Bomberman" variants on the second menu page, it turns out that the data latch should not be applied at all in NROM mode.
Code:
void   Sync (void) {
   if (Latch::Addr.b0 &0x20) {
      EMU->SetPRG_ROM16(0x8, Latch::Addr.b0);
      EMU->SetPRG_ROM16(0xC, Latch::Addr.b0);
   } else {
      EMU->SetPRG_ROM16(0x8, Latch::Addr.b0 | Latch::Data);
      EMU->SetPRG_ROM16(0xC, Latch::Addr.b0 | 7);
   }
   EMU->SetCHR_RAM8(0, 0);
   if ((Latch::Addr.b0 &0x25) ==0x25)
      EMU->Mirror_H();
   else
      EMU->Mirror_V();
}


Top
 Profile  
 
 Post subject: Re: Mapper 340
PostPosted: Sat Apr 06, 2019 12:52 pm 
Offline
User avatar

Joined: Mon Dec 29, 2014 1:46 pm
Posts: 911
Location: New York, NY
Yes! That's the secret! It worked for me:

Code:
  @Override public void writeRegister(final int address, int value) {
    final int outer = address & 0x00FF;
    if (getBitBool(address, 5)) {
      setPrgBank(2, outer);
      setPrgBank(3, outer);
    } else {
      setPrgBank(2, outer | value);
      setPrgBank(3, outer | 7);
    }
    setNametableMirroring(((address & 0x25) == 0x25) ? HORIZONTAL : VERTICAL);
  }


Edit: You might want to update the wiki.


Top
 Profile  
 
 Post subject: Re: Mapper 340
PostPosted: Sat Apr 06, 2019 1:09 pm 
Offline

Joined: Thu May 19, 2005 11:30 am
Posts: 923
Done.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 6 posts ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 10 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group