This page is a mirror of Tepples' nesdev forum mirror (URL TBD).
Last updated on Oct-18-2019 Download

Sound

Sound
by on (#47926)
I am able to make a simple up-scaled sound effect in ca65 but if I want to add another sound, it won't let me?

; Do a up-scaled sweep sound
lda #1
sta $4015 ; Turn on the sound output
lda #$FF
sta $4000 ; pAPU Sound Register 1 (sq)
lda #%11011011
sta $4001
lda #$A5
sta $4002
lda #$AB
sta $4003

; Do a second up-scaled sweep sound
lda #1
sta $4015
lda #$FF
sta $4000 ; pAPU Sound Register 1 (sq)
lda #%11011011
sta $4001
lda #$A5
sta $4002
lda #$AB
sta $4003

by on (#47928)
You're doing them right immediately after one another. :P You need to put some kind of a pause after the first one so you give it some time to be audible, before you play the second sound.

by on (#47934)
You should add a frame counter, and only advance after a certain amount of frames has passed. something like this:

Code:
   lda #120
   sta Counter
Wait:
   lda Counter
   bne Wait

This would be between the two sounds, so that there is an interval of 120 frames (or 2 seconds) between them. With an 8-bit counter you can count up to about 4 seconds, if you need more you'll need a 16-bit counter. And of course, for this to work NMIs must be enabled, and your NMI must routine must include the following command anywhere in it:

Code:
   dec Counter

Anyway, this will work if you have nothing else going on in the program between the sounds. If you want anything else, you'll need a more complex system, where each task has it's own counter.

by on (#47967)
> Executing: C:\Program Files (x86)\ConTEXT\ConExec.exe "C:\Program Files (x86)\cc65\bin\ca65.exe" "test3.asm"

test3.asm(86): Error: Symbol `Counter' is undefined
> Execution finished.


Code:
.include "nes.h"

.Segment "HEADER"
  .byte "NES",$1A,1,0,0,0,0,0,0,0,0,0,0,0
.Segment "ZEROPAGE"
  .res 1
.Segment "PRG0"
.Segment "PRG1"
.Segment "PRG2"
.Segment "PRG3"
.Segment "PRG4"
.Segment "PRG5"
.Segment "THEGAME"
.Segment "PRG6"
.Segment "PRG7"
.Segment "PRG8"
.Segment "PRG9"
.Segment "PRGA"
.Segment "PRGB"
.Segment "PRGC"
.Segment "PRGD"
.Segment "PRGE"
.Segment "PRGBOOT"
  .org $C000
RESET:
    sei        ; disable IRQs
    cld        ; disable decimal mode
    ldx #$40
    stx $4017  ; disable APU frame IRQ
    ldx #$ff
    txs        ; Set up stack
    inx        ; now X = 0
    stx $2000  ; disable NMI
    stx $2001  ; disable rendering
    stx $4010  ; disable DMC IRQs
    txa        ; Set up accumulator

  vblankppuready:
    bit $2002
    bpl vblankppuready

  clrmem:
    sta $000,x
    sta $100,x
    sta $200,x
    sta $400,x
    sta $500,x
    sta $600,x
    sta $700,x  ; Remove this if you're storing reset-persistent data
    lda #$FE
    sta $300,x
    inx
    bne clrmem

  vblankwait:
    bit $2002
    bpl vblankwait

    lda #%00001000
    sta $2000        ; PPU Control Register 1
    lda #%11101000
    sta $2001        ; PPU Control Register 2

  ; Set the color to black (0F)
    lda #$3F
    sta $2006
    lda #$00
    sta $2006
    lda #$03         ; Coconial Black Palette Color
    sta $2007        ; Write Color to VRAM Register
    ldx #$08         ; Screen color change timing

    ; Do a up-scaled sweep sound
    lda #1
    sta $4015        ; Turn on the sound output
    lda #$FF
    sta $4000        ; pAPU Sound Register 1 (sq)
    lda #%11011011
    sta $4001
    lda #$A5
    sta $4002
    lda #$AB
    sta $4003

    lda #120
    sta Counter
  Wait:
    lda Counter
    bne Wait

    ; Do a second up-scaled sweep sound
    lda #1
    sta $4015
    lda #$FF
    sta $4000        ; pAPU Sound Register 1 (sq)
    lda #%11011011
    sta $4001
    lda #$A5
    sta $4002
    lda #$AB
    sta $4003
  stop:
       jmp stop

NMI:
    rti
    dec Counter
IRQ:
    rti

.Segment "CHR"
.Segment "SAMPLES"
.Segment "VECTORS"
  .addr NMI, RESET, IRQ

by on (#47968)
Code:
  clrmem:
    sta $000,x
    sta $100,x
    sta $200,x
    sta $400,x
    sta $500,x
    sta $600,x
    sta $700,x  ; Remove this if you're storing reset-persistent data
    lda #$FE
    sta $300,x
    inx
    bne clrmem


If you're attempting to clear RAM by making all data $00, this doesn't do it. You are making $0, $100, $200, $400, $500, $600, and $700 = 0, but everything else = $FE. That LDA #$FE is the problem. Instead, do this:

Code:
    lda #0
    ldy #$FE
  clrmem:
    sta $000,x
    sta $100,x
    sta $200,x
    sta $400,x
    sta $500,x
    sta $600,x
    sta $700,x  ; Remove this if you're storing reset-persistent data

    sty $300,x
    inx
    bne clrmem


You can see in this code that A is unaltered and Y instead holds #$FE which is stored into $300,x.

EDIT: Also, I don't see any ".DEFINE Counter" or something similar in your ASM file. Your assembler needs to know that when you write "Counter" it is a synonym for a numerical value. So something like:

.DEFINE Counter $240

Would tell your assembler that "Counter" is a synonym for $240.

by on (#47970)
dmaresca wrote:
Error: Symbol `Counter' is undefined

"Counter" is just a name I made up for a variable. As Celius said, you have to declare it. Variables are just nicknames for memory locations, you might just as well call it "Crap" instead of "Counter", it's your call.

Also:
Code:
NMI:
    rti
    dec Counter

Will never work. If you return (RTI) before decrementing the counter, it will never be decremented. Put the DEC before the RTI.