It is currently Wed Dec 13, 2017 8:09 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 70 posts ]  Go to page Previous  1, 2, 3, 4, 5  Next
Author Message
PostPosted: Sun Dec 20, 2015 1:34 pm 
Offline

Joined: Sun Apr 13, 2008 11:12 am
Posts: 6513
Location: Seattle
The 2A03 can't have an idle cycle. M2 always goes high, because it's derived from the master clock, and ignores whatever internal processing (including /RDY) is going on... every cycle is always a read or write cycle.


Top
 Profile  
 
PostPosted: Sun Dec 20, 2015 2:40 pm 
Offline
User avatar

Joined: Mon Dec 29, 2014 1:46 pm
Posts: 750
Location: New York, NY
lidnariq wrote:
The 2A03 can't have an idle cycle. M2 always goes high, because it's derived from the master clock, and ignores whatever internal processing (including /RDY) is going on... every cycle is always a read or write cycle.


Do you have any idea why there is an additional read if the transfer starts on an odd CPU cycle? Is there some sort of latch that toggles every CPU cycle, determining if there is an extra read?

Also, when I wrote that pseudo-code above, I wasn't sure what address it would reading. I assumed it was like the start of an instruction fetch, reading from PC.


Top
 Profile  
 
PostPosted: Sun Dec 20, 2015 3:53 pm 
Offline

Joined: Sun Apr 13, 2008 11:12 am
Posts: 6513
Location: Seattle
The DMA units are kinda part of the sound hardware in the 2A03, and everything (except the triangle wave) in the sound unit runs at CPU clock ÷2, the DMA units reading on even cycles and writing on odd cycles.

So... "Yes".


Top
 Profile  
 
PostPosted: Sun Dec 20, 2015 4:22 pm 
Offline
User avatar

Joined: Mon Dec 29, 2014 1:46 pm
Posts: 750
Location: New York, NY
lidnariq wrote:
The DMA units are kinda part of the sound hardware in the 2A03, and everything (except the triangle wave) in the sound unit runs at CPU clock ÷2, the DMA units reading on even cycles and writing on odd cycles.

So... "Yes".


Cool.

What about the address read during the idle cycles? Is it the PC address like I speculated above?


Top
 Profile  
 
PostPosted: Sun Dec 20, 2015 7:55 pm 
Offline
Formerly Fx3
User avatar

Joined: Fri Nov 12, 2004 4:59 pm
Posts: 3076
Location: Brazil
Disch wrote:
Zepper wrote:
That code (the for() loop) shouldn't be taken as "correct".


Why not? It looks correct to me.


Easier to fire up against my code? Go ahead.
Code:
//Sprite DMA
//----------
void cpu_spritedma(C_DWORD addr, C_BYTE flag)
{
   register DWORD offset = addr << 8;
   register const DWORD offset_lim = offset + 0xF8;
   register BYTE value;
   /* 3 if it lands on a CPU write,
      2 if it lands on the $4014 write or during OAM DMA,
      1 if on the next-to-next-to-last DMA cycle,
      3 if on the last DMA cycle.
     DMA transfer takes 513 cycles on even cycles
     and 514 on odd cycles. */
   // 513+1 cycles
   if(flag)
   {
      _readvalue(cpu->PC);
   }

   do {
      dmc_runfor(2);
      value = _readvalue(offset);
      _writevalue(0x2004,value);
      dmc_runfor(2);
      value = _readvalue(offset|1);
      _writevalue(0x2004,value);
      dmc_runfor(2);
      value = _readvalue(offset|2);
      _writevalue(0x2004,value);
      dmc_runfor(2);
      value = _readvalue(offset|3);
      _writevalue(0x2004,value);
      dmc_runfor(2);
      value = _readvalue(offset|4);
      _writevalue(0x2004,value);
      dmc_runfor(2);
      value = _readvalue(offset|5);
      _writevalue(0x2004,value);
      dmc_runfor(2);
      value = _readvalue(offset|6);
      _writevalue(0x2004,value);
      dmc_runfor(2);
      value = _readvalue(offset|7);
      _writevalue(0x2004,value);
      offset += 8;
   } while(offset < offset_lim);
   
   dmc_runfor(2);
   value = _readvalue(offset++);
   _writevalue(0x2004,value);

   dmc_runfor(2);
   value = _readvalue(offset++);
   _writevalue(0x2004,value);

   dmc_runfor(2);
   value = _readvalue(offset++);
   _writevalue(0x2004,value);

   dmc_runfor(2);
   value = _readvalue(offset++);
   _writevalue(0x2004,value);

   dmc_runfor(2);
   value = _readvalue(offset++);
   _writevalue(0x2004,value);

   dmc_runfor(2);
   value = _readvalue(offset++);
   _writevalue(0x2004,value);

   dmc_runfor(2);
   value = _readvalue(offset++);
   _writevalue(0x2004,value);

   dmc_runfor(1);
   value = _readvalue(offset);
   _writevalue(0x2004,value);

   dmc_runfor(3);
   _readvalue(cpu->PC);
}

