;=======================================================================
;
; Name: ICEU10.700
;
; Group: S-NES Emulator SE BIOS.
;
; Revision: 1.02
;
; Date: 11/05/2004
;
; Author: Frank Hughes (fh512@yahoo.co.uk)
;
;
; Changes:
;
; DATE REVISION DESCRIPTION
; -------- -------- -------------------------------------------------------
; 11/05/4 1.02 Corrected name of the ROM Dumper.
; 30/03/4 1.01 Added name of the ROM Dumper to Source Description.
; 12/11/3 1.00 Original
;
; Description:
;
; This is a Reverse Engineering of the sound code
; used in the Development Unit, 'S-NES Emulator SE'.
; It provides functions to allow the S-NES CPU to play one
; of two samples with various timbre and envelopes, allows
; modification to these presets, and can pass requested
; RAM data back to the S-NES.
; I plan on writing a S-NES interface to allow users
; to experiment with this interesting piece of software! :)
;
; *Big* thanks to interacti for dumping this ROM.
; Note: this code is the property of Nintendo Co. Ltd., and
; is provided here for non-profit and educational purposes.
;
; --- Snes-CPU Commands to the Snes-APU: ---
; 01: Setup Voice Data (SCPUIO0 = Table No.) and play voice.
; $02: Stop Voice.
; $7f: Play voice.
; -ve: S-SDSP Write (SCPUIO0 = Data , SCPUIO1 = Addr (lower 7bits).
; default: Send APU-RAM byte to S-SCPU (SCPUIO2/3 = APU-RAM Addr).
;
; --- APU Block Structure ---
; Block 00: start $0800 length $01F5
; Block 01: start $8000 length $0008
; Block 02: start $8100 length $007E
; Execution Address: $0800
; ---------------------------
;
; --- Memory Map: ---
; $0000 - $007f : S-SDSP Buffer (mirror image of Addresses).
; $0080 - $0081 : Indirect Pointer.
; $0091 - $0091 : Voice Parameter Table number.
; $09ae - $09f4 : A table of 8 Voice parameters (8-bytes a piece).
; $8000 - $8007 : Source Directory.
; $8100 - $817d : Source Data.
; -------------------
;
;=======================================================================
ApuBlockStart $0800
ApuBiosBegin
clrp ; Set Direct Page to Page0.
mov x,#$cf ; Load X with Stack Top.
mov sp,x ; Set Stack Top to #$cf.
mov a,#$00 ; Write value to 0.
mov x,a ; Indirect Index to 0.
; -- Zero RAM Area $00~$c7.
_dis0807
mov (x)+,a
cmp x,#$c8
bne _dis0807
;--- Initialise S-DSP Unused Voices.
mov y,#$10 ; Preset to Voice #1.
_dis080e
push y ; Push Current Voice index onto stack.
mov a,#$00 ; VOL_L = 0.
call _dis09ee ; Write Byte to S-SDSP.
inc y
mov a,#$00 ; VOL_R = 0.
call _dis09ee ; Write Byte to S-SDSP.
inc y
inc y
inc y
mov a,#$00 ; SCRN = $00.
call _dis09ee ; Write Byte to S-SDSP.
inc y
mov a,#$00 ; ADSR_1 = $00.
call _dis09ee ; Write Byte to S-SDSP.
inc y
inc y
mov a,#$00 ; GAIN = 0.
call _dis09ee ; Write Byte to S-SDSP.
pop a ; Pull Current Index off the stack.
clrc ; Reset Carry for Addition.
adc a,#$10 ; Adjust to next channel index.
mov y,a ; Transfer back to Y.
cmp a,#$80 ; Done for all channels?
bne _dis080e ; Loop back if no.
;--- Voice 0 Initialisation.
mov y,#$2c ; EVOL_L
mov a,#$00 ; Set Echo Volume (Left) to 0.
call _dis09ee ; Write Byte to S-SDSP.
mov y,#$3c ; EVOL_R
mov a,#$00 ; Set Echo Volume (Right) to 0.
call _dis09ee ; Write Byte to S-SDSP.
mov y,#$0d ; EFB
mov a,#$00 ; Set Echo Feedback to 0.
call _dis09ee ; Write Byte to S-SDSP.
mov y,#$7d ; EDL
mov a,#$00 ; Set Echo Delay to 0.
call _dis09ee ; Write Byte to S-SDSP.
mov a,#$80 ; Source Directory Address = $8000.
mov y,#$5d ; DIR
call _dis09ee ; Write Byte to S-SDSP.
mov a,#$20 ; Noise Off, Enable Echo Region.
mov y,#$6c ; FLG
call _dis09ee ; Write Byte to S-SDSP.
; ================= Setup Default parameter for Voice. ==================
; --- Set Main Volume to +96.
mov a,#$60
mov $000c,a ; Variable for Main Volume Left.
mov $001c,a ; Variable for Main Volume Right.
; --- Disable Echo Memory Area.
mov a,#$20 ; #%0-0-1-000000 (Echo Memory Disable)
mov $006c,a ; FLG
; --- Disable Pitch Modulation, Noise and Echo.
mov a,#$00
mov $002d,a ; Variable for Pitch Modulation.
mov $003d,a ; Variable for Noise Flag.
mov $004d,a ; Variable for Voice Echo On/Off.
; --- Set Main Volume to +96.
mov a,#$60
mov $0000,a ; Variable for Voice0 Volume Left.
mov $0001,a ; Variable for Voice0 Volume Right.
; --- Set Pitch Height.
mov a,#$08
mov $0002,a
mov a,#$08
mov $0003,a
; --- Set Source Offset.
mov a,#$01
mov $0004,a
; --- Set ADSR_1
mov a,#$8d
mov $0005,a
; --- Set ADSR_2
mov a,#$c4
mov $0006,a
; --- Set Gain Type.
mov a,#$7f
mov $0007,a
; ============================ S-SCPU Wait. ===============================
_dis08a0
mov a,$00f5 ; Fetch SCPUIO1
cmp a,$0092 ; Compare to SnesCpuPrevApuCmd.
beq _dis08a0 ; Continue to poll if it was the same.
; --- Here if new ApuCmd.
mov $0092,a ; Set as SnesCpuPrevApuCmd.
cmp a,#$00 ; Check if ApuCmd#0.
beq _dis08a0 ; Branch back if we passed zero.
; --- Here if ApuCmd !=0.
mov y,$00f4 ; Y<-SCPUIO0
mov $0091,y ; SnesCpuIOBuffer0 <- SCPUIO0
mov $0090, a ; SnesCpuIOBuffer1 <- SCPUIO1
mov $00f5,a ; SCPUIO1 <- SnesCpuIObuffer1
;--- Check ApuCmd.
cmp a,#$01 ; Check if ApuCmd#1.
beq _dis08fe ; Branch if 'yes'.
cmp a,#$02 ; Check if ApuCmd#2.
beq _dis08f4 ; Branch if 'yes'.
cmp a,#$7f ; Check if ApuCmd#127.
beq _dis0901 ; Branch if 'yes'.
cmp a,#$00 ; Condition Status_Negative flag.
bmi _dis08e1 ; Branch if ApuCmd > $7f.
; --- Fall through ApuCmd.
mov a,$00f6 ; Fetch low byte of addr from SCPUIO2.
mov $0080,a ; Store as low word of pointer.
mov a,$00f7 ; Fetch high byte of addr from SCPUIO3.
mov $0081,a ; Store as high word of pointer.
mov x,#$00 ; Init index for indirection.
mov a,[$80+x] ; Fetch RAM value.
mov $00f7,a ; Pass Back S-NES via SCPUIO3.
jmp _dis08a0 ; Jump back to 'Poll S-SCPU'.
; --- Here if S-SCPU Command -ve.
; Write Byte to S-SDSP Buffer.
; "PAGE0[SnesCpuIOBuffer1 & 0x7f] = SnesCpuIOBuffer0;"
_dis08e1
mov a,$0090 ; Fetch SnesCpuIOBuffer1.
and a,#$7f ; Mask off Sign bit.
mov x,a ; Pass it to X.
mov y,a ; Pass it to Y.
mov a,$0091 ; Fetch SnesCpuIOBuffer0.
mov $0000+x,a ; PAGE0[SnesCpuIOBuffer1 & 0x7f] = SnesCpuIOBuffer0;
call _dis09ee ; Write Byte to S-SDSP.
jmp _dis08a0 ; Jump back to 'Poll S-SCPU'.
; --- Here if S-SCPU Command #2.
_dis08f4
mov y,#$5c ; KOF
mov a,#$7f ; voices 0~6
call _dis09ee ; Write Byte to S-SDSP.
jmp _dis08a0 ; Jump Back to 'Poll S-SCPU'.
; --- Here if S-SCPU Command #1.
_dis08fe
call _dis0980 ; Copy table data.
; ================ Refresh S-SDSP with buffer data =====================
; --- Here if S-SCPU Command #$7f.
_dis0901
mov y,#$4c ; KON
mov a,#$00 ; clear voices 0~7.
call _dis09ee ; Write Byte to S-SDSP.
; --- Clear settings for voices 0~7.
mov y,#$5c ; KOF
call _dis09ee ; Write Byte to S-SDSP.
; --- Main Volume.
mov a,$000c ; Variable for Main Volume (Left).
mov y,#$0c ; MVOL(L).
call _dis09ee ; Write Byte to S-SDSP.
mov a,$001c ; Variable for Main Volume (Right).
mov y,#$1c ; MVOL(R).
call _dis09ee ; Write Byte to S-SDSP.
; --- Flag Register.
mov a,$006c ; Variable for Flag Register.
mov y,#$6c ; FLG
call _dis09ee ; Write Byte to S-SDSP.
; --- Pitch Modulation.
mov a,$002d ; Variable for Pitch Modulation.
mov y,#$2d ; PMON.
call _dis09ee ; Write Byte to S-SDSP.
; --- Noise On/Off.
mov a,$003d ; Variable for Noise On/Off.
mov y,#$3d ; EVOL_R
call _dis09ee ; Write Byte to S-SDSP.
; --- Echo On/Off.
mov a,$004d ; Variable for Echo ON/OFF.
mov y,#$4d ; EON
call _dis09ee ; Write Byte to S-SDSP.
; --- Voice0 Volume.
mov y,#$00 ; VOL_L
mov a,$0000 ; Variable for Voice0 Volume Left.
call _dis09ee ; Write Byte to S-SDSP.
inc y ; VOL_R
mov a,$0001 ; Variable for Voice0 Volume Right.
call _dis09ee ; Write Byte to S-SDSP.
; --- Voice0 Pitch Height
inc y ; P_L
mov a,$0002 ; Var for Voice0 Pitch Height (low).
call _dis09ee ; Write Byte to S-SDSP.
inc y ; P_H
mov a,$0003 ; Var for Voice0 Pitch Height (high).
call _dis09ee ; Write Byte to S-SDSP.
; --- Voice0 Source Number.
inc y ; SCRN
mov a,$0004 ; Variable for Voice0 Source Number.
call _dis09ee ; Write Byte to S-SDSP.
; --- Voice0 ADSR.
inc y ; ADSR_1
mov a,$0005
call _dis09ee ; Write Byte to S-SDSP.
inc y ; ADSR_2
mov a,$0006
call _dis09ee ; Write Byte to S-SDSP.
; --- Voice0 Gain Type.
inc y ; GAIN
mov a,$0007 ; Variable for Gain Envelope Type.
call _dis09ee ; Write Byte to S-SDSP.
; --- Voice Enable.
mov y,#$4c ; KON
mov a,#$01 ; Enable voice #0.
call _dis09ee ; Write Byte to S-SDSP.
; --- End of Refresh.
jmp _dis08a0 ; Jump back to 'Poll S-SCPU'.
;---------------------------------------
; Fetch Selected Table of Voice Parameters
; and Pass to our variable table.
_dis0980
mov a,$0091 ; Move this value into the accum.
and a,#$07 ; Mask to leave 0~7 table access.
asl a ; Multiply by 8.
asl a
asl a
mov x,a ; Use as 8-byte table index.
;--- Pitch Height (low)
mov a,$09ae+x ; Transfer these values.
mov $0002,a
;--- Pitch Height (high)
mov a,$09af+x
mov $0003,a
;--- Source Number.
mov a,$09b0+x
mov $0004,a
;--- ADSR_1
mov a,$09b1+x
mov $0005,a
;--- ADSR_2
mov a,$09b2+x
mov $0006,a
;--- Gain Type.
mov a,$09b3+x
mov $0007,a
ret ; Return
;---------------------------------------
; Table of Voice Parameters (0~7)
;
DB $00,$10,$00,$CD,$CF,$00,$00,$00
DB $00,$0C,$01,$AD,$8F,$00,$00,$00
DB $00,$0E,$00,$88,$E0,$00,$00,$00
DB $00,$10,$01,$88,$E0,$00,$00,$00
DB $00,$20,$00,$CD,$D8,$00,$00,$00
DB $00,$18,$00,$CD,$CF,$00,$00,$00
DB $00,$0A,$01,$CD,$D8,$00,$00,$00
DB $00,$14,$01,$CD,$CF,$00,$00,$00
; ====== Write a byte to the S-SDSP =========
_dis09ee
mov $00f2,y
mov $00f3,a
ret
ApuBlockend
; ===========================================
ApuBlockStart $8000
; --- Source Directory.
DW Src0Start ; Source#0 Start Address.
DW Src0Loop ; Source#0 Loop Address.
DW Src1Start ; Source#1 Start Address.
DW Src1Loop ; Source#1 Loop Address.
ApuBlockEnd
;------------------------------------------------------------------
ApuBlockStart $8100
; Source#0 ; Address $8100
Src0Start
DB %00000010 ; Range=0,Filter=no,Loop=yes,End=no.
DB $00,$00,$00,$00,$00,$00,$00,$00
DB %10010110 ; Range=9,Filter=1st,Loop=yes,End=no.
DB $00,$00,$00,$07,$55,$54,$43,$43
DB %10011110 ; Range=9,Filter=3rd,Loop=yes,End=no.
DB $00,$10,$00,$00,$F0,$F0,$FE,$ED
; Source#0 Loop Address.
Src0Loop
DB %01111110 ; Range=7,Filter=3rd,Loop=yes,End=no.
DB $22,$0E,$DF,$E0,$0F,$E0,$F0,$12
DB %10001110 ; Range=8,Filter=3rd,Loop=yes,End=no.
DB $10,$12,$22,$42,$20,$02,$01,$11
DB %10011110 ; Range=9,Filter=3rd,Loop=yes,End=no.
DB $00,$01,$0F,$10,$FF,$00,$E0,$CE
DB %01111111 ; Range=7,Filter=3rd,Loop=yes,End=yes.
DB $12,$0E,$DF,$E0,$0F,$E0,$0F,$12
;--------------------------------------------------------------------
; Source#1 ; Address $813f
Src1Start
DB %00000010 ; Range=0,Filter=no,Loop=yes,End=no.
DB $00,$00,$00,$00,$00,$00,$00,$00
DB %10011110 ; Range=9,Filter=3rd,Loop=yes,End=no.
DB $00,$00,$00,$0E,$D3,$20,$F0,$E1
DB %10101110 ; Range=10,Filter=3rd,Loop=yes,End=no.
DB $EE,$02,$45,$0E,$E0,$F0,$F1,$01
# Source#1 Loop Address
Src1Loop
DB %10111110 ; Range=11,Filter=3rd,Loop=yes,End=no.
DB $10,$01,$ED,$E1,$21,$10,$F1,$F0
DB %10010110 ; Range=9,Filter=1st,Loop=yes,End=no.
DB $ED,$E3,$66,$FA,$CE,$12,$0F,$FF
DB %10101110 ; Range=10,Filter=3rd,Loop=yes,End=no.
DB $EE,$03,$35,$0E,$E0,$0F,$F1,$02
DB %10111111 ; Range=11,Filter=3rd,Loop=yes,End=yes.
DB $01,$00,$EE,$E0,$22,$01,$F0,$0F
ApuBlockEnd
; ---------------------------------------
ApuBlockExec ApuBiosBegin