It is currently Wed Nov 22, 2017 8:04 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 2 posts ] 
Author Message
PostPosted: Fri Jan 25, 2013 7:17 pm 
Offline

Joined: Tue Mar 08, 2011 9:45 am
Posts: 64
OK, I am trying to get MMC5 implemented correctly and I honestly don't see where I am going wrong.

Here's the quirk rundown. I have my mapper's able to hook VRAM reads/writes so they can do what they like there. Here's the relevant parts (snipped for brevity):

Code:
void Mapper5::write_5(uint16_t address, uint8_t value) {

   switch(address) {
   // ...
   case 0x5101:
      chr_mode_ = value & 0x03;
      break;
   case 0x5120:
   case 0x5121:
   case 0x5122:
   case 0x5123:
   case 0x5124:
   case 0x5125:
   case 0x5126:
   case 0x5127:
      sp_chr_banks_[address & 0x07] = value;
      last_chr_write_ = CHR_BANK_A;
      break;
   case 0x5128:
   case 0x5129:
   case 0x512a:
   case 0x512b:
      bg_chr_banks_[(address & 0x07) ^ 0x00] = value;
      bg_chr_banks_[(address & 0x07) ^ 0x04] = value; // mirrored here so the implementation later is simpler
      last_chr_write_ = CHR_BANK_B;
      break;
   // ...
   }
}


And now for the VRAM/VROM read hook:

