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

All times are UTC - 7 hours





Post new topic Reply to topic  [ 23 posts ]  Go to page Previous  1, 2
Author Message
PostPosted: Mon Dec 03, 2018 12:24 am 
Offline
User avatar

Joined: Thu Mar 31, 2016 11:15 am
Posts: 441
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.


Top
 Profile  
 
PostPosted: Mon Dec 03, 2018 1:09 am 
Offline
User avatar

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

_________________
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: Mon Dec 03, 2018 1:51 am 
Offline
User avatar

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

_________________
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: Mon Dec 03, 2018 2:14 am 
Offline
User avatar

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


Top
 Profile  
 
PostPosted: Mon Dec 03, 2018 2:22 am 
Offline
User avatar

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


Top
 Profile  
 
PostPosted: Mon Dec 03, 2018 8:35 am 
Offline

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


Top
 Profile  
 
PostPosted: Mon Dec 03, 2018 8:45 am 
Offline
User avatar

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

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


Top
 Profile  
 
PostPosted: Mon Dec 03, 2018 5:39 pm 
Offline
User avatar

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


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

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 2 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:  
cron
Powered by phpBB® Forum Software © phpBB Group