How does fceux detect a lag?

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
How does fceux detect a lag?
by on (#229622)
fceux has the ability to show you lag frames. But how does it do this? I mean, a lag simply means that the NMI fires and I detect that I'm not ready yet and leave it again. And when I'm ready, I go into an infinite loop until NMI fires.

So, how is fceux able to detect that a certain frame indeed lags?
On a technical level, as far as I see, it makes no difference that I use an if-else condition or whether I'm in the actual game logic vs. whether I'm in a "label: goto label" situation.
Re: How does fceux detect a lag?
by on (#229624)
Looking at the source code:
FCEU_UpdateInput();
lagFlag = 1;
if (lagFlag) {
lagCounter++;
justLagged = true;
} else justLagged = false;
static DECLFR(JPRead)
{
lagFlag = 0;

In other words, two NMIs without reading either joypad in between.
Re: How does fceux detect a lag?
by on (#229625)
Thanks.

Yeah, that's quite clever. It's unlikely that a game has frames where there are no controller updates by design.

I was assuming it has to do with PPU updates, but then, I was wondering why my games don't increase the lag counter in text screens.
Re: How does fceux detect a lag?
by on (#229630)
DRW wrote:
Yeah, that's quite clever. It's unlikely that a game has frames where there are no controller updates by design.

Blank screen loading data into VRAM might skip reading controllers. So might a loop to display a legal notice or "Amy has cleared Act 1" for 256 frames.
Re: How does fceux detect a lag?
by on (#229631)
Yeah the terminology isn't quite precise, but that feature is there because it was critical for TASers to know when they can affect the game with input and not.
Re: How does fceux detect a lag?
by on (#229632)
tepples wrote:
Blank screen loading data into VRAM might skip reading controllers. So might a loop to display a legal notice or "Amy has cleared Act 1" for 256 frames.

I personally always read the controller. This is basically one of the "system" functions and literally the first thing the game logic does in every frame.

Whether a certain screen displays itself for a fixed amount when no input is processed: Well, this is entirely the current screen's business. If it has no input, it simply doesn't check for the current controller value that holds the button status.
But the general controller reading function doesn't get polluted with the information in which specific game section we are at the moment.

(As a related topic, there is exactly one way to update graphics during NMI: An array that stores the necessary values. There are not several different NMI handlers based on the game's situation, so no matter if we are in the title screen or during gameplay updates or if we fade out the screen: The NMI always processes the same function.)

rainwarrior wrote:
Yeah the terminology isn't quite precise, but that feature is there because it was critical for TASers to know when they can affect the game with input and not.

I assume a TAS speedrunner knows the game well enough to know when he can make inputs.
Especially since, during gameplay, it's usually always possible to press pause, so a counter to indicate when controller input isn't read doesn't help you in any way to determine, for example, at which frame after a jump you can regain control of your character again or how often you can shoot a weapon.

So, the lag counter is most-likely really supposed to be a lag counter and not a TAS input check. Because a much more useful function for this counter is to check whether your self-made game has, well, lags.
Re: How does fceux detect a lag?
by on (#229634)
I come from the TASing community, and I believe rainwarrior is correct. Maybe it isn't necessary now, but over 10 years ago TASes were a bit more imprecise and having a lag counter was really helpful to compare if attempts to reduce lag were succesful or not. Or maybe it still is useful, I don't know because I kind of quit the scene a long time ago.
Re: How does fceux detect a lag?
by on (#229635)
nesrocks wrote:
[...] I believe rainwarrior is correct. [...] to compare if attempts to reduce lag were succesful or not.

But this makes the lag counter really a lag counter, i.e. not what rainwarrior said, since he claimed that the name "lag counter" is not quite precise.
Re: How does fceux detect a lag?
by on (#229639)
DRW wrote:
I assume a TAS speedrunner knows the game well enough to know when he can make inputs.

Well, they certainly do when they have something that can indicate it for them, like maybe this "lag" counter. :P

DRW wrote:
I personally always read the controller. This is basically one of the "system" functions and literally the first thing the game logic does in every frame.

If you have more than one loop for different modes, there is really no point to reading the input and ignoring it. Extra code for nothing.

If you're not in a loop (e.g. loading level data to the screen, filling CHR-RAM, etc.) then there's really no place to read the input anyway, and again no point in adding extra code to do so if you're going to ignore it. ...though there are some valid reasons why you might want to respond to input during this time too.
Re: How does fceux detect a lag?
by on (#229641)
DRW wrote:

(As a related topic, there is exactly one way to update graphics during NMI: An array that stores the necessary values. There are not several different NMI handlers based on the game's situation, so no matter if we are in the title screen or during gameplay updates or if we fade out the screen: The NMI always processes the same function.)
.


Actually in the game I'm working on now, with how I've arranged my bank-switching, I do have different NMI handlers for different situations. Each bank has a specialized duty, so the NMI routine can be adapted to do exactly what that situation needs.
Re: How does fceux detect a lag?
by on (#229643)
In my current game engine I update the NMI based on the situation so in a stage, a NMI could be changed more than once.
Re: How does fceux detect a lag?
by on (#229645)
rainwarrior wrote:
DRW wrote:
I assume a TAS speedrunner knows the game well enough to know when he can make inputs.

Well, they certainly do when they have something that can indicate it for them, like maybe this "lag" counter. :P

And how many times would a speedrunner actually need this? The only time where the lag counter indicates the possibility of inputs and not actual slowdowns would be during some status screens and only if the game is programmed in a way so that the input isn't read during this time.

But the lag counter as an input indicator helps you in no way for, well, basically evey situation imaginable:
If you want to know when you can attack again after you already attacked, the lag counter will not help you. If you want to know when you can move again after landing on the ground or after being hit, the lag counter will not help you.

Using the lag counter as an input indicator helps only in one way: If the level starts with a status screen. And even in this case it's pretty much useless: Firstly, not every game is programmed so that status screens increase the lag counter constantly. Secondly, the moment when input is possible is usually as soon as the screen shows the level again.

So, yeah, the lag counter isn't mis-labeled. It's not intended as an indicator to know whether you can input commands. It is what it says it is: A lag counter. To check whenever the game requires more than one screen to render a scene. To see whether the game experienced actual slowdown. Not an indicator to tell the speedrunner: "Now your button press has an effect and now it doesn't". Which would be a situation that couldn't be implemented with a lag counter in 99.999% of every game situation anyway.

rainwarrior wrote:
If you have more than one loop for different modes, there is really no point to reading the input and ignoring it. Extra code for nothing.

Who said anything about extra code, even if there are more statuses for the game? And who said that I have more than one loop to begin with?
Code:
StartGameLoop:

ReadInput

if Status = TextScreen
    ProcessTextScreen
else
    ProcessLevel

WaitForNmi

goto StartGameLoop


If you seriously have several game loops like in:
Code:
if Status = TextScreenWithInput
    StartTextScreenWithInput:
    ReadInput
    ProcessTextScreenWithInput
    WaitForNmi
    goto StartTextScreenWithInput
else if Status = AutomaticTextScreen
    StartAutomaticTextScreen:
    ; No input reading
    ProcessAutomaticTextScreen
    WaitForNmi
    goto StartAutomaticTextScreen
else
    StartLevel:
    ReadInput
    ProcessLevel
    WaitForNmi
    goto StartLevel

maybe you should think about removing redundant code.

I on the other hand cannot think of any reason why you should ever have more than one game loop.
It's one game loop to do all the generic stuff at the start (read input) and the end (update music values, wait for nmi). And one if-else (or switch case 1, case 2, case 3 etc.) to distinguish between the different game sections that require completely different logic, like title screen, level, in-game menu etc.
But in no way would I ever use more than one game loop. Why should anybody do that?

rainwarrior wrote:
If you're not in a loop (e.g. loading level data to the screen, filling CHR-RAM, etc.) then there's really no place to read the input anyway, and again no point in adding extra code to do so if you're going to ignore it.

Again, where do you see extra code or anything like that?
If I load level data, then some sub function in ProcessGameplay will set PpuMaskBuffer to 0, so that NMI disables the PpuMask. Then the function will update all graphics and afterward set PpuMaskBuffer back to its original value.
None of this contradicts or requires any additional code regarding the fact that controller input is always the first thing in the game logic.

gauauu wrote:
Actually in the game I'm working on now, with how I've arranged my bank-switching, I do have different NMI handlers for different situations. Each bank has a specialized duty, so the NMI routine can be adapted to do exactly what that situation needs.

Banshaku wrote:
In my current game engine I update the NMI based on the situation so in a stage, a NMI could be changed more than once.

What do your NMIs do, so that you need different ones?

Mine does these things:
Check whether we actually want to run the NMI's code.
Set the WaitForNmi flag back to false.
Set the PpuMask buffer value to the actual PpuMask register.
Copy the sprite array to OAM.
Update the PPU based on a buffer array.
Update name table and scrolling based on buffer values.
Call the sound update function.

Every section-related things are written in the regular game logic. The NMI does nothing but those completely generic things.

Even the question if you update a text in a text screen or a destroyed bush on the playfield makes no difference once the NMI is reached. Because the buffer array only includes the data length, the PPU address where to draw to and the tiles. Then it has either a 0 or another collection of data length, PPU address and tiles.

The distinct stuff (text rendering preparation is processed differently from background element change preparation since both read their data from totally different sources, access different banks etc.) is only ever done in the regular game logic.
The narrow window of vblank that gets started by the call to NMI never wastes time to do section-specific stuff. It's completely agnostic to anything that's actually going on and merely puts values into the PPU and the APU based on some general-purpose variables.
That's why I never need more than one NMI, nor does NMI need to check for the current game section.
Re: How does fceux detect a lag?
by on (#229648)
Lag Counter is for TASing, in that you can pick different actions to try to reduce CPU usage (kill more monsters, etc) to avoid the lag frames. It also helps come up with strategies for non tool assisted speedruns as well.
Re: How does fceux detect a lag?
by on (#229649)
It depends on your need so it doesn't means that you have to make dynamic NMI. In my current use-case, it was useful.

I have some generic handlers for:
- nmi count only
- nmi + non banked player
- nmi + banked player
- nmi + banked player + sprite/maps etc

the generic code can be reused in more custom ones. In one stage, there is 1 place that uses 1 palette to be animated and only one part requires 2 of them. It would have been unnecessary to have the animation code in all nmi for the complete game.

For the title screen, I have some raster code that have call back function inside C code to time when some data should be updated. In that case, it wouldn't make sense to have the sprite/map code in it.

So it just the way I make my code, it doesn't means it's universal and everyone should do it: I just like it that way and work for my own use case. so if I have one case that require a specific animation for mini boss or something, I can create a NMI for that case only and leave the code in the stage bank.
Re: How does fceux detect a lag?
by on (#229650)
DRW wrote:
The only time where the lag counter indicates the possibility of inputs and not actual slowdowns would be during some status screens and only if the game is programmed in a way so that the input isn't read during this time.

For an example it happens in many games during dialogue, where input isn't read until the player can press to continue.

The "lag" concept is tied together with the TAS editor which displays such frames as red in the grid view. From its glossary:
Quote:
The criterion is simple: if the game didn't poll Input during the frame then it's the lag frame. If it did poll Input then this is normal frame. Taseditor highlights lag frames with red color, and it's useless to draw any Input on these frames.
i.e. It's something a TASer would want to know. It's a helpful metric. It's useful to know when your input is read. It's also an extremely important concept if you want to run a TASBot or something similar.

Is it really that difficult for you to understand that there is a use for this besides just detecting slowdown?

DRW wrote:
If you seriously have... (blah blah blah) maybe you should think about removing redundant code.

I was offering some examples because you seem to be having trouble understanding the idea that it might be reasonable to not take input on every single frame of the game. I have no interest in having some bullshit argument about whether you would do it, or whether you would use the lag counter this way if you were doing a TAS (which you clearly never have). I really don't care. I wasn't telling you what to do.

You asked some questions following this, but you don't seem to be interested in civil discussion, so unless you can convince me that you were actually asking them in good faith I'm not going to continue, sorry.
Re: How does fceux detect a lag?
by on (#229653)
Separate game loops/NMIs is a reasonable way to keep code separate and uncoupled. The pattern is especially nice when coding in assembly, where switch statements do not exist and the stack can be manipulated directly. Putting everything in a single loop often gets messy.

Anyway, you speak with very strong words DRW and it riles people up. I think you should read the story of Chesterton's Fence.
Re: How does fceux detect a lag?
by on (#229654)
rainwarrior wrote:
Is it really that difficult for you to understand that there is a use for this besides just detecting slowdown?

No, this isn't difficult for me to understand. What is difficult to accept though is the idea that it's not actually a lag counter, but primarily an input-is-possible indicator and that the term "lag counter" is a terminology that isn't quite precise.

You were pretty much accusing the developers of fceux that they misname their features. And everybody else in this forum so far confirms that the feature was intended to check for lags to reduce the time the run takes.

rainwarrior wrote:
I was offering some examples because you seem to be having trouble understanding the idea that it might be reasonable to not take input on every single frame of the game. [...] I wasn't telling you what to do.

In fact you did. You didn't merely talk about any random game, you directly criticized my attempt (which you didn't even understand since you assumed I have some kind of extra redundant code):
rainwarrior wrote:
DRW wrote:
I personally always read the controller. This is basically one of the "system" functions and literally the first thing the game logic does in every frame.

If you have more than one loop for different modes, there is really no point to reading the input and ignoring it. Extra code for nothing.

At least admit that my whole argumentation was based on the fact that you were berating me. You weren't talking about what "Ghosts 'n' Goblins" or "Ikari Warriors" do, you were directly criticizing my attempt by telling me that my way of doing is pointless.

rainwarrior wrote:
but you don't seem to be interested in civil discussion

Said the guy who uses the word "bullshit", accuses emulator developers of misnaming their features and who quotes someone with "blablabla".


But yeah, I'm the one who riles up the discussion again because I explained what exactly I'm doing in my code and because I invented a totally fictitious example (that I don't even know you're using) where I said: If you did this specific way, then you should maybe rethink your contruct because it would be imperfect code style.
Re: How does fceux detect a lag?
by on (#229656)
Banshaku wrote:
the generic code can be reused in more custom ones. In one stage, there is 1 place that uses 1 palette to be animated and only one part requires 2 of them. It would have been unnecessary to have the animation code in all nmi for the complete game.

Indeed. That's why I would suggest a generic PPU update array that is simply used for everything:

You have an array with the following values:
- data length
- PPUADDR high byte
- PPUADDR low byte
- tiles

The NMI puts the first byte into a counter (for example the X register).
If the counter is 0, the function ends.
Otherwise:
It writes the next two bytes to PPUADDR.
Then, with a loop that decrements the counter, it goes thorugh the next bytes and writes them into the PPU.
If the loop is finished, you go back to the start of the function and do it again, until the first value is 0.
Afterwards, you write a 0 to the first array entry (so that the array is now considered empty.)

This way, it doesn't matter if you have animated palettes or tile updates or whatever.
You do all the different things in your several game logic functions that run normally outside of vblank. And the NMI simply processes an array that has pure PPU-usable data in it, including the actual PPU address, without caring whether it's a palette update or a sprite update, whether it's from the title screen or from a game area or a boss made of background tiles.

Banshaku wrote:
so if I have one case that require a specific animation for mini boss or something, I can create a NMI for that case only and leave the code in the stage bank.

In this case, I would also suggest: You calculate your mini boss animation inside the regular game logic. Then, still outside of NMI, you put each animation tile into a shadow sprite array. And the NMI simply uses this shadow array to update the actual sprites.
And if your mini boss is a background element: Same method as above: Just put all tiles that need to be updated, together with their PPU addresses, into the generic PPU update array.

Advantage: The NMI, which has a very short time frame to update graphics, does only the bare minimum. Every actual game content decision is done earlier, in the regular game logic that doesn't have such a narrow time window.
Re: How does fceux detect a lag?
by on (#229658)
Sure, this is one of many possible way to update, it just happened that I didn't do it that way :lol:

My current nmi mostly just update:
- palette, if required
- oam data
- map data, only if buffered data exist (max 2 columns)
- finally, play music

The rest is done outside the NMI because of the limited time, like you mentioned. I'm sure I could animate the palette somehow for that part outside the nmi and request a palette update if required. It just happened I had that code 10 years ago and it was working well so for that case it not worth it to put back in main loop. It was timed to the NMI so it was in proper sync, like I wanted. Maybe someday I will put it outside but for now, nah, not worth it.

As for the mini-boss, without details it doesn't make sense, my bad ^^;; It was just an example that if I need a special display code (raster whatever) for that specific case, I just switch the NMI and more effects could be done. Of course, no logic would be done there, that would be careless to do such thing. I just a way that seems natural to me. I could use a LUT to call proper method too and set them with flags, there is many, many way. I can set those method written in ASM inside my C code so it's quite useful.

And this is not only for NMI, I do the same thing for IRQ too. So in my C code, I set one NMI handler that trigger the scanline counter and I set one IRQ handler that handle the counter. The thing is, I don't need the counter in all case but set it only when required. Another example, I have one transition between map that will require the counter for some issue I have. I will only set both handlers during that transition and when it is over, it will go back to the original ones.

Maybe I got those ideas because I remember during the dos days when you set interrupt handlers to read the keyboard in a better way, maybe. There is no perfect way and if in another project I need a generic NMI then I will program it, of course. I will do it based on my need and develop based on that.
Re: How does fceux detect a lag?
by on (#229660)
DRW wrote:
You were pretty much accusing the developers of fceux that they misname their features.

I said it doesn't precisely mean lag, and this is simply and factually true. The glossary link I posted above from the FCEUX documentation says as much.

This is not an "accusation", I was helping to define the term as used by FCEUX.

As for the way you interpreted my use of the word "you", well, maybe this is a language barrier thing, but:
https://en.wikipedia.org/wiki/Generic_you

Sorry if that was misread, but if you want to presume a hostile tone in everything I say, well, please don't. There was no hostility intended until my third post. I'm really not interested in debating that. I'll clarify what I meant, if you want, but I'm not going to argue about it.
Re: How does fceux detect a lag?
by on (#229678)
DRW wrote:
That's why I would suggest a generic PPU update array that is simply used for everything:

You have an array with the following values:
- data length
- PPUADDR high byte
- PPUADDR low byte
- tiles

I do essentially the same thing in my Popslide library, except it uses NES Stripe Image RLE as its buffer format for consistency with other NES games.

But that's on the whole unrelated to whether your program reads the controller after the NMI handler pushes data to VRAM and sets the scroll. And I agree with rainwarrior that "you" was probably intended in the same sense as German man. Would it have been clearer to use "someone", as in the following?
Pretend for a moment that rainwarrior wrote:
DRW wrote:
I personally always read the controller. This is basically one of the "system" functions and literally the first thing the game logic does in every frame.

If someone has more than one loop for different modes, there is really no point to reading the input and ignoring it.


EDIT: add example of "someone" phrasing
Re: How does fceux detect a lag?
by on (#229680)
tepples wrote:
DRW wrote:
That's why I would suggest a generic PPU update array that is simply used for everything:

You have an array with the following values:
- data length
- PPUADDR high byte
- PPUADDR low byte
- tiles

I do essentially the same thing in my Popslide library, except it uses NES Stripe Image RLE as its buffer format for consistency with other NES games.


One thing I've done for my current game (maybe it's overkill, I'm not sure I really need it) is have two different PPU update routines. One for during scrolling parts of gameplay where I know how the updates will be shaped, and I can unroll it a bit and optimize it. A separate one for all sorts of other menus/special cases/etc, which is slower but more flexible.
Re: How does fceux detect a lag?
by on (#229703)
gauauu wrote:
One thing I've done for my current game (maybe it's overkill, I'm not sure I really need it) is have two different PPU update routines. One for during scrolling parts of gameplay where I know how the updates will be shaped, and I can unroll it a bit and optimize it. A separate one for all sorts of other menus/special cases/etc, which is slower but more flexible.


It's not overkill: that's exactly what I'm doing ;) For the menu and title screen, the way the data is generated is different (for example, just a RLE screen is more than enough) so you don't need the metatile handing for the background and stuff like that. This is why my NMI/RTI code can be replaced is a special case occurs. This help a lot and even have some callback function inside NMI that request the C code to do menial stuff when necessary.

It's a case by case thing though. "All roads lead to Rome" ;)