I'm working in this emulator for 17 years. A few things are missing from my mind, but I confirm there are NO hacks. It passes in all test ROMs (now that someone says such stuff is obsolete).


Top
 Profile  
 
PostPosted: Sun Dec 20, 2015 8:20 pm 
Offline
User avatar

Joined: Wed Nov 10, 2004 6:47 pm
Posts: 1845
lidnariq wrote:
The 2A03 can't have an idle cycle. M2 always goes high, because it's derived from the master clock, and ignores whatever internal processing (including /RDY) is going on... every cycle is always a read or write cycle.



The wiki should be updated then, as 'idle' is clearly the wrong term there and is misleading:

http://wiki.nesdev.com/w/index.php/PPU_registers#OAMDMA
The wiki wrote:
The CPU is suspended during the transfer, which will take 513 or 514 cycles after the $4014 write tick. (1 idle cycle, +1 if on an odd CPU cycle, then 256 alternating read/write cycles.)


zeroone wrote:
What about the address read during the idle cycles? Is it the PC address like I speculated above?


This was my next question -- though I doubt it's the PC, as there'd be no reason to put the PC on the bus for the DMA. My completely blind guess would be that it's reading from $4014, since that'd be what is sitting on the address lines when DMA is triggered.

Quote:
Easier to fire up against my code? Go ahead.


I'm sure your code is fine and works great -- but why is zeroone's code wrong? I don't see any problems with it.

The only real difference I see is that you're embedding the DMC DMA logic inside the OAM DMA logic -- but I would probably want to keep those separate... which is what I assume zeroone is doing.


Top
 Profile  
 
PostPosted: Sun Dec 20, 2015 8:38 pm 
Offline
User avatar

Joined: Mon Dec 29, 2014 1:46 pm
Posts: 750
Location: New York, NY
Zepper also reads from PC for the idle cycles:

Code:
if(flag)
{
   _readvalue(cpu->PC);
}

...

_readvalue(cpu->PC);


Though, it's unclear why one is at the top and the bottom of the function.

@Zepper I reviewed my code a bit. I put the DMC update logic inside the read() function itself. And, I did not unroll any loops like you did, which explains why my code appears more compact.

By the way, in your unrolled loop at the bottom, why are the final calls to dmc_runfor() with parameters 1 and 3 as opposed to both being 2 like the rest of them (see below). Is that a timing hack?

Code:
   dmc_runfor(2);
   value = _readvalue(offset++);
   _writevalue(0x2004,value);

   dmc_runfor(2);
   value = _readvalue(offset++);
   _writevalue(0x2004,value);

   dmc_runfor(1);
   value = _readvalue(offset);
   _writevalue(0x2004,value);

   dmc_runfor(3);
   _readvalue(cpu->PC);


Top
 Profile  
 
PostPosted: Sun Dec 20, 2015 10:09 pm 
Offline
User avatar

Joined: Wed Nov 10, 2004 6:47 pm
Posts: 1845
It's not a hack. DMC DMA takes a different length depending on where they land during the OAM DMA.

Though I thought the last few cycles were 1,2,3 ... not 2,1,3. Lemme find that page.

EDIT: Here's the post:

viewtopic.php?p=62690#p62690

blargg wrote:
DMC DMA adds 4 cycles normally, 3 if it lands on a CPU write, 2 if it lands on the $4014 write or during OAM DMA, 1 if on the next-to-next-to-last DMA cycle, 3 if on the last DMA cycle.


So:

last cycle = 3 cycles
next-to last cycle = 2 cycles
next-to-next-to-last cycle = 1 cycle

so the last 3 DMC runs in Zepper's code should be 1,2,3 -- not 2,1,3

Though the wiki makes no mention of this and just says it's 2 cycles throughout the entirety of OAM DMA. Which is correct?



EDIT 2: I'm still not convinced reading from PC is correct for the dummy cycles. I guess it could be, but $4014 still makes more sense to me.

blargg's post suggests that the OAM DMA process starts on the 4014 write cycle (since that's in the '2 cycle' zone), and if that's true it would mean 4014 would still be on the address bus, and the DMA unit would have no reason to put the PC back on the bus.


So either:

1)
- CPU puts PC on address bus before DMA starts (possibly as part of pipelining for the next instruction)
- DMA cuts in, reads dummy value(s) from PC (since that's what on the bus)
- DMA does it's thing
- DMA restores PC on address bus so that normal CPU execution is uninterrupted
- normal CPU execution resumes with the next opcode read


or

2)
- DMA cuts in while 4014 is still on the bus, before PC is put back on the bus
- dummy values read from whatever is on the bus (which would be 4014)
- DMA does it's thing
- DMA does not need to restore the PC because the PC was never put on the bus in the first place
- normal CPu execution resumes... and NOW the PC is placed on the bus for the next opcode read


