It is currently Fri Nov 24, 2017 4:56 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 106 posts ]  Go to page 1, 2, 3, 4, 5 ... 8  Next
Author Message
PostPosted: Mon Mar 23, 2015 1:42 am 
Offline
User avatar

Joined: Sun Oct 12, 2014 11:06 am
Posts: 123
Location: Finland
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


Top
 Profile  
 
PostPosted: Mon Mar 23, 2015 6:15 am 
Offline

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


Top
 Profile  
 
PostPosted: Mon Mar 23, 2015 6:21 am 
Offline
User avatar

Joined: Fri Nov 12, 2004 2:49 pm
Posts: 7274
Location: Chexbres, VD, Switzerland
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.


Top
 Profile  
 
PostPosted: Mon Mar 23, 2015 6:43 am 
Offline
User avatar

Joined: Sun Oct 12, 2014 11:06 am
Posts: 123
Location: Finland
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


Top
 Profile  
 
PostPosted: Mon Mar 23, 2015 7:18 am 
Offline
User avatar

Joined: Fri Nov 12, 2004 2:49 pm
Posts: 7274
Location: Chexbres, VD, Switzerland
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.


Top
 Profile  
 
PostPosted: Mon Mar 23, 2015 8:02 am 
Offline
User avatar

Joined: Sun Oct 12, 2014 11:06 am
Posts: 123
Location: Finland
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:
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


Top
 Profile  
 
PostPosted: Mon Mar 23, 2015 8:55 am 
Offline
User avatar

Joined: Fri Nov 12, 2004 2:49 pm
Posts: 7274
Location: Chexbres, VD, Switzerland
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.


Top
 Profile  
 
PostPosted: Mon Mar 23, 2015 9:07 am 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10119
Location: Rio de Janeiro - Brazil
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.

Quote:
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:
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.


Top
 Profile  
 
PostPosted: Mon Mar 23, 2015 9:11 am 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10119
Location: Rio de Janeiro - Brazil
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.


Top
 Profile  
 
PostPosted: Mon Mar 23, 2015 9:13 am 
Offline
User avatar

Joined: Fri Nov 12, 2004 2:49 pm
Posts: 7274
Location: Chexbres, VD, Switzerland
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.


Top
 Profile  
 
PostPosted: Mon Mar 23, 2015 9:23 am 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10119
Location: Rio de Janeiro - Brazil
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.

Quote:
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.


Top
 Profile  
 
PostPosted: Mon Mar 23, 2015 10:38 am 
Offline
User avatar

Joined: Sun Oct 12, 2014 11:06 am
Posts: 123
Location: Finland
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


Top
 Profile  
 
PostPosted: Mon Mar 23, 2015 10:58 am 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10119
Location: Rio de Janeiro - Brazil
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.


Top
 Profile  
 
PostPosted: Mon Mar 23, 2015 5:06 pm 
Offline
User avatar

Joined: Mon Feb 07, 2011 12:46 pm
Posts: 932
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.

_________________
.


Top
 Profile  
 
PostPosted: Tue Mar 24, 2015 12:06 am 
Offline
User avatar

Joined: Sun Oct 12, 2014 11:06 am
Posts: 123
Location: Finland
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


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 106 posts ]  Go to page 1, 2, 3, 4, 5 ... 8  Next

All times are UTC - 7 hours


Who is online

Users browsing this forum: Bing [Bot] and 4 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