/*
* HalfNES by Andrew Hoffman
* Licensed under the GNU GPL Version 3. See LICENSE file
*/
package com.grapeshot.halfnes.audio;
import com.grapeshot.halfnes.utils;
/**
*
* @author Andrew
*/
public class Sunsoft5BSoundChip implements ExpansionSoundChip {
//not complete... missing volume envelopes and noise channel at the moment.
//sound test for Gimmick - Hold Select, push Start on title screen
private final Timer[] timers = {new SquareTimer(32), new SquareTimer(32), new SquareTimer(32)};
private final boolean[] enable = {false, false, false};
private final boolean[] useenvelope = {false, false, false};
private final int[] volume = {0, 0, 0};
int enval = 0;
private static final int[] VOLTBL = getvoltbl();
@Override
public final void write(final int register, final int data) {
//System.err.println(register + " " + data);
switch (register) {
case 0:
timers[0].setperiod((timers[0].getperiod() & 0xf00) + data);
break;
case 1:
timers[0].setperiod((timers[0].getperiod() & 0xff) + ((data & 0xf) << 8));
break;
case 2:
timers[1].setperiod((timers[1].getperiod() & 0xf00) + data);
break;
case 3:
timers[1].setperiod((timers[1].getperiod() & 0xff) + ((data & 0xf) << 8));
break;
case 4:
timers[2].setperiod((timers[2].getperiod() & 0xf00) + data);
break;
case 5:
timers[2].setperiod((timers[2].getperiod() & 0xff) + ((data & 0xf) << 8));
break;
case 7:
for (int i = 0; i < 3; ++i) {
enable[i] = !(((data & (1 << i)) != 0));
}
break;
case 8:
volume[0] = data & 0xf;
useenvelope[0] = ((data & (utils.BIT4)) != 0);
break;
case 9:
volume[1] = data & 0xf;
useenvelope[1] = ((data & (utils.BIT4)) != 0);
break;
case 10:
volume[2] = data & 0xf;
useenvelope[2] = ((data & (utils.BIT4)) != 0);
break;
case 13:
enval = 15;
break;
default:
//System.err.println("Unrecognized register write to " + register + " ," + data);
}
}
@Override
public final void clock(final int cycle) {
clockenvelope(cycle);
timers[0].clock(cycle);
timers[1].clock(cycle);
timers[2].clock(cycle);
}
@Override
public final int getval() {
return (enable[0] ? ((useenvelope[0] ? enval : VOLTBL[volume[0]]) * timers[0].getval()) : 0)
+ (enable[1] ? ((useenvelope[1] ? enval : VOLTBL[volume[1]]) * timers[1].getval()) : 0)
+ (enable[2] ? ((useenvelope[2] ? enval : VOLTBL[volume[2]]) * timers[2].getval()) : 0);
}
public static int[] getvoltbl() {
//the AY-3-8910 volume levels are NOT linear, but logarithmic.
int[] vols = new int[16];
for (int i = 0; i < 16; ++i) {
vols[i] = (int) (90 * Math.pow(1.4, i));
//matches YMZ284 datasheet info
}
//utils.printarray(vols);
return vols;
}
private void clockenvelope(final int cycles) {
enval = 0; //gimmick only uses the envelope to mute a channel.
}
}