It is currently Sun Dec 17, 2017 2:45 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 24 posts ]  Go to page Previous  1, 2
Author Message
 Post subject:
PostPosted: Thu Dec 22, 2011 11:35 pm 
Offline
User avatar

Joined: Thu Sep 23, 2010 7:28 pm
Posts: 232
i'm now modifying the nametable and scroll registers on writes to $2006, which fixes some bugs in games but seems to break things in other games that worked properly before, like the cutscenes in ninja gaiden.

Image

they look correct if i dont change the scroll registers on $2006 writes. am i parsing the values correctly here?

Code:
void writePPUregs(uint16_t addr, uint8_t value) {
     PPU->regs[addr & 7] = value;
    lastwritten = value;
     switch (addr) {
       case 0x2000:
            if (value&128) PPU->nmivblank = 1; else PPU->nmivblank = 0;
            if (value&32) PPU->sprsize = 16; else PPU->sprsize = 8;
            if (value&16) PPU->bgtable = 0x1000; else PPU->bgtable = 0x0000;
            if (value&8) PPU->sprtable = 0x1000; else PPU->sprtable = 0x0000;
            if (value&4) PPU->addrinc = 32; else PPU->addrinc = 1;
            PPU->nametable = value&3;
            break;
       case 0x2001:
            if (value&16) PPU->sprvisible = 1; else PPU->sprvisible = 0;
            if (value&8) PPU->bgvisible = 1; else PPU->bgvisible = 0;
            if (value&4) PPU->sprclip = 0; else PPU->sprclip = 1;
            if (value&2) PPU->bgclip = 0; else PPU->bgclip = 1;
            break;
       case 0x2003:
            OAM->addr = value;
            break;
       case 0x2004:
            OAM->RAM[OAM->addr++] = value;
            break;
       case 0x2005:
            if (PPU->addrlatch == 0) {
              PPU->xscroll = value;
              PPU->addrlatch = 1;
            } else {
              PPU->yscroll = value;
              PPU->addrlatch = 0;
            }
         break;
       case 0x2006:
            if (PPU->addrlatch == 0) {
              PPU->r2006[1] = value;
           PPU->nametable = ((value >> 2) & 3);
           PPU->xscroll = (PPU->xscroll & 0x3F) | (((uint16_t)value & 3) << 6);
           PPU->xscroll = (PPU->xscroll & 0xF8) | (((uint16_t)value >> 4) & 7);
              PPU->addrlatch = 1;
            } else {
              PPU->r2006[0] = value;
           PPU->yscroll = (PPU->yscroll & 7) | ((uint16_t)value << 3);
           PPU->xscroll = (PPU->xscroll & 0xC7) | (((uint16_t)value >> 2) & 0x38);
           PPU->addr = ((uint16_t)PPU->r2006[1] << 8) | (uint16_t)PPU->r2006[0];
              PPU->addrlatch = 0;
            }
         break;
       case 0x2007:
            writePPU(PPU->addr, value);
            PPU->addr = (PPU->addr + PPU->addrinc) & 0x3FFF;
            break;
     }
}


Top
 Profile  
 
 Post subject:
PostPosted: Fri Dec 23, 2011 5:58 am 
Offline
Formerly Fx3
User avatar

Joined: Fri Nov 12, 2004 4:59 pm
Posts: 3076
Location: Brazil
Aren't you using loopy's logic?

_________________
Zepper
RockNES developer


Top
 Profile  
 
 Post subject:
PostPosted: Sat Dec 24, 2011 5:58 pm 
Offline

