#include <math.h>
#include <stdint.h>
-
// Missing shit (from M.A.M.E.)
#if 1
#endif
-
/*
** some globals ...
*/
static void (* envelope_calc[5])(OscilRec *);
static void (* register_writes[256])(uint8_t, uint8_t, uint8_t);
-//save output as raw 16-bit sample - just in case you would like to listen to it offline ;-)
-//#define SAVE_SAMPLE
-//#define SAVE_SEPARATE_CHANNELS
-
-#ifdef SAVE_SAMPLE
-#ifdef SAVE_SEPARATE_CHANNELS
-FILE * sample1;
-FILE * sample2;
-FILE * sample3;
-FILE * sample4;
-FILE * sample5;
-FILE * sample6;
-#endif
-FILE * samplesum;
-#endif
-
int PMTab[8]; /*8 channels */
/* this table is used for PM setup of LFO */
static signed int LFOdeltas[256]; /*frequency deltas for LFO*/
-
void sin_init(void)
{
int x, i;
decib45[x] = i;
//if (errorlog) fprintf(errorlog,"decib45[%04x]=%08x\n",x,i );
}
-
-#ifdef SAVE_SAMPLE
-#ifdef SAVE_SEPARATE_CHANNELS
-sample1=fopen("samp.raw","wb");
-sample2=fopen("samp2.raw","wb");
-sample3=fopen("samp3.raw","wb");
-sample4=fopen("samp4.raw","wb");
-sample5=fopen("samp5.raw","wb");
-sample6=fopen("samp6.raw","wb");
-#endif
-samplesum=fopen("sampsum.raw","wb");
-#endif
}
-
void hertz(void)
{
int i, j, oct;
}
}
-
void envelope_attack(OscilRec * op)
{
if ((op->attack_volume -= op->delta_AR) < MIN_VOLUME_INDEX) //is volume index min already ?
op->volume = attack_curve[op->attack_volume>>ENV_SH];
}
-
void envelope_decay(OscilRec * op)
{
if ((op->volume += op->delta_D1R) > op->D1L)
}
}
-
void envelope_sustain(OscilRec * op)
{
if ((op->volume += op->delta_D2R) > MAX_VOLUME_INDEX)
}
}
-
void envelope_release(OscilRec * op)
{
if ((op->volume += op->delta_RR) > MAX_VOLUME_INDEX)
}
}
-
void envelope_nothing(OscilRec *op)
{
}
-
inline void envelope_KOFF(OscilRec * op)
{
op->state = 3; /*release*/
}
-
inline void envelope_KON(OscilRec * op)
{
/*this is to remove the gap time if TL>0*/
op->OscilFB = 0; /*Clear feedback after key on */
}
-
void refresh_chip(YM2151 * PSG)
{
uint16_t kc_index_oscil, kc_index_channel, mul;
}
}
-
void write_YM_NON_EMULATED(uint8_t n, uint8_t r, uint8_t v)
{
if (errorlog)
fprintf(errorlog, "Write to non emulated register %02x value %02x\n", r, v);
}
-
void write_YM_KON(uint8_t n, uint8_t r, uint8_t v)
{
uint8_t chan;
envelope_KOFF(&PSG->Oscils[chan + 24]);
}
-
void write_YM_CLOCKA1(uint8_t n, uint8_t r, uint8_t v)
{
YMPSG[n].Regs[r] = v;
}
-
void write_YM_CLOCKA2(uint8_t n, uint8_t r, uint8_t v)
{
YMPSG[n].Regs[r] = v & 0x03;
}
-
void write_YM_CLOCKB(uint8_t n, uint8_t r, uint8_t v)
{
YMPSG[n].Regs[r] = v;
}
-
static void timer_callback_a(int n)
{
YM2151 * PSG = &YMPSG[n];
PSG->TimATimer = 0;
}
-
static void timer_callback_b(int n)
{
YM2151 * PSG = &YMPSG[n];
PSG->TimBTimer = 0;
}
-
void write_YM_CLOCKSET(uint8_t n, uint8_t r, uint8_t v)
{
YM2151 * PSG = &(YMPSG[n]);
}
}
-
void write_YM_CT1_CT2_W(uint8_t n, uint8_t r, uint8_t v)
{
YMPSG[n].Regs[r] = v;
}
-
void write_YM_CONNECT_BASE(uint8_t n, uint8_t r, uint8_t v)
{
// NOTE: L/R Channel enables are ignored! This emu is mono!
PSG->FeedBack[chan] = FEED[(v >> 3) & 7];
}
-
void write_YM_KC_BASE(uint8_t n, uint8_t r, uint8_t v)
{
YMPSG[n].KC[r - YM_KC_BASE] = v;
//freq_calc(chan,PSG);
}
-
void write_YM_KF_BASE(uint8_t n, uint8_t r, uint8_t v)
{
YMPSG[n].KF[r - YM_KF_BASE] = v >> 2;
//freq_calc(chan,PSG);
}
-
void write_YM_PMS_AMS_BASE(uint8_t n, uint8_t r, uint8_t v)
{
// uint8_t chan, i;
}
-
void write_YM_DT1_MUL_BASE(uint8_t n, uint8_t r, uint8_t v)
{
YMPSG[n].Regs[r] = v;
//freq_calc(chan,PSG);
}
-
void write_YM_TL_BASE(uint8_t n, uint8_t r, uint8_t v)
{
v &= 0x7F;
YMPSG[n].Oscils[r - YM_TL_BASE].TL = v << (ENV_BITS - 7); /*7bit TL*/
}
-
void write_YM_KS_AR_BASE(uint8_t n, uint8_t r, uint8_t v)
{
uint8_t op;
PSG->Oscils[op].AR = (v & 0x1F) << 1;
}
-
void write_YM_AMS_D1R_BASE(uint8_t n, uint8_t r, uint8_t v)
{
uint8_t op = r - YM_AMS_D1R_BASE;
YMPSG[n].Oscils[op].D1R = (v & 0x1F) << 1;
}
-
void write_YM_DT2_D2R_BASE(uint8_t n, uint8_t r, uint8_t v)
{
YM2151 * PSG = &(YMPSG[n]);
//freq_calc(chan,PSG);
}
-
void write_YM_D1L_RR_BASE(uint8_t n, uint8_t r, uint8_t v)
{
OscilRec * osc = &YMPSG[n].Oscils[r - YM_D1L_RR_BASE];
osc->RR = ((v & 0x0F) << 2) | 0x02;
}
-
/*
** Initialize YM2151 emulator(s).
**
** 'rate' is sampling rate and 'bufsiz' is the size of the
** buffer that should be updated at each interval
*/
-int YMInit(int num, int clock, int rate, int sample_bits, int bufsiz)//, SAMPLE ** buffer)
+//int YMInit(int num, int clock, int rate, int sample_bits, int bufsiz)//, SAMPLE ** buffer)
+int YMInit(int clock, int rate)
{
int i;
if (YMPSG)
return (-1); /* duplicate init. */
- YMNumChips = num;
+// YMNumChips = num;
+ YMNumChips = 1;
YM2151_SAMPFREQ = rate;
#if 0
#endif
YM2151_CLOCK = clock;
- YMBufSize = bufsiz;
+// YMBufSize = bufsiz;
envelope_calc[0] = envelope_attack;
envelope_calc[1] = envelope_decay;
return 0;
}
-
void YMShutdown()
{
if (!YMPSG)
}
YM2151_SAMPFREQ = YMBufSize = 0;
-
-#ifdef SAVE_SAMPLE
-#ifdef SAVE_SEPARATE_CHANNELS
-fclose(sample1);
-fclose(sample2);
-fclose(sample3);
-fclose(sample4);
-fclose(sample5);
-fclose(sample6);
-#endif
-fclose(samplesum);
-#endif
}
-
/* write a register on YM2151 chip number 'n' */
void YMWriteReg(int n, int r, int v)
{
register_writes[(uint8_t)r]((uint8_t)n, (uint8_t)r, (uint8_t)v);
}
-
uint8_t YMReadReg(uint8_t n)
{
return YMPSG[n].TimIRQ;
}
-
/*
** reset all chip registers.
*/
PSG->TimIRQ = 0;
}
-
static inline signed int op_calc(OscilRec * OP, signed int pm)
{
return sin_tab[(((OP->phase += OP->freq) >> FREQ_SH) + (pm)) & SIN_MASK]
[OP->TL + (OP->volume >> ENV_SH)];
}
-
//void YM2151UpdateOne(int num, int endp)
void YM2151UpdateOne(void * BUF, int endp)
{
OscilRec * OP0, * OP1, * OP2, * OP3;
uint16_t i;
signed int k, wy;
-#ifdef SAVE_SEPARATE_CHANNELS
- signed int pom;
-#endif
refresh_chip(PSG);
case 6: *(PSGBUF) = op_calc(OP2, wy) + op_calc(OP1, 0) + op_calc(OP3, 0); break;
default: *(PSGBUF) = wy + op_calc(OP2, 0) + op_calc(OP1, 0) + op_calc(OP3, 0); break;
}
-#ifdef SAVE_SEPARATE_CHANNELS
-fputc((uint16_t)(*PSGBUF) & 0xFF, sample1);
-fputc(((uint16_t)(*PSGBUF) >> 8) & 0xFF, sample1);
-#endif
}
//chan1
else
OP0->OscilFB = 0;
-#ifdef SAVE_SEPARATE_CHANNELS
-pom = *(PSGBUF);
-#endif
switch(PSG->ConnectTab[1])
{
case 0: *(PSGBUF) += op_calc(OP3, op_calc(OP1, op_calc(OP2,wy) ) ); break;
case 6: *(PSGBUF) += op_calc(OP2,wy) + op_calc(OP1,0) + op_calc(OP3,0); break;
default: *(PSGBUF) += wy + op_calc(OP2, 0) + op_calc(OP1, 0) + op_calc(OP3, 0); break;
}
-
-#ifdef SAVE_SEPARATE_CHANNELS
-fputc((uint16_t)((*PSGBUF)-pom)&0xff,sample2);
-fputc(((uint16_t)((*PSGBUF)-pom)>>8)&0xff,sample2);
-#endif
}
//chan2
else
OP0->OscilFB = 0;
-#ifdef SAVE_SEPARATE_CHANNELS
- pom=*(PSGBUF);
-#endif
switch(PSG->ConnectTab[2])
{
case 0: *(PSGBUF) += op_calc(OP3, op_calc(OP1, op_calc(OP2,wy) ) ); break;
case 6: *(PSGBUF) += op_calc(OP2,wy) + op_calc(OP1,0) + op_calc(OP3,0); break;
default:*(PSGBUF) += wy + op_calc(OP2,0) + op_calc(OP1,0) + op_calc(OP3,0);break;
}
-#ifdef SAVE_SEPARATE_CHANNELS
-fputc((uint16_t)((*PSGBUF)-pom)&0xff,sample3);
-fputc(((uint16_t)((*PSGBUF)-pom)>>8)&0xff,sample3);
-#endif
}
//chan3
else
OP0->OscilFB = 0;
-#ifdef SAVE_SEPARATE_CHANNELS
- pom=*(PSGBUF);
-#endif
switch(PSG->ConnectTab[3])
{
case 0: *(PSGBUF) += op_calc(OP3, op_calc(OP1, op_calc(OP2,wy) ) ); break;
case 6: *(PSGBUF) += op_calc(OP2,wy) + op_calc(OP1,0) + op_calc(OP3,0); break;
default:*(PSGBUF) += wy + op_calc(OP2,0) + op_calc(OP1,0) + op_calc(OP3,0);break;
}
-#ifdef SAVE_SEPARATE_CHANNELS
-fputc((uint16_t)((*PSGBUF)-pom)&0xff,sample4);
-fputc(((uint16_t)((*PSGBUF)-pom)>>8)&0xff,sample4);
-#endif
}
//chan4
else
OP0->OscilFB = 0;
- #ifdef SAVE_SEPARATE_CHANNELS
- pom = *(PSGBUF);
- #endif
-
switch(PSG->ConnectTab[4])
{
case 0: *(PSGBUF) += op_calc(OP3, op_calc(OP1, op_calc(OP2,wy) ) ); break;
case 6: *(PSGBUF) += op_calc(OP2,wy) + op_calc(OP1,0) + op_calc(OP3,0); break;
default:*(PSGBUF) += wy + op_calc(OP2,0) + op_calc(OP1,0) + op_calc(OP3,0);break;
}
-
-#ifdef SAVE_SEPARATE_CHANNELS
-fputc((uint16_t)((*PSGBUF)-pom)&0xff,sample5);
-fputc(((uint16_t)((*PSGBUF)-pom)>>8)&0xff,sample5);
-#endif
}
//chan5
else
OP0->OscilFB = 0;
-#ifdef SAVE_SEPARATE_CHANNELS
- pom=*(PSGBUF);
-#endif
switch(PSG->ConnectTab[5])
{
case 0: *(PSGBUF) += op_calc(OP3, op_calc(OP1, op_calc(OP2,wy) ) ); break;
case 6: *(PSGBUF) += op_calc(OP2,wy) + op_calc(OP1,0) + op_calc(OP3,0); break;
default:*(PSGBUF) += wy + op_calc(OP2,0) + op_calc(OP1,0) + op_calc(OP3,0);break;
}
-#ifdef SAVE_SEPARATE_CHANNELS
-fputc((uint16_t)((*PSGBUF)-pom)&0xff,sample6);
-fputc(((uint16_t)((*PSGBUF)-pom)>>8)&0xff,sample6);
-#endif
}
//chan6
{
k = *(PSGBUF++);
-#ifdef SAVE_SAMPLE
-fputc((uint16_t)(-k) & 0xFF, samplesum);
-fputc(((uint16_t)(-k) >> 8) & 0xFF, samplesum);
-#endif
-
#if 1
// if (sample_16bit)
{
/*16 bit mode*/
k >>= FINAL_SH16; //AUDIO_CONV
- k <<= 2;
+// We don't shift by 2, as it's too loud (eventually, we need to do proper volume control here)
+// k <<= 2;
+ k <<= 1;
if (k > 32767)
k = 32767;
PSG->bufp = endp;
}
-
/*
** called to update all chips
*/
}
}
-
/*
** return the buffer into which YM2151Update() has just written it's sample
** data
return YMPSG[n].Buf;
}
-
void YMSetIrqHandler(int n, void(* handler)(void))
{
YMPSG[n].handler = handler;
}
-