Game project help and progress thread

A place where you can keep others updated about your NES-related projects through screenshots, videos or information in general.

Moderator: Moderators

Post Reply
User avatar
Tsutarja
Posts: 123
Joined: Sun Oct 12, 2014 11:06 am
Location: Finland

Game project help and progress thread

Post by Tsutarja »

In this thread I'll be sharing progress and asking help if there is something I can't figure out.
Right now I have few questions:
1. What would be the best way to do a fade in/out with a single routine?
2. What would be a good way to make main loop recognize the game's state (title, paused, main game, cutscene etc.)? Should I put a short code at the beginning of the main loop that checks a variable for game state and then jumps to that part of the main loop?
3. How do I make indirect jump with NESASM3? Most places seem to use JMP (address), but it doesn't seem to work. NESASM seems to convert it to a absolute jump.
UP SIDE DOWN A B A B B A B A Hidari migi
L R L R STOP & DASH & UP & TALK Ijou nashi
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Game project help and progress thread

Post by tepples »

1. What do you mean by "single routine"?

You'll have to compute the faded palette and then write it to the PPU during vblank. Which step are you looking for?

3. NESASM requires the nonstandard JMP [address] for indirection.
User avatar
Bregalad
Posts: 8056
Joined: Fri Nov 12, 2004 2:49 pm
Location: Divonne-les-bains, France

Re: Game project help and progress thread

Post by Bregalad »