or

3)
- something else



I just find scenario 2 much more likely than scenario 1.... but that's a total guess and I have zero evidence to back it up.


Top
 Profile  
 
PostPosted: Mon Dec 21, 2015 6:08 am 
Offline
Formerly Fx3
User avatar

Joined: Fri Nov 12, 2004 4:59 pm
Posts: 3076
Location: Brazil
sprdma_and_dmc_dma_512.nes
Fails with 1,2,3 and passes with 2,1,3.


Attachments:
sprdma_and_dmc_dma_512 001.bmp
sprdma_and_dmc_dma_512 001.bmp [ 720.05 KiB | Viewed 2280 times ]
sprdma_and_dmc_dma_512 000.bmp
sprdma_and_dmc_dma_512 000.bmp [ 720.05 KiB | Viewed 2280 times ]
Top
 Profile  
 
PostPosted: Mon Dec 21, 2015 7:40 am 
Offline
User avatar

Joined: Mon Dec 29, 2014 1:46 pm
Posts: 750
Location: New York, NY
Interesting. Nintendulator 0.970 and 0.975-beta fail test sprdma_and_dmc_dma_512.nes.

edit: Nintendulator does not pass 7-dmc_basics.nes either.


Last edited by zeroone on Mon Dec 21, 2015 8:53 am, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: CPU timing precision
PostPosted: Mon Dec 21, 2015 8:09 am 
Offline
Formerly Fx3
User avatar

Joined: Fri Nov 12, 2004 4:59 pm
Posts: 3076
Location: Brazil
@Disch
I'm not familiar with the 6502 simulator, but you (or anyone else) can give a try, regarding $4014.


Top
 Profile  
 
 Post subject: Re: CPU timing precision
PostPosted: Mon Dec 21, 2015 9:11 am 
Offline
User avatar

Joined: Mon Dec 29, 2014 1:46 pm
Posts: 750
Location: New York, NY
From Blargg's post:

blargg wrote:
Based on the following tests, DMC DMA adds 4 cycles normally, 3 if it lands on a CPU write, 2 if it lands on the $4014 write or during OAM DMA, 1 if on the next-to-next-to-last DMA cycle, 3 if on the last DMA cycle.


Does "if it lands on a CPU write" mean if it coincides with a CPU write cycle?


Top
 Profile  
 
 Post subject: Re: CPU timing precision
PostPosted: Mon Dec 21, 2015 11:02 am 
Offline
User avatar

Joined: Wed Nov 10, 2004 6:47 pm
Posts: 1845
@ Zepper:

Could the reason the test is failing be due to something else? Blargg's post clearly indicates it should be 1,2,3.



zeroone wrote:
Does "if it lands on a CPU write" mean if it coincides with a CPU write cycle?


It probably means if the 'rw' signal is low at the time the DMA cuts in -- which happens during write cycles.

Since the DMA transfer can't happen "on" a cycle (since the CPU can either be performing its normal exeuction or DMA fetch -- it can't do both at the same time) I assume this means if the DMA happens "immediately after" a write cycle.

Example, "STA $10" is a 3 cycle instruction, two reads and one write:

Code:
Cycle 0:   read(PC) for opcode
  ** DMA here takes 4 cycles **
Cycle 1:   read(PC) for address
  ** DMA here takes 4 cycles **
Cycle 2:   write(address,A) to perform the STA
  ** DMA here takes 2 cycles **
...




EDIT:

Looks like I'm wrong about 4014. According to visual2A03 the dummy reads are from the PC.


Last edited by Disch on Mon Dec 21, 2015 11:13 am, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: CPU timing precision
PostPosted: Mon Dec 21, 2015 11:09 am 
Offline
User avatar

Joined: Mon Dec 29, 2014 1:46 pm
Posts: 750
Location: New York, NY
Disch wrote:
It probably means if the 'rw' signal is low at the time the DMA cuts in -- which happens during write cycles.

Since the DMA transfer can't happen "on" a cycle (since the CPU can either be performing it's normal exeuction or DMA -- it can't do both at the same time) I assume this means if the DMA happens "immediately after" a write cycle.


It could also mean, in place of what would normally be a write cycle (effectively, immediately before a write cycle).

Either way, if RockNES does not process instructions at the microcode level, how does it handle such a case?


Top
 Profile  
 
 Post subject: Re: CPU timing precision
PostPosted: Mon Dec 21, 2015 1:55 pm 
Offline
Formerly Fx3
User avatar

Joined: Fri Nov 12, 2004 4:59 pm
Posts: 3076
Location: Brazil
@zeroone
You're being more boring than constructive. :shock:
#define microcode with an example, then we'll continue.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 70 posts ]  Go to page Previous  1, 2, 3, 4, 5  Next

All times are UTC - 7 hours


Who is online

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