summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2010-07-01 00:26:01 +0000
committerMichael Sevakis <jethead71@rockbox.org>2010-07-01 00:26:01 +0000
commitcf73340f1e85d3b39dc452d57e28d2a9a9081051 (patch)
tree27a89d40fae023d994c7a59d3950f7af32dc00aa
parent10b8e327d8c0d37b8a9f1997e33e4bf1a97bb39b (diff)
downloadrockbox-cf73340f1e85d3b39dc452d57e28d2a9a9081051.tar.gz
rockbox-cf73340f1e85d3b39dc452d57e28d2a9a9081051.zip
Enable game sounds in PacBox. Sound is OFF by default but can be enabled from the menu. Enable a function for SWCODEC in the middle of the plugin API, so plugins must be made incompatible (full update).
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@27202 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/plugin.c2
-rw-r--r--apps/plugin.h14
-rw-r--r--apps/plugins/pacbox/SOURCES1
-rw-r--r--apps/plugins/pacbox/arcade.c58
-rw-r--r--apps/plugins/pacbox/arcade.h2
-rw-r--r--apps/plugins/pacbox/hardware.c3
-rw-r--r--apps/plugins/pacbox/pacbox.c142
-rw-r--r--apps/plugins/pacbox/pacbox.h3
-rw-r--r--apps/plugins/pacbox/wsg3.c148
-rw-r--r--apps/plugins/pacbox/wsg3.h124
10 files changed, 473 insertions, 24 deletions
diff --git a/apps/plugin.c b/apps/plugin.c
index 56d2be9f40..51ef40f010 100644
--- a/apps/plugin.c
+++ b/apps/plugin.c
@@ -637,9 +637,7 @@ static const struct plugin_api rockbox_api = {
637 get_codec_filename, 637 get_codec_filename,
638 find_array_ptr, 638 find_array_ptr,
639 remove_array_ptr, 639 remove_array_ptr,
640#if defined(HAVE_RECORDING) && (defined(HAVE_LINE_IN) || defined(HAVE_MIC_IN))
641 round_value_to_list32, 640 round_value_to_list32,
642#endif
643#endif /* CONFIG_CODEC == SWCODEC */ 641#endif /* CONFIG_CODEC == SWCODEC */
644 get_metadata, 642 get_metadata,
645 mp3info, 643 mp3info,
diff --git a/apps/plugin.h b/apps/plugin.h
index b0f4e051c5..edad8c4e9b 100644
--- a/apps/plugin.h
+++ b/apps/plugin.h
@@ -144,12 +144,12 @@ void* plugin_get_buffer(size_t *buffer_size);
144#define PLUGIN_MAGIC 0x526F634B /* RocK */ 144#define PLUGIN_MAGIC 0x526F634B /* RocK */
145 145
146/* increase this every time the api struct changes */ 146/* increase this every time the api struct changes */
147#define PLUGIN_API_VERSION 187 147#define PLUGIN_API_VERSION 188
148 148
149/* update this to latest version if a change to the api struct breaks 149/* update this to latest version if a change to the api struct breaks
150 backwards compatibility (and please take the opportunity to sort in any 150 backwards compatibility (and please take the opportunity to sort in any
151 new function which are "waiting" at the end of the function table) */ 151 new function which are "waiting" at the end of the function table) */
152#define PLUGIN_MIN_API_VERSION 187 152#define PLUGIN_MIN_API_VERSION 188
153 153
154/* plugin return codes */ 154/* plugin return codes */
155enum plugin_status { 155enum plugin_status {
@@ -782,12 +782,10 @@ struct plugin_api {
782 const char *(*get_codec_filename)(int cod_spec); 782 const char *(*get_codec_filename)(int cod_spec);
783 void ** (*find_array_ptr)(void **arr, void *ptr); 783 void ** (*find_array_ptr)(void **arr, void *ptr);
784 int (*remove_array_ptr)(void **arr, void *ptr); 784 int (*remove_array_ptr)(void **arr, void *ptr);
785#if defined(HAVE_RECORDING) && (defined(HAVE_LINE_IN) || defined(HAVE_MIC_IN)) 785 int (*round_value_to_list32)(unsigned long value,
786int (*round_value_to_list32)(unsigned long value, 786 const unsigned long list[],
787 const unsigned long list[], 787 int count,
788 int count, 788 bool signd);
789 bool signd);
790#endif
791#endif /* CONFIG_CODEC == SWCODEC */ 789#endif /* CONFIG_CODEC == SWCODEC */
792 bool (*get_metadata)(struct mp3entry* id3, int fd, const char* trackname); 790 bool (*get_metadata)(struct mp3entry* id3, int fd, const char* trackname);
793 bool (*mp3info)(struct mp3entry *entry, const char *filename); 791 bool (*mp3info)(struct mp3entry *entry, const char *filename);
diff --git a/apps/plugins/pacbox/SOURCES b/apps/plugins/pacbox/SOURCES
index fdda4ca2d7..65a5cf1cb9 100644
--- a/apps/plugins/pacbox/SOURCES
+++ b/apps/plugins/pacbox/SOURCES
@@ -2,6 +2,7 @@ arcade.c
2pacbox.c 2pacbox.c
3hardware.c 3hardware.c
4z80.c 4z80.c
5wsg3.c
5#if defined(CPU_PP502x) && (LCD_WIDTH >= 288) && (LCD_HEIGHT >= 224) 6#if defined(CPU_PP502x) && (LCD_WIDTH >= 288) && (LCD_HEIGHT >= 224)
6pacbox_arm.S 7pacbox_arm.S
7#else 8#else
diff --git a/apps/plugins/pacbox/arcade.c b/apps/plugins/pacbox/arcade.c
index b8a0f105bb..ecf6d10af8 100644
--- a/apps/plugins/pacbox/arcade.c
+++ b/apps/plugins/pacbox/arcade.c
@@ -24,8 +24,10 @@
24 * 24 *
25 ****************************************************************************/ 25 ****************************************************************************/
26 26
27#include "pacbox.h"
27#include "arcade.h" 28#include "arcade.h"
28#include "hardware.h" 29#include "hardware.h"
30#include "wsg3.h"
29#include <string.h> 31#include <string.h>
30#include "plugin.h" 32#include "plugin.h"
31 33
@@ -92,6 +94,43 @@ enum {
92 FlipXY = 0x03 94 FlipXY = 0x03
93}; 95};
94 96
97// Namco 3-channel Wave Sound Generator wave data (8 waveforms with 32 4-bit entries each)
98static unsigned char default_sound_prom[] =
99{
100 0x07, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0D, 0x0E,
101 0x0E, 0x0E, 0x0D, 0x0D, 0x0C, 0x0B, 0x0A, 0x09,
102 0x07, 0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x00,
103 0x00, 0x00, 0x01, 0x01, 0x02, 0x03, 0x04, 0x05,
104 0x07, 0x0C, 0x0E, 0x0E, 0x0D, 0x0B, 0x09, 0x0A,
105 0x0B, 0x0B, 0x0A, 0x09, 0x06, 0x04, 0x03, 0x05,
106 0x07, 0x09, 0x0B, 0x0A, 0x08, 0x05, 0x04, 0x03,
107 0x03, 0x04, 0x05, 0x03, 0x01, 0x00, 0x00, 0x02,
108 0x07, 0x0A, 0x0C, 0x0D, 0x0E, 0x0D, 0x0C, 0x0A,
109 0x07, 0x04, 0x02, 0x01, 0x00, 0x01, 0x02, 0x04,
110 0x07, 0x0B, 0x0D, 0x0E, 0x0D, 0x0B, 0x07, 0x03,
111 0x01, 0x00, 0x01, 0x03, 0x07, 0x0E, 0x07, 0x00,
112 0x07, 0x0D, 0x0B, 0x08, 0x0B, 0x0D, 0x09, 0x06,
113 0x0B, 0x0E, 0x0C, 0x07, 0x09, 0x0A, 0x06, 0x02,
114 0x07, 0x0C, 0x08, 0x04, 0x05, 0x07, 0x02, 0x00,
115 0x03, 0x08, 0x05, 0x01, 0x03, 0x06, 0x03, 0x01,
116 0x00, 0x08, 0x0F, 0x07, 0x01, 0x08, 0x0E, 0x07,
117 0x02, 0x08, 0x0D, 0x07, 0x03, 0x08, 0x0C, 0x07,
118 0x04, 0x08, 0x0B, 0x07, 0x05, 0x08, 0x0A, 0x07,
119 0x06, 0x08, 0x09, 0x07, 0x07, 0x08, 0x08, 0x07,
120 0x07, 0x08, 0x06, 0x09, 0x05, 0x0A, 0x04, 0x0B,
121 0x03, 0x0C, 0x02, 0x0D, 0x01, 0x0E, 0x00, 0x0F,
122 0x00, 0x0F, 0x01, 0x0E, 0x02, 0x0D, 0x03, 0x0C,
123 0x04, 0x0B, 0x05, 0x0A, 0x06, 0x09, 0x07, 0x08,
124 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
125 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
126 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08,
127 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00,
128 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
129 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
130 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
131 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
132};
133
95/* Putting this in IRAM actually slows down the iPods, but is good for 134/* Putting this in IRAM actually slows down the iPods, but is good for
96 the Coldfire 135 the Coldfire
97*/ 136*/
@@ -110,6 +149,12 @@ void init_PacmanMachine(int dip)
110 z80_reset(); 149 z80_reset();
111 rb->memset( &ram_[0x4000], 0xFF, 0x1000 ); 150 rb->memset( &ram_[0x4000], 0xFF, 0x1000 );
112 151
152 /* Initialize the WSG3 */
153 wsg3_init(SoundClock);
154
155 /* Set the sound PROM to the default values for the original Namco chip */
156 wsg3_set_sound_prom(default_sound_prom);
157
113 /* Initialize parameters */ 158 /* Initialize parameters */
114 port1_ = 0xFF; 159 port1_ = 0xFF;
115 port2_ = 0xFF; 160 port2_ = 0xFF;
@@ -595,6 +640,19 @@ void renderSprites( unsigned char * buffer )
595 } 640 }
596} 641}
597 642
643void playSound( int * buf, int len )
644{
645 /* Clear the buffer */
646 memset( buf, 0, sizeof (int)*len);
647
648 /* Exit now if sound is disabled */
649 if( (output_devices_ & SoundEnabled) == 0 )
650 return;
651
652 /* Let the chip play the sound */
653 wsg3_play_sound( buf, len );
654}
655
598/* Enables/disables the speed hack. */ 656/* Enables/disables the speed hack. */
599int setSpeedHack( int enabled ) 657int setSpeedHack( int enabled )
600{ 658{
diff --git a/apps/plugins/pacbox/arcade.h b/apps/plugins/pacbox/arcade.h
index 32ec0b45be..33dd6d6981 100644
--- a/apps/plugins/pacbox/arcade.h
+++ b/apps/plugins/pacbox/arcade.h
@@ -123,6 +123,8 @@ void init_PacmanMachine(int dip);
123int run(void); 123int run(void);
124void reset_PacmanMachine(void); 124void reset_PacmanMachine(void);
125void decodeROMs(void); 125void decodeROMs(void);
126void playSound( int * buf, int len );
127
126 128
127/** 129/**
128 Tells the emulator that the status of an input device has changed. 130 Tells the emulator that the status of an input device has changed.
diff --git a/apps/plugins/pacbox/hardware.c b/apps/plugins/pacbox/hardware.c
index f5a7184475..bfdcf39362 100644
--- a/apps/plugins/pacbox/hardware.c
+++ b/apps/plugins/pacbox/hardware.c
@@ -26,6 +26,7 @@
26 26
27#include "plugin.h" 27#include "plugin.h"
28#include "hardware.h" 28#include "hardware.h"
29#include "wsg3.h"
29 30
30/* The main data for Pacman */ 31/* The main data for Pacman */
31 32
@@ -140,7 +141,7 @@ void writeByte( unsigned addr, unsigned char b )
140 default: 141 default:
141 if( addr >= 0x5040 && addr < 0x5060 ) { 142 if( addr >= 0x5040 && addr < 0x5060 ) {
142 // Sound registers 143 // Sound registers
143 //SOUND sound_chip_.setRegister( addr-0x5040, b ); 144 wsg3_set_register( addr-0x5040, b );
144 } 145 }
145 else if( addr >= 0x5060 && addr < 0x5070 ) { 146 else if( addr >= 0x5060 && addr < 0x5070 ) {
146 // Sprite coordinates, x/y pairs for 8 sprites 147 // Sprite coordinates, x/y pairs for 8 sprites
diff --git a/apps/plugins/pacbox/pacbox.c b/apps/plugins/pacbox/pacbox.c
index badf171927..9bbc00d094 100644
--- a/apps/plugins/pacbox/pacbox.c
+++ b/apps/plugins/pacbox/pacbox.c
@@ -28,6 +28,7 @@
28#include "arcade.h" 28#include "arcade.h"
29#include "pacbox.h" 29#include "pacbox.h"
30#include "pacbox_lcd.h" 30#include "pacbox_lcd.h"
31#include "wsg3.h"
31#include "lib/configfile.h" 32#include "lib/configfile.h"
32#include "lib/playback_control.h" 33#include "lib/playback_control.h"
33 34
@@ -40,10 +41,12 @@ struct pacman_settings {
40 int bonus; 41 int bonus;
41 int ghostnames; 42 int ghostnames;
42 int showfps; 43 int showfps;
44 int sound;
43}; 45};
44 46
45static struct pacman_settings settings; 47static struct pacman_settings settings;
46static struct pacman_settings old_settings; 48static struct pacman_settings old_settings;
49static bool sound_playing = false;
47 50
48#define SETTINGS_VERSION 1 51#define SETTINGS_VERSION 1
49#define SETTINGS_MIN_VERSION 1 52#define SETTINGS_MIN_VERSION 1
@@ -53,7 +56,7 @@ static char* difficulty_options[] = { "Normal", "Hard" };
53static char* numlives_options[] = { "1", "2", "3", "5" }; 56static char* numlives_options[] = { "1", "2", "3", "5" };
54static char* bonus_options[] = {"10000", "15000", "20000", "No Bonus"}; 57static char* bonus_options[] = {"10000", "15000", "20000", "No Bonus"};
55static char* ghostnames_options[] = {"Normal", "Alternate"}; 58static char* ghostnames_options[] = {"Normal", "Alternate"};
56static char* showfps_options[] = {"No", "Yes"}; 59static char* yesno_options[] = {"No", "Yes"};
57 60
58static struct configdata config[] = 61static struct configdata config[] =
59{ 62{
@@ -65,7 +68,9 @@ static struct configdata config[] =
65 {TYPE_ENUM, 0, 2, { .int_p = &settings.ghostnames }, "Ghost Names", 68 {TYPE_ENUM, 0, 2, { .int_p = &settings.ghostnames }, "Ghost Names",
66 ghostnames_options}, 69 ghostnames_options},
67 {TYPE_ENUM, 0, 2, { .int_p = &settings.showfps }, "Show FPS", 70 {TYPE_ENUM, 0, 2, { .int_p = &settings.showfps }, "Show FPS",
68 showfps_options}, 71 yesno_options},
72 {TYPE_ENUM, 0, 2, { .int_p = &settings.sound }, "Sound",
73 yesno_options},
69}; 74};
70 75
71static bool loadFile( const char * name, unsigned char * buf, int len ) 76static bool loadFile( const char * name, unsigned char * buf, int len )
@@ -173,9 +178,21 @@ static bool pacbox_menu(void)
173 { "Alternate", -1 }, 178 { "Alternate", -1 },
174 }; 179 };
175 180
181 enum
182 {
183 PBMI_DIFFICULTY = 0,
184 PBMI_PACMEN_PER_GAME,
185 PBMI_BONUS_LIFE,
186 PBMI_GHOST_NAMES,
187 PBMI_DISPLAY_FPS,
188 PBMI_SOUND,
189 PBMI_RESTART,
190 PBMI_QUIT,
191 };
192
176 MENUITEM_STRINGLIST(menu, "Pacbox Menu", NULL, 193 MENUITEM_STRINGLIST(menu, "Pacbox Menu", NULL,
177 "Difficulty", "Pacmen Per Game", "Bonus Life", 194 "Difficulty", "Pacmen Per Game", "Bonus Life",
178 "Ghost Names", "Display FPS", 195 "Ghost Names", "Display FPS", "Sound",
179 "Restart", "Quit"); 196 "Restart", "Quit");
180 197
181 rb->button_clear_queue(); 198 rb->button_clear_queue();
@@ -189,7 +206,7 @@ static bool pacbox_menu(void)
189 206
190 switch(result) 207 switch(result)
191 { 208 {
192 case 0: 209 case PBMI_DIFFICULTY:
193 new_setting=settings.difficulty; 210 new_setting=settings.difficulty;
194 rb->set_option("Difficulty", &new_setting, INT, 211 rb->set_option("Difficulty", &new_setting, INT,
195 difficulty_options , 2, NULL); 212 difficulty_options , 2, NULL);
@@ -198,7 +215,7 @@ static bool pacbox_menu(void)
198 need_restart=true; 215 need_restart=true;
199 } 216 }
200 break; 217 break;
201 case 1: 218 case PBMI_PACMEN_PER_GAME:
202 new_setting=settings.numlives; 219 new_setting=settings.numlives;
203 rb->set_option("Pacmen Per Game", &new_setting, INT, 220 rb->set_option("Pacmen Per Game", &new_setting, INT,
204 numlives_options , 4, NULL); 221 numlives_options , 4, NULL);
@@ -207,7 +224,7 @@ static bool pacbox_menu(void)
207 need_restart=true; 224 need_restart=true;
208 } 225 }
209 break; 226 break;
210 case 2: 227 case PBMI_BONUS_LIFE:
211 new_setting=settings.bonus; 228 new_setting=settings.bonus;
212 rb->set_option("Bonus Life", &new_setting, INT, 229 rb->set_option("Bonus Life", &new_setting, INT,
213 bonus_options , 4, NULL); 230 bonus_options , 4, NULL);
@@ -216,7 +233,7 @@ static bool pacbox_menu(void)
216 need_restart=true; 233 need_restart=true;
217 } 234 }
218 break; 235 break;
219 case 3: 236 case PBMI_GHOST_NAMES:
220 new_setting=settings.ghostnames; 237 new_setting=settings.ghostnames;
221 rb->set_option("Ghost Names", &new_setting, INT, 238 rb->set_option("Ghost Names", &new_setting, INT,
222 ghostname_options , 2, NULL); 239 ghostname_options , 2, NULL);
@@ -225,11 +242,15 @@ static bool pacbox_menu(void)
225 need_restart=true; 242 need_restart=true;
226 } 243 }
227 break; 244 break;
228 case 4: /* Show FPS */ 245 case PBMI_DISPLAY_FPS:
229 rb->set_option("Display FPS",&settings.showfps,INT, 246 rb->set_option("Display FPS",&settings.showfps,INT,
230 noyes, 2, NULL); 247 noyes, 2, NULL);
231 break; 248 break;
232 case 5: /* Restart */ 249 case PBMI_SOUND:
250 rb->set_option("Sound",&settings.sound, INT,
251 noyes, 2, NULL);
252 break;
253 case PBMI_RESTART:
233 need_restart=true; 254 need_restart=true;
234 menu_quit=1; 255 menu_quit=1;
235 break; 256 break;
@@ -252,16 +273,93 @@ static bool pacbox_menu(void)
252 restart game 273 restart game
253 usb connected 274 usb connected
254 */ 275 */
255 return (result==6); 276 return (result==PBMI_QUIT);
277}
278
279/* Sound is emulated in ISR context, so not much is done per sound frame */
280#define NBSAMPLES 128
281static uint32_t sound_buf[NBSAMPLES];
282static int raw_buf[NBSAMPLES] IBSS_ATTR;
283
284/*
285 Audio callback
286 */
287static void get_more(unsigned char **start, size_t *size)
288{
289 int i;
290 int32_t *out;
291 int *raw;
292
293 /* Emulate the audio for the current register settings */
294 playSound(raw_buf, NBSAMPLES);
295
296 out = sound_buf;
297 raw = raw_buf;
298
299 /* Normalize the audio and convert to stereo */
300 for (i = 0; i < NBSAMPLES; i++)
301 {
302 uint32_t sample = (uint16_t)*raw++ << 6;
303 *out++ = sample | (sample << 16);
304 }
305
306 *start = (unsigned char *)sound_buf;
307 *size = NBSAMPLES*sizeof(sound_buf[0]);
308}
309
310/*
311 Start the sound emulation
312*/
313static void start_sound(void)
314{
315 int sr_index;
316
317 if (sound_playing)
318 return;
319
320#ifndef PLUGIN_USE_IRAM
321 /* Ensure control of PCM - stopping music isn't obligatory */
322 rb->plugin_get_audio_buffer(NULL);
323#endif
324
325 /* Get the closest rate >= to what is preferred */
326 sr_index = rb->round_value_to_list32(PREFERRED_SAMPLING_RATE,
327 rb->hw_freq_sampr, HW_NUM_FREQ, false);
328
329 if (rb->hw_freq_sampr[sr_index] < PREFERRED_SAMPLING_RATE
330 && sr_index > 0)
331 {
332 /* Round up */
333 sr_index--;
334 }
335
336 wsg3_set_sampling_rate(rb->hw_freq_sampr[sr_index]);
337
338 rb->pcm_set_frequency(rb->hw_freq_sampr[sr_index]);
339 rb->pcm_play_data(get_more, NULL, 0);
340
341 sound_playing = true;
256} 342}
257 343
344/*
345 Stop the sound emulation
346*/
347static void stop_sound(void)
348{
349 if (!sound_playing)
350 return;
351
352 rb->pcm_play_stop();
353 rb->pcm_set_frequency(HW_SAMPR_DEFAULT);
354
355 sound_playing = false;
356}
258 357
259/* 358/*
260 Runs the game engine for one frame. 359 Runs the game engine for one frame.
261*/ 360*/
262static int gameProc( void ) 361static int gameProc( void )
263{ 362{
264 int x;
265 int fps; 363 int fps;
266 char str[80]; 364 char str[80];
267 int status; 365 int status;
@@ -269,6 +367,9 @@ static int gameProc( void )
269 int frame_counter = 0; 367 int frame_counter = 0;
270 int yield_counter = 0; 368 int yield_counter = 0;
271 369
370 if (settings.sound)
371 start_sound();
372
272 while (1) 373 while (1)
273 { 374 {
274 /* Run the machine for one frame (1/60th second) */ 375 /* Run the machine for one frame (1/60th second) */
@@ -289,14 +390,25 @@ static int gameProc( void )
289 || status == PACMAN_RC_MENU 390 || status == PACMAN_RC_MENU
290#endif 391#endif
291 ) { 392 ) {
393 bool menu_res;
394
292 end_time = *rb->current_tick; 395 end_time = *rb->current_tick;
293 x = pacbox_menu(); 396
397 stop_sound();
398
399 menu_res = pacbox_menu();
400
294 rb->lcd_clear_display(); 401 rb->lcd_clear_display();
295#ifdef HAVE_REMOTE_LCD 402#ifdef HAVE_REMOTE_LCD
296 rb->lcd_remote_clear_display(); 403 rb->lcd_remote_clear_display();
297 rb->lcd_remote_update(); 404 rb->lcd_remote_update();
298#endif 405#endif
299 if (x == 1) { return 1; } 406 if (menu_res)
407 return 1;
408
409 if (settings.sound)
410 start_sound();
411
300 start_time += *rb->current_tick-end_time; 412 start_time += *rb->current_tick-end_time;
301 } 413 }
302 414
@@ -368,6 +480,9 @@ static int gameProc( void )
368 } 480 }
369 } 481 }
370 } 482 }
483
484 stop_sound();
485
371 return 0; 486 return 0;
372} 487}
373 488
@@ -392,6 +507,7 @@ enum plugin_status plugin_start(const void* parameter)
392 settings.bonus = 0; /* 10000 points */ 507 settings.bonus = 0; /* 10000 points */
393 settings.ghostnames = 0; /* Normal names */ 508 settings.ghostnames = 0; /* Normal names */
394 settings.showfps = 0; /* Do not show FPS */ 509 settings.showfps = 0; /* Do not show FPS */
510 settings.sound = 0; /* Sound off by default */
395 511
396 if (configfile_load(SETTINGS_FILENAME, config, 512 if (configfile_load(SETTINGS_FILENAME, config,
397 sizeof(config)/sizeof(*config), 513 sizeof(config)/sizeof(*config),
diff --git a/apps/plugins/pacbox/pacbox.h b/apps/plugins/pacbox/pacbox.h
index 1ff51e2872..f4cc738b02 100644
--- a/apps/plugins/pacbox/pacbox.h
+++ b/apps/plugins/pacbox/pacbox.h
@@ -299,4 +299,7 @@
299#define FPS 20 299#define FPS 20
300#endif 300#endif
301 301
302/* 16kHz sounds pretty good - use it if available */
303#define PREFERRED_SAMPLING_RATE SAMPR_16
304
302#endif 305#endif
diff --git a/apps/plugins/pacbox/wsg3.c b/apps/plugins/pacbox/wsg3.c
new file mode 100644
index 0000000000..3c861312b9
--- /dev/null
+++ b/apps/plugins/pacbox/wsg3.c
@@ -0,0 +1,148 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Pacbox - a Pacman Emulator for Rockbox
11 *
12 * Based on PIE - Pacman Instructional Emulator
13 *
14 * Namco custom waveform sound generator 3 (Pacman hardware)
15 *
16 * Copyright (c) 2003,2004 Alessandro Scotti
17 * http://www.ascotti.org/
18 *
19 * This program is free software; you can redistribute it and/or
20 * modify it under the terms of the GNU General Public License
21 * as published by the Free Software Foundation; either version 2
22 * of the License, or (at your option) any later version.
23 *
24 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
25 * KIND, either express or implied.
26 *
27 ****************************************************************************/
28#include "plugin.h"
29#include "wsg3.h"
30
31struct wsg3 wsg3;
32
33static bool wsg3_get_voice(struct wsg3_voice *voice, int index)
34{
35 int base = 5*index;
36 const unsigned char *regs = wsg3.sound_regs;
37 unsigned x;
38
39 x = regs[0x15 + base] & 0x0F;
40
41 if (x == 0)
42 return false;
43
44 voice->volume = x;
45
46 x = (regs[0x14 + base] & 0x0F);
47 x = (x << 4) | (regs[0x13 + base] & 0x0F);
48 x = (x << 4) | (regs[0x12 + base] & 0x0F);
49 x = (x << 4) | (regs[0x11 + base] & 0x0F);
50 x = (x << 4);
51
52 if (index == 0)
53 {
54 /* The first voice has an extra 4-bit of data */
55 x |= regs[0x10 + base] & 0x0F;
56 }
57
58 if (x == 0)
59 return false;
60
61 voice->frequency = x;
62
63 voice->waveform = regs[0x05 + base] & 0x07;
64
65 return true;
66}
67
68void wsg3_play_sound(int * buf, int len)
69{
70 struct wsg3_voice voice;
71
72 if (wsg3_get_voice(&voice, 0))
73 {
74 unsigned offset = wsg3.wave_offset[0];
75 unsigned step = voice.frequency * wsg3.resample_step;
76 int * wave_data = wsg3.sound_wave_data + 32 * voice.waveform;
77 int volume = voice.volume;
78 int i;
79
80 for (i = 0; i < len; i++)
81 {
82 /* Should be shifted right by 15, but we must also get rid
83 * of the 10 bits used for decimals */
84 buf[i] += wave_data[(offset >> 25) & 0x1F] * volume;
85 offset += step;
86 }
87
88 wsg3.wave_offset[0] = offset;
89 }
90
91 if (wsg3_get_voice(&voice, 1))
92 {
93 unsigned offset = wsg3.wave_offset[1];
94 unsigned step = voice.frequency * wsg3.resample_step;
95 int * wave_data = wsg3.sound_wave_data + 32 * voice.waveform;
96 int volume = voice.volume;
97 int i;
98
99 for (i = 0; i < len; i++)
100 {
101 /* Should be shifted right by 15, but we must also get rid
102 * of the 10 bits used for decimals */
103 buf[i] += wave_data[(offset >> 25) & 0x1F] * volume;
104 offset += step;
105 }
106
107 wsg3.wave_offset[1] = offset;
108 }
109
110 if (wsg3_get_voice(&voice, 2))
111 {
112 unsigned offset = wsg3.wave_offset[2];
113 unsigned step = voice.frequency * wsg3.resample_step;
114 int * wave_data = wsg3.sound_wave_data + 32 * voice.waveform;
115 int volume = voice.volume;
116 int i;
117
118 for (i = 0; i < len; i++)
119 {
120 /* Should be shifted right by 15, but we must also get rid
121 * of the 10 bits used for decimals */
122 buf[i] += wave_data[(offset >> 25) & 0x1F] * volume;
123 offset += step;
124 }
125
126 wsg3.wave_offset[2] = offset;
127 }
128}
129
130void wsg3_set_sampling_rate(unsigned sampling_rate)
131{
132 wsg3.sampling_rate = sampling_rate;
133 wsg3.resample_step = (wsg3.master_clock << 10) / sampling_rate;
134}
135
136void wsg3_set_sound_prom( const unsigned char * prom )
137{
138 int i;
139
140 for (i = 0; i < 32*8; i++)
141 wsg3.sound_wave_data[i] = (int)*prom++ - 8;
142}
143
144void wsg3_init(unsigned master_clock)
145{
146 memset(&wsg3, 0, sizeof (struct wsg3));
147 wsg3.master_clock = master_clock;
148}
diff --git a/apps/plugins/pacbox/wsg3.h b/apps/plugins/pacbox/wsg3.h
new file mode 100644
index 0000000000..1ee385cdf9
--- /dev/null
+++ b/apps/plugins/pacbox/wsg3.h
@@ -0,0 +1,124 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Pacbox - a Pacman Emulator for Rockbox
11 *
12 * Based on PIE - Pacman Instructional Emulator
13 *
14 * Namco custom waveform sound generator 3 (Pacman hardware)
15 *
16 * Copyright (c) 2003,2004 Alessandro Scotti
17 * http://www.ascotti.org/
18 *
19 * This program is free software; you can redistribute it and/or
20 * modify it under the terms of the GNU General Public License
21 * as published by the Free Software Foundation; either version 2
22 * of the License, or (at your option) any later version.
23 *
24 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
25 * KIND, either express or implied.
26 *
27 ****************************************************************************/
28#ifndef WSG3_H
29#define WSG3_H
30
31/**
32 Namco 3-channel sound generator voice properties.
33
34 This information is only needed by applications that want to do their own
35 sound rendering, as the playSound() function already plays and mixes all
36 three voices.
37
38 @see PacmanMachine::playSound
39*/
40struct wsg3_voice
41{
42 /** Volume (from 0 to 15) */
43 unsigned volume;
44 /** Index into the 4-bit 32-entry waveform table (0 to 7) */
45 unsigned waveform;
46 /** Frequency */
47 unsigned frequency;
48};
49
50
51struct wsg3
52{
53 unsigned master_clock;
54 unsigned sampling_rate;
55 unsigned char sound_regs[0x20];
56 unsigned char sound_prom[32*8];
57 unsigned resample_step;
58 unsigned wave_offset[3];
59 int sound_wave_data[32*8];
60};
61
62extern struct wsg3 wsg3;
63
64/**
65 Constructor.
66
67 @param masterClock clock frequency of sound chip (in Hertz)
68
69 @see #wsg3_play_sound
70*/
71void wsg3_init(unsigned master_clock);
72
73/**
74 Sets the 256 byte PROM that contains the waveform table used by the sound chip.
75*/
76void wsg3_set_sound_prom( const unsigned char * prom );
77
78/**
79 Sets the value of the specified register.
80*/
81static inline void wsg3_set_register(unsigned reg, unsigned char value)
82 { wsg3.sound_regs[reg] = value; }
83
84/**
85 Returns the value of the specified register.
86*/
87static inline unsigned char wsg3_get_register(unsigned reg)
88 { return wsg3.sound_regs[reg]; }
89
90/**
91 Reproduces the sound that is currently being generated by the sound
92 chip into the specified buffer.
93
94 The sound chip has three independent voices that generate 8-bit signed
95 PCM audio. This function resamples the voices at the currently specified
96 sampling rate and mixes them into the output buffer. The output buffer
97 can be converted to 8-bit (signed) PCM by dividing each sample by 3 (since
98 there are three voices) or it can be expanded to 16-bit by multiplying
99 each sample by 85 (i.e. 256 divided by 3). If necessary, it is possible
100 to approximate these values with 4 and 64 in order to use arithmetic
101 shifts that are usually faster to execute.
102
103 Note: this function does not clear the content of the output buffer before
104 mixing voices into it.
105
106 @param buf pointer to sound buffer that receives the audio samples
107 @param len length of the sound buffer
108*/
109void wsg3_play_sound(int * buf, int len);
110
111/**
112 Returns the sampling rate currently in use for rendering sound.
113*/
114static inline unsigned wsg3_get_sampling_rate(void)
115 { return wsg3.sampling_rate; }
116
117/**
118 Sets the output sampling rate for playSound().
119
120 @param samplingRate sampling rate in Hertz (samples per second)
121*/
122void wsg3_set_sampling_rate(unsigned sampling_rate);
123
124#endif /* WSG3_H */