Sadly, I am stuck with an example and I don't manage to see the mistake by my own.
The exercise is in principle very simple:
1) set the background to green
2) wait until the user press START
3) set the bg to blue
4) wait until the user press START
5) set the bg to red
The problem is: my code seems to go from (2) directly to (5), ignoring the waiting in the between.
In other words, when start is pressed, the background goes directly from green to red, while I expect to have the pause with the blue picture.
I know that I omitted the classic "memory clear" at the beginning, but I doubt that the problem lies there.
Meanwhile, I noticed another related problem.
I tried to debug my code with fceux, the emulator I am currently using, but, when in debug mode, what is the best way to handle the controller input?
My code is attached, including the assembler (original NESASM3.zip file), the needed "mario.chr" file (unused but needed to assemble) and the .nes.
Thank you in advance for any kind of feedback!
If that's the case, there are two things you can do:
1- Frame-limit you program: the NES generates pictures at 60fps, and games work by animating everything in the scene bit by bit between frames. For this to work, you have update the game state by one logic frame, wait for that frame to be displayed, then do the update for the next frame, and repeat this forever. If you don't wait for frames to be displayed, you're gonna process several logic frames at once. In your program, the work you have to do each frame is: read the controller, then decide whether to change the color. You're supposed to do this only once per frame, otherwise you'll change the color more than once per frame and not see all the changes. The exact method you can use to implement frame-limiting will vary depending on the program structure you're using (all in NMI, all in main or main + NMI). All in NMI practically gives you free frame-limiting, just do the work of one frame and RTI - your game loop will be called once per frame automatically. All in main requires you to wait for the NMI to fire before looping back and executing another iteration of your game loop. This is commonly achieved by incrementing a counter in the NMI handler (e.g. INC FrameCounter) and waiting for that counter to change in the main thread. For example:
Code: Select all
GameLoop: ;do the work of 1 frame here lda FrameCounter Wait: cmp FameCounter beq Wait jmp GameLoop
2- Check for changes in the input, not the immediate state of the buttons: even if you frame-limit your program to process input only once per frame, the vast majority of players will hold buttons down for longer than a frame, meaning that the screen would be blue for a single frame, and then red, since start would be pressed for 2 consecutive frames. The solution to that is to trigger the color changes only button transitions from not pressed to pressed, so you can only change colors again if you release the button and press it again. In your program, the simplest way to do that is to save the previous state of the button to another variable before reading the new state, and then check both states when deciding whether to change the color: the old state has to be "not pressed" and the new state has to be "pressed", otherwise, don't change colors. In actual games, there are also actions that should only start on button state changes, such as shooting: you don't want to spawn bullets every frame for as long as the player holds the fire button down, you want to spawn a single bullet in the frame when the button goes from "not pressed" to "pressed" and that's it.
The quickest fix here is very simple: before waiting for the second keypress, wait for the button to be released before waiting for it to be pressed again (e.g. make a "WaitForNoStart" subroutine that tests the opposite condition, and returns only when start is NOT pressed, then call that subroutine between the 2 color changes).
My apologies for being a bit in late: before replying, I wanted to be completely sure to have properly understood all your points.
So I wrote the same exercise multiple times and using all the different approaches, and they worked well
Another step is done, thanks again