-
Notifications
You must be signed in to change notification settings - Fork 2
/
spc700.asm
125 lines (102 loc) · 2.66 KB
/
spc700.asm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; SPC-700 CODE
;;; The init code is from "Xka Shack"'s
;;; SPC engine, which was written by smkdan.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
!EngineAddress = $0200
!SampleAddress = $3000
!IsPlaying = $2004
macro WriteDSP(DSP, Value)
mov $f2,#<DSP>
mov $f3,<Value>
endmacro
;SPC engine block
SPC: {
dw SPCEND-SPCSTART
dw !EngineAddress
SPCSTART:
arch spc700
base !EngineAddress
call InitDSP ;brief DSP setup
call StartSNES ;tell SNES to begin
MainLoop:
mov a,$F4
beq .stopsound
mov a,!IsPlaying
bne .stillplaying
mov a,#$01
mov !IsPlaying,a
%WriteDSP($4C, #$01)
%WriteDSP($5C, #$00)
jmp MainLoop
.stopsound
mov a,!IsPlaying
beq .alreadysilenced
%WriteDSP($4C, #$00)
%WriteDSP($5C, #$01)
mov a,#$00
mov !IsPlaying,a
.alreadysilenced
.stillplaying
jmp MainLoop
;intializes registers
;--------------------
InitDSP:
;GLOBAL
%WriteDSP($6C, #$80) ;'soft-reset' itself
%WriteDSP($6C, #$20) ;= 20, normal operation and disable echo writes
%WriteDSP($5C, #$00) ;key off 0
%WriteDSP($0C, #$7F) ;left master volume max
%WriteDSP($1C, #$7F) ;right master volume max
%WriteDSP($5D, #$20) ;Sample pointer table at $2000
%WriteDSP($2C, #$00) ;echo left mute
%WriteDSP($3C, #$00) ;echo right mute
%WriteDSP($2D, #$00) ;disable pitch modulation
%WriteDSP($3D, #$00) ;disable noise
%WriteDSP($4D, #$00) ;disable echo
;CH 0
%WriteDSP($00, #$7F) ;left volume
%WriteDSP($01, #$7F) ;right volume
%WriteDSP($02, #!BeepSamplePitch&$00FF) ;pitch low
%WriteDSP($03, #!BeepSamplePitch>>8) ; pitch high
%WriteDSP($04, #$00) ;sample #
%WriteDSP($05, #$00) ;clear ADSR1
%WriteDSP($06, #$00) ;clear ADSR2
%WriteDSP($07, #$7F) ;GAIN at max
;sample dir
mov a,#!SampleAddress&$00FF ;pointer low
mov x,#!SampleAddress>>8 ;pointer high
mov $2000,a ;main pointer xx00
mov $2001,x ;main pointer 30xx
mov $2002,a ;loop pointer is same
mov $2003,x
mov a,#$00
mov !IsPlaying,a
ret
;signal ready to stream
;2140 = $11
;2141 = $22
;----------------------
StartSNES:
mov $f4,#$11 ;2140 = 11
mov $f5,#$22 ;2141 = 22
mov $f1,#$30 ;reset all input regs
ret
base off
arch 65816
SPCEND: }
;Sample block
TriangleSample: {
dw .end-.start
dw !SampleAddress
.start
db $B0,$01,$23,$45,$67,$76,$54,$32,$10
db $B3,$FE,$DC,$BA,$98,$89,$AB,$CD,$EF
.end }
;Terminator block
{
dw $0000
dw !EngineAddress ;SPC jumps to this address to start running the engine
}