Non-textbox based pause

Razzie.P

Member
Works great. Thanks! I don't think I would have figured that out on my own anytime soon.

I'm not familiar with discord. Guess it's time to check that out and see what useful info is happening on there.
 

dale_coop

Moderator
Staff member
Glad it worked ;)

Discord is more for direct tchat... talking... helping each others. I am new there, but it's fun.
 

Raftronaut

Member
dale_coop said:
As Kasumi epxlained somewhere (on the Discord channel maybe), for pausing the music...
Modify the MainASM.asm script, under the "skipNMIstuff:", you will find this block of code:

Code:
	LDA currentBank
	STA prevBank
	LDY #BANK_MUSIC  ;; switch to music bank
	JSR bankswitchY
	soundengine_update  
	LDY prevBank
	JSR bankswitchY

Comment those 7 lines, like this:

Code:
	; LDA currentBank
	; STA prevBank
	; LDY #BANK_MUSIC  ;; switch to music bank
	; JSR bankswitchY
	; soundengine_update  
	; LDY prevBank
	; JSR bankswitchY

And just after them, add this block of code:

Code:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; PAUSE MUSIC
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	LDA currentBank
	STA prevBank
	LDY #BANK_MUSIC  ;; switch to music bank
	JSR bankswitchY

	LDA isPaused
	BEQ unpause_music
	JSR pause_song
	JMP post_pause_music_handle
unpause_music:
	JSR resume_song
post_pause_music_handle:
	soundengine_update  
	LDY prevBank
	JSR bankswitchY   
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


Ooooh, this has been fairly low on my priority list, but it certainly has been on my mind to do something with. Pausing the music completely would probably the BEST thing to do with the music while paused... however.... I had a discussion with Kasumi about the Mother soundtrack and how the DPCM drums are muted whenever a sub-menu is opened.. (Maybe this is due to CPU usage) it creates a really unique aspect to the sound design, whenever you close a sub-menu the Drums kick back in and you are launched back into the action! This might be of use to other Nesmakers as well, which is why I bring it up. Kasumi mentioned that GGsound has the capability to Mute up to two channels independently... I had thought it would be interesting to try something like this, and MUTE my drums and melody when the game is paused, then when unpaused the player would feel thrown back into the action...

Kasumi dropped this code on me, but I am still too inexperienced to understand how to put it to use:

Code:
ldx #1;Square 2
    lda stream_flags,x
    ora #STREAM_SILENCE_SET
    sta stream_flags,x

    lda stream_channel_register_1,x
    and #%11110000
    sta stream_channel_register_1,x

Does anyone have any insight as to whether or not this will work?

If so, I Imagine it could be used in all many different scripts for cool sound tricks, like muting melody when displaying text boxes, Or this pause screen application, or muting sound channel during certain enemy AI actions, or an Ice bomb that temporarily mutes the drums or something....Seems like playing with the lack of sound could be used creatively here...
 

Mugi

Member
well, Kasumi generally knows what he's talking about so i'd assume it does work, although i havent looked at the sound flags myself to verify if these are correct.

basically it should work if you put this into the pause script for the pause function, and an opposite function (to unmute the channels) into the unpause function.
 

Raftronaut

Member
Mugi said:
well, Kasumi generally knows what he's talking about so i'd assume it does work, although i havent looked at the sound flags myself to verify if these are correct.

basically it should work if you put this into the pause script for the pause function, and an opposite function (to unmute the channels) into the unpause function.

Any idea what the label would be for the Noise channel? The script shows square 2, in this case would it simply be: noise?
 

Mugi

Member
well the channels go in order as far as i know,
0: square 1
1: square 2
2: triangle
3: noise

kasumi's script loads 1 in X
Code:
ldx #1 ;Square 2

again, going off my head here, i really didnt dig that much into the sound driver since my parallaxer made it impossible for me to use DPCM and i had no reason to mess with it anymore :p
 

Raftronaut

Member
LOL, off topic but I love the idea of Parallax being a proper noun or verb..

"what are you up to?" "Oh, not much... just... Parallaxing"
 

Kasumi

New member
Raftronaut said:
Kasumi dropped this code on me, but I am still too inexperienced to understand how to put it to use:

Code:
ldx #1;Square 2
    lda stream_flags,x
    ora #STREAM_SILENCE_SET
    sta stream_flags,x

    lda stream_channel_register_1,x
    and #%11110000
    sta stream_channel_register_1,x

Does anyone have any insight as to whether or not this will work?
Yes, it works.