Code:
uint8_t Mapper5::read_vram(uint16_t address) {

   switch((address >> 10) & 0x0f) {
   // ...
   case 0x00:
   case 0x01:
   case 0x02:
   case 0x03:
   case 0x04:
   case 0x05:
   case 0x06:
   case 0x07:
      // CHR-ROM ($0000 - $1fff)
      const uint8_t *chr_selector;
      
      if(sprite_size_ == 16) {
         // sprite fetches seem to bebe between fetch #130 and #162
         // I've tried basing this on a few factors, more or less same results
         if(fetch_count_ >= 130 && fetch_count_ < 162) {
            chr_selector = sp_chr_banks_;
         } else {
            chr_selector = bg_chr_banks_;
         }
      } else {
         if(last_chr_write_ == CHR_BANK_A) {
            chr_selector = sp_chr_banks_;
         } else {
            chr_selector = bg_chr_banks_;
         }
      }
      
      const uint8_t *chr_rom_banks[8];
      const uint8_t *const chr_rom  = nes::cart.chr();
      const uint32_t chr_mask       = nes::cart.chr_mask();
      
      switch(chr_mode_ & 0x03) {
      case 0x00: // 8K mode
         chr_rom_banks[0] = chr_rom + ((chr_selector[7] * 0x2000) & chr_mask) + 0x0000; // $0000
         chr_rom_banks[1] = chr_rom + ((chr_selector[7] * 0x2000) & chr_mask) + 0x0400; // $0400
         chr_rom_banks[2] = chr_rom + ((chr_selector[7] * 0x2000) & chr_mask) + 0x0800; // $0800
         chr_rom_banks[3] = chr_rom + ((chr_selector[7] * 0x2000) & chr_mask) + 0x0c00; // $0c00
         chr_rom_banks[4] = chr_rom + ((chr_selector[7] * 0x2000) & chr_mask) + 0x1000; // $1000
         chr_rom_banks[5] = chr_rom + ((chr_selector[7] * 0x2000) & chr_mask) + 0x1400; // $1400
         chr_rom_banks[6] = chr_rom + ((chr_selector[7] * 0x2000) & chr_mask) + 0x1800; // $1800
         chr_rom_banks[7] = chr_rom + ((chr_selector[7] * 0x2000) & chr_mask) + 0x1c00; // $1c00
         break;
      case 0x01: // 4K mode
         chr_rom_banks[0] = chr_rom + ((chr_selector[3] * 0x1000) & chr_mask) + 0x0000; // $0000
         chr_rom_banks[1] = chr_rom + ((chr_selector[3] * 0x1000) & chr_mask) + 0x0400; // $0400
         chr_rom_banks[2] = chr_rom + ((chr_selector[3] * 0x1000) & chr_mask) + 0x0800; // $0800
         chr_rom_banks[3] = chr_rom + ((chr_selector[3] * 0x1000) & chr_mask) + 0x0c00; // $0c00
         chr_rom_banks[4] = chr_rom + ((chr_selector[7] * 0x1000) & chr_mask) + 0x0000; // $1000
         chr_rom_banks[5] = chr_rom + ((chr_selector[7] * 0x1000) & chr_mask) + 0x0400; // $1400
         chr_rom_banks[6] = chr_rom + ((chr_selector[7] * 0x1000) & chr_mask) + 0x0800; // $1800
         chr_rom_banks[7] = chr_rom + ((chr_selector[7] * 0x1000) & chr_mask) + 0x0c00; // $1c00
         break;
      case 0x02: // 2K mode
         chr_rom_banks[0] = chr_rom + ((chr_selector[1] * 0x0800) & chr_mask) + 0x0000; // $0000
         chr_rom_banks[1] = chr_rom + ((chr_selector[1] * 0x0800) & chr_mask) + 0x0400; // $0400
         chr_rom_banks[2] = chr_rom + ((chr_selector[3] * 0x0800) & chr_mask) + 0x0000; // $0800
         chr_rom_banks[3] = chr_rom + ((chr_selector[3] * 0x0800) & chr_mask) + 0x0400; // $0c00
         chr_rom_banks[4] = chr_rom + ((chr_selector[5] * 0x0800) & chr_mask) + 0x0000; // $1000
         chr_rom_banks[5] = chr_rom + ((chr_selector[5] * 0x0800) & chr_mask) + 0x0400; // $1400
         chr_rom_banks[6] = chr_rom + ((chr_selector[7] * 0x0800) & chr_mask) + 0x0000; // $1800
         chr_rom_banks[7] = chr_rom + ((chr_selector[7] * 0x0800) & chr_mask) + 0x0400; // $1c00
         break;
      case 0x03: // 1K mode
         chr_rom_banks[0] = chr_rom + ((chr_selector[0] * 0x0400) & chr_mask) + 0x0000; // $0000
         chr_rom_banks[1] = chr_rom + ((chr_selector[1] * 0x0400) & chr_mask) + 0x0000; // $0400
         chr_rom_banks[2] = chr_rom + ((chr_selector[2] * 0x0400) & chr_mask) + 0x0000; // $0800
         chr_rom_banks[3] = chr_rom + ((chr_selector[3] * 0x0400) & chr_mask) + 0x0000; // $0c00
         chr_rom_banks[4] = chr_rom + ((chr_selector[4] * 0x0400) & chr_mask) + 0x0000; // $1000
         chr_rom_banks[5] = chr_rom + ((chr_selector[5] * 0x0400) & chr_mask) + 0x0000; // $1400
         chr_rom_banks[6] = chr_rom + ((chr_selector[6] * 0x0400) & chr_mask) + 0x0000; // $1800
         chr_rom_banks[7] = chr_rom + ((chr_selector[7] * 0x0400) & chr_mask) + 0x0000; // $1c00
         break;
      }

      return chr_rom_banks[(address >> 10) & 0x0f][0x03ff]; // for reads at $0000-$1ffff result is our implementation
   }
   
   // default implementation if not caught above
   return Mapper::read_vram(address);
}


The current result is a mostly white title screen and single color blocks during game play (attributes seem right...).

I am currently counting fetches to determine when rendering sprites/bg. My IRQ is implemented in terms of 3 consecutive identical reads (and seems to fire at the correct point). When the IRQ fires, I reset the "fetch count" to 0. So it should be 0-130 for BG rendering, 130-162 for sprites, and 162+ for next scanline BG.

I have been staring at this for a while now and can't find my mistake.

hopefully it's something obvious someone here can point out.


NOTE: I've chosen for now to implement CHR set "B" like the "proposed revision" in Disch's Doc. (where $512B is a full 8K in 8K mode).

Thanks,
proxy


Top
 Profile  
 
PostPosted: Sat Jan 26, 2013 2:17 pm 
Offline

Joined: Tue Mar 08, 2011 9:45 am
Posts: 64
OK, I missed something **really** obvious and feel kinda dumb missing it :-P.

Code:
return chr_rom_banks[(address >> 10) & 0x0f][0x03ff];


should **obviously** be:

Code:
return chr_rom_banks[(address >> 10) & 0x0f][address & 0x03ff];


The graphics look pretty much perfect now.


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

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 6 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