[4.5.6] Non-Textbox Pause Script

CutterCross

Active member
I've seen a few people asking for an adaptation of the non-textbox based pause script Mugi / Dale developed for 4.1 and couldn't figure out how to port it themselves, so I went ahead and did that.

This is my quick recreation of the non-textbox pause script for 4.5.6, with PlaySound macros commented out for you to uncomment and use your own SFX labels / indices when you're ready to use them. Just assign it to the button you want to pause with under the game state you want it acting under:
Code:
    LDA gameStatusByte
    AND #%00000001
    BNE unpausegame
    INC gameStatusByte
    ;; OPTIONAL: Play pause sfx:
    ;PlaySound #SND_PAUSE    
    ;; OPTIONAL: Make the screen dark - set all 3 emphasis bits of $2001 to 1
    LDA soft2001
    ORA #%11100000
    STA soft2001
    RTS
unpausegame:
    LDA gameStatusByte
    AND #%11111110
    STA gameStatusByte
    ;; OPTIONAL: Play unpause sfx:
    ;PlaySound #SND_UNPAUSE
    ;; OPTIONAL: Make the screen normal - set all 3 emphasis bits of $2001 to 0
    LDA soft2001
    AND #%00011111
    STA soft2001
    RTS


Then, you'll want to open up your doHandleObjects.asm file and replace the first RTS at the end of the doHandleObjects label (line 5) to JMP JustDrawObject (assuming you still want all objects to draw when paused):
Code:
doHandleObjects:
    LDA gameStatusByte
    AND #%00000001 ;;; this will skip object handling.
    BEQ dontSkipObjectHandling
    JMP JustDrawObject


And of course, you can go into your Sprite PreDraw script and add in DrawSprite macros to write "PAUSED" or whatever indicator you want, and then add a conditional check for gameStatusByte to control when those sprites draw. You'll also want to put in similar conditional checks for gameStatusByte in any file that involves input or automated actions. So something like...
Code:
    LDA gameStatusByte
    AND #%00000001	;;;; when this bit is 1, the game is in a paused state.
    BNE skipRoutine
	
    ;;;; your routine here
	
skipRoutine:


Seeing as how gameHandler seems to have some free bits that don't control anything, I have no idea why Joe decided to make an extra byte to control 1 thing, but you could probably set things up so you can just use a free bit in gameHandler to do this and get rid of gameStatusByte entirely.
 

PasseGaming

Active member
Awesome, thank you. I am going to give this a try with my scrolling shooter. Hoping it works as many other pause scripts haven't. Just about ready to give up on this feature.
 

vanderblade

Active member
This works in the Brawler mod. Thanks, Cutter.

There is some major glitching if you try to want your sprites to remain visible, but I imagine it's because of automated systems that I have to fix with the GameStatusByte check you provided.
 
Last edited:

Jonny

Well-known member
you could probably set things up so you can just use a free bit in gameHandler to do this and get rid of gameStatusByte entirely.

I did this and it works fine. gameStatusByte is also used in doDrawBox.asm but changing that didn't seem to create any issues either.

I've got a few questions about doing this...

When disabling gameStatusByte (or any variable) in NesMaker, does that mean it will no longer compile with the game i.e free up that memory space? Or would it have to be actually deleted to not be included in the code? Pretty dumb question probably, I'm just asking because I ran space checker before and after and didn't notice a change. Maybe the difference is too small on its own?

Also, I didn't change the bits being used as I figured gameHandler bit 0 is for 'day or night' and I'm not using that in my game anyway. Is that the wrong thing to do?

And finally, whats the difference between "zero page RAM" and "overflow RAM". Is overflow RAM in a different bank or not necessarily?
 

CutterCross

Active member
I did this and it works fine. gameStatusByte is also used in doDrawBox.asm but changing that didn't seem to create any issues either.

I've got a few questions about doing this...

When disabling gameStatusByte (or any variable) in NesMaker, does that mean it will no longer compile with the game i.e free up that memory space? Or would it have to be actually deleted to not be included in the code? Pretty dumb question probably, I'm just asking because I ran space checker before and after and didn't notice a change. Maybe the difference is too small on its own?

Also, I didn't change the bits being used as I figured gameHandler bit 0 is for 'day or night' and I'm not using that in my game anyway. Is that the wrong thing to do?

And finally, whats the difference between "zero page RAM" and "overflow RAM". Is overflow RAM in a different bank or not necessarily?
gameStatusByte is a defined byte in RAM, not ROM, so of course you're not going to see it in NES Space Checker.

