1 //
2 // Audio Overload
3 // Emulated music player
4 //
5 // (C) 2000-2008 Richard F. Bannister
6 //
7
8 //
9 // eng_dsf.c
10 //
11
12 #include <stdio.h>
13 #include <string.h>
14 #include <stdlib.h>
15
16 #include "ao.h"
17 #include "eng_protos.h"
18 #include "corlett.h"
19 #include "dc_hw.h"
20 #include "cpuintrf.h"
21 #include "aica.h"
22 #include "aicadsp.h"
23
24 #define DEBUG_LOADER (0)
25 #define DK_CORE (1)
26
27 #if DK_CORE
28 #include "arm7.h"
29 #else
30 #include "arm7core.h"
31 #endif
32
33 typedef struct {
34 corlett_t *c;
35 char psfby[256];
36 uint32 decaybegin, decayend, total_samples;
37 struct sARM7 *cpu;
38 uint8 init_dc_ram[8*1024*1024];
39 } dsf_synth_t;
40
dsf_start(const char * path,uint8 * buffer,uint32 length)41 void *dsf_start(const char *path, uint8 *buffer, uint32 length)
42 {
43 dsf_synth_t *s = malloc (sizeof (dsf_synth_t));
44 memset (s, 0, sizeof (dsf_synth_t));
45
46 uint8 *file = NULL, *lib_decoded = NULL, *lib_raw_file = NULL;
47 uint32 offset, lengthMS, fadeMS;
48 uint64 file_len, lib_len, lib_raw_length;
49 corlett_t *lib;
50 char *libfile;
51 int i;
52
53 // Decode the current SSF
54 if (corlett_decode(buffer, length, &file, &file_len, &s->c) != AO_SUCCESS)
55 {
56 dsf_stop (s);
57 return NULL;
58 }
59
60 #if DEBUG_LOADER
61 printf("%d bytes decoded\n", file_len);
62 #endif
63
64 s->cpu = ARM7_Alloc ();
65 // Get the library file, if any
66 for (i=0; i<9; i++) {
67 libfile = i ? s->c->libaux[i-1] : s->c->lib;
68 if (libfile[0] != 0)
69 {
70 uint64 tmp_length;
71 char libpath[PATH_MAX];
72 ao_getlibpath (path, s->c->lib, libpath, sizeof (libpath));
73
74 #if DEBUG_LOADER
75 printf("Loading library: %s\n", libpath);
76 #endif
77 if (ao_get_lib(libpath, &lib_raw_file, &tmp_length) != AO_SUCCESS)
78 {
79 dsf_stop (s);
80 return NULL;
81 }
82 lib_raw_length = tmp_length;
83
84 if (corlett_decode(lib_raw_file, lib_raw_length, &lib_decoded, &lib_len, &lib) != AO_SUCCESS)
85 {
86 free(lib_raw_file);
87 dsf_stop (s);
88 return NULL;
89 }
90
91 // Free up raw file
92 free(lib_raw_file);
93
94 // patch the file into ram
95 offset = lib_decoded[0] | lib_decoded[1]<<8 | lib_decoded[2]<<16 | lib_decoded[3]<<24;
96 memcpy(&s->cpu->dc_ram[offset], lib_decoded+4, lib_len-4);
97
98 // Dispose the corlett structure for the lib - we don't use it
99 free(lib_decoded);
100 free(lib);
101 }
102 }
103
104 // now patch the file into RAM over the libraries
105 offset = file[3]<<24 | file[2]<<16 | file[1]<<8 | file[0];
106 memcpy(&s->cpu->dc_ram[offset], file+4, file_len-4);
107
108 free(file);
109
110 // Finally, set psfby/ssfby tag
111 strcpy(s->psfby, "n/a");
112 if (s->c)
113 {
114 for (i = 0; i < MAX_UNKNOWN_TAGS; i++)
115 {
116 if ((!strcasecmp(s->c->tag_name[i], "psfby")) || (!strcasecmp(s->c->tag_name[i], "ssfby")))
117 strcpy(s->psfby, s->c->tag_data[i]);
118 }
119 }
120
121 #if DEBUG_LOADER && 0
122 {
123 FILE *f;
124
125 f = fopen("dcram.bin", "wb");
126 fwrite(s->cpu->dc_ram, 2*1024*1024, 1, f);
127 fclose(f);
128 }
129 #endif
130
131
132 memcpy (s->init_dc_ram, s->cpu->dc_ram, sizeof (s->init_dc_ram));
133 #if DK_CORE
134 ARM7_Init(s->cpu);
135 #else
136 arm7_init(cpu, 0, 45000000, NULL, NULL);
137 arm7_reset(s->cpu);
138 #endif
139 dc_hw_init(s->cpu);
140
141 // now figure out the time in samples for the length/fade
142 lengthMS = psfTimeToMS(s->c->inf_length);
143 fadeMS = psfTimeToMS(s->c->inf_fade);
144 s->total_samples = 0;
145
146 if (lengthMS == 0)
147 {
148 lengthMS = ~0;
149 }
150
151 if (lengthMS == ~0)
152 {
153 s->decaybegin = lengthMS;
154 }
155 else
156 {
157 lengthMS = (lengthMS * 441) / 10;
158 fadeMS = (fadeMS * 441) / 10;
159
160 s->decaybegin = lengthMS;
161 s->decayend = lengthMS + fadeMS;
162 }
163
164 return s;
165 }
166
dsf_gen(void * handle,int16 * buffer,uint32 samples)167 int32 dsf_gen(void *handle, int16 *buffer, uint32 samples)
168 {
169 dsf_synth_t *s = handle;
170
171 int i;
172 int16 output[44100/30], output2[44100/30];
173 int16 *stereo[2];
174 int16 *outp = buffer;
175 int opos;
176
177 opos = 0;
178 for (i = 0; i < samples; i++)
179 {
180 #if DK_CORE
181 ARM7_Execute(s->cpu, (33000000 / 60 / 4) / 735);
182 #else
183 arm7_execute(s->cpu, (33000000 / 60 / 4) / 735);
184 #endif
185 stereo[0] = &output[opos];
186 stereo[1] = &output2[opos];
187 AICA_Update(s->cpu->AICA, NULL, NULL, stereo, 1);
188 opos++;
189 }
190
191 for (i = 0; i < samples; i++)
192 {
193 // process the fade tags
194 if (s->total_samples >= s->decaybegin)
195 {
196 if (s->total_samples >= s->decayend)
197 {
198 // song is done here, signal your player appropriately!
199 // ao_song_done = 1;
200 output[i] = 0;
201 output2[i] = 0;
202 }
203 else
204 {
205 int32 fader = 256 - (256*(s->total_samples - s->decaybegin)/(s->decayend-s->decaybegin));
206 output[i] = (output[i] * fader)>>8;
207 output2[i] = (output2[i] * fader)>>8;
208
209 s->total_samples++;
210 }
211 }
212 else
213 {
214 s->total_samples++;
215 }
216
217 *outp++ = output[i];
218 *outp++ = output2[i];
219 }
220
221 return AO_SUCCESS;
222 }
223
dsf_stop(void * handle)224 int32 dsf_stop(void *handle)
225 {
226 dsf_synth_t *s = handle;
227 if (s->cpu) {
228 dc_hw_free (s->cpu);
229 ARM7_Free (s->cpu);
230 }
231 if (s->c) {
232 free (s->c);
233 }
234 free (s);
235 return AO_SUCCESS;
236 }
237
dsf_command(void * handle,int32 command,int32 parameter)238 int32 dsf_command(void *handle, int32 command, int32 parameter)
239 {
240 dsf_synth_t *s = handle;
241 switch (command)
242 {
243 case COMMAND_RESTART:
244 dc_hw_free (s->cpu);
245 memcpy (s->cpu->dc_ram, s->init_dc_ram, sizeof (s->init_dc_ram));
246 ARM7_Init(s->cpu);
247 dc_hw_init (s->cpu);
248 s->total_samples = 0;
249 return AO_SUCCESS;
250
251 }
252 return AO_FAIL;
253 }
254
dsf_fill_info(void * handle,ao_display_info * info)255 int32 dsf_fill_info(void *handle, ao_display_info *info)
256 {
257 dsf_synth_t *s = handle;
258 if (s->c == NULL)
259 return AO_FAIL;
260
261 strcpy(info->title[1], "Name: ");
262 sprintf(info->info[1], "%s", s->c->inf_title);
263
264 strcpy(info->title[2], "Game: ");
265 sprintf(info->info[2], "%s", s->c->inf_game);
266
267 strcpy(info->title[3], "Artist: ");
268 sprintf(info->info[3], "%s", s->c->inf_artist);
269
270 strcpy(info->title[4], "Copyright: ");
271 sprintf(info->info[4], "%s", s->c->inf_copy);
272
273 strcpy(info->title[5], "Year: ");
274 sprintf(info->info[5], "%s", s->c->inf_year);
275
276 strcpy(info->title[6], "Length: ");
277 sprintf(info->info[6], "%s", s->c->inf_length);
278
279 strcpy(info->title[7], "Fade: ");
280 sprintf(info->info[7], "%s", s->c->inf_fade);
281
282 strcpy(info->title[8], "Ripper: ");
283 sprintf(info->info[8], "%s", s->psfby);
284
285 return AO_SUCCESS;
286 }
287