Bucket Mouse
Active member
It appears in just a few short days I'll have access to the NES Maker beta. Though the proper introduction would be to take things slowly and work within the limits of its capabilities.....I know myself, and it won't be long before my impatient self tries to figure out how to make cutscenes.
When I say cutscenes I don't mean giant still drawings accompanied with text -- graphical data is at a premium and you can only have a scarce few of those, best saved for the opening and ending scenes. Also, the tool to make them is already in NES Maker anyway. Instead of dedicated drawings, many games in the NES's era told their narratives by creating scenes where the sprites moved and changed position on their own, speaking with text boxes.
I've brought this up several times with the NES Maker Makers and they've implied they have no interest in automating cutscenes, and that it won't be a feature unless someone else figures it out and creates some kind of plug-in.
Great. Assembly is totally foreign to me. Everything I know about programming, I learned in BASIC. This is how I would set up a cutscene to trigger itself in that language:
CUT=1
First I would set up a variable and turn it on at the appropriate point. This would appear in the code after the player performed a certain unrepeatable action.
IF CUT=1 THEN GOSUB 65000
Then I would set up a door or a tile with this command. If this flag is up when the player steps on the tile or opens the door, the program subroutines to where the cutscene data is.
X=20: FOR A=1 TO 15: X=X+1: DRAW (SPRITE1) AT 30,X: XDRAW (SPRITE A) AT 30,X: NEXT A
Here is how I would make the sprites move in the cutscene. X is the variable representing the vertical coordinate. I create a loop with A that repeats itself 15 times. Outside of the loop I define X as 20. Within the loop the program adds 1 to that and continues to add 1 with each loop-around, making the sprite move down 15 pixels by itself.
I already know at least one of these things is different on NES. On the Apple II you had to undraw a sprite from a frame before you drew it again. That creates a flickering effect, but in BASIC it was the only way. (You could code in Assembly on Apple to avoid that -- it used the same 6502 processor that the NES did.)
As for the text....simple. "PRINT "BLAH BLAH BLAH DIALOGUE." That was easy with BASIC.
CUT=0: RETURN
After the scene finishes, the final bit of code before leaving the subroutine sets CUT back to 0, ensuring the scene will not repeat every time the player steps on that tile or opens that door.
****
So....how do I translate this to something the NES can understand? After hours of poring over Nerdy Nights, I'm going to take a stab at cobbling it together. I'm under no delusion that any of this is correct. You can tell me where I've got it wrong.
First off....how to set the flag.
LDA #$07
This flag should only go up once in the game. I'm not sure yet how to make flags unrepeatable in Assembly.
It's my understanding that the digit being loaded here could be anything because it's intended as a flag. I've made it a 7.
STA $802C
It won't be long before that byte of memory is rewritten with something else, so we should save it. I'll stick it here and remember that address later.
Now the player has opened the door, or stepped on the tile. We need an IF-THEN-ELSE argument.
LDA $802C
Before we begin let's load the number back in.
CMP #$07
CMP means "Compare," assigned to a value of 7. If A equals 7.....
BEQ $FF00
BEQ means "Branch If Equal." CMP and BEQ are used together. If A equals 7 THEN jump to $FF00, the address in the ROM where the cutscene data is.
Like we did in BASIC, the last thing we should do in that data is establish a value of 0 at $802C. The next time the player performs the same action, the game will read that address and not get a 7, thereby refusing to trigger the cutscene.
But how to make the cutscene itself? This requires more thought, and it is getting late.
In the meantime, someone who knows Assembly better than me can point out my mistakes and suggest corrections.
When I say cutscenes I don't mean giant still drawings accompanied with text -- graphical data is at a premium and you can only have a scarce few of those, best saved for the opening and ending scenes. Also, the tool to make them is already in NES Maker anyway. Instead of dedicated drawings, many games in the NES's era told their narratives by creating scenes where the sprites moved and changed position on their own, speaking with text boxes.
I've brought this up several times with the NES Maker Makers and they've implied they have no interest in automating cutscenes, and that it won't be a feature unless someone else figures it out and creates some kind of plug-in.
Great. Assembly is totally foreign to me. Everything I know about programming, I learned in BASIC. This is how I would set up a cutscene to trigger itself in that language:
CUT=1
First I would set up a variable and turn it on at the appropriate point. This would appear in the code after the player performed a certain unrepeatable action.
IF CUT=1 THEN GOSUB 65000
Then I would set up a door or a tile with this command. If this flag is up when the player steps on the tile or opens the door, the program subroutines to where the cutscene data is.
X=20: FOR A=1 TO 15: X=X+1: DRAW (SPRITE1) AT 30,X: XDRAW (SPRITE A) AT 30,X: NEXT A
Here is how I would make the sprites move in the cutscene. X is the variable representing the vertical coordinate. I create a loop with A that repeats itself 15 times. Outside of the loop I define X as 20. Within the loop the program adds 1 to that and continues to add 1 with each loop-around, making the sprite move down 15 pixels by itself.
I already know at least one of these things is different on NES. On the Apple II you had to undraw a sprite from a frame before you drew it again. That creates a flickering effect, but in BASIC it was the only way. (You could code in Assembly on Apple to avoid that -- it used the same 6502 processor that the NES did.)
As for the text....simple. "PRINT "BLAH BLAH BLAH DIALOGUE." That was easy with BASIC.
CUT=0: RETURN
After the scene finishes, the final bit of code before leaving the subroutine sets CUT back to 0, ensuring the scene will not repeat every time the player steps on that tile or opens that door.
****
So....how do I translate this to something the NES can understand? After hours of poring over Nerdy Nights, I'm going to take a stab at cobbling it together. I'm under no delusion that any of this is correct. You can tell me where I've got it wrong.
First off....how to set the flag.
LDA #$07
This flag should only go up once in the game. I'm not sure yet how to make flags unrepeatable in Assembly.
It's my understanding that the digit being loaded here could be anything because it's intended as a flag. I've made it a 7.
STA $802C
It won't be long before that byte of memory is rewritten with something else, so we should save it. I'll stick it here and remember that address later.
Now the player has opened the door, or stepped on the tile. We need an IF-THEN-ELSE argument.
LDA $802C
Before we begin let's load the number back in.
CMP #$07
CMP means "Compare," assigned to a value of 7. If A equals 7.....
BEQ $FF00
BEQ means "Branch If Equal." CMP and BEQ are used together. If A equals 7 THEN jump to $FF00, the address in the ROM where the cutscene data is.
Like we did in BASIC, the last thing we should do in that data is establish a value of 0 at $802C. The next time the player performs the same action, the game will read that address and not get a 7, thereby refusing to trigger the cutscene.
But how to make the cutscene itself? This requires more thought, and it is getting late.
In the meantime, someone who knows Assembly better than me can point out my mistakes and suggest corrections.