When you disable or remove a byte of RAM, you're basically just freeing up a RAM byte for other things. Now if you don't take advantage of that freed-up memory there's no tangible benefit, but it means when developing you have a little more RAM to work with.

When using bits in an already used variable it's good to search your full demo.txt file (using Notepad++'s keyword Search feature) to make sure it's not already using certain bits you plan on using. Bit 0 of gameHandler IS checked for in the Trigger scripts, so you'll want to instead use the free bits 1-4 to be safe.

The NES's 2 KB of RAM is split up into different sections. Zero Page RAM is the first page of the NES's onboard RAM ($0000-$00FF). NESmaker's User Variables also go in this area. The rest is Overflow RAM ($0100-07FF), which is shared with NESmaker's Object Variables, the stack, Sound RAM, Sprite RAM, Collision RAM, Scratch RAM (buffer), Scroll Update RAM (buffer), and the Overflow RAM variables.

The big main difference why you'd choose ZP RAM over Overflow RAM or vise-versa is that ZP RAM can be accessed more quickly by the CPU. So any variable that is going to be read / written to multiple times per frame is better off in ZP RAM. Anything else can be stored in Overflow RAM if it doesn't need that access speed. But it's a matter of priority, At the end of the day, they're still RAM.
 
Last edited:

Jonny

Well-known member
Ahh, thank you so much for this!
That's all extreamly helpful to me. I understand things a hell of a lot better now.

I'm going to change that bit and use your search tip going forward.

After tinkering with the Pause script and some input scripts I have almost got to exactly what I want to happen for my pausing...
(still got an issue to fix (see end of video) but I'll keep trying))

 

PasseGaming

Active member
I feel kind of stupid for asking but what does this life mean ";; OPTIONAL: Make the screen normal - set all 3 emphasis bits of $2001 to 0", like what bits do I set?
 

CutterCross

Active member
That comment is to note how the following lines are for setting the emphasis bits of PPU register $2001. I wrote that functionality in by default. I say it's "optional" because if you don't want to have the screen darken / normalize you can just comment those following lines out.

Darkens the screen:
Code:
    LDA soft2001
    ORA #%11100000
    STA soft2001

Restores screen brightness to normal:
Code:
    LDA soft2001
    AND #%00011111
    STA soft2001
 

Arctic Blizzard

New member
Thanks for posting this script Cutter Cross. Im using this script. It works great. Just been trying to figure out how to pause the music... The music still plays in pause state. Anybody know how I can pause the music as well. Any help would be greatly appreciated. I racked my brain for a week on this.
 

Razzie.P

Member
Anyone tried this with the arcade platformer module? I haven't had a chance to troubleshoot yet, but plugging in the code verbatim has 2 issues for me ---

1) it only seems to pause the player object. Everything else continues to run normally
2) It starts the first screen in "main game" with the player object paused. He's kind of suspended in air (at the warp in point) and can't be moved until I press start to "unpause" the game.

Probably something simple, and I hope to get a chance to check it out soon, but figured I'd see if anyone else has already cleared that hurdle and knew what was up.

Thanks!
 

Subotai

Active member
Anyone tried this with the arcade platformer module? I haven't had a chance to troubleshoot yet, but plugging in the code verbatim has 2 issues for me ---

1) it only seems to pause the player object. Everything else continues to run normally
2) It starts the first screen in "main game" with the player object paused. He's kind of suspended in air (at the warp in point) and can't be moved until I press start to "unpause" the game.

Probably something simple, and I hope to get a chance to check it out soon, but figured I'd see if anyone else has already cleared that hurdle and knew what was up.

Thanks!

Great script CutterCross, thanks for sharing it.

I'm using the Arcade Platformer module too.
When the game is paused, the player is able to animate without moving, but the monster continue to move.

In the section when you say : doHandleObjects.asm file and replace the first RTS at the end of the doHandleObjects label (line 5) to JMP JustDrawObject (assuming you still want all objects to draw when paused):

In my case, I prefer to rollback this section and keep the RTS in place, because when I'm pausing, I prefer to do not see any sprite. In that case even the monster don't move.
 

puppydrum64

Active member
I've seen a few people asking for an adaptation of the non-textbox based pause script Mugi / Dale developed for 4.1 and couldn't figure out how to port it themselves, so I went ahead and did that.

