It is currently Tue Jun 19, 2018 10:55 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 43 posts ]  Go to page 1, 2, 3  Next
Author Message
PostPosted: Sun Nov 01, 2015 12:15 pm 
Offline
User avatar

Joined: Sat Sep 07, 2013 2:59 pm
Posts: 1629
Is there a way to measure the time that a certain function takes to process? I'm thinking of something that is immediately visible on the screen, so I don't have to stop the game and check some stuff in the binary code of the emulator's PPU or something.

For example, is there a way to read the current pixel position that the cathode ray is in the moment? This way I could read that value, store it into a variable and then use a few debug sprites to display that value on the screen.

Or something else to manipulate the screen output so that I see what the cathode ray is drawing in the moment.

_________________
Available now: My game "City Trouble".
Website: https://megacatstudios.com/products/city-trouble
Trailer: https://youtu.be/IYXpP59qSxA
Gameplay: https://youtu.be/Eee0yurkIW4
German Retro Gamer article: http://i67.tinypic.com/345o108.jpg


Top
 Profile  
 
PostPosted: Sun Nov 01, 2015 12:32 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 6342
Location: Canada
Writes to $2001 (PPUMASK) take effect immediately. Turning on greyscale + a colour emphasis can be a great way to mark on the screen when a particular thing happened. This is what I do in my own project.

