diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2010-07-01 00:26:01 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2010-07-01 00:26:01 +0000 |
commit | cf73340f1e85d3b39dc452d57e28d2a9a9081051 (patch) | |
tree | 27a89d40fae023d994c7a59d3950f7af32dc00aa /apps | |
parent | 10b8e327d8c0d37b8a9f1997e33e4bf1a97bb39b (diff) | |
download | rockbox-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
Diffstat (limited to 'apps')
-rw-r--r-- | apps/plugin.c | 2 | ||||
-rw-r--r-- | apps/plugin.h | 14 | ||||
-rw-r--r-- | apps/plugins/pacbox/SOURCES | 1 | ||||
-rw-r--r-- | apps/plugins/pacbox/arcade.c | 58 | ||||
-rw-r--r-- | apps/plugins/pacbox/arcade.h | 2 | ||||
-rw-r--r-- | apps/plugins/pacbox/hardware.c | 3 | ||||
-rw-r--r-- | apps/plugins/pacbox/pacbox.c | 142 | ||||
-rw-r--r-- | apps/plugins/pacbox/pacbox.h | 3 | ||||
-rw-r--r-- | apps/plugins/pacbox/wsg3.c | 148 | ||||
-rw-r--r-- | apps/plugins/pacbox/wsg3.h | 124 |
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 */ |
155 | enum plugin_status { | 155 | enum 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, |
786 | int (*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 | |||
2 | pacbox.c | 2 | pacbox.c |
3 | hardware.c | 3 | hardware.c |
4 | z80.c | 4 | z80.c |
5 | wsg3.c | ||
5 | #if defined(CPU_PP502x) && (LCD_WIDTH >= 288) && (LCD_HEIGHT >= 224) | 6 | #if defined(CPU_PP502x) && (LCD_WIDTH >= 288) && (LCD_HEIGHT >= 224) |
6 | pacbox_arm.S | 7 | pacbox_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) | ||
98 | static 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 | ||
643 | void 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. */ |
599 | int setSpeedHack( int enabled ) | 657 | int 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); | |||
123 | int run(void); | 123 | int run(void); |
124 | void reset_PacmanMachine(void); | 124 | void reset_PacmanMachine(void); |
125 | void decodeROMs(void); | 125 | void decodeROMs(void); |
126 | void 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 | ||
45 | static struct pacman_settings settings; | 47 | static struct pacman_settings settings; |
46 | static struct pacman_settings old_settings; | 48 | static struct pacman_settings old_settings; |
49 | static 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" }; | |||
53 | static char* numlives_options[] = { "1", "2", "3", "5" }; | 56 | static char* numlives_options[] = { "1", "2", "3", "5" }; |
54 | static char* bonus_options[] = {"10000", "15000", "20000", "No Bonus"}; | 57 | static char* bonus_options[] = {"10000", "15000", "20000", "No Bonus"}; |
55 | static char* ghostnames_options[] = {"Normal", "Alternate"}; | 58 | static char* ghostnames_options[] = {"Normal", "Alternate"}; |
56 | static char* showfps_options[] = {"No", "Yes"}; | 59 | static char* yesno_options[] = {"No", "Yes"}; |
57 | 60 | ||
58 | static struct configdata config[] = | 61 | static 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 | ||
71 | static bool loadFile( const char * name, unsigned char * buf, int len ) | 76 | static 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 | ||
281 | static uint32_t sound_buf[NBSAMPLES]; | ||
282 | static int raw_buf[NBSAMPLES] IBSS_ATTR; | ||
283 | |||
284 | /* | ||
285 | Audio callback | ||
286 | */ | ||
287 | static 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 | */ | ||
313 | static 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 | */ | ||
347 | static 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 | */ |
262 | static int gameProc( void ) | 361 | static 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 | |||
31 | struct wsg3 wsg3; | ||
32 | |||
33 | static 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 | |||
68 | void 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 | |||
130 | void 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 | |||
136 | void 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 | |||
144 | void 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 | */ | ||
40 | struct 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 | |||
51 | struct 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 | |||
62 | extern 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 | */ | ||
71 | void wsg3_init(unsigned master_clock); | ||
72 | |||
73 | /** | ||
74 | Sets the 256 byte PROM that contains the waveform table used by the sound chip. | ||
75 | */ | ||
76 | void wsg3_set_sound_prom( const unsigned char * prom ); | ||
77 | |||
78 | /** | ||
79 | Sets the value of the specified register. | ||
80 | */ | ||
81 | static 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 | */ | ||
87 | static 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 | */ | ||
109 | void wsg3_play_sound(int * buf, int len); | ||
110 | |||
111 | /** | ||
112 | Returns the sampling rate currently in use for rendering sound. | ||
113 | */ | ||
114 | static 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 | */ | ||
122 | void wsg3_set_sampling_rate(unsigned sampling_rate); | ||
123 | |||
124 | #endif /* WSG3_H */ | ||