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