1. Basically you need to keep a buffer with the internal state of the palette, and darkens the values that sits here before writing them to the hardware palette. Fading out means substracting $10 from all entries, and using $0f whenever an entry becomes negative. Fading in is more complicated and there is several approaches you could use (personally I don't fade the palette in :) )

2. Normally the PC (program counter) holds the game's state. Only if you are going in a "everything in NMI" type of code architecture will you have to do something like what you described, whenever you want to do that is up to you.
User avatar
Tsutarja
Posts: 123
Joined: Sun Oct 12, 2014 11:06 am
Location: Finland

Re: Game project help and progress thread

Post by Tsutarja »

Bregalad wrote:1. Basically you need to keep a buffer with the internal state of the palette, and darkens the values that sits here before writing them to the hardware palette. Fading out means substracting $10 from all entries, and using $0f whenever an entry becomes negative. Fading in is more complicated and there is several approaches you could use (personally I don't fade the palette in :) )
The only reason I want the fade is because in title screen when you press start, the screen will start wobbling a little and fades out before the game starts. I don't have other plans for fading yet, but If I can make it work as a routine that checks variables for what it should do etc., I could use it elsewhere too.
Bregalad wrote:2. Normally the PC (program counter) holds the game's state. Only if you are going in a "everything in NMI" type of code architecture will you have to do something like what you described, whenever you want to do that is up to you.
How does the program counter do that? I haven't heard of it begin able to do that.
UP SIDE DOWN A B A B B A B A Hidari migi
L R L R STOP & DASH & UP & TALK Ijou nashi
User avatar
Bregalad
Posts: 8056
Joined: Fri Nov 12, 2004 2:49 pm
Location: Divonne-les-bains, France

Re: Game project help and progress thread

Post by Bregalad »

Mmh, a good idea would be to keep a "darkness" level, where 0 = normal, 1 = a little dark, 2 = medium dark, 3 = completely dark, 4 = black.

Then, you substract (darkness << 4) from each palette and use $0f whenever the result is negative as you update the palette, without writing the result back in the palette buffer. That would allow both fade in, out, and darkness changes anytime during gameplay. The main problem is that it would not allow to have lightness greater than normal, but that is not what you asked for.

For the program counter it's completely transparent. You just have different parts of your game coded as different routines (or different parts of the main routine), and the PC keeps tracks of this, because that's how the 6502 works. It couldn't get simpler really.
User avatar
Tsutarja
Posts: 123
Joined: Sun Oct 12, 2014 11:06 am
Location: Finland

Re: Game project help and progress thread

Post by Tsutarja »

Bregalad wrote: For the program counter it's completely transparent. You just have different parts of your game coded as different routines (or different parts of the main routine), and the PC keeps tracks of this, because that's how the 6502 works. It couldn't get simpler really.
So, do you mean that I need to have something like this:

Code: Select all

MainLoopTitle:
; Code
SleepTitle:
; Check for "sleep" variable
JMP MainLoopTitle

MainLoopGame:
; Code
SleepGame:
; Check for "sleep" variable
JMP MainLoopGame

MainLoopPaused:
; Code
SleepPaused:
; Check for "sleep" variable
JMP MainLoopPaused

MainLoopScene:
; Code
SleepScene:
; Check for "sleep" variable
JMP MainLoopScene

; And so on...
UP SIDE DOWN A B A B B A B A Hidari migi
L R L R STOP & DASH & UP & TALK Ijou nashi
User avatar
Bregalad
Posts: 8056
Joined: Fri Nov 12, 2004 2:49 pm
Location: Divonne-les-bains, France

Re: Game project help and progress thread

Post by Bregalad »

No. I don't even know what is your sleep variable. Why would you want multiple main loops ? Just one is enough. However if you do it differently than me, if it works and if it makes more sense for you by all means go for it.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Game project help and progress thread

Post by tokumaru »

Tsutarja wrote:1. What would be the best way to do a fade in/out with a single routine?
I like to keep a copy of the unmodified palette in RAM, and have a routine generate a darkened copy of it based on a global brightness level. Pretty much what Bregalad said, except I'm not a big fan of the 4-step fade because it looks very jerky unless you animate it really fast, which kinda defeats the purpose of having a fading routine, which is to make transitions smoother. I prefer to simulate more brightness levels in some way, like darkening the colors one frame, moving them towards blue the other frame, or darkening colors of different brightness at different times ($0x colors become black, then $1x colors become $0x, and so on, until they're all black). You can use whatever darkening method you like in the fading function.
2. What would be a good way to make main loop recognize the game's state (title, paused, main game, cutscene etc.)? Should I put a short code at the beginning of the main loop that checks a variable for game state and then jumps to that part of the main loop?
I vote for different loops for different states. In fact, all the different states in my programs have an entry point, where any necessary initialization takes place, followed by the loop itself. This way I can switch to another game mode simply by JMPing to its entry point.

Code: Select all

InitializeTitleScreen:
	;initialize variables, draw the name table, etc.
UpdateTitleScreen:
	;read controllers, move the cursor, etc.
	jmp UpdateTitleScreen

InitializeGameplay:
	;initialize variables, decode a level, set up the pattern tables, etc.
UpdateGameplay:
	;read the controllers, process game objects, etc.
	jmp UpdateGameplay
Depending on how complex your pause screen is, it might not deserve its own state, but if it's a complicated menu or something, you might want to make it a sub-state, since it will interrupt the gameplay and resume it later. The main difference is that its initialization can't be destructive, it has to use RAM that's not in use by the parent state and it has to be aware that modifications to the screen and other things used by the gameplay have to be undone before returning.

In my projects I even allow custom NMI routines for the different states. My NMI checks the high byte of a pointer in RAM, and if that byte isn't 0, it jumps to that address. If the byte is 0, it just sets a flag indicating that VBlank has started, so that simpler game states can use the good old "wait for VBlank" structure.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Game project help and progress thread

Post by tokumaru »

Bregalad wrote:No. I don't even know what is your sleep variable. Why would you want multiple main loops ?
I also have no idea what the sleep variable is, but multiple main loops help keep the program organized and the different parts independent from each other. Personally I'd prefer that over spaghetti code with multiple game states mixed together any day. If separate game states happen to share a lot of code, you can consider merging them or turning the shared code into subroutines.
User avatar
Bregalad
Posts: 8056
Joined: Fri Nov 12, 2004 2:49 pm
Location: Divonne-les-bains, France

Re: Game project help and progress thread

Post by Bregalad »

Oh, the method tokumaru posted looks quite organized and powerful. Personally I just don't work with "states" at all. To pause the game, well I just read the controller until start is pressed again and then return. Same for the title screen, I have a loop and when start is pressed, it continues down into the main program. It is just logical for me. However, it might not be as organized.

I think what I describe above could be considered multiple game loops. However, all of them are implicit, they are just natural, because I don't leave a routine (or part of a routine) until some event happen that makes me leave it with the rts instruction.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Game project help and progress thread

Post by tokumaru »

Bregalad wrote:Personally I just don't work with "states" at all. To pause the game, well I just read the controller until start is pressed again and then return. Same for the title screen, I have a loop and when start is pressed, it continues down into the main program. It is just logical for me.
I don't think this is bad as long as the states aren't very complex. A pause screen that does nothing but wait for the game to be unpaused certainly doesn't deserve its own state. The same goes for a title screen that only waits for start. But once you have states that allow navigation and so on, I think it becomes important to separate things, otherwise the code might become hell to maintain.
I think what I describe above could be considered multiple game loops. However, all of them are implicit, they are just natural, because I don't leave a routine (or part of a routine) until some event happen that makes me leave it with the rts instruction.
Yeah, I guess it's not that different.
User avatar
Tsutarja
Posts: 123
Joined: Sun Oct 12, 2014 11:06 am
Location: Finland

Re: Game project help and progress thread

Post by Tsutarja »

The sleep variable is what prevents main loop from running more than once per frame. I have seen a lot of people use this name for it.
UP SIDE DOWN A B A B B A B A Hidari migi
L R L R STOP & DASH & UP & TALK Ijou nashi
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Game project help and progress thread

Post by tokumaru »

Tsutarja wrote:The sleep variable is what prevents main loop from running more than once per frame.
In other words, it's a wait for VBlank.
zzo38
Posts: 1096
Joined: Mon Feb 07, 2011 12:46 pm

Re: Game project help and progress thread

Post by zzo38 »

When using NESASM, remember these feature of its syntax:
  • For zero page addressing, put < before the address or label (for example LDA <var0 if your variable in the zero page is called var0).
  • For indirection in all cases, you must use square brackets rather than parentheses.
Some people (including myself) prefer this nonstandard syntax, although still remember it is nonstandard and many documents don't use it.
(Free Hero Mesh - FOSS puzzle game engine)
User avatar
Tsutarja
Posts: 123
Joined: Sun Oct 12, 2014 11:06 am
Location: Finland

Re: Game project help and progress thread

Post by Tsutarja »

zzo38 wrote:When using NESASM, remember these feature of its syntax:
  • For zero page addressing, put < before the address or label (for example LDA <var0 if your variable in the zero page is called var0).
  • For indirection in all cases, you must use square brackets rather than parentheses.
Some people (including myself) prefer this nonstandard syntax, although still remember it is nonstandard and many documents don't use it.
Is there a syntax guide for NESASM somewhere? I haven't been able to find one. I feel like there might be some functions in NESASM that I don't know about.
UP SIDE DOWN A B A B B A B A Hidari migi
L R L R STOP & DASH & UP & TALK Ijou nashi
Post Reply