(Greyscale in conjunction with emphasis is important because it replaces black with grey, so you don't lose the ability to see the mark against black.)


Top
 Profile  
 
PostPosted: Sun Nov 01, 2015 12:41 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 6342
Location: Canada
Alternatively, if you're using an emulator, in FCEUX you can create LUA scripts that would measure timing information and overlay it on the screen for you. I often use this when debugging to visualize hitboxes, etc.


Top
 Profile  
 
PostPosted: Sun Nov 01, 2015 12:59 pm 
Offline
User avatar

Joined: Sat Sep 07, 2013 2:59 pm
Posts: 1629
Thanks. Writing to PPUMASK seems to be the best way for me.
Writing a LUA script would mean that I first have to read how this works.

_________________
Available now: My game "City Trouble".
Website: https://megacatstudios.com/products/city-trouble
Trailer: https://youtu.be/IYXpP59qSxA
Gameplay: https://youtu.be/Eee0yurkIW4
German Retro Gamer article: http://i67.tinypic.com/345o108.jpg


Top
 Profile  
 
PostPosted: Sun Nov 01, 2015 1:00 pm 
Offline

Joined: Sun Apr 13, 2008 11:12 am
Posts: 7216
Location: Seattle
Thefox's NintendulatorDX variant adds a set of registers at $402X/$403X for timing:
NintendulatorDX readme wrote:
Cycle Counting Timers
---------------------
16 CPU cycle counting timers are available for timing different parts of your code. The timers can only be used by writing to a register at the moment. They work by writing to register $402x when you want the timing to start, and to $403x when you want it to end. "x" is the timer number.

E.g.
Code:
  ; Start timer #5. The written value doesn't matter.
  sta $4025
  ; Do whatever.
  nop
  lda #123
  ; Stop timer #5. After this the Debugger window will display the
  ; number of CPU cycles taken by the above code block (4 cycles).
  sta $4035

The number of cycles taken by the STA instructions do not count into the reported number of cycles!

By defining a specially named symbol it's possible to define a name for the timer. The symbol name should be "__timerN_title", and it should point to a zero terminated string containing the name of the timer (replace N with the timer number). This name is displayed in the Debugger window.

E.g.

Code:
  .code
    __timer5_title:
      .asciiz "nmi routine"

The following macros may be useful:
Code:
  .macro startTimer timer
    sta $4020 + timer
  .endmacro

  .macro stopTimer timer
    sta $4030 + timer
  .endmacro

  .macro timerTitle timer, title
    .ident( .sprintf( "__timer%d_title", timer ) ):
      .asciiz title
  .endmacro

Known problems:
* The address of the registers ($402x/$403x) overlaps the FDS register area.

See also:
* [Lua] NDX.getCPUCycles()


Top
 Profile  
 
PostPosted: Sun Nov 01, 2015 1:14 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10513
Location: Rio de Janeiro - Brazil
I would simply set grayscale + emphasis in the beginning of the function, and return to normal in the end. This should give a very clear visual indication of how much of the frame's time is being spent on the function. You could even use different emphasis configurations if you wanted to time different functions.


Top
 Profile  
 
PostPosted: Sun Nov 01, 2015 1:38 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 20160
Location: NE Indiana, USA (NTSC)
More methods to measure execution time:
  1. Setup up a mapper's interval timer for some estimate of your subroutine's duration, run the subroutine, and then count cycles until the IRQ triggers.
  2. Do the above using APU DMC. Play a 1-byte sample at maximum rate through the DMC, wait for the IRQ, play the sample at a lower rate, call the subroutine, and then count cycles until a second IRQ triggers.
  3. Make your program buildable for both the NES and Super NES. The latter has a readable H/V counter.
  4. Set up your subroutine's preconditions, then run it in a 6502 simulator that counts cycles.

But for me, the easiest way is to open the debugger of FCEUX for Windows, set a breakpoint at the start of the subroutine, run the program until the subroutine starts, click "Step Out", and then check the cycle counter. It'll be of the form "CPU cycles: xxxxxxxxx (+yyyy)"; the yyyy is how many cycles the subroutine takes. This breaks down, however, if the subroutine runs once a frame and has an execution time varies based the player's actions in the last few frames, because it's so hard to send input to a program where a breakpoint triggers every frame. Is this the problem you're running into?


Top
 Profile  
 
PostPosted: Sun Nov 01, 2015 2:09 pm 
Offline
User avatar

Joined: Sat Sep 07, 2013 2:59 pm
Posts: 1629
Isn't this all a huge overkill? To me, writing to PPUMASK seems to be the most straightforward and easy to implement thing. And it gives me a pretty accurate, easy to see at first glance output

About the FCEUX debugger: That's what I wanted to avoid. Because I want to see how much time everything takes during regular gameplay.
So, yes, actions that take different time every frame might be an issue. In the moment, I don't have a specific problem. I just want to have a general way to measure the time. Especially since I have to split the game logic in three parts since I have the status bar and the parallax split. So, I want to see what I can push into the smaller parts.

_________________
Available now: My game "City Trouble".
Website: https://megacatstudios.com/products/city-trouble
Trailer: https://youtu.be/IYXpP59qSxA
Gameplay: https://youtu.be/Eee0yurkIW4
German Retro Gamer article: http://i67.tinypic.com/345o108.jpg


Top
 Profile  
 
PostPosted: Sun Nov 01, 2015 2:20 pm 
Offline
User avatar

Joined: Sat Jul 25, 2015 1:22 pm
Posts: 501
It sounds to me like the best thing for what you need is to use the cycle counting timers with NintendulatorDX.

This is what I do when I need to gauge the length in cycles of a routine, the entire program, the vBlank handler, or essentially any part of the program that can be marked with a start and stop position.

With this you get an average of what the total has been while your program has been running, which sounds like what you want.


Top
 Profile  
 
PostPosted: Sun Nov 01, 2015 2:20 pm 
Offline
User avatar

Joined: Mon Feb 07, 2011 12:46 pm
Posts: 985
Often I just try to count the cycles manually. This won't work if it is too complicated though.

_________________
.


Top
 Profile  
 
PostPosted: Sun Nov 01, 2015 2:21 pm 
Offline
User avatar

Joined: Wed Apr 02, 2008 2:09 pm
Posts: 1149
DRW codes in C, so counting cycles manually isn't an option.

_________________
https://kasumi.itch.io/indivisible


Top
 Profile  
 
PostPosted: Sun Nov 01, 2015 3:08 pm 
Offline
User avatar

Joined: Mon Sep 15, 2014 4:35 pm
Posts: 3333
Location: Nacogdoches, Texas
What's he coding in C for if he's concerned about cycle count? :lol:


Top
 Profile  
 
PostPosted: Sun Nov 01, 2015 3:56 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 6342
Location: Canada
Espozo wrote:
What's he coding in C for if he's concerned about cycle count? :lol:

Performance always matters when your CPU time is limited, and I guess this surprises you, but it actually even matters more when using C.

Using C is like trying to work with a CPU with 1/10th the power. You probably have a LOT more need to monitor performance to check on your budget than when doing things an assembly. :P

It's also very easy to write code that looks simple in C, but accidentally generates horribly slow code. This is yet another reason why you need to check frequently, because otherwise it's hard to know when you wrote something that destroyed your timing budget.


Top
 Profile  
 
PostPosted: Sun Nov 01, 2015 4:38 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10513
Location: Rio de Janeiro - Brazil
Could Espozo have meant that DRW shouldn't be using C if he's concerned about the cycle count?


Top
 Profile  
 
PostPosted: Sun Nov 01, 2015 4:46 pm 
Offline

Joined: Sun Apr 13, 2008 11:12 am
Posts: 7216
Location: Seattle
Of course that's what Espozo meant. Espozo's also made it clear in the past that he doesn't understand the point of using any higher-level language, so it's not clear that his point is useful.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 43 posts ]  Go to page 1, 2, 3  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