Joined: Thu Apr 14, 2011 9:27 pm
Posts: 85
I'm not entirely sure how to explain what you're doing wrong here (since you didn't post your rendering code as well), but the most obvious thing is that you are still storing a separate x scroll and y scroll values as well as the PPU memory address. Writes to $2005 and $2006 should both change different bits of the same counter, as described in loopy's famous documentation.


Last edited by Grapeshot on Sat Dec 24, 2011 6:09 pm, edited 1 time in total.

Top
 Profile  
 
 Post subject:
PostPosted: Sat Dec 24, 2011 6:05 pm 
Offline
User avatar

Joined: Thu Sep 23, 2010 7:28 pm
Posts: 232
yeah, thanks guys. i had read it before, quite a few times but it never totally made sense to me the way explained it. in the last day or so, it finally clicked in my head so i'm working on changing my code right now actually.

i felt a bit dumb for asking about it even though loopy's doc is there.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Dec 24, 2011 7:17 pm 
Offline
User avatar

Joined: Fri Nov 19, 2004 7:35 pm
Posts: 3969
Loopy's document is also formatted badly...

Code:
           Fine Y
              Nametable Y,X
                Coarse Y
                     Coarse X
         
          .yyyNNYYYYYXXXXX
2000 write:
        t:....xx..........=d:......xx
2005 first write:
        t:...........xxxxx=d:xxxxx...
        x=d:.....xxx
2005 second write:
        t:......xxxxx.....=d:xxxxx...
        t:.xxx............=d:.....xxx
2006 first write:
        t:..xxxxxx........=d:..xxxxxx
        t:xx..............=0
2006 second write:
        t:........xxxxxxxx=d:xxxxxxxx
        v=t
scanline start (if background and sprites are enabled):  (ppu clock 257)
        v:.....x.....xxxxx=t:.....x.....xxxxx
frame start (prerender line, ppu clock 304) (if background and sprites are enabled):
        v=t

Others:
PPU clock 251, if screen is on: Y scroll bits of V are incremented.  If it wraps from 239 to 240, toggle the Y nametable, and set Y to 0.  If it wraps from 255 to 0, DO NOT toggle the Y nametable bit.



Top
 Profile  
 
 Post subject:
PostPosted: Sat Dec 24, 2011 11:00 pm 
Offline
User avatar

Joined: Thu Sep 23, 2010 7:28 pm
Posts: 232
HOLY SHIT i never thought i'd see the day. MoarNES now runs battletoads perfectly now that i got the loopy scrolling stuff figured out correctly.

Image

still can't believe my eyes. thanks for the help, everybody. i will upload a new version of this probably tomorrow if anybody wants to give it a try again. :twisted:

i've only tried the first level of battletoads, so maybe something screws up later. i've only ever gotten to level 3 before, i suck at battletoads. :x

EDIT: just tried levels 2 and 3, they both work perfectly too.

i think battletoads and ninja gaiden 1 are the hardest video games ever created. i can get to the final jaquio battle in ninja gaiden, but i owned the cart when i was a kid. i never played battletoads before about a year ago.

also, i still don't have APU sweeps working. i can't seem to understand quite how that messes with the period values. once i figure that out, and add movie and AVI recording support, i might just have a respectable emulator here.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Dec 24, 2011 11:31 pm 
Offline
User avatar

Joined: Thu Sep 23, 2010 7:28 pm
Posts: 232
oh, and this wasn't related to the scrolling thing but i've also fixed the PPU-CPU timing so it's accurate enough to do the marble madness mid-scanline nametable switching on the textboxes. it looks absolutely flawless. i'm now accurate down to the pixel. :)

Image

i've only used a small handful of NES emus that actually showed that part of marble madness correctly.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Dec 25, 2011 1:29 am 
Offline
User avatar

Joined: Fri Nov 19, 2004 7:35 pm
Posts: 3969
If you need help with the APU sweeps, read the code to Blargg's NES APU. It's very easy to follow.

Most relevant portion:
Code:
void Nes_Square::clock_sweep( int negative_adjust )
{
   int sweep = regs [1];
   
   if ( --sweep_delay < 0 )
   {
      reg_written [1] = true;
      
      int period = this->period();
      int shift = sweep & shift_mask;
      if ( shift && (sweep & 0x80) && period >= 8 )
      {
         int offset = period >> shift;
         
         if ( sweep & negate_flag )
            offset = negative_adjust - offset;
         
         if ( period + offset < 0x800 )
         {
            period += offset;
            // rewrite period
            regs [2] = period & 0xff;
            regs [3] = (regs [3] & ~7) | ((period >> 8) & 7);
         }
      }
   }
   
   if ( reg_written [1] ) {
      reg_written [1] = false;
      sweep_delay = (sweep >> 4) & 7;
   }
}


Sweep is clocked about twice each frame.

BTW, the "negative_adjust" parameter is -1 for Square #1, and 0 for Square #2.

Note that part of the sweep feature is always running no matter what, namely the part which silences the channel when adding the shifted period would make the period become out of range.

_________________
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!


Top
 Profile  
 
 Post subject:
PostPosted: Fri Dec 30, 2011 2:18 pm 
Offline

Joined: Wed Mar 31, 2010 12:40 pm
Posts: 207
- MMC3 IRQ is broken.
- SMB1 title screen is broken, suggesting improper $2007 read buffering behavior.
- Batman refuses to boot
- Bee 52 crashes the emulator

Those are the only 4 things I tested (MMC3 with Mega Man 3 boss select screen)


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 24 posts ]  Go to page Previous  1, 2

All times are UTC - 7 hours


Who is online

Users browsing this forum: krzysiobal, lidnariq, tepples and 4 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