cycle for cycle stuff

Discuss emulation of the Nintendo Entertainment System and Famicom.
6502 Timing

cycle for cycle stuff

Post by 6502 Timing »

Does anybody have any accurate documents on 6502 timing (i.e. cycle for cycle stuff). I have used 6502_cpu.txt and the w65c02s.pdf document but they don't make sense or have conflicting theories. I am trying to implement accurate emulation so that I can execute 1 CPU cycle then 3 PPU cycles for my emulator. What did you use for your emulator?

For instance:

inline void TYA( int Cycle )
{
switch(Cycle)
{
case 0: increment CPU cc break;
case 1: A = Y break;
}
}
User avatar
Quietust
Posts: 2030
Joined: Sun Sep 19, 2004 10:59 pm

Post by Quietust »

Executing partial CPU instructions is largely a waste, since it takes so much overhead and provides no benefit. If you want the precision, just emulate the CPU one instruction at a time, but have each instruction update the PPU/APU/etc. during each cycle of each instruction.
Quietust, QMT Productions
P.S. If you don't get this note, let me know and I'll write you another.
Guest

Post by Guest »

Have you written an emulator Quietust? If so do you have accurate CPU emulation?

It's not just for the NES I also wanted an accurate 6502 for other console/pc emulators. So I really am desperate.
User avatar
Bregalad
Posts: 8181
Joined: Fri Nov 12, 2004 2:49 pm
Location: Divonne-les-bains, France

Post by Bregalad »

Yes, his emulator is the most accuratest in the world about CPU and PPU timing / syncronistation.
Useless, lumbering half-wits don't scare us.
Guest

Post by Guest »

Thanks, but I still need some documents on accurate on the 6502's timing.
User avatar
Disch
Posts: 1848
Joined: Wed Nov 10, 2004 6:47 pm

Post by Disch »

I was under the impression that the following had accurate per-cycle operations of the CPU:

http://nesdev.com/6502_cpu.txt

near the end it gets into which reads/writes are performed on every cycle of the instruction.


As for implimentation, the easiest would probably be to pass an additional timestamp to your read/write proc indicated the number of cycles into the instruction. For example, the code for STA absolute might look something like this:

Code: Select all

byte opcode = Read( PC, 0 );
PC++;

switch(opcode)
{
 case 0x8D:
  adr = Read( PC, 1 );
  adr |= Read( PC + 1, 2 ) << 8;
  Write( adr, A, 3 );
  PC += 2;
  cpu_timestamp += 4;
  break;
}
cpu_timestamp would contain the overall cycle (which in incremented by the time determined by each instruction). the last parameter passed to Read()/Write() indicates the number of cycles to add to the cpu_timestamp when "catching up" other systems. This value can usually be ignored for areas which dont' need it (for example, when reading from ROM, or reading/writing RAM... the last param will be tossed). However for register writes/reads the extra given cycle will allow you to have cycle-accurate precision when catching up the PPU and APU to the current CPU time -- at little processing cost.
}
User avatar
teaguecl
Posts: 211
Joined: Thu Oct 21, 2004 4:02 pm
Location: San Diego

Post by teaguecl »

Anonymous wrote:Have you written an emulator Quietust? If so do you have accurate CPU emulation?
A good example of how a perfectly legitimate questions becomes hilarious given the right context.
For the benefit of the thread author, Q's emulation called Nintendulator is as close to hardware as you get.
Guest

Post by Guest »

Thanks I'll try that but the 6502_cpu.txt cycles explanation differs from WDC own w65c02s.pdf (basically the same CPU). This is what is concerning me.

http://www.westerndesigncenter.com/wdc/ ... 65c02s.pdf

Can anyone give a better explanation to the details of the PDF's cycle chart as I find them verry hard to understand.
User avatar
Disch
Posts: 1848
Joined: Wed Nov 10, 2004 6:47 pm

Post by Disch »

that PDF document you linked to seems to be for a more recent processor than the processor used by the NES. It makes reference to various instructions unavailable on the 6502 (BRA, PLY, PLX) -- plus it does things 6502_cpu.txt says are CMOS processor behavior (such as doing read/write for Absolute Read/Modify/Write instrutcions, rather than dual writes) NES has an NMOS, not CMOS processor)


I'd stick with 6502_cpu.txt
Guest

Post by Guest »

Ok I'll do that, I don't think that it'll make much difference anyway. I'll post again later on today or tomorrow to see how it goes.
User avatar
Anes
Posts: 717
Joined: Tue Dec 21, 2004 8:35 pm
Location: Mendoza, Argentina

Post by Anes »

Yes, his emulator is the most accuratest in the world about CPU and PPU timing / syncronistation
Is it the "accuratest" or the "most accurate" bregalad?
When words are large you should use "most", but not "more accurastest".
ANes
6502 Timing

Post by 6502 Timing »

Anes wrote:
Yes, his emulator is the most accuratest in the world about CPU and PPU timing / syncronistation
Is it the "accuratest" or the "most accurate" bregalad?
When words are large you should use "most", but not "more accurastest".
lmao. True. But sticking with my post...
jarodcanal
Posts: 1
Joined: Tue Sep 20, 2005 6:42 am

Post by jarodcanal »

Hi,
I am having a look at nintendulator sources (955 beta).
I would like to be sure that I am understanding the base of your CPU emulation (I mean I am asking :) ). Please could you confirm that the following is correct?

Instead of having an external clock system synching CPU, PPU and APU, you use CPU cycles to synch PPU and APU.
To do that, you call RunCycle (which internally calls PPU_Run and APU_Run) from CPU_MemGet and CPU_MemSet.
CPU_MemGet and CPU_MemSet are called from opcodes and interrupts.

I suppose that this reflects the following lines from Kim programming manual:
The major point to be noted is that every clock cycle in the MCS650X microprocessor is a memory cycle in which memory is either read or written. Simultaneously with the read or Write of memory, an internal operation of the microprocessor is also occurring.
(http://users.telenet.be/kim1-6502/6502/proman.html#51)

Thanks.
Best regards
User avatar
Quietust
Posts: 2030
Joined: Sun Sep 19, 2004 10:59 pm

Post by Quietust »

jarodcanal wrote:Instead of having an external clock system synching CPU, PPU and APU, you use CPU cycles to synch PPU and APU.
To do that, you call RunCycle (which internally calls PPU_Run and APU_Run) from CPU_MemGet and CPU_MemSet.
CPU_MemGet and CPU_MemSet are called from opcodes and interrupts.
That is correct.
Quietust, QMT Productions
P.S. If you don't get this note, let me know and I'll write you another.
WedNESday
Posts: 1311
Joined: Thu Sep 15, 2005 9:23 am
Location: London, England

Post by WedNESday »

(BTW: I started this post, under the (accidental) name of 6502 Timing)
Quietust wrote:Executing partial CPU instructions is largely a waste, since it takes so much overhead and provides no benefit. If you want the precision, just emulate the CPU one instruction at a time, but have each instruction update the PPU/APU/etc. during each cycle of each instruction.

...and provides no benefit.
That is not true. Observe the following.

Code: Select all

Clock Cycle #
1	2	3	4
|	|	|	|
|	|	|	+-	Load From $2002 (i.e. $00)
|	|	|	|
|	|	|	|
|	|	|	|
|	+-	VBlank Ends ($2002 = $00)
+-	($2002 = $80)

An emulator without perfect timing would read that back as $80.