forked from len0rd/rockbox
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
This commit is contained in:
parent
10b8e327d8
commit
cf73340f1e
10 changed files with 473 additions and 24 deletions
|
@ -637,9 +637,7 @@ static const struct plugin_api rockbox_api = {
|
||||||
get_codec_filename,
|
get_codec_filename,
|
||||||
find_array_ptr,
|
find_array_ptr,
|
||||||
remove_array_ptr,
|
remove_array_ptr,
|
||||||
#if defined(HAVE_RECORDING) && (defined(HAVE_LINE_IN) || defined(HAVE_MIC_IN))
|
|
||||||
round_value_to_list32,
|
round_value_to_list32,
|
||||||
#endif
|
|
||||||
#endif /* CONFIG_CODEC == SWCODEC */
|
#endif /* CONFIG_CODEC == SWCODEC */
|
||||||
get_metadata,
|
get_metadata,
|
||||||
mp3info,
|
mp3info,
|
||||||
|
|
|
@ -144,12 +144,12 @@ void* plugin_get_buffer(size_t *buffer_size);
|
||||||
#define PLUGIN_MAGIC 0x526F634B /* RocK */
|
#define PLUGIN_MAGIC 0x526F634B /* RocK */
|
||||||
|
|
||||||
/* increase this every time the api struct changes */
|
/* increase this every time the api struct changes */
|
||||||
#define PLUGIN_API_VERSION 187
|
#define PLUGIN_API_VERSION 188
|
||||||
|
|
||||||
/* update this to latest version if a change to the api struct breaks
|
/* update this to latest version if a change to the api struct breaks
|
||||||
backwards compatibility (and please take the opportunity to sort in any
|
backwards compatibility (and please take the opportunity to sort in any
|
||||||
new function which are "waiting" at the end of the function table) */
|
new function which are "waiting" at the end of the function table) */
|
||||||
#define PLUGIN_MIN_API_VERSION 187
|
#define PLUGIN_MIN_API_VERSION 188
|
||||||
|
|
||||||
/* plugin return codes */
|
/* plugin return codes */
|
||||||
enum plugin_status {
|
enum plugin_status {
|
||||||
|
@ -782,12 +782,10 @@ struct plugin_api {
|
||||||
const char *(*get_codec_filename)(int cod_spec);
|
const char *(*get_codec_filename)(int cod_spec);
|
||||||
void ** (*find_array_ptr)(void **arr, void *ptr);
|
void ** (*find_array_ptr)(void **arr, void *ptr);
|
||||||
int (*remove_array_ptr)(void **arr, void *ptr);
|
int (*remove_array_ptr)(void **arr, void *ptr);
|
||||||
#if defined(HAVE_RECORDING) && (defined(HAVE_LINE_IN) || defined(HAVE_MIC_IN))
|
int (*round_value_to_list32)(unsigned long value,
|
||||||
int (*round_value_to_list32)(unsigned long value,
|
|
||||||
const unsigned long list[],
|
const unsigned long list[],
|
||||||
int count,
|
int count,
|
||||||
bool signd);
|
bool signd);
|
||||||
#endif
|
|
||||||
#endif /* CONFIG_CODEC == SWCODEC */
|
#endif /* CONFIG_CODEC == SWCODEC */
|
||||||
bool (*get_metadata)(struct mp3entry* id3, int fd, const char* trackname);
|
bool (*get_metadata)(struct mp3entry* id3, int fd, const char* trackname);
|
||||||
bool (*mp3info)(struct mp3entry *entry, const char *filename);
|
bool (*mp3info)(struct mp3entry *entry, const char *filename);
|
||||||
|
|
|
@ -2,6 +2,7 @@ arcade.c
|
||||||
pacbox.c
|
pacbox.c
|
||||||
hardware.c
|
hardware.c
|
||||||
z80.c
|
z80.c
|
||||||
|
wsg3.c
|
||||||
#if defined(CPU_PP502x) && (LCD_WIDTH >= 288) && (LCD_HEIGHT >= 224)
|
#if defined(CPU_PP502x) && (LCD_WIDTH >= 288) && (LCD_HEIGHT >= 224)
|
||||||
pacbox_arm.S
|
pacbox_arm.S
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -24,8 +24,10 @@
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "pacbox.h"
|
||||||
#include "arcade.h"
|
#include "arcade.h"
|
||||||
#include "hardware.h"
|
#include "hardware.h"
|
||||||
|
#include "wsg3.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
|
|
||||||
|
@ -92,6 +94,43 @@ enum {
|
||||||
FlipXY = 0x03
|
FlipXY = 0x03
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Namco 3-channel Wave Sound Generator wave data (8 waveforms with 32 4-bit entries each)
|
||||||
|
static unsigned char default_sound_prom[] =
|
||||||
|
{
|
||||||
|
0x07, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0D, 0x0E,
|
||||||
|
0x0E, 0x0E, 0x0D, 0x0D, 0x0C, 0x0B, 0x0A, 0x09,
|
||||||
|
0x07, 0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x00,
|
||||||
|
0x00, 0x00, 0x01, 0x01, 0x02, 0x03, 0x04, 0x05,
|
||||||
|
0x07, 0x0C, 0x0E, 0x0E, 0x0D, 0x0B, 0x09, 0x0A,
|
||||||
|
0x0B, 0x0B, 0x0A, 0x09, 0x06, 0x04, 0x03, 0x05,
|
||||||
|
0x07, 0x09, 0x0B, 0x0A, 0x08, 0x05, 0x04, 0x03,
|
||||||
|
0x03, 0x04, 0x05, 0x03, 0x01, 0x00, 0x00, 0x02,
|
||||||
|
0x07, 0x0A, 0x0C, 0x0D, 0x0E, 0x0D, 0x0C, 0x0A,
|
||||||
|
0x07, 0x04, 0x02, 0x01, 0x00, 0x01, 0x02, 0x04,
|
||||||
|
0x07, 0x0B, 0x0D, 0x0E, 0x0D, 0x0B, 0x07, 0x03,
|
||||||
|
0x01, 0x00, 0x01, 0x03, 0x07, 0x0E, 0x07, 0x00,
|
||||||
|
0x07, 0x0D, 0x0B, 0x08, 0x0B, 0x0D, 0x09, 0x06,
|
||||||
|
0x0B, 0x0E, 0x0C, 0x07, 0x09, 0x0A, 0x06, 0x02,
|
||||||
|
0x07, 0x0C, 0x08, 0x04, 0x05, 0x07, 0x02, 0x00,
|
||||||
|
0x03, 0x08, 0x05, 0x01, 0x03, 0x06, 0x03, 0x01,
|
||||||
|
0x00, 0x08, 0x0F, 0x07, 0x01, 0x08, 0x0E, 0x07,
|
||||||
|
0x02, 0x08, 0x0D, 0x07, 0x03, 0x08, 0x0C, 0x07,
|
||||||
|
0x04, 0x08, 0x0B, 0x07, 0x05, 0x08, 0x0A, 0x07,
|
||||||
|
0x06, 0x08, 0x09, 0x07, 0x07, 0x08, 0x08, 0x07,
|
||||||
|
0x07, 0x08, 0x06, 0x09, 0x05, 0x0A, 0x04, 0x0B,
|
||||||
|
0x03, 0x0C, 0x02, 0x0D, 0x01, 0x0E, 0x00, 0x0F,
|
||||||
|
0x00, 0x0F, 0x01, 0x0E, 0x02, 0x0D, 0x03, 0x0C,
|
||||||
|
0x04, 0x0B, 0x05, 0x0A, 0x06, 0x09, 0x07, 0x08,
|
||||||
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||||
|
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||||
|
0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08,
|
||||||
|
0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00,
|
||||||
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||||
|
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||||
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||||
|
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||||
|
};
|
||||||
|
|
||||||
/* Putting this in IRAM actually slows down the iPods, but is good for
|
/* Putting this in IRAM actually slows down the iPods, but is good for
|
||||||
the Coldfire
|
the Coldfire
|
||||||
*/
|
*/
|
||||||
|
@ -110,6 +149,12 @@ void init_PacmanMachine(int dip)
|
||||||
z80_reset();
|
z80_reset();
|
||||||
rb->memset( &ram_[0x4000], 0xFF, 0x1000 );
|
rb->memset( &ram_[0x4000], 0xFF, 0x1000 );
|
||||||
|
|
||||||
|
/* Initialize the WSG3 */
|
||||||
|
wsg3_init(SoundClock);
|
||||||
|
|
||||||
|
/* Set the sound PROM to the default values for the original Namco chip */
|
||||||
|
wsg3_set_sound_prom(default_sound_prom);
|
||||||
|
|
||||||
/* Initialize parameters */
|
/* Initialize parameters */
|
||||||
port1_ = 0xFF;
|
port1_ = 0xFF;
|
||||||
port2_ = 0xFF;
|
port2_ = 0xFF;
|
||||||
|
@ -595,6 +640,19 @@ void renderSprites( unsigned char * buffer )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void playSound( int * buf, int len )
|
||||||
|
{
|
||||||
|
/* Clear the buffer */
|
||||||
|
memset( buf, 0, sizeof (int)*len);
|
||||||
|
|
||||||
|
/* Exit now if sound is disabled */
|
||||||
|
if( (output_devices_ & SoundEnabled) == 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Let the chip play the sound */
|
||||||
|
wsg3_play_sound( buf, len );
|
||||||
|
}
|
||||||
|
|
||||||
/* Enables/disables the speed hack. */
|
/* Enables/disables the speed hack. */
|
||||||
int setSpeedHack( int enabled )
|
int setSpeedHack( int enabled )
|
||||||
{
|
{
|
||||||
|
|
|
@ -123,6 +123,8 @@ void init_PacmanMachine(int dip);
|
||||||
int run(void);
|
int run(void);
|
||||||
void reset_PacmanMachine(void);
|
void reset_PacmanMachine(void);
|
||||||
void decodeROMs(void);
|
void decodeROMs(void);
|
||||||
|
void playSound( int * buf, int len );
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Tells the emulator that the status of an input device has changed.
|
Tells the emulator that the status of an input device has changed.
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
|
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
#include "hardware.h"
|
#include "hardware.h"
|
||||||
|
#include "wsg3.h"
|
||||||
|
|
||||||
/* The main data for Pacman */
|
/* The main data for Pacman */
|
||||||
|
|
||||||
|
@ -140,7 +141,7 @@ void writeByte( unsigned addr, unsigned char b )
|
||||||
default:
|
default:
|
||||||
if( addr >= 0x5040 && addr < 0x5060 ) {
|
if( addr >= 0x5040 && addr < 0x5060 ) {
|
||||||
// Sound registers
|
// Sound registers
|
||||||
//SOUND sound_chip_.setRegister( addr-0x5040, b );
|
wsg3_set_register( addr-0x5040, b );
|
||||||
}
|
}
|
||||||
else if( addr >= 0x5060 && addr < 0x5070 ) {
|
else if( addr >= 0x5060 && addr < 0x5070 ) {
|
||||||
// Sprite coordinates, x/y pairs for 8 sprites
|
// Sprite coordinates, x/y pairs for 8 sprites
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include "arcade.h"
|
#include "arcade.h"
|
||||||
#include "pacbox.h"
|
#include "pacbox.h"
|
||||||
#include "pacbox_lcd.h"
|
#include "pacbox_lcd.h"
|
||||||
|
#include "wsg3.h"
|
||||||
#include "lib/configfile.h"
|
#include "lib/configfile.h"
|
||||||
#include "lib/playback_control.h"
|
#include "lib/playback_control.h"
|
||||||
|
|
||||||
|
@ -40,10 +41,12 @@ struct pacman_settings {
|
||||||
int bonus;
|
int bonus;
|
||||||
int ghostnames;
|
int ghostnames;
|
||||||
int showfps;
|
int showfps;
|
||||||
|
int sound;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct pacman_settings settings;
|
static struct pacman_settings settings;
|
||||||
static struct pacman_settings old_settings;
|
static struct pacman_settings old_settings;
|
||||||
|
static bool sound_playing = false;
|
||||||
|
|
||||||
#define SETTINGS_VERSION 1
|
#define SETTINGS_VERSION 1
|
||||||
#define SETTINGS_MIN_VERSION 1
|
#define SETTINGS_MIN_VERSION 1
|
||||||
|
@ -53,7 +56,7 @@ static char* difficulty_options[] = { "Normal", "Hard" };
|
||||||
static char* numlives_options[] = { "1", "2", "3", "5" };
|
static char* numlives_options[] = { "1", "2", "3", "5" };
|
||||||
static char* bonus_options[] = {"10000", "15000", "20000", "No Bonus"};
|
static char* bonus_options[] = {"10000", "15000", "20000", "No Bonus"};
|
||||||
static char* ghostnames_options[] = {"Normal", "Alternate"};
|
static char* ghostnames_options[] = {"Normal", "Alternate"};
|
||||||
static char* showfps_options[] = {"No", "Yes"};
|
static char* yesno_options[] = {"No", "Yes"};
|
||||||
|
|
||||||
static struct configdata config[] =
|
static struct configdata config[] =
|
||||||
{
|
{
|
||||||
|
@ -65,7 +68,9 @@ static struct configdata config[] =
|
||||||
{TYPE_ENUM, 0, 2, { .int_p = &settings.ghostnames }, "Ghost Names",
|
{TYPE_ENUM, 0, 2, { .int_p = &settings.ghostnames }, "Ghost Names",
|
||||||
ghostnames_options},
|
ghostnames_options},
|
||||||
{TYPE_ENUM, 0, 2, { .int_p = &settings.showfps }, "Show FPS",
|
{TYPE_ENUM, 0, 2, { .int_p = &settings.showfps }, "Show FPS",
|
||||||
showfps_options},
|
yesno_options},
|
||||||
|
{TYPE_ENUM, 0, 2, { .int_p = &settings.sound }, "Sound",
|
||||||
|
yesno_options},
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool loadFile( const char * name, unsigned char * buf, int len )
|
static bool loadFile( const char * name, unsigned char * buf, int len )
|
||||||
|
@ -173,9 +178,21 @@ static bool pacbox_menu(void)
|
||||||
{ "Alternate", -1 },
|
{ "Alternate", -1 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PBMI_DIFFICULTY = 0,
|
||||||
|
PBMI_PACMEN_PER_GAME,
|
||||||
|
PBMI_BONUS_LIFE,
|
||||||
|
PBMI_GHOST_NAMES,
|
||||||
|
PBMI_DISPLAY_FPS,
|
||||||
|
PBMI_SOUND,
|
||||||
|
PBMI_RESTART,
|
||||||
|
PBMI_QUIT,
|
||||||
|
};
|
||||||
|
|
||||||
MENUITEM_STRINGLIST(menu, "Pacbox Menu", NULL,
|
MENUITEM_STRINGLIST(menu, "Pacbox Menu", NULL,
|
||||||
"Difficulty", "Pacmen Per Game", "Bonus Life",
|
"Difficulty", "Pacmen Per Game", "Bonus Life",
|
||||||
"Ghost Names", "Display FPS",
|
"Ghost Names", "Display FPS", "Sound",
|
||||||
"Restart", "Quit");
|
"Restart", "Quit");
|
||||||
|
|
||||||
rb->button_clear_queue();
|
rb->button_clear_queue();
|
||||||
|
@ -189,7 +206,7 @@ static bool pacbox_menu(void)
|
||||||
|
|
||||||
switch(result)
|
switch(result)
|
||||||
{
|
{
|
||||||
case 0:
|
case PBMI_DIFFICULTY:
|
||||||
new_setting=settings.difficulty;
|
new_setting=settings.difficulty;
|
||||||
rb->set_option("Difficulty", &new_setting, INT,
|
rb->set_option("Difficulty", &new_setting, INT,
|
||||||
difficulty_options , 2, NULL);
|
difficulty_options , 2, NULL);
|
||||||
|
@ -198,7 +215,7 @@ static bool pacbox_menu(void)
|
||||||
need_restart=true;
|
need_restart=true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 1:
|
case PBMI_PACMEN_PER_GAME:
|
||||||
new_setting=settings.numlives;
|
new_setting=settings.numlives;
|
||||||
rb->set_option("Pacmen Per Game", &new_setting, INT,
|
rb->set_option("Pacmen Per Game", &new_setting, INT,
|
||||||
numlives_options , 4, NULL);
|
numlives_options , 4, NULL);
|
||||||
|
@ -207,7 +224,7 @@ static bool pacbox_menu(void)
|
||||||
need_restart=true;
|
need_restart=true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 2:
|
case PBMI_BONUS_LIFE:
|
||||||
new_setting=settings.bonus;
|
new_setting=settings.bonus;
|
||||||
rb->set_option("Bonus Life", &new_setting, INT,
|
rb->set_option("Bonus Life", &new_setting, INT,
|
||||||
bonus_options , 4, NULL);
|
bonus_options , 4, NULL);
|
||||||
|
@ -216,7 +233,7 @@ static bool pacbox_menu(void)
|
||||||
need_restart=true;
|
need_restart=true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 3:
|
case PBMI_GHOST_NAMES:
|
||||||
new_setting=settings.ghostnames;
|
new_setting=settings.ghostnames;
|
||||||
rb->set_option("Ghost Names", &new_setting, INT,
|
rb->set_option("Ghost Names", &new_setting, INT,
|
||||||
ghostname_options , 2, NULL);
|
ghostname_options , 2, NULL);
|
||||||
|
@ -225,11 +242,15 @@ static bool pacbox_menu(void)
|
||||||
need_restart=true;
|
need_restart=true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 4: /* Show FPS */
|
case PBMI_DISPLAY_FPS:
|
||||||
rb->set_option("Display FPS",&settings.showfps,INT,
|
rb->set_option("Display FPS",&settings.showfps,INT,
|
||||||
noyes, 2, NULL);
|
noyes, 2, NULL);
|
||||||
break;
|
break;
|
||||||
case 5: /* Restart */
|
case PBMI_SOUND:
|
||||||
|
rb->set_option("Sound",&settings.sound, INT,
|
||||||
|
noyes, 2, NULL);
|
||||||
|
break;
|
||||||
|
case PBMI_RESTART:
|
||||||
need_restart=true;
|
need_restart=true;
|
||||||
menu_quit=1;
|
menu_quit=1;
|
||||||
break;
|
break;
|
||||||
|
@ -252,16 +273,93 @@ static bool pacbox_menu(void)
|
||||||
restart game
|
restart game
|
||||||
usb connected
|
usb connected
|
||||||
*/
|
*/
|
||||||
return (result==6);
|
return (result==PBMI_QUIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Sound is emulated in ISR context, so not much is done per sound frame */
|
||||||
|
#define NBSAMPLES 128
|
||||||
|
static uint32_t sound_buf[NBSAMPLES];
|
||||||
|
static int raw_buf[NBSAMPLES] IBSS_ATTR;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Audio callback
|
||||||
|
*/
|
||||||
|
static void get_more(unsigned char **start, size_t *size)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int32_t *out;
|
||||||
|
int *raw;
|
||||||
|
|
||||||
|
/* Emulate the audio for the current register settings */
|
||||||
|
playSound(raw_buf, NBSAMPLES);
|
||||||
|
|
||||||
|
out = sound_buf;
|
||||||
|
raw = raw_buf;
|
||||||
|
|
||||||
|
/* Normalize the audio and convert to stereo */
|
||||||
|
for (i = 0; i < NBSAMPLES; i++)
|
||||||
|
{
|
||||||
|
uint32_t sample = (uint16_t)*raw++ << 6;
|
||||||
|
*out++ = sample | (sample << 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
*start = (unsigned char *)sound_buf;
|
||||||
|
*size = NBSAMPLES*sizeof(sound_buf[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Start the sound emulation
|
||||||
|
*/
|
||||||
|
static void start_sound(void)
|
||||||
|
{
|
||||||
|
int sr_index;
|
||||||
|
|
||||||
|
if (sound_playing)
|
||||||
|
return;
|
||||||
|
|
||||||
|
#ifndef PLUGIN_USE_IRAM
|
||||||
|
/* Ensure control of PCM - stopping music isn't obligatory */
|
||||||
|
rb->plugin_get_audio_buffer(NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Get the closest rate >= to what is preferred */
|
||||||
|
sr_index = rb->round_value_to_list32(PREFERRED_SAMPLING_RATE,
|
||||||
|
rb->hw_freq_sampr, HW_NUM_FREQ, false);
|
||||||
|
|
||||||
|
if (rb->hw_freq_sampr[sr_index] < PREFERRED_SAMPLING_RATE
|
||||||
|
&& sr_index > 0)
|
||||||
|
{
|
||||||
|
/* Round up */
|
||||||
|
sr_index--;
|
||||||
|
}
|
||||||
|
|
||||||
|
wsg3_set_sampling_rate(rb->hw_freq_sampr[sr_index]);
|
||||||
|
|
||||||
|
rb->pcm_set_frequency(rb->hw_freq_sampr[sr_index]);
|
||||||
|
rb->pcm_play_data(get_more, NULL, 0);
|
||||||
|
|
||||||
|
sound_playing = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Stop the sound emulation
|
||||||
|
*/
|
||||||
|
static void stop_sound(void)
|
||||||
|
{
|
||||||
|
if (!sound_playing)
|
||||||
|
return;
|
||||||
|
|
||||||
|
rb->pcm_play_stop();
|
||||||
|
rb->pcm_set_frequency(HW_SAMPR_DEFAULT);
|
||||||
|
|
||||||
|
sound_playing = false;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Runs the game engine for one frame.
|
Runs the game engine for one frame.
|
||||||
*/
|
*/
|
||||||
static int gameProc( void )
|
static int gameProc( void )
|
||||||
{
|
{
|
||||||
int x;
|
|
||||||
int fps;
|
int fps;
|
||||||
char str[80];
|
char str[80];
|
||||||
int status;
|
int status;
|
||||||
|
@ -269,6 +367,9 @@ static int gameProc( void )
|
||||||
int frame_counter = 0;
|
int frame_counter = 0;
|
||||||
int yield_counter = 0;
|
int yield_counter = 0;
|
||||||
|
|
||||||
|
if (settings.sound)
|
||||||
|
start_sound();
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
/* Run the machine for one frame (1/60th second) */
|
/* Run the machine for one frame (1/60th second) */
|
||||||
|
@ -289,14 +390,25 @@ static int gameProc( void )
|
||||||
|| status == PACMAN_RC_MENU
|
|| status == PACMAN_RC_MENU
|
||||||
#endif
|
#endif
|
||||||
) {
|
) {
|
||||||
|
bool menu_res;
|
||||||
|
|
||||||
end_time = *rb->current_tick;
|
end_time = *rb->current_tick;
|
||||||
x = pacbox_menu();
|
|
||||||
|
stop_sound();
|
||||||
|
|
||||||
|
menu_res = pacbox_menu();
|
||||||
|
|
||||||
rb->lcd_clear_display();
|
rb->lcd_clear_display();
|
||||||
#ifdef HAVE_REMOTE_LCD
|
#ifdef HAVE_REMOTE_LCD
|
||||||
rb->lcd_remote_clear_display();
|
rb->lcd_remote_clear_display();
|
||||||
rb->lcd_remote_update();
|
rb->lcd_remote_update();
|
||||||
#endif
|
#endif
|
||||||
if (x == 1) { return 1; }
|
if (menu_res)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (settings.sound)
|
||||||
|
start_sound();
|
||||||
|
|
||||||
start_time += *rb->current_tick-end_time;
|
start_time += *rb->current_tick-end_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -368,6 +480,9 @@ static int gameProc( void )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stop_sound();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -392,6 +507,7 @@ enum plugin_status plugin_start(const void* parameter)
|
||||||
settings.bonus = 0; /* 10000 points */
|
settings.bonus = 0; /* 10000 points */
|
||||||
settings.ghostnames = 0; /* Normal names */
|
settings.ghostnames = 0; /* Normal names */
|
||||||
settings.showfps = 0; /* Do not show FPS */
|
settings.showfps = 0; /* Do not show FPS */
|
||||||
|
settings.sound = 0; /* Sound off by default */
|
||||||
|
|
||||||
if (configfile_load(SETTINGS_FILENAME, config,
|
if (configfile_load(SETTINGS_FILENAME, config,
|
||||||
sizeof(config)/sizeof(*config),
|
sizeof(config)/sizeof(*config),
|
||||||
|
|
|
@ -299,4 +299,7 @@
|
||||||
#define FPS 20
|
#define FPS 20
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* 16kHz sounds pretty good - use it if available */
|
||||||
|
#define PREFERRED_SAMPLING_RATE SAMPR_16
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
148
apps/plugins/pacbox/wsg3.c
Normal file
148
apps/plugins/pacbox/wsg3.c
Normal file
|
@ -0,0 +1,148 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* __________ __ ___.
|
||||||
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||||
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||||
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||||
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||||
|
* \/ \/ \/ \/ \/
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* Pacbox - a Pacman Emulator for Rockbox
|
||||||
|
*
|
||||||
|
* Based on PIE - Pacman Instructional Emulator
|
||||||
|
*
|
||||||
|
* Namco custom waveform sound generator 3 (Pacman hardware)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2003,2004 Alessandro Scotti
|
||||||
|
* http://www.ascotti.org/
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||||
|
* KIND, either express or implied.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
#include "plugin.h"
|
||||||
|
#include "wsg3.h"
|
||||||
|
|
||||||
|
struct wsg3 wsg3;
|
||||||
|
|
||||||
|
static bool wsg3_get_voice(struct wsg3_voice *voice, int index)
|
||||||
|
{
|
||||||
|
int base = 5*index;
|
||||||
|
const unsigned char *regs = wsg3.sound_regs;
|
||||||
|
unsigned x;
|
||||||
|
|
||||||
|
x = regs[0x15 + base] & 0x0F;
|
||||||
|
|
||||||
|
if (x == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
voice->volume = x;
|
||||||
|
|
||||||
|
x = (regs[0x14 + base] & 0x0F);
|
||||||
|
x = (x << 4) | (regs[0x13 + base] & 0x0F);
|
||||||
|
x = (x << 4) | (regs[0x12 + base] & 0x0F);
|
||||||
|
x = (x << 4) | (regs[0x11 + base] & 0x0F);
|
||||||
|
x = (x << 4);
|
||||||
|
|
||||||
|
if (index == 0)
|
||||||
|
{
|
||||||
|
/* The first voice has an extra 4-bit of data */
|
||||||
|
x |= regs[0x10 + base] & 0x0F;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
voice->frequency = x;
|
||||||
|
|
||||||
|
voice->waveform = regs[0x05 + base] & 0x07;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wsg3_play_sound(int * buf, int len)
|
||||||
|
{
|
||||||
|
struct wsg3_voice voice;
|
||||||
|
|
||||||
|
if (wsg3_get_voice(&voice, 0))
|
||||||
|
{
|
||||||
|
unsigned offset = wsg3.wave_offset[0];
|
||||||
|
unsigned step = voice.frequency * wsg3.resample_step;
|
||||||
|
int * wave_data = wsg3.sound_wave_data + 32 * voice.waveform;
|
||||||
|
int volume = voice.volume;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
/* Should be shifted right by 15, but we must also get rid
|
||||||
|
* of the 10 bits used for decimals */
|
||||||
|
buf[i] += wave_data[(offset >> 25) & 0x1F] * volume;
|
||||||
|
offset += step;
|
||||||
|
}
|
||||||
|
|
||||||
|
wsg3.wave_offset[0] = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wsg3_get_voice(&voice, 1))
|
||||||
|
{
|
||||||
|
unsigned offset = wsg3.wave_offset[1];
|
||||||
|
unsigned step = voice.frequency * wsg3.resample_step;
|
||||||
|
int * wave_data = wsg3.sound_wave_data + 32 * voice.waveform;
|
||||||
|
int volume = voice.volume;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
/* Should be shifted right by 15, but we must also get rid
|
||||||
|
* of the 10 bits used for decimals */
|
||||||
|
buf[i] += wave_data[(offset >> 25) & 0x1F] * volume;
|
||||||
|
offset += step;
|
||||||
|
}
|
||||||
|
|
||||||
|
wsg3.wave_offset[1] = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wsg3_get_voice(&voice, 2))
|
||||||
|
{
|
||||||
|
unsigned offset = wsg3.wave_offset[2];
|
||||||
|
unsigned step = voice.frequency * wsg3.resample_step;
|
||||||
|
int * wave_data = wsg3.sound_wave_data + 32 * voice.waveform;
|
||||||
|
int volume = voice.volume;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
/* Should be shifted right by 15, but we must also get rid
|
||||||
|
* of the 10 bits used for decimals */
|
||||||
|
buf[i] += wave_data[(offset >> 25) & 0x1F] * volume;
|
||||||
|
offset += step;
|
||||||
|
}
|
||||||
|
|
||||||
|
wsg3.wave_offset[2] = offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void wsg3_set_sampling_rate(unsigned sampling_rate)
|
||||||
|
{
|
||||||
|
wsg3.sampling_rate = sampling_rate;
|
||||||
|
wsg3.resample_step = (wsg3.master_clock << 10) / sampling_rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wsg3_set_sound_prom( const unsigned char * prom )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 32*8; i++)
|
||||||
|
wsg3.sound_wave_data[i] = (int)*prom++ - 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wsg3_init(unsigned master_clock)
|
||||||
|
{
|
||||||
|
memset(&wsg3, 0, sizeof (struct wsg3));
|
||||||
|
wsg3.master_clock = master_clock;
|
||||||
|
}
|
124
apps/plugins/pacbox/wsg3.h
Normal file
124
apps/plugins/pacbox/wsg3.h
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* __________ __ ___.
|
||||||
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||||
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||||
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||||
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||||
|
* \/ \/ \/ \/ \/
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* Pacbox - a Pacman Emulator for Rockbox
|
||||||
|
*
|
||||||
|
* Based on PIE - Pacman Instructional Emulator
|
||||||
|
*
|
||||||
|
* Namco custom waveform sound generator 3 (Pacman hardware)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2003,2004 Alessandro Scotti
|
||||||
|
* http://www.ascotti.org/
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||||
|
* KIND, either express or implied.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef WSG3_H
|
||||||
|
#define WSG3_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
Namco 3-channel sound generator voice properties.
|
||||||
|
|
||||||
|
This information is only needed by applications that want to do their own
|
||||||
|
sound rendering, as the playSound() function already plays and mixes all
|
||||||
|
three voices.
|
||||||
|
|
||||||
|
@see PacmanMachine::playSound
|
||||||
|
*/
|
||||||
|
struct wsg3_voice
|
||||||
|
{
|
||||||
|
/** Volume (from 0 to 15) */
|
||||||
|
unsigned volume;
|
||||||
|
/** Index into the 4-bit 32-entry waveform table (0 to 7) */
|
||||||
|
unsigned waveform;
|
||||||
|
/** Frequency */
|
||||||
|
unsigned frequency;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct wsg3
|
||||||
|
{
|
||||||
|
unsigned master_clock;
|
||||||
|
unsigned sampling_rate;
|
||||||
|
unsigned char sound_regs[0x20];
|
||||||
|
unsigned char sound_prom[32*8];
|
||||||
|
unsigned resample_step;
|
||||||
|
unsigned wave_offset[3];
|
||||||
|
int sound_wave_data[32*8];
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct wsg3 wsg3;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Constructor.
|
||||||
|
|
||||||
|
@param masterClock clock frequency of sound chip (in Hertz)
|
||||||
|
|
||||||
|
@see #wsg3_play_sound
|
||||||
|
*/
|
||||||
|
void wsg3_init(unsigned master_clock);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sets the 256 byte PROM that contains the waveform table used by the sound chip.
|
||||||
|
*/
|
||||||
|
void wsg3_set_sound_prom( const unsigned char * prom );
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sets the value of the specified register.
|
||||||
|
*/
|
||||||
|
static inline void wsg3_set_register(unsigned reg, unsigned char value)
|
||||||
|
{ wsg3.sound_regs[reg] = value; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the value of the specified register.
|
||||||
|
*/
|
||||||
|
static inline unsigned char wsg3_get_register(unsigned reg)
|
||||||
|
{ return wsg3.sound_regs[reg]; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
Reproduces the sound that is currently being generated by the sound
|
||||||
|
chip into the specified buffer.
|
||||||
|
|
||||||
|
The sound chip has three independent voices that generate 8-bit signed
|
||||||
|
PCM audio. This function resamples the voices at the currently specified
|
||||||
|
sampling rate and mixes them into the output buffer. The output buffer
|
||||||
|
can be converted to 8-bit (signed) PCM by dividing each sample by 3 (since
|
||||||
|
there are three voices) or it can be expanded to 16-bit by multiplying
|
||||||
|
each sample by 85 (i.e. 256 divided by 3). If necessary, it is possible
|
||||||
|
to approximate these values with 4 and 64 in order to use arithmetic
|
||||||
|
shifts that are usually faster to execute.
|
||||||
|
|
||||||
|
Note: this function does not clear the content of the output buffer before
|
||||||
|
mixing voices into it.
|
||||||
|
|
||||||
|
@param buf pointer to sound buffer that receives the audio samples
|
||||||
|
@param len length of the sound buffer
|
||||||
|
*/
|
||||||
|
void wsg3_play_sound(int * buf, int len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the sampling rate currently in use for rendering sound.
|
||||||
|
*/
|
||||||
|
static inline unsigned wsg3_get_sampling_rate(void)
|
||||||
|
{ return wsg3.sampling_rate; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sets the output sampling rate for playSound().
|
||||||
|
|
||||||
|
@param samplingRate sampling rate in Hertz (samples per second)
|
||||||
|
*/
|
||||||
|
void wsg3_set_sampling_rate(unsigned sampling_rate);
|
||||||
|
|
||||||
|
#endif /* WSG3_H */
|
Loading…
Add table
Add a link
Reference in a new issue