|
|
1.1 ! root 1: /*****************************************************************************/ ! 2: /* Generator - Sega Genesis emulation - (c) James Ponder 1997-2000 */ ! 3: /*****************************************************************************/ ! 4: /* */ ! 5: /* gensound-allegro.c */ ! 6: /* */ ! 7: /*****************************************************************************/ ! 8: ! 9: #include <string.h> ! 10: #include <stdio.h> ! 11: #include <sys/types.h> ! 12: #include <sys/stat.h> ! 13: #include <fcntl.h> ! 14: #include <errno.h> ! 15: #include <sys/ioctl.h> ! 16: #include <unistd.h> ! 17: #include <math.h> ! 18: ! 19: #include <allegro.h> ! 20: ! 21: #include "generator.h" ! 22: #include "gensound.h" ! 23: #include "vdp.h" ! 24: #include "ui.h" ! 25: ! 26: #ifdef JFM ! 27: # include "jfm.h" ! 28: #else ! 29: # include "support.h" ! 30: # include "fm.h" ! 31: #endif ! 32: ! 33: /*** variables externed ***/ ! 34: ! 35: int sound_feedback = 0; /* -1, running out of sound ! 36: +0, lots of sound, do something */ ! 37: ! 38: /* SN76489 snd_cpu; */ ! 39: ! 40: /*** forward references ***/ ! 41: ! 42: /* void snd_sndout(int chan, int freq, int vol); */ ! 43: void sound_readyblock(void); ! 44: ! 45: /*** file scoped variables ***/ ! 46: ! 47: #define SOUND_MAXRATE 44100 ! 48: #define SOUND_THRESHOLD 5 ! 49: ! 50: static unsigned int sound_sampsperfield = 0; ! 51: static int sound_dev = 0; ! 52: /* static int sound_dump = 0; */ ! 53: static uint16 soundbuf[2][SOUND_MAXRATE/50]; /* pal is lowest framerate */ ! 54: static unsigned int sound_speed; ! 55: static unsigned int sound_blocks; ! 56: static unsigned int sound_block; ! 57: static SAMPLE *sound_sample; ! 58: static int sound_voice; ! 59: static int sound_inited = 0; /* flag to say whether we've inited */ ! 60: ! 61: #ifdef JFM ! 62: static t_jfm_ctx *sound_ctx; ! 63: #endif ! 64: ! 65: /*** sound_init - initialise this sub-unit ***/ ! 66: ! 67: int sound_init(void) ! 68: { ! 69: unsigned int i; ! 70: uint16 *p; ! 71: static int once = 0; ! 72: ! 73: if (!once) { ! 74: once = 1; ! 75: LOG_NORMAL(("Initialising sound...")); ! 76: sound_blocks = SOUND_THRESHOLD*2; ! 77: sound_speed = SOUND_SAMPLERATE; ! 78: if (detect_digi_driver(DIGI_AUTODETECT) < 1) { ! 79: LOG_CRITICAL(("Allegro failed to detect hardware")); ! 80: return 1; ! 81: } ! 82: if (install_sound(DIGI_AUTODETECT, MIDI_NONE, NULL)) { ! 83: LOG_CRITICAL(("Failed to initialise sound")); ! 84: return 1; ! 85: } ! 86: } ! 87: sound_sampsperfield = SOUND_SAMPLERATE / vdp_framerate; ! 88: /* allocate block capable of holding sound_blocks frames */ ! 89: if ((sound_sample = create_sample(16, 1, sound_speed, sound_sampsperfield * ! 90: sound_blocks)) == NULL) { ! 91: LOG_CRITICAL(("Failed to create sample")); ! 92: return 1; ! 93: } ! 94: p = (uint16 *)sound_sample->data; ! 95: for (i = 0; i < sound_sampsperfield*sound_blocks*2; i--) ! 96: p[i] = 0x8000; ! 97: if ((sound_voice = allocate_voice(sound_sample)) == -1) { ! 98: LOG_CRITICAL(("Failed to allocate voice")); ! 99: return 1; ! 100: } ! 101: voice_set_playmode(sound_voice, PLAYMODE_LOOP); ! 102: voice_set_volume(sound_voice, 256); ! 103: voice_set_pan(sound_voice, 128); ! 104: voice_set_frequency(sound_voice, sound_speed); ! 105: voice_start(sound_voice); ! 106: sound_block = sound_blocks-1; /* next block to write to */ ! 107: #ifdef JFM ! 108: if ((sound_ctx = jfm_init(0, 2612, vdp_clock/7, sound_speed, ! 109: NULL, NULL)) == NULL) ! 110: #else ! 111: if (YM2612Init(1, vdp_clock/7, sound_speed, NULL, NULL)) ! 112: #endif ! 113: return 1; ! 114: LOG_NORMAL(("YM2612 Initialised @ sample rate %d", sound_speed)); ! 115: sound_readyblock(); ! 116: return 0; ! 117: } ! 118: ! 119: /*** sound_final - finalise this sub-unit ***/ ! 120: ! 121: void sound_final(void) ! 122: { ! 123: #ifdef JFM ! 124: jfm_final(sound_ctx); ! 125: #else ! 126: YM2612Shutdown(); ! 127: #endif ! 128: voice_stop(sound_voice); ! 129: deallocate_voice(sound_voice); ! 130: destroy_sample(sound_sample); ! 131: } ! 132: ! 133: /*** sound_reset - reset sound sub-unit ***/ ! 134: ! 135: int sound_reset(void) ! 136: { ! 137: sound_final(); ! 138: return sound_init(); ! 139: } ! 140: ! 141: /*** sound_genreset - reset genesis sound ***/ ! 142: ! 143: void sound_genreset(void) ! 144: { ! 145: #ifdef JFM ! 146: jfm_reset(sound_ctx); ! 147: #else ! 148: YM2612ResetChip(0); ! 149: #endif ! 150: } ! 151: ! 152: /*** sound_process - process sound ***/ ! 153: ! 154: void sound_process(void) ! 155: { ! 156: static uint16 *tbuf[2]; ! 157: int s1 = (sound_sampsperfield*(vdp_line))/vdp_totlines; ! 158: int s2 = (sound_sampsperfield*(vdp_line+1))/vdp_totlines; ! 159: ! 160: tbuf[0] = soundbuf[0] + s1; ! 161: tbuf[1] = soundbuf[1] + s1; ! 162: ! 163: /* printf("YM2612: %d to %d\n", s1, s2); */ ! 164: ! 165: if (s2 > s1) ! 166: #ifdef JFM ! 167: jfm_update(sound_ctx, (void **)tbuf, s2 - s1); ! 168: #else ! 169: YM2612UpdateOne(0, (void **)tbuf, s2 -s1); ! 170: #endif ! 171: } ! 172: ! 173: /*** sound_endfield - end frame and output sound ***/ ! 174: ! 175: void sound_endfield(void) ! 176: { ! 177: static int oldpos = 0; ! 178: int pos = voice_get_position(sound_voice); ! 179: unsigned int blockpos = pos / sound_sampsperfield; ! 180: int writepos = sound_block*sound_sampsperfield; ! 181: uint16 *buffer = sound_sample->data + writepos*2*2; /* 16bit, stereo */ ! 182: unsigned int i; ! 183: ! 184: /* write into new block */ ! 185: for (i = 0; i < sound_sampsperfield; i++) { ! 186: buffer[i*2] = ((sint16)soundbuf[0][i]) + 0x8000; ! 187: buffer[i*2+1] = ((sint16)soundbuf[1][i]) + 0x8000; ! 188: } ! 189: if ((oldpos <= writepos && (pos < oldpos || pos > writepos)) || ! 190: (oldpos > writepos && (pos > writepos && pos < oldpos))) { ! 191: /* under-run occured - reset to new sound block */ ! 192: voice_set_position(sound_voice, writepos); ! 193: sound_feedback = -1; ! 194: } else { ! 195: if (blockpos < sound_block) { ! 196: if ((sound_block - blockpos) < SOUND_THRESHOLD) ! 197: sound_feedback = -1; ! 198: else ! 199: sound_feedback = 0; ! 200: } else { ! 201: if ((sound_block - blockpos + sound_blocks) < SOUND_THRESHOLD) ! 202: sound_feedback = -1; ! 203: else ! 204: sound_feedback = 0; ! 205: } ! 206: } ! 207: sound_block++; ! 208: if (sound_block >= sound_blocks) ! 209: sound_block = 0; ! 210: sound_readyblock(); ! 211: oldpos = pos; ! 212: } ! 213: ! 214: void sound_readyblock(void) ! 215: { ! 216: static int locked = 0; ! 217: int writepos = sound_block*sound_sampsperfield; ! 218: unsigned int a = 0; ! 219: if (locked && digi_driver->unlock_voice) ! 220: digi_driver->unlock_voice(sound_voice); ! 221: ! 222: while((voice_get_position(sound_voice) / ! 223: sound_sampsperfield) == sound_block) { ! 224: usleep(100); ! 225: a++; ! 226: if (a > 100000) { ! 227: LOG_CRITICAL(("Sound error - pos=%d %d=%d", ! 228: voice_get_position(sound_voice), ! 229: sound_sampsperfield, sound_block)); ! 230: exit(0); ! 231: } ! 232: /* cannot write to the next block until it's played! */ ! 233: } ! 234: if (digi_driver->lock_voice) { ! 235: digi_driver->lock_voice(sound_voice, writepos, ! 236: writepos+sound_sampsperfield); ! 237: locked = 1; ! 238: } ! 239: } ! 240: ! 241: #ifdef JFM ! 242: ! 243: /*** sound_ym2612fetch - fetch byte from ym2612 chip ***/ ! 244: ! 245: uint8 sound_ym2612fetch(uint8 addr) ! 246: { ! 247: return jfm_read(sound_ctx, addr); ! 248: } ! 249: ! 250: /*** sound_ym2612store - store a byte to the ym2612 chip ***/ ! 251: ! 252: void sound_ym2612store(uint8 addr, uint8 data) ! 253: { ! 254: jfm_write(sound_ctx, addr, data); ! 255: } ! 256: ! 257: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.