It is currently Wed Dec 12, 2018 3:44 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 23 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: Sun Dec 02, 2018 11:55 am 
Offline
User avatar

Joined: Sat Sep 07, 2013 2:59 pm
Posts: 1765
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.

_________________
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 Dec 02, 2018 12:11 pm 
Offline

Joined: Sun Apr 13, 2008 11:12 am
Posts: 7817
Location: Seattle
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.


Top
 Profile  
 
PostPosted: Sun Dec 02, 2018 12:25 pm 
Offline
User avatar

Joined: Sat Sep 07, 2013 2:59 pm
Posts: 1765
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.

_________________
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 Dec 02, 2018 2:47 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 20854
Location: NE Indiana, USA (NTSC)
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.


Top
 Profile  
 
PostPosted: Sun Dec 02, 2018 2:49 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 7011
Location: Canada
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.


Top
 Profile  
 
PostPosted: Sun Dec 02, 2018 3:00 pm 
Offline
User avatar

Joined: Sat Sep 07, 2013 2:59 pm
Posts: 1765
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.

_________________
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 Dec 02, 2018 3:19 pm 
Offline
User avatar

Joined: Thu Aug 13, 2015 4:40 pm
Posts: 325
Location: Rio de Janeiro - Brazil
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.

_________________
https://twitter.com/bitinkstudios <- Follow me on twitter! Thanks!


Top
 Profile  
 
PostPosted: Sun Dec 02, 2018 3:30 pm 
Offline
User avatar

Joined: Sat Sep 07, 2013 2:59 pm
Posts: 1765
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.

_________________
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 Dec 02, 2018 6:00 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 7011
Location: Canada
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.


Top
 Profile  
 
PostPosted: Sun Dec 02, 2018 6:48 pm 
Offline
User avatar

Joined: Sat Jan 09, 2016 9:21 pm
Posts: 518
Location: Central Illinois, USA
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.

_________________
My games: http://www.bitethechili.com


Top
 Profile  
 
PostPosted: Sun Dec 02, 2018 6:53 pm 
Offline
User avatar

Joined: Tue Jun 24, 2008 8:38 pm
Posts: 2124
Location: Fukuoka, Japan
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.


Top
 Profile  
 
PostPosted: Sun Dec 02, 2018 7:09 pm 
Offline
User avatar

Joined: Sat Sep 07, 2013 2:59 pm
Posts: 1765
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.

_________________
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 Dec 02, 2018 8:52 pm 
Offline
User avatar

Joined: Fri Nov 19, 2004 7:35 pm
Posts: 4108
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.

_________________
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!


Top
 Profile  
 
PostPosted: Sun Dec 02, 2018 8:54 pm 
Offline
User avatar

Joined: Tue Jun 24, 2008 8:38 pm
Posts: 2124
Location: Fukuoka, Japan
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.


Top
 Profile  
 
PostPosted: Sun Dec 02, 2018 11:23 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 7011
Location: Canada
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.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 23 posts ]  Go to page 1, 2  Next

All times are UTC - 7 hours


Who is online

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