home *** CD-ROM | disk | FTP | other *** search
- -------------------------------------------------------------------------------
- SUPER N.E.S. MUSIC DRIVER - (c) Martin Walker 1992/1993
- -------------------------------------------------------------------------------
-
- UPDATED:
- 07/12/93 - Additional problem solving text
- 20/10/93 - TRK0call added to ReceiveStatus
- 21/09/93 - Info mode added for status/clock switching
- 14/09/93 - Interrupts disabled during Sound_Init/status bit added
- 26/08/93 - Mini SNES-CLR power-up routine added to Sound_Init
- 18/08/93 - Improved handshaking routines/ new clock routine
- 06/08/93 - Boot_APU anti hang-up mod added as per REV.D CAUTION #7
- Updated Sound_Init/Send_Data
- 26/07/93 - external volume of sound calls/ problem solving section at end.
- 19/07/93 - to clarify initialisation procedure.
-
-
-
-
- SNES MUSIC DEMO
- ---------------
- To help test the music files, a file named 'SNESMUS.ROM' may be supplied.
- You can download this to the SNES for a demo of the music and effects.
- The joypad keys to use are as follows:
-
- UP/DOWN Increment/Decrement current call number.
- SELECT Stop all sound calls.
- START Start music/effect.
- Y Fades all sound calls.
-
-
-
-
- OVERVIEW
- --------
- The player and music/effect data needs to be downloaded from its chosen ROM
- position to the SOUND CPU during the initialisation of the game. Suitable
- source code to do this appears below, along with the Sound Boot Loader routine
- taken from the SNES Manual (Appendix D with REV.D CAUTION #7).
-
-
-
- 1. WHEN INITIALISING THE GAME USE 'Sound_Init'.
-
- The Sound_Init routine needs to be called at power up and when 'RESET' is
- pressed. At both these times the SNES forces the Sound CPU to reset and then
- jump into its internal IPLROM routine. It is then waiting for data to be sent
- to it via the ports. First, a tiny routine is downloaded to clear all RAM, set
- up all DSP registers and initialise the Echo to minimise any stray sounds on
- power up. The driver is then downloaded; control then passes to the driver,
- and all subsequent downloads in this routine are made using the $82 DOWNLOAD
- command. (Sound_Init uses this technique to download the Musicdata and both
- sample Banks to the SOUND CPU memory).
-
-
-
- 2. TO START ANY DESIRED MUSIC OR EFFECT USE 'Send_Sound'.
-
- The following calls can be made during the game using Send_Sound. They are all
- made in the form:
-
- lda #N ;N = sound call number
- ldx #V ;V = volume (use $FF=full volume normally)
- jsr SendSound
-
-
-
- N = $00-$7F START
- Music or Effect call (See accompanying PROJECT.DOC)
- The 'X' register volume is only used by START calls.
- It may be omitted with other calls.
-
- N = $80 INIT
- stops all current sounds.
- resets master volume to maximum.
- (Use after fade if you require effects only).
-
- N = $81 FADE
- fades music and current effects to zero volume.
-
- N = $82 DOWNLOAD
- Stops driver processing to download music data or samples.
-
- N = $83 INFOMODE
- Sets mode to either status byte (default) or realtime clock.
-
-
-
- 3. FOR SUBSEQUENT LEVELS OF THE GAME USE 'Send_Data'.
-
- Send_Data stops all sound processing and then allows additional Musicdata
- and/or sample Banks to be downloaded. Normally both a Musicdata (.SND) file
- and at least 1 sample Bank (.BIN) file will need to be sent. Full details of
- particular files will be found in the file 'PROJECT.DOC'.
-
-
-
-
- -------------------------------------------------------------------------------
- SOURCE CODE DETAILS
- -------------------------------------------------------------------------------
-
- Since the SOUND CPU in the SNES is a completely separate processor, sending
- commands to it relies either on the SNES code looping until the sound code
- calls its 'check for external commands' routine (this can waste a lot of time
- that could be more usefully spent on the SNES side), or the way implemented
- in 'Send_Sound' below. This relies on the fact that once an external command
- from the SNES side has been processed by the music driver, it writes a unique
- number back to PORT0. By reading PORT0 from the SNES side and checking for
- this value the SNES programmer will only send a sound call when the sound
- driver has finished processing the previous one. By placing all sound calls
- into a buffer (16 bytes should normally be sufficient), you can call
- 'SendSound' at intervals without waiting each time for a response. The worst
- case wait will be 8mS (hardware loop time). Normally 1 sound call per VBL
- (20mS) should be fast enough (50 new sounds maximum per second!).
-
- KEY: < = byte (8 bit value)
- | = word (16 bit value)
- > = long word (24 bit value)
- >> = bank (top 8 bits of 24 bit value)
-
-
- ;Macro Definitions
-
- SET16 MACRO
- rep %00110000 ;Enable 16-bit mode ie clear M&X
- ENDM
-
- CLR16 MACRO
- sep %00110000 ;Disable 16-bit mode ie set M&X
- ENDM
-
- SETLONGA MACRO
- rep %100000 ;16 Bit Accumulator
- ENDM
-
- CLRLONGA MACRO
- sep %100000 ;8 bit Accumulator
- ENDM
-
-
- ;EQUATES
-
- APU_PORT0 equ $2140
- APU_PORT1 equ $2141
- APU_PORT2 equ $2142
- APU_PORT3 equ $2143
-
- SonyAddr equ $10 ;any 4 byte zero page address
- callnum equ $14 ;any 1 byte address
- SONYclock equ $15 ;word value
- SONYstatus equ $17 ;8 bits (1 = chan active/0 = chan stopped)
- SONYtrk0call equ $18 ;byte value (FF = chan stopped)
-
-
-
- SendSound: CLR16
- pha ;save call number
- lda >APU_PORT0 ;latest value sent by SOUND CPU
- cmp <callnum
- bne SoundAbort ;previous call still not finished
- pla
- sta >APU_PORT0 ;store new call
- txa
- sta >APU_PORT1 ;store new volume
- inc <callnum
- lda <callnum
- sta >APU_PORT3 ;confirms a new call
- rts
- SoundAbort: pla
- rts
-
-
- -------------------------------------------------------------------------------
- Sound_Init should be called as a subroutine once only during the
- Initialisation of the game, or after a user reset. It downloads the driver,
- music data and sample data to the SOUND CPU memory.
- -------------------------------------------------------------------------------
-
- Sound_Init: php
- sei ;disable any other interrupts
- SET16
- lda #MusicInit ;download SNES_CLR.BIN (24 bit address)
- sta <SonyAddr lda #RamII
- lda #MusicInit>>16
- sta <SonyAddr+2
- jsr Boot_APU ;exits straight to IPLROM
-
- SET16
- lda #MusicDriver ;download driver (24 bit address)
- sta <SonyAddr lda #RamII
- lda #MusicDriver>>16
- sta <SonyAddr+2
- jsr SONY_send
-
- lda #$82 ;DOWNLOAD data (music)
- sta >APU_PORT0
- SET16
- lda #Musicdata
- sta <SonyAddr
- lda #Musicdata>>16
- sta <SonyAddr+2
- jsr SONY_send
-
- lda #$82 ;DOWNLOAD data (samples)
- sta >APU_PORT0
- SET16
- lda #Samples1
- sta <SonyAddr
- lda #Samples1>>16
- sta <SonyAddr+2
- jsr SONY_send
-
- lda #$82 ;DOWNLOAD data (samples)
- sta >APU_PORT0
- SET16
- lda #Samples2
- sta <SonyAddr
- lda #Samples2>>16
- sta <SonyAddr+2
- jsr SONY_send
-
- sta >APU_PORT3
- plp ;restore any interrupts
- rts
-
-
- ;-----------------------------------------------------------------------------
- SONY_send: jsr Boot_APU
- CLR16
- @wait0: lda >APU_PORT0 ;wait for handshake
- bne @wait0
- dec a
- sta >APU_PORT2 ;acknowledge handshake
- sta <callnum ;init call number to $FF
- rts
-
-
- -------------------------------------------------------------------------------
- Once the Sound_Init routine has been called, the following routine can be
- used to download additional music data (or sample data with '#Musicdata'
- replaced by '#Samples') which is required for later levels of the game.
- -------------------------------------------------------------------------------
-
- Send_Data: CLR16
- php
- sei ;disable any other interrupts
- S_D0: lda >APU_PORT0 ;latest value sent by SOUND CPU
- cmp <callnum
- bne S_D0 ;previous call still not finished
-
- lda #$82 ;DOWNLOAD data (music)
- sta >APU_PORT0
- inc <callnum
- lda <callnum
- sta >APU_PORT3 ;forces a new call
- SET16
- lda #Musicdata
- sta <SonyAddr
- lda #Musicdata>>16
- sta <SonyAddr+2
- jsr SONY_send
-
- sta >APU_PORT3
- plp ;restore any interrupts
- rts
-
-
- -------------------------------------------------------------------------------
- Info_Mode is used to set the mode. It only needs to be called once with the
- appropriate mode number in PORT1. After this the appropriate routine (either
- ReceiveStatus or ReceiveClock can be called at any time for the latest values.
- Normally, after any download the info mode defaults to 0 (status)
-
- MODE = 0 (STATUS=default)
- In this mode PORT1 is updated with current status of all 8 channels (bit high
- = channel active). This can be used to check for the end of a particular sound.
- PORT2 is updated with the current call in channel 0, and can be used to
- monitor the progress of specially written music ($FF = no call active)
-
- MODE=1 (CLOCK)
- In this mode PORT1 & PORT2 are updated with the current value of an internal
- music 'CLOCK' to allow syncing of action to music with specially designed
- tracks.
- -------------------------------------------------------------------------------
-
- Info_Mode: CLR16
- php
- sei ;disable any other interrupts
- I_M0: lda >APU_PORT0 ;latest value sent by SOUND CPU
- cmp <callnum
- bne I_M0 ;previous call still not finished
-
- lda #$83 ;INFOMODE
- sta >APU_PORT0
- lda #0 ;0=status(default)
- sta >APU_PORT1 ;1=clock mode
- inc <callnum
- lda <callnum
- sta >APU_PORT3 ;forces a new call
- plp ;restore any interrupts
- rts
-
-
- ReceiveStatus: SETLONGA
- lda >APU_PORT1 ;16 bit (get data word)
- sta <SONYstatus ;8 bits of channel status
- CLRLONGA ;1 byte TRK0call
- rts
-
-
- ReceiveClock: SETLONGA ;clock is waiting in PORT1 & 2
- lda >APU_PORT1 ;16 bit (get data word)
- sta <SONYclock
- CLRLONGA
- rts
-
-
- -------------------------------------------------------------------------------
- SOUND BOOT LOADER V1.1 (from Appendix D of the SNES manual)
- -------------------------------------------------------------------------------
-
- Boot_APU: php
- SET16
- ldy #|$0000
- lda #$bbaa
- boot_initial: cmp >APU_PORT0
- bne boot_initial
- CLRLONGA
- lda #$cc
- bra boot_entry1
-
- boot_repeat: lda [SonyAddr],y
- iny
- xba
- lda #0
- bra boot_entry2
- boot_loop: xba
- lda [SonyAddr],y
- iny
- xba
- boot_wait1: cmp >APU_PORT0
- bne boot_wait1
- inc a
- boot_entry2: SETLONGA
- sta >APU_PORT0
- CLRLONGA
- dex
- bne boot_loop
- boot_wait2: cmp >APU_PORT0
- bne boot_wait2
- boot_zero: adc #3
- beq boot_zero
- boot_entry1: pha
- SETLONGA
- lda [SonyAddr],y
- iny
- iny
- tax
- lda [SonyAddr],y
- iny
- iny
- sta >APU_PORT2
- CLRLONGA
- cpx #|1
- lda #0
- rol a
- sta >APU_PORT1
- adc #$7f
- pla
- sta >APU_PORT0
- boot_wait3: cmp >APU_PORT0
- bne boot_wait3
- bvs boot_repeat
- boot_ret: plp
- rts
-
-
-
-
- ------------------------------------------------------------------------------
- SNES MUSIC PROBLEM SOLVING
- ------------------------------------------------------------------------------
- PROBLEM 1:
- Music crashes after using the 'reset' button
-
- REASON:
- At this time the SNES hardware forces the Sound CPU to reset and then jump
- into its internal IPLROM routine. It is then waiting for data to be sent to it
- via the ports, using the Boot_APU routine (above) which is reprinted from the
- SNES manual. Although on 'RESET' the sound driver and data are still in sound
- memory, you MUST treat this button the same as a power up and use 'Sound_Init'
-
- CURE:
- ALWAYS use 'Sound_Init' after a 'RESET', rather then Send_Data.
-
-
-
- PROBLEM 2:
- Corruption of sample data after loading new BANK1.
-
- REASON:
- If after loading a new bank of sounds you get some noises garbled, it is
- possible that the musician has inadvertantly allowed BANK2 to overwrite the
- end of BANK1 data by a few bytes. Normally a BANK1 load followed by BANK2 will
- ensure that the sample pointer table at the beginning of each bank is
- preserved, and a tiny corruption at the end of the final sample in BANK1 may
- be inaudible, but loading a new BANK1 may overwrite the table at the beginning
- of BANK2. This will cause every sound in BANK2 to emerge as gibberish. You can
- check for this by re-sending the banks in the opposite order. If the problem
- disappears, contact the musician for a BANK update file!
-
- CURE:
- Send BANKS in the order BANK1 then BANK2 for a temporary cure, and contact the
- musician for an amended BANK file.
-
-
-
- PROBLEM 3:
- Occasional hang-up after sending new sound data.
-
- REASON:
- Bug in Nintendo's own Boot_APU routine (see REV.D CAUTION #7). It is possible
- that an interrupt will strike during a download of sound data - if this
- happens during the 300-400 microseconds of handshake it is possible that the
- SNES side will miss the ackowledgement and then wait for indefinitely (crash).
-
- CURE:
- Make sure you disable SNES interrupts during Sound_Init as shown.
-
-
-
- PROBLEM 4:
- Sound always hangs when game is aborted.
-
- REASON:
- Only on power up or by pressing RESET will the Sound CPU be in a state to use
- Sound_Init. Restarting the game as a user option will not work in this case.
-
- CURE:
- Re-arrange the code so that Sound_Init occurs before the game restart
- point, and use Send_Data to re-send the first music data required.
-
-
-
- PROBLEM 5:
- Occasional crackle or 'break-up' in sound with lots of simultaneous sounds.
-
- REASON:
- It is possible to overload the sound chip, but sometimes this only appears
- during playtesting when everyting is happening at once.
-
- CURE:
- First confirm that it is overload by inserting a temporary '/2' command before
- the volume setting in SendSound to drastically reduce all volumes. If this
- cures the problem then remove the '/2' command and set all volumes to a
- significantly lower setting (e.g. from $FF to $D0) and retest.
-