|
|
1.1 root 1: /* Generator is (c) James Ponder, 1997-2001 http://www.squish.net/generator/ */
2:
1.1.1.2 ! root 3: #include <stdlib.h>
1.1 root 4:
5: #include "generator.h"
6: #include "gensound.h"
1.1.1.2 ! root 7: #include "gensoundp.h"
1.1 root 8: #include "vdp.h"
9: #include "ui.h"
1.1.1.2 ! root 10: #include "sn76496.h"
1.1 root 11:
12: #ifdef JFM
13: # include "jfm.h"
14: #else
15: # include "support.h"
16: # include "fm.h"
17: #endif
18:
19: /*** variables externed ***/
20:
1.1.1.2 ! root 21: int sound_debug = 0; /* debug mode */
! 22: int sound_feedback = 0; /* -1, running out of sound
! 23: +0, lots of sound, do something */
! 24: unsigned int sound_minfields = 5; /* min fields to try to buffer */
! 25: unsigned int sound_maxfields = 10; /* max fields before blocking */
! 26: unsigned int sound_speed; /* sample rate */
! 27: unsigned int sound_sampsperfield; /* samples per field */
! 28: unsigned int sound_threshold; /* samples in buffer aiming for */
1.1 root 29: uint8 sound_regs1[256];
30: uint8 sound_regs2[256];
31: uint8 sound_address1 = 0;
32: uint8 sound_address2 = 0;
33: uint8 sound_keys[8];
34:
1.1.1.2 ! root 35: /* pal is lowest framerate */
! 36: uint16 sound_soundbuf[2][SOUND_MAXRATE / 50];
1.1 root 37:
38: /*** forward references ***/
39:
40: /*** file scoped variables ***/
41:
42: static int sound_active = 0;
43:
44: #ifdef JFM
1.1.1.2 ! root 45: static t_jfm_ctx *sound_ctx;
1.1 root 46: #endif
47:
48: /*** sound_init - initialise this sub-unit ***/
49:
50: int sound_init(void)
51: {
52: int ret;
53:
1.1.1.2 ! root 54: /* The sound_minfields parameter specifies how many fields worth of sound we
! 55: should try and keep around (a display field is 1/50th or 1/60th of a
! 56: second) - generator works by trying to keep sound_minfields number of
! 57: fields worth of sound around, and drops plotting frames to keep up on slow
! 58: machines */
! 59:
! 60: sound_speed = SOUND_SAMPLERATE;
! 61: sound_sampsperfield = sound_speed / vdp_framerate;
! 62: sound_threshold = sound_sampsperfield * sound_minfields;
! 63:
1.1 root 64: ret = sound_start();
65: if (ret)
66: return ret;
67: #ifdef JFM
1.1.1.2 ! root 68: if ((sound_ctx = jfm_init(0, 2612, vdp_clock / 7, sound_speed,
! 69: NULL, NULL)) == NULL) {
! 70: #else
! 71: if (YM2612Init(1, vdp_clock / 7, sound_speed, NULL, NULL)) {
! 72: #endif
! 73: LOG_VERBOSE(("YM2612 failed init"));
! 74: sound_stop();
! 75: return 1;
! 76: }
! 77: if (SN76496Init(0, vdp_clock / 15, 0, sound_speed)) {
! 78: LOG_VERBOSE(("SN76496 failed init"));
! 79: sound_stop();
! 80: #ifdef JFM
! 81: jfm_final(sound_ctx);
1.1 root 82: #else
1.1.1.2 ! root 83: YM2612Shutdown();
1.1 root 84: #endif
85: return 1;
86: }
87: LOG_VERBOSE(("YM2612 Initialised @ sample rate %d", sound_speed));
88: return 0;
89: }
90:
91: /*** sound_final - finalise this sub-unit ***/
92:
93: void sound_final(void)
94: {
95: sound_stop();
96: #ifdef JFM
97: jfm_final(sound_ctx);
98: #else
99: YM2612Shutdown();
100: #endif
101: }
102:
1.1.1.2 ! root 103: /*** sound_start - start sound ***/
1.1 root 104:
105: int sound_start(void)
106: {
107: if (sound_active)
108: sound_stop();
1.1.1.2 ! root 109: LOG_VERBOSE(("Starting sound..."));
! 110: if (soundp_start() == -1) {
! 111: LOG_VERBOSE(("Failed to start sound hardware"));
! 112: return -1;
1.1 root 113: }
114: sound_active = 1;
1.1.1.2 ! root 115: LOG_VERBOSE(("Started sound."));
1.1 root 116: return 0;
117: }
1.1.1.2 ! root 118:
1.1 root 119: /*** sound_stop - stop sound ***/
120:
121: void sound_stop(void)
122: {
123: if (!sound_active)
124: return;
125: LOG_VERBOSE(("Stopping sound..."));
1.1.1.2 ! root 126: soundp_stop();
1.1 root 127: sound_active = 0;
128: LOG_VERBOSE(("Stopped sound."));
129: }
1.1.1.2 ! root 130:
1.1 root 131: /*** sound_reset - reset sound sub-unit ***/
132:
133: int sound_reset(void)
134: {
135: sound_final();
136: return sound_init();
137: }
138:
139: /*** sound_endfield - end frame and output sound ***/
140:
141: void sound_endfield(void)
142: {
143: unsigned int i;
1.1.1.2 ! root 144: int pending;
! 145:
! 146: /* work out feedback from sound system */
! 147:
! 148: if ((pending = soundp_samplesbuffered()) == -1)
! 149: ui_err("Failed to read pending bytes in output sound buffer");
! 150: if ((unsigned int)pending < sound_threshold)
1.1 root 151: sound_feedback = -1;
152: else
153: sound_feedback = 0;
1.1.1.2 ! root 154:
1.1 root 155: if (sound_debug) {
1.1.1.2 ! root 156: LOG_VERBOSE(("End of field - sound system says %d bytes buffered",
! 157: pending));
! 158: LOG_VERBOSE(("Threshold %d, therefore feedback = %d ", sound_threshold,
! 159: sound_feedback));
1.1 root 160: }
1.1.1.2 ! root 161: soundp_output(sound_soundbuf[0], sound_soundbuf[1], sound_sampsperfield);
1.1 root 162: }
163:
164: /*** sound_ym2612fetch - fetch byte from ym2612 chip ***/
165:
166: uint8 sound_ym2612fetch(uint8 addr)
167: {
168: #ifdef JFM
169: return jfm_read(sound_ctx, addr);
170: #else
171: return YM2612Read(0, addr);
172: #endif
173: }
174:
175: /*** sound_ym2612store - store a byte to the ym2612 chip ***/
176:
177: void sound_ym2612store(uint8 addr, uint8 data)
178: {
179: switch (addr) {
180: case 0:
181: sound_address1 = data;
182: break;
183: case 1:
184: if (sound_address1 == 0x28 && (data & 3) != 3)
185: sound_keys[data & 7] = data >> 4;
186: if (sound_address1 == 0x2a) {
187: sound_keys[7] = 0;
188: }
189: if (sound_address1 == 0x2b)
190: sound_keys[7] = data & 0x80 ? 0xf : 0;
191: sound_regs1[sound_address1] = data;
192: break;
193: case 2:
194: sound_address2 = data;
195: break;
196: case 3:
197: sound_regs2[sound_address2] = data;
198: break;
199: }
200: #ifdef JFM
201: jfm_write(sound_ctx, addr, data);
202: #else
203: YM2612Write(0, addr, data);
204: #endif
205: }
206:
1.1.1.2 ! root 207: /*** sound_sn76496store - store a byte to the sn76496 chip ***/
! 208:
! 209: void sound_sn76496store(uint8 data)
! 210: {
! 211: SN76496Write(0, data);
! 212: }
! 213:
! 214: /*** sound_genreset - reset genesis sound ***/
! 215:
! 216: void sound_genreset(void)
! 217: {
! 218: #ifdef JFM
! 219: jfm_reset(sound_ctx);
! 220: #else
! 221: YM2612ResetChip(0);
! 222: #endif
! 223: }
! 224:
! 225: /*** sound_process - process sound ***/
! 226:
! 227: void sound_process(void)
! 228: {
! 229: static sint16 *tbuf[2];
! 230: int s1 = (sound_sampsperfield * (vdp_line)) / vdp_totlines;
! 231: int s2 = (sound_sampsperfield * (vdp_line + 1)) / vdp_totlines;
! 232: /* pal is lowest framerate */
! 233: uint16 sn76496buf[SOUND_MAXRATE / 50]; /* far too much but who cares */
! 234: unsigned int samples = s2 - s1;
! 235: unsigned int i;
! 236:
! 237: tbuf[0] = sound_soundbuf[0] + s1;
! 238: tbuf[1] = sound_soundbuf[1] + s1;
! 239:
! 240: if (s2 > s1) {
! 241: #ifdef JFM
! 242: jfm_update(sound_ctx, (void **)tbuf, samples1);
! 243: #else
! 244: YM2612UpdateOne(0, (void **)tbuf, samples);
! 245: #endif
! 246: SN76496Update(0, sn76496buf, samples);
! 247:
! 248: /* SN76496 outputs sound in range -0x4000 to 0x3fff
! 249: YM2612 ouputs sound in range -0x8000 to 0x7fff - therefore
! 250: we take 3/4 of the YM2612 and add half the SN76496 */
! 251: for (i = 0; i < samples; i++) {
! 252: sint16 snsample = sn76496buf[i] - 0x4000;
! 253: sint32 l = (tbuf[0][i] * 3) >> 2; /* left channel */
! 254: sint32 r = (tbuf[1][i] * 3) >> 2; /* right channel */
! 255: l += snsample >> 1;
! 256: r += snsample >> 1;
! 257: /* write with clipping
! 258: tbuf[0][i] = l > 0x7FFF ? 0x7fff : ((l < -0x7fff) ? -0x7fff : l);
! 259: tbuf[1][i] = r > 0x7FFF ? 0x7fff : ((r < -0x7fff) ? -0x7fff : r); */
! 260: tbuf[0][i] = l;
! 261: tbuf[1][i] = r;
! 262: }
! 263: }
! 264: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.