-
Notifications
You must be signed in to change notification settings - Fork 0
/
spccmd.h
152 lines (104 loc) · 3.04 KB
/
spccmd.h
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
//sound variables
static unsigned char snes_spc_sync;
static unsigned int snes_spc_stereo;
static unsigned int snes_spc_volume;
//APU registers
#define APU0(x) *((unsigned char*)0x2140)=(x);
#define APU1(x) *((unsigned char*)0x2141)=(x);
#define APU2(x) *((unsigned char*)0x2142)=(x);
#define APU3(x) *((unsigned char*)0x2143)=(x);
#define APU01(x) *((unsigned int*)0x2140)=(x);
#define APU23(x) *((unsigned int*)0x2142)=(x);
#define APU0RD *((unsigned char*)0x2140)
#define APU1RD *((unsigned char*)0x2141)
#define APU2RD *((unsigned char*)0x2142)
#define APU3RD *((unsigned char*)0x2143)
#define APU01RD *((unsigned int*)0x2140)
#define APU23RD *((unsigned int*)0x2142)
//command codes
#define SCMD_STEREO 0x0000 //change stereo sound mode
#define SCMD_VOLUME 0x1000 //set global volume
#define SCMD_MUSIC_STOP 0x2000 //stop music
#define SCMD_MUSIC_PLAY 0x3000 //start music
#define SCMD_SFX_PLAY 0x4000 //play sound effect
#define SCMD_RELOAD 0x5000 //load new music dara
//command aliases
#define spc_music_stop() (spc_command(SCMD_MUSIC_STOP,0))
#define spc_music_play() (spc_command(SCMD_MUSIC_PLAY,0))
#define spc_sfx_play(chn,x,pan) (spc_command(SCMD_SFX_PLAY|((chn)<<8),(x)|((pan)<<8)))
#define spc_reload() (spc_command(SCMD_RELOAD,0))
#ifdef SOUND_DISABLE
void spc_command(unsigned int command,unsigned int param) {}
void spc_stereo(unsigned int stereo) {}
void spc_volume(unsigned int volume) {}
void spc_load_data(unsigned int adr,const unsigned char *src,unsigned int size) {}
void spc_setup(void) {}
void spc_load_music(const unsigned char *data,unsigned int size) {}
#else
//send a command to the SPC driver
void spc_command(unsigned int command,unsigned int param)
{
APU01(command|snes_spc_sync);
APU23(param);
if(command!=SCMD_RELOAD)
{
while(APU0RD!=snes_spc_sync);
++snes_spc_sync;
}
}
//change stereo sound mode
void spc_stereo(unsigned int stereo)
{
snes_spc_stereo=stereo;
spc_command(SCMD_STEREO,stereo);
}
//set global sound volume
void spc_volume(unsigned int volume)
{
if(volume>127) volume=127;
snes_spc_volume=volume;
spc_command(SCMD_VOLUME,volume);
}
//upload data into the sound memory using IPL loader
void spc_load_data(unsigned int adr,const unsigned char *src,unsigned int size)
{
static unsigned char cnt;
static unsigned int i;
NMITIMEEN(0);
while(APU01RD!=0xbbaa);//apu ready?
APU23(adr);//set location
APU1(1);//not last block
APU0(0xcc);
while(APU0RD!=0xcc);//ready?
cnt=0;
while(size)
{
APU1(*src++);
APU0(cnt);
while(APU0RD!=cnt);//ready?
++cnt;
--size;
}
APU23(0x0200);//startup address
APU1(0);//run apu code
APU0(cnt+2);
snes_spc_sync=cnt;
NMITIMEEN(0x81);
nmi_wait();
}
//initialize sound, set variables and upload driver code
void spc_setup(void)
{
snes_spc_stereo=0;
snes_spc_volume=127;
spc_load_data(0x0200,spc700_data,spc700_size);
}
//upload music data
void spc_load_music(const unsigned char *data,unsigned int size)
{
spc_reload();
spc_load_data(0xe000,data,size);
spc_stereo(snes_spc_stereo);
spc_volume(snes_spc_volume);
}
#endif