|
|
1.1.1.2 ! root 1: /* Generator is (c) James Ponder, 1997-2001 http://www.squish.net/generator/ */ 1.1 root 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" 1.1.1.2 ! root 19: #include "ui-console.h" 1.1 root 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: 1.1.1.2 ! root 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 */ 1.1 root 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 */ 1.1.1.2 ! root 49: static int sound_active = 0; 1.1 root 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; 1.1.1.2 ! root 55: static unsigned int sound_threshold; /* bytes in buffer we're trying for */ 1.1 root 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: 1.1.1.2 ! root 69: /* see sound_init in gensound.c for comments */ ! 70: 1.1 root 71: if (!once) { 72: once = 1; 1.1.1.2 ! root 73: LOG_VERBOSE(("Initialising sound...")); 1.1 root 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: } 1.1.1.2 ! root 84: if (sound_active) ! 85: sound_final(); ! 86: sound_threshold = sound_minfields; ! 87: sound_blocks = sound_threshold*2; 1.1 root 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 * 1.1.1.2 ! root 91: sound_blocks)) == NULL) { 1.1 root 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")); 1.1.1.2 ! root 100: destroy_sample(sound_sample); 1.1 root 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, 1.1.1.2 ! root 111: NULL, NULL)) == NULL) { 1.1 root 112: #else 1.1.1.2 ! root 113: if (YM2612Init(1, vdp_clock/7, sound_speed, NULL, NULL)) { 1.1 root 114: #endif 1.1.1.2 ! root 115: voice_stop(sound_voice); ! 116: deallocate_voice(sound_voice); ! 117: destroy_sample(sound_sample); 1.1 root 118: return 1; 1.1.1.2 ! root 119: } ! 120: LOG_VERBOSE(("YM2612 Initialised @ sample rate %d", sound_speed)); ! 121: sound_active = 1; 1.1 root 122: sound_readyblock(); 123: return 0; 124: } 125: 126: /*** sound_final - finalise this sub-unit ***/ 127: 128: void sound_final(void) 129: { 1.1.1.2 ! root 130: if (!sound_active) ! 131: return; ! 132: LOG_VERBOSE(("Finalising sound...")); 1.1 root 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); 1.1.1.2 ! root 141: sound_active = 0; ! 142: LOG_VERBOSE(("Finalised sound.")); 1.1 root 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) { 1.1.1.2 ! root 208: if ((sound_block - blockpos) < sound_threshold) ! 209: sound_feedback = -1; 1.1 root 210: else 1.1.1.2 ! root 211: sound_feedback = 0; 1.1 root 212: } else { 1.1.1.2 ! root 213: if ((sound_block - blockpos + sound_blocks) < sound_threshold) ! 214: sound_feedback = -1; 1.1 root 215: else 1.1.1.2 ! root 216: sound_feedback = 0; 1.1 root 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) / 1.1.1.2 ! root 235: sound_sampsperfield) == sound_block) { 1.1 root 236: usleep(100); 237: a++; 238: if (a > 100000) { 239: LOG_CRITICAL(("Sound error - pos=%d %d=%d", 1.1.1.2 ! root 240: voice_get_position(sound_voice), ! 241: sound_sampsperfield, sound_block)); 1.1 root 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, 1.1.1.2 ! root 248: writepos+sound_sampsperfield); 1.1 root 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.