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