637 lines
15 KiB
C
637 lines
15 KiB
C
/* Mednafen - Multi-system Emulator
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
//#include "vb.h"
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include "mamedef.h"
|
|
#include "vsu.h"
|
|
|
|
typedef struct
|
|
{
|
|
UINT8 IntlControl[6];
|
|
UINT8 LeftLevel[6];
|
|
UINT8 RightLevel[6];
|
|
UINT16 Frequency[6];
|
|
UINT16 EnvControl[6]; // Channel 5/6 extra functionality tacked on too.
|
|
|
|
UINT8 RAMAddress[6];
|
|
|
|
UINT8 SweepControl;
|
|
|
|
UINT8 WaveData[5][0x20];
|
|
|
|
UINT8 ModData[0x20];
|
|
|
|
//
|
|
//
|
|
//
|
|
INT32 EffFreq[6];
|
|
INT32 Envelope[6];
|
|
|
|
INT32 WavePos[6];
|
|
INT32 ModWavePos;
|
|
|
|
INT32 LatcherClockDivider[6];
|
|
|
|
INT32 FreqCounter[6];
|
|
INT32 IntervalCounter[6];
|
|
INT32 EnvelopeCounter[6];
|
|
INT32 SweepModCounter;
|
|
|
|
INT32 EffectsClockDivider[6];
|
|
INT32 IntervalClockDivider[6];
|
|
INT32 EnvelopeClockDivider[6];
|
|
INT32 SweepModClockDivider;
|
|
|
|
INT32 NoiseLatcherClockDivider;
|
|
UINT32 NoiseLatcher;
|
|
|
|
UINT32 lfsr;
|
|
|
|
//INT32 last_output[6][2];
|
|
INT32 last_ts;
|
|
|
|
//Blip_Buffer *sbuf[2];
|
|
//Blip_Synth<blip_good_quality, 1024> Synth;
|
|
int clock;
|
|
int smplrate;
|
|
UINT8 Muted[6];
|
|
// values for Timing Calculation
|
|
int tm_smpl;
|
|
int tm_clk;
|
|
} vsu_state;
|
|
|
|
static void VSU_Power(vsu_state* chip);
|
|
//void VSU_Write(UINT8 ChipID, UINT32 A, UINT8 V);
|
|
|
|
INLINE void VSU_CalcCurrentOutput(vsu_state* chip, int ch, int* left, int* right);
|
|
static void VSU_Update(vsu_state* chip, INT32 timestamp, int* outleft, int* outright);
|
|
|
|
|
|
static const int Tap_LUT[8] = { 15 - 1, 11 - 1, 14 - 1, 5 - 1, 9 - 1, 7 - 1, 10 - 1, 12 - 1 };
|
|
|
|
static void VSU_Power(vsu_state* chip)
|
|
{
|
|
int ch;
|
|
|
|
chip->SweepControl = 0;
|
|
chip->SweepModCounter = 0;
|
|
chip->SweepModClockDivider = 1;
|
|
|
|
for(ch = 0; ch < 6; ch++)
|
|
{
|
|
chip->IntlControl[ch] = 0;
|
|
chip->LeftLevel[ch] = 0;
|
|
chip->RightLevel[ch] = 0;
|
|
chip->Frequency[ch] = 0;
|
|
chip->EnvControl[ch] = 0;
|
|
chip->RAMAddress[ch] = 0;
|
|
|
|
chip->EffFreq[ch] = 0;
|
|
chip->Envelope[ch] = 0;
|
|
chip->WavePos[ch] = 0;
|
|
chip->FreqCounter[ch] = 0;
|
|
chip->IntervalCounter[ch] = 0;
|
|
chip->EnvelopeCounter[ch] = 0;
|
|
|
|
chip->EffectsClockDivider[ch] = 4800;
|
|
chip->IntervalClockDivider[ch] = 4;
|
|
chip->EnvelopeClockDivider[ch] = 4;
|
|
|
|
chip->LatcherClockDivider[ch] = 120;
|
|
}
|
|
|
|
|
|
chip->NoiseLatcherClockDivider = 120;
|
|
chip->NoiseLatcher = 0;
|
|
|
|
memset(chip->WaveData, 0, sizeof(chip->WaveData));
|
|
memset(chip->ModData, 0, sizeof(chip->ModData));
|
|
|
|
chip->last_ts = 0;
|
|
}
|
|
|
|
void VSU_Write(void *_info, UINT32 A, UINT8 V)
|
|
{
|
|
vsu_state* chip = (vsu_state *)_info;
|
|
|
|
A <<= 2;
|
|
A &= 0x7FF;
|
|
|
|
//Update(timestamp);
|
|
|
|
//printf("VSU Write: %d, %08x %02x\n", timestamp, A, V);
|
|
|
|
if(A < 0x280)
|
|
chip->WaveData[A >> 7][(A >> 2) & 0x1F] = V & 0x3F;
|
|
else if(A < 0x400)
|
|
{
|
|
//if(A >= 0x300)
|
|
// printf("Modulation mirror write? %08x %02x\n", A, V);
|
|
chip->ModData[(A >> 2) & 0x1F] = V;
|
|
}
|
|
else if(A < 0x600)
|
|
{
|
|
int ch = (A >> 6) & 0xF;
|
|
|
|
//if(ch < 6)
|
|
//printf("Ch: %d, Reg: %d, Value: %02x\n", ch, (A >> 2) & 0xF, V);
|
|
|
|
if(ch > 5)
|
|
{
|
|
if(A == 0x580 && (V & 1))
|
|
{
|
|
int i;
|
|
//puts("STOP, HAMMER TIME");
|
|
for(i = 0; i < 6; i++)
|
|
chip->IntlControl[i] &= ~0x80;
|
|
}
|
|
}
|
|
else
|
|
switch((A >> 2) & 0xF)
|
|
{
|
|
case 0x0:
|
|
chip->IntlControl[ch] = V & ~0x40;
|
|
|
|
if(V & 0x80)
|
|
{
|
|
chip->EffFreq[ch] = chip->Frequency[ch];
|
|
if(ch == 5)
|
|
chip->FreqCounter[ch] = 10 * (2048 - chip->EffFreq[ch]);
|
|
else
|
|
chip->FreqCounter[ch] = 2048 - chip->EffFreq[ch];
|
|
chip->IntervalCounter[ch] = (V & 0x1F) + 1;
|
|
chip->EnvelopeCounter[ch] = (chip->EnvControl[ch] & 0x7) + 1;
|
|
|
|
if(ch == 4)
|
|
{
|
|
chip->SweepModCounter = (chip->SweepControl >> 4) & 7;
|
|
chip->SweepModClockDivider = (chip->SweepControl & 0x80) ? 8 : 1;
|
|
chip->ModWavePos = 0;
|
|
}
|
|
|
|
chip->WavePos[ch] = 0;
|
|
|
|
if(ch == 5)
|
|
chip->lfsr = 1;
|
|
|
|
//if(!(chip->IntlControl[ch] & 0x80))
|
|
// chip->Envelope[ch] = (chip->EnvControl[ch] >> 4) & 0xF;
|
|
|
|
chip->EffectsClockDivider[ch] = 4800;
|
|
chip->IntervalClockDivider[ch] = 4;
|
|
chip->EnvelopeClockDivider[ch] = 4;
|
|
}
|
|
break;
|
|
|
|
case 0x1:
|
|
chip->LeftLevel[ch] = (V >> 4) & 0xF;
|
|
chip->RightLevel[ch] = (V >> 0) & 0xF;
|
|
break;
|
|
|
|
case 0x2:
|
|
chip->Frequency[ch] &= 0xFF00;
|
|
chip->Frequency[ch] |= V << 0;
|
|
chip->EffFreq[ch] &= 0xFF00;
|
|
chip->EffFreq[ch] |= V << 0;
|
|
break;
|
|
|
|
case 0x3:
|
|
chip->Frequency[ch] &= 0x00FF;
|
|
chip->Frequency[ch] |= (V & 0x7) << 8;
|
|
chip->EffFreq[ch] &= 0x00FF;
|
|
chip->EffFreq[ch] |= (V & 0x7) << 8;
|
|
break;
|
|
|
|
case 0x4:
|
|
chip->EnvControl[ch] &= 0xFF00;
|
|
chip->EnvControl[ch] |= V << 0;
|
|
|
|
chip->Envelope[ch] = (V >> 4) & 0xF;
|
|
break;
|
|
|
|
case 0x5:
|
|
chip->EnvControl[ch] &= 0x00FF;
|
|
if(ch == 4)
|
|
chip->EnvControl[ch] |= (V & 0x73) << 8;
|
|
else if(ch == 5)
|
|
chip->EnvControl[ch] |= (V & 0x73) << 8;
|
|
else
|
|
chip->EnvControl[ch] |= (V & 0x03) << 8;
|
|
break;
|
|
|
|
case 0x6:
|
|
chip->RAMAddress[ch] = V & 0xF;
|
|
break;
|
|
|
|
case 0x7:
|
|
if(ch == 4)
|
|
{
|
|
chip->SweepControl = V;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
INLINE void VSU_CalcCurrentOutput(vsu_state* chip, int ch, int* left, int* right)
|
|
{
|
|
int WD;
|
|
int l_ol, r_ol;
|
|
|
|
if(!(chip->IntlControl[ch] & 0x80) || chip->Muted[ch])
|
|
{
|
|
*left = *right = 0;
|
|
return;
|
|
}
|
|
|
|
if(ch == 5)
|
|
WD = chip->NoiseLatcher; //(NoiseLatcher << 6) - NoiseLatcher;
|
|
else
|
|
{
|
|
if(chip->RAMAddress[ch] > 4)
|
|
WD = 0x20; //0;
|
|
else
|
|
WD = chip->WaveData[chip->RAMAddress[ch]][chip->WavePos[ch]]; // - 0x20;
|
|
}
|
|
l_ol = chip->Envelope[ch] * chip->LeftLevel[ch];
|
|
if(l_ol)
|
|
{
|
|
l_ol >>= 3;
|
|
l_ol += 1;
|
|
}
|
|
|
|
r_ol = chip->Envelope[ch] * chip->RightLevel[ch];
|
|
if(r_ol)
|
|
{
|
|
r_ol >>= 3;
|
|
r_ol += 1;
|
|
}
|
|
|
|
WD -= 0x20;
|
|
(*left) += WD * l_ol;
|
|
(*right) += WD * r_ol;
|
|
return;
|
|
}
|
|
|
|
static void VSU_Update(vsu_state* chip, INT32 timestamp, int* outleft, int* outright)
|
|
{
|
|
//int left, right;
|
|
int ch;
|
|
|
|
*outleft = 0;
|
|
*outright = 0;
|
|
|
|
//puts("VSU Start");
|
|
for(ch = 0; ch < 6; ch++)
|
|
{
|
|
INT32 clocks = timestamp - chip->last_ts;
|
|
//INT32 running_timestamp = chip->last_ts;
|
|
|
|
if(!(chip->IntlControl[ch] & 0x80) || chip->Muted[ch])
|
|
continue; // channel disabled - don't add anything to output
|
|
|
|
//// Output sound here
|
|
//VSU_CalcCurrentOutput(chip, ch, &left, &right);
|
|
//Synth.offset_inline(running_timestamp, left - chip->last_output[ch][0], sbuf[0]);
|
|
//Synth.offset_inline(running_timestamp, right - chip->last_output[ch][1], sbuf[1]);
|
|
//chip->last_output[ch][0] = left;
|
|
//chip->last_output[ch][1] = right;
|
|
|
|
//if(!(chip->IntlControl[ch] & 0x80))
|
|
// continue;
|
|
|
|
while(clocks > 0)
|
|
{
|
|
INT32 chunk_clocks = clocks;
|
|
|
|
if(chunk_clocks > chip->EffectsClockDivider[ch])
|
|
chunk_clocks = chip->EffectsClockDivider[ch];
|
|
|
|
if(ch == 5)
|
|
{
|
|
if(chunk_clocks > chip->NoiseLatcherClockDivider)
|
|
chunk_clocks = chip->NoiseLatcherClockDivider;
|
|
}
|
|
else
|
|
{
|
|
if(chip->EffFreq[ch] >= 2040)
|
|
{
|
|
if(chunk_clocks > chip->LatcherClockDivider[ch])
|
|
chunk_clocks = chip->LatcherClockDivider[ch];
|
|
}
|
|
else
|
|
{
|
|
if(chunk_clocks > chip->FreqCounter[ch])
|
|
chunk_clocks = chip->FreqCounter[ch];
|
|
}
|
|
}
|
|
|
|
if(ch == 5 && chunk_clocks > chip->NoiseLatcherClockDivider)
|
|
chunk_clocks = chip->NoiseLatcherClockDivider;
|
|
|
|
chip->FreqCounter[ch] -= chunk_clocks;
|
|
while(chip->FreqCounter[ch] <= 0)
|
|
{
|
|
if(ch == 5)
|
|
{
|
|
int feedback = ((chip->lfsr >> 7) & 1) ^ ((chip->lfsr >> Tap_LUT[(chip->EnvControl[5] >> 12) & 0x7]) & 1);
|
|
chip->lfsr = ((chip->lfsr << 1) & 0x7FFF) | feedback;
|
|
|
|
chip->FreqCounter[ch] += 10 * (2048 - chip->EffFreq[ch]);
|
|
}
|
|
else
|
|
{
|
|
chip->FreqCounter[ch] += 2048 - chip->EffFreq[ch];
|
|
chip->WavePos[ch] = (chip->WavePos[ch] + 1) & 0x1F;
|
|
}
|
|
}
|
|
|
|
chip->LatcherClockDivider[ch] -= chunk_clocks;
|
|
while(chip->LatcherClockDivider[ch] <= 0)
|
|
chip->LatcherClockDivider[ch] += 120;
|
|
|
|
if(ch == 5)
|
|
{
|
|
chip->NoiseLatcherClockDivider -= chunk_clocks;
|
|
if(!chip->NoiseLatcherClockDivider)
|
|
{
|
|
chip->NoiseLatcherClockDivider = 120;
|
|
chip->NoiseLatcher = ((chip->lfsr & 1) << 6) - (chip->lfsr & 1);
|
|
}
|
|
}
|
|
|
|
chip->EffectsClockDivider[ch] -= chunk_clocks;
|
|
while(chip->EffectsClockDivider[ch] <= 0)
|
|
{
|
|
chip->EffectsClockDivider[ch] += 4800;
|
|
|
|
chip->IntervalClockDivider[ch]--;
|
|
while(chip->IntervalClockDivider[ch] <= 0)
|
|
{
|
|
chip->IntervalClockDivider[ch] += 4;
|
|
|
|
if(chip->IntlControl[ch] & 0x20)
|
|
{
|
|
chip->IntervalCounter[ch]--;
|
|
if(!chip->IntervalCounter[ch])
|
|
{
|
|
chip->IntlControl[ch] &= ~0x80;
|
|
}
|
|
}
|
|
|
|
chip->EnvelopeClockDivider[ch]--;
|
|
while(chip->EnvelopeClockDivider[ch] <= 0)
|
|
{
|
|
chip->EnvelopeClockDivider[ch] += 4;
|
|
|
|
if(chip->EnvControl[ch] & 0x0100) // Enveloping enabled?
|
|
{
|
|
chip->EnvelopeCounter[ch]--;
|
|
if(!chip->EnvelopeCounter[ch])
|
|
{
|
|
chip->EnvelopeCounter[ch] = (chip->EnvControl[ch] & 0x7) + 1;
|
|
|
|
if(chip->EnvControl[ch] & 0x0008) // Grow
|
|
{
|
|
if(chip->Envelope[ch] < 0xF || (chip->EnvControl[ch] & 0x200))
|
|
chip->Envelope[ch] = (chip->Envelope[ch] + 1) & 0xF;
|
|
}
|
|
else // Decay
|
|
{
|
|
if(chip->Envelope[ch] > 0 || (chip->EnvControl[ch] & 0x200))
|
|
chip->Envelope[ch] = (chip->Envelope[ch] - 1) & 0xF;
|
|
}
|
|
}
|
|
}
|
|
|
|
} // end while(chip->EnvelopeClockDivider[ch] <= 0)
|
|
} // end while(chip->IntervalClockDivider[ch] <= 0)
|
|
|
|
if(ch == 4)
|
|
{
|
|
chip->SweepModClockDivider--;
|
|
while(chip->SweepModClockDivider <= 0)
|
|
{
|
|
chip->SweepModClockDivider += (chip->SweepControl & 0x80) ? 8 : 1;
|
|
|
|
if(((chip->SweepControl >> 4) & 0x7) && (chip->EnvControl[ch] & 0x4000))
|
|
{
|
|
if(chip->SweepModCounter)
|
|
chip->SweepModCounter--;
|
|
|
|
if(!chip->SweepModCounter)
|
|
{
|
|
chip->SweepModCounter = (chip->SweepControl >> 4) & 0x7;
|
|
|
|
if(chip->EnvControl[ch] & 0x1000) // Modulation
|
|
{
|
|
if(chip->ModWavePos < 32 || (chip->EnvControl[ch] & 0x2000))
|
|
{
|
|
chip->ModWavePos &= 0x1F;
|
|
|
|
chip->EffFreq[ch] = (chip->EffFreq[ch] + (INT8)chip->ModData[chip->ModWavePos]);
|
|
if(chip->EffFreq[ch] < 0)
|
|
{
|
|
//puts("Underflow");
|
|
chip->EffFreq[ch] = 0;
|
|
}
|
|
else if(chip->EffFreq[ch] > 0x7FF)
|
|
{
|
|
//puts("Overflow");
|
|
chip->EffFreq[ch] = 0x7FF;
|
|
}
|
|
chip->ModWavePos++;
|
|
}
|
|
//puts("Mod");
|
|
}
|
|
else // Sweep
|
|
{
|
|
INT32 delta = chip->EffFreq[ch] >> (chip->SweepControl & 0x7);
|
|
INT32 NewFreq = chip->EffFreq[ch] + ((chip->SweepControl & 0x8) ? delta : -delta);
|
|
|
|
//printf("Sweep(%d): Old: %d, New: %d\n", ch, EffFreq[ch], NewFreq);
|
|
|
|
if(NewFreq < 0)
|
|
chip->EffFreq[ch] = 0;
|
|
else if(NewFreq > 0x7FF)
|
|
{
|
|
//chip->EffFreq[ch] = 0x7FF;
|
|
chip->IntlControl[ch] &= ~0x80;
|
|
}
|
|
else
|
|
chip->EffFreq[ch] = NewFreq;
|
|
}
|
|
}
|
|
}
|
|
} // end while(chip->SweepModClockDivider <= 0)
|
|
} // end if(ch == 4)
|
|
} // end while(chip->EffectsClockDivider[ch] <= 0)
|
|
clocks -= chunk_clocks;
|
|
//running_timestamp += chunk_clocks;
|
|
|
|
// Output sound here too.
|
|
//VSU_CalcCurrentOutput(chip, ch, &left, &right);
|
|
//Synth.offset_inline(running_timestamp, left - chip->last_output[ch][0], sbuf[0]);
|
|
//Synth.offset_inline(running_timestamp, right - chip->last_output[ch][1], sbuf[1]);
|
|
//chip->last_output[ch][0] = left;
|
|
//chip->last_output[ch][1] = right;
|
|
}
|
|
|
|
VSU_CalcCurrentOutput(chip, ch, outleft, outright);
|
|
}
|
|
chip->last_ts = timestamp;
|
|
//puts("VSU End");
|
|
}
|
|
|
|
/*void VSU_EndFrame(INT32 timestamp)
|
|
{
|
|
Update(chip, timestamp);
|
|
chip->last_ts = 0;
|
|
}*/
|
|
|
|
/*int VSU_StateAction(StateMem *sm, int load, int data_only)
|
|
{
|
|
SFORMAT StateRegs[] =
|
|
{
|
|
SFARRAY(IntlControl, 6),
|
|
SFARRAY(LeftLevel, 6),
|
|
SFARRAY(RightLevel, 6),
|
|
|
|
SFARRAY16(Frequency, 6),
|
|
SFARRAY16(EnvControl, 6),
|
|
SFARRAY(RAMAddress, 6),
|
|
SFVAR(SweepControl),
|
|
|
|
SFARRAY(&WaveData[0][0], 5 * 0x20),
|
|
SFARRAY(ModData, 0x20),
|
|
|
|
SFARRAY32(EffFreq, 6),
|
|
SFARRAY32(Envelope, 6),
|
|
|
|
SFARRAY32(WavePos, 6),
|
|
|
|
SFVAR(ModWavePos),
|
|
|
|
SFARRAY32(LatcherClockDivider, 6),
|
|
SFARRAY32(FreqCounter, 6),
|
|
SFARRAY32(IntervalCounter, 6),
|
|
SFARRAY32(EnvelopeCounter, 6),
|
|
|
|
SFVAR(SweepModCounter),
|
|
|
|
SFARRAY32(EffectsClockDivider, 6),
|
|
SFARRAY32(IntervalClockDivider, 6),
|
|
SFARRAY32(EnvelopeClockDivider, 6),
|
|
|
|
SFVAR(SweepModClockDivider),
|
|
|
|
SFVAR(NoiseLatcherClockDivider),
|
|
SFVAR(NoiseLatcher),
|
|
SFVAR(lfsr),
|
|
SFEND
|
|
};
|
|
|
|
int ret = MDFNSS_StateAction(sm, load, data_only, StateRegs, "VSU");
|
|
|
|
|
|
if(load)
|
|
{
|
|
|
|
}
|
|
|
|
return(ret);
|
|
}*/
|
|
|
|
|
|
void vsu_stream_update(void *_info, stream_sample_t **outputs, int samples)
|
|
{
|
|
vsu_state* chip = (vsu_state *)_info;
|
|
int curSmpl;
|
|
|
|
for (curSmpl = 0; curSmpl < samples; curSmpl ++)
|
|
{
|
|
chip->tm_smpl ++;
|
|
chip->tm_clk = (int)((INT64)chip->tm_smpl * chip->clock / chip->smplrate);
|
|
|
|
VSU_Update(chip, chip->tm_clk, &outputs[0][curSmpl], &outputs[1][curSmpl]);
|
|
if (chip->last_ts >= chip->clock)
|
|
{
|
|
chip->last_ts -= chip->clock;
|
|
chip->tm_clk -= chip->clock;
|
|
chip->tm_smpl -= chip->smplrate;
|
|
}
|
|
|
|
// Volume per channel: 0x1F (envelope/volume) * 0x3F (unsigned sample) = 0x7A1 (~0x800)
|
|
// I turned the samples into signed format (-0x20..0x1F), so the used range is +-0x400.
|
|
// 16-bit values are up to 0x8000
|
|
// 0x8000 / 0x400 / 6 = 5.33 (possible boost without clipping)
|
|
// Because music usually doesn't use the maximum volume (SFX do), I boost by 2^3 = 8.
|
|
outputs[0][curSmpl] <<= 3;
|
|
outputs[1][curSmpl] <<= 3;
|
|
}
|
|
return;
|
|
}
|
|
|
|
int device_start_vsu(void **_info, int clock, int CHIP_SAMPLING_MODE, int CHIP_SAMPLE_RATE)
|
|
{
|
|
vsu_state* chip;
|
|
UINT8 CurChn;
|
|
|
|
chip = (vsu_state *) calloc(1, sizeof(vsu_state));
|
|
*_info = (void *) chip;
|
|
|
|
chip->clock = clock;
|
|
chip->smplrate = chip->clock / 120; // most effects run with a /120 divider
|
|
if (((CHIP_SAMPLING_MODE & 0x01) && chip->smplrate < CHIP_SAMPLE_RATE) ||
|
|
CHIP_SAMPLING_MODE == 0x02)
|
|
chip->smplrate = CHIP_SAMPLE_RATE;
|
|
|
|
for (CurChn = 0; CurChn < 6; CurChn ++)
|
|
chip->Muted[CurChn] = 0x00;
|
|
|
|
return chip->smplrate;
|
|
}
|
|
|
|
void device_stop_vsu(void *chip)
|
|
{
|
|
free(chip);
|
|
}
|
|
|
|
void device_reset_vsu(void *_info)
|
|
{
|
|
vsu_state* chip = (vsu_state *)_info;
|
|
|
|
VSU_Power(chip);
|
|
chip->tm_smpl = 0;
|
|
chip->tm_clk = 0;
|
|
|
|
return;
|
|
}
|
|
|
|
void vsu_set_mute_mask(void *_info, UINT32 MuteMask)
|
|
{
|
|
vsu_state* chip = (vsu_state *)_info;
|
|
UINT8 CurChn;
|
|
|
|
for (CurChn = 0; CurChn < 6; CurChn ++)
|
|
chip->Muted[CurChn] = (MuteMask >> CurChn) & 0x01;
|
|
|
|
return;
|
|
}
|