timing 2 ^_^;;

Discuss emulation of the Nintendo Entertainment System and Famicom.

Moderator: Moderators

Post Reply
User avatar
Zepper
Formerly Fx3
Posts: 3262
Joined: Fri Nov 12, 2004 4:59 pm
Location: Brazil
Contact:

timing 2 ^_^;;

Post by Zepper »

Because of APU test issues, I rebuild my CPU core to handle cycles in a lower level - it means:

* By taking STA $HHLL, it does 1 clock cycle to read the opcode, 2 cycles to fetch the address HHLL, instead of clocking 4 cycles at end of STA. That's an example.

It caused the timing to be better for a few games/demos, but very bad for others (mapper #7). Battletoads&Double Dragon does not hang when a PCM sound is played. While it was playing nicely, it stopped on level 5 beginning. >_<. I suspect I would have to rewrite my PPU core too.

Detail (NTSC only): for each CPU cycle, the PPU does 3 clock cycles, APU does 1 clock cycle. I gave a look in other emus and (except for Nintendulator?), they use a cycle table. Is the PPU/APU clocked before or after an instruction? Any help?
User avatar
Quietust
Posts: 1920
Joined: Sun Sep 19, 2004 10:59 pm
Contact:

Re: timing 2 ^_^;;

Post by Quietust »

Fx3 wrote:I gave a look in other emus and (except for Nintendulator?), they use a cycle table
That's because Nintendulator already uses the "high precision timing" method you just implemented.
Quietust, QMT Productions
P.S. If you don't get this note, let me know and I'll write you another.
User avatar
blargg
Posts: 3715
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Post by blargg »

Fx3 wrote:Is the PPU/APU clocked before or after an instruction?
Good question. The APU is likely clocked at the same time as the CPU (well, technically the CPU has a two-phase clock). This brings up the question, if the CPU performs a read on a given clock, does it get data generated by the APU on that clock, or from the previous clock? Answering this probably requires hooking a scope up to the NES bus.

Fortunately what really matters is the behavior you get by running code, which can be determined by running test code and observing the results. Thus it becomes irrelevant as to when the units are clocked. What one needs to know (both for programming the NES and writing an emulator) is, if this read occurs at such-and-such time relative to a previous write (or NMI etc.), what value do I get?

Regarding instruction timing, can't you just use a "regular" CPU core and pass a timestamp adjustment along with memory reads/writes? So for STA $xxxx, instead of WRITE( addr, a ) you do WRITE( addr, a, 3 ) since the write is on the fourth clock.

I doubt that it really matters to be precise with regard to opcode reads, since it's unlikely anything is going to try to execute from I/O space. In my CPU core I even avoid the usual memory access function for opcode reads, instead going directly through the memory mapping table without any function calls. And hopefully you optimize zero-page and stack accesses to avoid function calls, since those can never cause any side-effects (as far as I know).
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Post by tepples »

blargg wrote:And hopefully you optimize zero-page and stack accesses to avoid function calls, since those can never cause any side-effects (as far as I know).
Is the CPU address bus visible on the cart edge during internal RAM accesses?
User avatar
Disch
Posts: 1848
Joined: Wed Nov 10, 2004 6:47 pm

Post by Disch »

blargg wrote:In my CPU core I even avoid the usual memory access function for opcode reads, instead going directly through the memory mapping table without any function calls.
How does that work for games like Zelda which move code to cartridge RAM and jump to it? or does your emu not support that?

edit:
Or do you mean you do like an if/else range check for opcode reads?
User avatar
blargg
Posts: 3715
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Post by blargg »

Post Reply