This is my quick recreation of the non-textbox pause script for 4.5.6, with PlaySound macros commented out for you to uncomment and use your own SFX labels / indices when you're ready to use them. Just assign it to the button you want to pause with under the game state you want it acting under:
Code:
    LDA gameStatusByte
    AND #%00000001
    BNE unpausegame
    INC gameStatusByte
    ;; OPTIONAL: Play pause sfx:
    ;PlaySound #SND_PAUSE   
    ;; OPTIONAL: Make the screen dark - set all 3 emphasis bits of $2001 to 1
    LDA soft2001
    ORA #%11100000
    STA soft2001
    RTS
unpausegame:
    LDA gameStatusByte
    AND #%11111110
    STA gameStatusByte
    ;; OPTIONAL: Play unpause sfx:
    ;PlaySound #SND_UNPAUSE
    ;; OPTIONAL: Make the screen normal - set all 3 emphasis bits of $2001 to 0
    LDA soft2001
    AND #%00011111
    STA soft2001
    RTS


Then, you'll want to open up your doHandleObjects.asm file and replace the first RTS at the end of the doHandleObjects label (line 5) to JMP JustDrawObject (assuming you still want all objects to draw when paused):
Code:
doHandleObjects:
    LDA gameStatusByte
    AND #%00000001 ;;; this will skip object handling.
    BEQ dontSkipObjectHandling
    JMP JustDrawObject


And of course, you can go into your Sprite PreDraw script and add in DrawSprite macros to write "PAUSED" or whatever indicator you want, and then add a conditional check for gameStatusByte to control when those sprites draw. You'll also want to put in similar conditional checks for gameStatusByte in any file that involves input or automated actions. So something like...
Code:
    LDA gameStatusByte
    AND #%00000001    ;;;; when this bit is 1, the game is in a paused state.
    BNE skipRoutine
   
    ;;;; your routine here
   
skipRoutine:


Seeing as how gameHandler seems to have some free bits that don't control anything, I have no idea why Joe decided to make an extra byte to control 1 thing, but you could probably set things up so you can just use a free bit in gameHandler to do this and get rid of gameStatusByte entirely.
Here's a question: How do the enemies know to continue doing what they were doing after you unpause? Does their programming pick up where they left off? If they were moving before pausing, will they continue after you unpause? Or will their AI "reset" as if you just entered the room again?
 

offparkway

Active member
Great script CutterCross, thanks for sharing it.

I'm using the Arcade Platformer module too.
When the game is paused, the player is able to animate without moving, but the monster continue to move.

In the section when you say : doHandleObjects.asm file and replace the first RTS at the end of the doHandleObjects label (line 5) to JMP JustDrawObject (assuming you still want all objects to draw when paused):

In my case, I prefer to rollback this section and keep the RTS in place, because when I'm pausing, I prefer to do not see any sprite. In that case even the monster don't move.
Same. Player still "walks" but doesn't move, and monsters still move and attack.
 

TolerantX

Active member
Using this in MAZE module. well, trying to. I got stuck. View attachment 5922
Bro, you can use my scripts. They're in the downloads in my video. Here's the video link. They're pretty general for this...
View: https://youtu.be/-5HMF3KDXJI

Be sure to download the TEXT file, watch the video and (unfortunately, apologies for mentioning this) please read this topic from beginning to end. You know I have always and will always have so much confidence in you (and your ability to succeed) and help you with anything, my dear friend.


(I will edit this post in the future and add the pause scripts to my repository.)
 

ResidentEmil

New member
is there any way to get the pause text to render from the hud bank tileset instead of the GameObject tiles? I've been trying to figure this out for a while and I'm low on space in the object tiles, so using part of it just for text that exists in another bank doesn't quite make sense in my case.. I've looked through how the hud is handling text and also how textbox rendering handles it but can't seem to put something together that works within the context of SpritePostDraw (and switching banks before rendering the PAUSE text just crashes the game)
 

Attachments

  • Capture.PNG
    Capture.PNG
    90 KB · Views: 2

SciNEStist

Well-known member
I too know the pain of a full game object sheet and trying to force "just one more thing" in there.

As far as I know, sprite tiles and background tiles aren't treated the same, so it might not be very easy to accomplish that.

You might be able to use your monster tile sets though, just have it pull a tile higher than #128 and see if it starts showing those tiles. If that does work, the cost of this is you would have to put them in ALL your monster tileset images in the same spot.
 
Top Bottom