Anyway, there's not much to getting it to work. Every frame you run the above code, Square 2 won't play. With ldx #0, every frame you run the above code, Square 1 won't play. To mute both in place of pausing using the code dale_coop posted above, you'd do:
Code:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; PAUSE MUSIC
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	LDA currentBank
	STA prevBank
	LDY #BANK_MUSIC  ;; switch to music bank
	JSR bankswitchY

	LDA isPaused
	BEQ unpause_music
	ldx #0;Square 1
    lda stream_flags,x
    ora #STREAM_SILENCE_SET
    sta stream_flags,x

    lda stream_channel_register_1,x
    and #%11110000
    sta stream_channel_register_1,x

    ldx #1;Square 2
    lda stream_flags,x
    ora #STREAM_SILENCE_SET
    sta stream_flags,x

    lda stream_channel_register_1,x
    and #%11110000
    sta stream_channel_register_1,x
unpause_music:
post_pause_music_handle:
	soundengine_update  
	LDY prevBank
	JSR bankswitchY   
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
There's no need to "unsilence", because the engine seems to do it every note. So if you want something silenced, set STREAM_SILENCE_SET that frame, and if you don't want something silenced, do nothing.

It doesn't work with the triangle or the noise channels because only square_1_play_note and square_2_play_note respect the flag. (DPCM also seems to respect it, but I haven't tested.) The engine is capable of pausing, but not pausing all channels breaks playback (the ones you don't pause continue to play, so when the paused ones are resumed, the channels are out of sync.) It may be simple to make noise and channel respect the flag:

Replacing this code in ggsound.asm seems to allow the triangle channel to be muted in the same way, but I don't yet know if it's actually a good way to do it. I'd need to look deeper into GGSound.

Note: There are multiple pieces of similar looking code in ggsound.asm. You want the one under the triangle_play_note label.
Code:
@pitch_already_loaded:
    lda stream_flags,x
    and #STREAM_SILENCE_TEST
    bne @silence_until_note
@note_not_silenced:

    ;Load volume offset.
    ldy stream_volume_offset,x

    ;Load volume value for this frame, but hard code flags and duty for now.
    lda (sound_local_word_0),y
    cmp #ENV_STOP
    beq @volume_stop
    cmp #ENV_LOOP
    bne @skip_volume_loop

    ;We hit a loop opcode, advance envelope index and load loop point.
    iny
    lda (sound_local_word_0),y
    sta stream_volume_offset,x
    tay

@skip_volume_loop:

    lda #%10000000
    ora (sound_local_word_0),y
    sta stream_channel_register_1,x

    inc stream_volume_offset,x
    jmp @done_volume
@volume_stop:
@silence_until_note:
    lda stream_channel_register_1,x
    and #%10000000
    sta stream_channel_register_1,x
@done_volume:
    ;Load pitch offset.
(Copy the above. Select everything between and including @pitch_already_loaded and ;Load pitch offset. Paste, which will replace what's there with this new code)

Then triangle can be muted with
Code:
ldx #2;Triangle
    lda stream_flags,x
    ora #STREAM_SILENCE_SET
    sta stream_flags,x
    
    lda stream_channel_register_1,x
    and #%11110000
    sta stream_channel_register_1,x
Noise channel probably requires a similar modification.

Edit: Oh. Seems you don't need the
Code:
lda stream_channel_register_1,x
    and #%11110000
    sta stream_channel_register_1,x
For any of the channels.
Probably a leftover from trying to mute the other channels that don't respect the flag.
 

Raftronaut

Member
dale_coop said:
As Kasumi epxlained somewhere (on the Discord channel maybe), for pausing the music...
Modify the MainASM.asm script, under the "skipNMIstuff:", you will find this block of code:

Code:
	LDA currentBank
	STA prevBank
	LDY #BANK_MUSIC  ;; switch to music bank
	JSR bankswitchY
	soundengine_update  
	LDY prevBank
	JSR bankswitchY

Comment those 7 lines, like this:

Code:
	; LDA currentBank
	; STA prevBank
	; LDY #BANK_MUSIC  ;; switch to music bank
	; JSR bankswitchY
	; soundengine_update  
	; LDY prevBank
	; JSR bankswitchY

And just after them, add this block of code:

Code:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; PAUSE MUSIC
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	LDA currentBank
	STA prevBank
	LDY #BANK_MUSIC  ;; switch to music bank
	JSR bankswitchY

	LDA isPaused
	BEQ unpause_music
	JSR pause_song
	JMP post_pause_music_handle
unpause_music:
	JSR resume_song
post_pause_music_handle:
	soundengine_update  
	LDY prevBank
	JSR bankswitchY   
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Dale, I am having some trouble finding this block of code within my MainASM file
Code:
	LDA currentBank
	STA prevBank
	LDY #BANK_MUSIC  ;; switch to music bank
	JSR bankswitchY
	soundengine_update  
	LDY prevBank
	JSR bankswitchY
By searching skipNMIstuff in mainASM.asm I can find two areas here that mention this, around lines 151 and 260.

the closest match I found was this:
Code:
skipNMIstuff:		


	
	DEC vBlankTimer
	INC randomSeed1
	;;return from this interrupt
	;; music player things
	
	LDA #$0
	STA sleeping

	LDA currentBank
	STA prevBank
	LDY #BANK_MUSIC  ;; switch to music bank
	JSR bankswitchY
	soundengine_update  
	LDY prevBank
	JSR bankswitchY

I'd really like to try Kasumi's code to pause the square channels, but I am not quite understanding this first bit.

As always, thanks for your patience guys...
 

Atarath

Member
This code is great!

I have noticed a glitch that appears when testing out the code to silence the square channels that I'm curious if anyone else has experienced. I got everything working, but noticed that if I transition between screens too quickly back and forth, my hud will become discolored and the player sprite will become corrupted. I have tested repeatedly with and without specifically that block of code.
 

red moon

Member
Hmm, I ran into some issues trying to implement this pause feature. I did adjust the predraw, add the pause script, assign the user constant, the inputs, create and assign the new sounds...but i must be missing something.

PREDRAW
Code:
    LDA isPaused
    BNE +
    JMP isNotPaused
    +
    DrawSprite #$6C, #$78, #$70, #%00000001, spriteOffset
    UpdateSpritePointer
    DrawSprite #$76, #$78, #$71, #%00000001, spriteOffset
    UpdateSpritePointer
    DrawSprite #$80, #$78, #$72, #%00000001, spriteOffset
    UpdateSpritePointer
    DrawSprite #$8A, #$78, #$73, #%00000001, spriteOffset
    UpdateSpritePointer
    DrawSprite #$94, #$78, #$74, #%00000001, spriteOffset
    UpdateSpritePointer
isNotPaused:
;; sprite pre-draw
;;; this will allow a user to draw sprites
;;; before object sprites are drawn.
;;; keep in mind, there are still only 64 sprites
;;; that can be drawn on a screen, 
;;; and still only 8 per scan line!

;;; you can use DrawSprite macro directly using the following scheme:
;DrawSprite arg0, arg1, arg2, arg3, arg4
	;arg0 = x
	;arg1 = y
	;arg2 = chr table value
	;arg3 = attribute data
	;arg3 = starting ram position
	
;; x and y are the direct positions on the screen in pixels.
;; chr table value is which sprite you'd like to draw from the ppu table.
;; attribute data is a binary number (starts with #%), and here are how the bits work:
	;;; bit 7 - Flip sprite vertically
	;;; bit 6 - Flip sprite horizontally
	;;; bit 5 - priority (0 in front of background, 1 behind background)
	;;; bit 4,3,2 - (null)
	;;; bit 1,0 - subpalette used (00, 01, 10, 11)
	
	
;;; for starting ram position, use spriteOffset.
;; this is set to 0 just before entering this script (or 4 if sprite 0 hit was used).
;; ***remember to increase spriteOffset by 4 for every sprite that is drawn,
;; including after the last one drawn*****, so that the first object's sprite begins
;; in the next available spot.

;; I have created a macro function to handle updating to the next sprite.  So, to update to the next sprite position,
;; all that you have to do is use the function UpdateSpritePointer

;;EXAMPLE:
; DrawSprite #$80, #$80, #$10, #%00000000, spriteOffset
; UpdateSpritePointer

;;;; DRAW SPRITE ZERO FOR SPRITE ZERO HIT

	LDA gameState
	CMP #GS_MainGame	
	BNE + ;dont draw sprite zero
	LDA #HIDE_HUD
	BNE +
	;DrawSprite #$f8, #$1e, #$7F, #%00000000, spriteOffset
				;248   30    127   bit 5 = priority
	DrawSprite #SPRITE_ZERO_X, #SPRITE_ZERO_Y, #SPRITE_ZERO_INDEX, #%00100000, spriteOffset
	UpdateSpritePointer
;dont draw sprite zero.
+

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



	
;;=================== Platform engine
;; In our platform engine, the player can shoot from a 'projectile source'.
;; Since this projectile source does not interact with the background in any way,
;; it is really just a sprite extention of the player, and would be truly foolish to waste
;; an object and processing time on it.  You can, but it would be wasteful.
;; So what we can do instead is use pre-drawn sprites.  If the player is in his attack state,
;; we will check the direction, and then draw the weapon sprite based on which direction he is
;; facing.

	;LDX player1_object ;; we are going to check some player 1 things.
	;;; but getting current action type will set x to this automatically
	JMP doneDrawingWeaponSprite ;;
	GetCurrentActionType player1_object ;; what object is the current player
										;; because if it's attack (3), we should draw weapon.
	CMP #$03
	BNE notAttackingSoDontDrawWeapon
	;;attacking, so draw weapon.
	LDA Object_movement,x
	AND #%00000111
	TAY ;; now y contains direction, so we can figure out position offset
	;CMP #RIGHT
	;BNE directionIsNotRightForDrawingWeapon
	;;; direction is right.
	 LDA Object_x_hi,x
     ;;; offset x for creation
     CLC
     ADC weaponOffsetTableX,y
	 SEC
	 SBC xScroll
     SEC 
     SBC #$08 ;; width of gun 
     STA temp
     LDA Object_y_hi,x
     CLC
     ADC weaponOffsetTableY,y
     sec
     sbc #$08 ;; height of gun
     STA temp1
	 
	 CPY #RIGHT
	 BNE directionIsNotRightForDrawingWeapon
	 ;; it is right, which means draw without flip
	 LDA #%00000001
	 STA temp2
	 JMP doDrawWeapon
directionIsNotRightForDrawingWeapon:
	LDA #%01000001
	STA temp2
doDrawWeapon:
	 
	DrawSprite temp, temp1, #$2c, temp2, spriteOffset
	 JMP doneDrawingWeaponSprite
	
	



doneDrawingWeaponSprite:
	UpdateSpritePointer
	
notAttackingSoDontDrawWeapon:

PAUSE
Code:
    LDA isPaused
    BNE unpausegame
    LDA gameHandler
    ORA #%00100000 ;; objects bit
    STA gameHandler
    LDA #$01
    STA isPaused
	;; we play the pause sfx:
	PlaySound #SND_PAUSE	
	;; we make the screen dark:
	LDA soft2001
	ORA #%11100000
	STA soft2001
	
    JMP thePauseEnd
unpausegame:
    LDA gameHandler
    AND #%11011111 ;; objects bit
    STA gameHandler
    LDA #$00
    STA isPaused
	;; we play the unpause sfx:
	PlaySound #SND_UNPAUSE
	;; we make the screen back normal:
	LDA soft2001
	AND #%00011111
	STA soft2001
thePauseEnd:
	RTS
 

Attachments

  • error1.jpg
    error1.jpg
    181.7 KB · Views: 3,215
  • input.jpg
    input.jpg
    392.4 KB · Views: 3,215
  • userconstant.jpg
    userconstant.jpg
    103.2 KB · Views: 3,215

Mugi

Member
you mispelled the variable.

its isPaused, not IsPaused (not a capital i)
variables are case-sensitive
 
This is GREAT! It took me a little to set it up but I finally managed it. No that it should be a big deal but i do notice when you are holding forward and press PAUSE it stops it on that frame but when you release the direction it goes back (In my case) idle state. Its not animated idle but yeah. The only thing I am trying to figure out here is how to make the screen when paused changed to a different color or tent it.

Anyone have any idea?
 

dale_coop

Moderator
Staff member
See my post on the page one...
I set the 3 colors tint, that makes the screen looking darker ("11100000" each of those "1" corresponds to a color emphasis/tint)
 

wallmasterr

Active member
color tint doesn't seem to work in built-in emulator but dose in messen.

Works on pal nes
but dose not work on retron hd
 

offparkway

Active member
Apologies if I'm missing something...

I created pause.asm and attached it to my start button. I used the screen dimming code that Dale posted.

The game runs, and when I press start, the screen dims. But the game doesn't pause... my player can still keep moving to the next screen, attack, etc. Monsters still keep moving.

I'm using 4.5, and this code has been around for a while. Is it possible it's referencing something that doesn't exist, or has been renamed?
 

mouse spirit

Well-known member
chronicleroflegends said:
mongolianmisfit said:
chronicleroflegends said:
A few questions:

The screen dimming doesn't seem to do anything for me. Any idea why?

Is it possible to use graphics from our HUD to make the word paused? How would you indicate that you wanted to use those graphics instead?
^^ This would be really useful to me, because it would solve the issue I have of using a number for the equipped ability in my game instead of text.

Edit:
The dimming does actually work, but only when I run the game in Mesen. Not the default emulator.

Were you able to get the game to display PAUSED by pulling from the HUDTiles file?
If so, I'd love to know how you accomplished it. :)

And Mugi, it looks like the following code on the input scripts results in the walk animation being locked in the first frame (so the character 'hovers around'):

LDA isPaused
BEQ +
RTS
+

Not yet, for now I just copied text over to the game object tiles. I'm sure there is a way but I haven't looked into it yet.
 
Top Bottom