Remove dead code

This commit is contained in:
Brendan Robert 2018-05-23 00:38:02 -05:00
parent eb776d44af
commit 9118b83a43

View File

@ -1,638 +0,0 @@
/*
* Copyright (C) 2012 Brendan Robert (BLuRry) brendan.robert@gmail.com.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package jace.hardware.mockingboard;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import jace.hardware.CardMockingboard;
// Port of AY code from AppleWin -- not used buy kept for reference.
/***************************************************************************
*
* ay8910.c
*
*
* Emulation of the AY-3-8910 / YM2149 sound chip.
*
* Based on various code snippets by Ville Hallik, Michael Cuddy,
* Tatsuyuki Satoh, Fabrice Frances, Nicola Salmoria.
*
***************************************************************************/
//
// From mame.txt (http://www.mame.net/readme.html)
//
// VI. Reuse of Source Code
// --------------------------
// This chapter might not apply to specific portions of MAME (e.g. CPU
// emulators) which bear different copyright notices.
// The source code cannot be used in a commercial product without the written
// authorization of the authors. Use in non-commercial products is allowed, and
// indeed encouraged. If you use portions of the MAME source code in your
// program, however, you must make the full source code freely available as
// well.
// Usage of the _information_ contained in the source code is free for any use.
// However, given the amount of time and energy it took to collect this
// information, if you find new information we would appreciate if you made it
// freely available as well.
//
public class AY8910_old {
static final int MAX_OUTPUT = 0x007fff;
static final int MAX_AY8910 = 2;
static final int CLOCK = 1789770;
static final int SAMPLE_RATE = 44100;
// See AY8910_set_clock() for definition of STEP
static final int STEP = 0x008000;
static int num = 0, ym_num = 0;
int SampleRate = 0;
/* register id's */
public enum Reg {
AFine(0, 255),
ACoarse(1, 15),
BFine(2, 255),
BCoarse(3, 15),
CFine(4, 255),
CCoarse(5, 15),
NoisePeriod(6, 31),
Enable(7, 255),
AVol(8, 31),
BVol(9, 31),
CVol(10, 31),
EnvFine(11, 255),
EnvCoarse(12, 255),
EnvShape(13, 15),
PortA(14, 255),
PortB(15, 255);
public final int registerNumber;
public final int max;
Reg(int number, int maxValue) {
registerNumber = number;
max=maxValue;
}
static Reg get(int number) {
for (Reg r:Reg.values())
if (r.registerNumber == number) return r;
return null;
}
static public Reg[] preferredOrder = new Reg[]{
Enable,EnvShape,EnvCoarse,EnvFine,NoisePeriod,AVol,BVol,CVol,
AFine,ACoarse,BFine,BCoarse,CFine,CCoarse};
}
public AY8910_old() {
chips = new ArrayList<PSG>();
for (int i=0; i < MAX_AY8910; i++) {
PSG chip = new PSG();
chips.add(chip);
}
initAll(CLOCK, SAMPLE_RATE);
}
///////////////////////////////////////////////////////////
private List<PSG> chips;
static int[] VolTable;
static {
buildMixerTable();
}
private class PSG {
int Channel;
int register_latch;
Map<Reg, Integer> registers;
int lastEnable;
int UpdateStep;
int PeriodA,PeriodB,PeriodC,PeriodN,PeriodE;
int CountA,CountB,CountC,CountN,CountE;
int VolA,VolB,VolC,VolE;
int EnvelopeA,EnvelopeB,EnvelopeC;
int OutputA,OutputB,OutputC,OutputN;
int CountEnv;
int Hold,Alternate,Attack,Holding;
int RNG;
public PSG() {
registers = new HashMap<Reg, Integer>();
for (Reg r: Reg.values())
setReg(r, 0);
}
public void reset() {
register_latch = 0;
RNG = 1;
OutputA = 0;
OutputB = 0;
OutputC = 0;
OutputN = 0x00ff;
lastEnable = -1; /* force a write */
for (Reg r: Reg.values())
writeReg(r, 0);
}
public void setClock(int clock) {
/* the step clock for the tone and noise generators is the chip clock */
/* divided by 8; for the envelope generator of the AY-3-8910, it is half */
/* that much (clock/16), but the envelope of the YM2149 goes twice as */
/* fast, therefore again clock/8. */
/* Here we calculate the number of steps which happen during one sample */
/* at the given sample rate. No. of events = sample rate / (clock/8). */
/* STEP is a multiplier used to turn the fraction into a fixed point */
/* number. */
double clk = clock;
double smprate = SampleRate;
UpdateStep = (int) ((STEP * smprate * 8.0 + clk/2.0) / clk);
}
public void setReg(Reg r, int value) {
registers.put(r,value);
}
public int getReg(Reg r) {
return registers.get(r);
}
public void writeReg(Reg r, int value) {
value &= r.max;
setReg(r, value);
int old;
/* A note about the period of tones, noise and envelope: for speed reasons,*/
/* we count down from the period to 0, but careful studies of the chip */
/* output prove that it instead counts up from 0 until the counter becomes */
/* greater or equal to the period. This is an important difference when the*/
/* program is rapidly changing the period to modulate the sound. */
/* To compensate for the difference, when the period is changed we adjust */
/* our internal counter. */
/* Also, note that period = 0 is the same as period = 1. This is mentioned */
/* in the YM2203 data sheets. However, this does NOT apply to the Envelope */
/* period. In that case, period = 0 is half as period = 1. */
switch(r) {
case ACoarse:
case AFine:
old = PeriodA;
PeriodA = (getReg(Reg.AFine) + 256 * getReg(Reg.ACoarse)) * UpdateStep;
if (PeriodA == 0) PeriodA = UpdateStep;
CountA += PeriodA - old;
if (CountA <= 0) CountA = 1;
break;
case BCoarse:
case BFine:
old = PeriodB;
PeriodB = (getReg(Reg.BFine) + 256 * getReg(Reg.BCoarse)) * UpdateStep;
if (PeriodB == 0) PeriodB = UpdateStep;
CountB += PeriodB - old;
if (CountB <= 0) CountB = 1;
break;
case CCoarse:
case CFine:
setReg(Reg.CCoarse, getReg(Reg.CCoarse) & 0x0f);
old = PeriodC;
PeriodA = (getReg(Reg.CFine) + 256 * getReg(Reg.CCoarse)) * UpdateStep;
if (PeriodC == 0) PeriodC = UpdateStep;
CountC += PeriodC - old;
if (CountC <= 0) CountC = 1;
break;
case NoisePeriod:
old = PeriodN;
PeriodN = getReg(Reg.NoisePeriod) * UpdateStep;
if (PeriodN == 0) PeriodN = UpdateStep;
CountN += PeriodN - old;
if (CountN <= 0) CountN = 1;
break;
case Enable:
lastEnable = value;
break;
case AVol:
EnvelopeA = value & 0x10;
if (EnvelopeA > 0)
VolA = VolE;
else {
if (value > 0)
VolA = CardMockingboard.VolTable[value];
else
VolA = CardMockingboard.VolTable[0];
}
break;
case BVol:
EnvelopeB = value & 0x10;
if (EnvelopeB > 0)
VolB = VolE;
else {
if (value > 0)
VolB = CardMockingboard.VolTable[value];
else
VolB = CardMockingboard.VolTable[0];
}
break;
case CVol:
EnvelopeC = value & 0x10;
if (EnvelopeC > 0)
VolC = VolE;
else {
if (value > 0)
VolC = CardMockingboard.VolTable[value];
else
VolC = CardMockingboard.VolTable[0];
}
break;
case EnvFine:
case EnvCoarse:
old = PeriodE;
PeriodE = ((getReg(Reg.EnvFine) + 256 * getReg(Reg.EnvCoarse))) * UpdateStep;
if (PeriodE == 0) PeriodE = UpdateStep / 2;
CountE += PeriodE - old;
if (CountE <= 0) CountE = 1;
if (PeriodE <= 0) PeriodE = 1;
break;
case EnvShape:
/* envelope shapes:
C AtAlH
0 0 x x \___
0 1 x x /|__
1 0 0 0 \\\\
1 0 0 1 \___
1 0 1 0 \/\/
__
1 0 1 1 \|
1 1 0 0 ////
___
1 1 0 1 /
1 1 1 0 /\/\
1 1 1 1 /|__
The envelope counter on the AY-3-8910 has 16 steps. On the YM2149 it
has twice the steps, happening twice as fast. Since the end result is
just a smoother curve, we always use the YM2149 behaviour.
*/
Attack = (value & 0x04) != 0 ? 0x1f : 0x00;
if ( (value & 0x08) == 0) {
/* if Continue = 0, map the shape to the equivalent one which has Continue = 1 */
Hold = 1;
Alternate = Attack;
} else {
Hold = value & 0x01;
Alternate = value & 0x02;
}
CountE = PeriodE;
CountEnv = 0x1f;
Holding = 0;
VolE = CardMockingboard.VolTable[CountEnv ^ Attack];
if (EnvelopeA != 0) VolA = VolE;
if (EnvelopeB != 0) VolB = VolE;
if (EnvelopeC != 0) VolC = VolE;
break;
case PortA:
case PortB:
break;
}
}
void update(int[][] buffer, int length) {
int[] buf1, buf2, buf3;
int outn;
buf1 = buffer[0];
buf2 = buffer[1];
buf3 = buffer[2];
/* The 8910 has three outputs, each output is the mix of one of the three */
/* tone generators and of the (single) noise generator. The two are mixed */
/* BEFORE going into the DAC. The formula to mix each channel is: */
/* (ToneOn | ToneDisable) & (NoiseOn | NoiseDisable). */
/* Note that this means that if both tone and noise are disabled, the output */
/* is 1, not 0, and can be modulated changing the volume. */
/* If the channels are disabled, set their output to 1, and increase the */
/* counter, if necessary, so they will not be inverted during this update. */
/* Setting the output to 1 is necessary because a disabled channel is locked */
/* into the ON state (see above); and it has no effect if the volume is 0. */
/* If the volume is 0, increase the counter, but don't touch the output. */
if ( (getReg(Reg.Enable) & 0x01) != 0) {
if (CountA <= length*STEP) CountA += length*STEP;
OutputA = 1;
} else if (getReg(Reg.AVol) == 0) {
/* note that I do count += length, NOT count = length + 1. You might think */
/* it's the same since the volume is 0, but doing the latter could cause */
/* interferencies when the program is rapidly modulating the volume. */
if (CountA <= length*STEP) CountA += length*STEP;
}
if ( (getReg(Reg.Enable) & 0x02) != 0) {
if (CountB <= length*STEP) CountB += length*STEP;
OutputB = 1;
} else if (getReg(Reg.BVol) == 0) {
if (CountB <= length*STEP) CountB += length*STEP;
}
if ( (getReg(Reg.Enable) & 0x04) != 0) {
if (CountC <= length*STEP) CountC += length*STEP;
OutputC = 1;
} else if (getReg(Reg.CVol) == 0) {
if (CountC <= length*STEP) CountC += length*STEP;
}
/* for the noise channel we must not touch OutputN - it's also not necessary */
/* since we use outn. */
if ((getReg(Reg.Enable) & 0x38) == 0x38) /* all off */
if (CountN <= length*STEP) CountN += length*STEP;
outn = (OutputN | getReg(Reg.Enable));
int index = 0;
//System.out.println("Length:"+length);
/* buffering loop */
while (length != 0) {
int vola,volb,volc;
int left;
/* vola, volb and volc keep track of how long each square wave stays */
/* in the 1 position during the sample period. */
vola = volb = volc = 0;
//System.out.println("STEP:"+STEP);
left = STEP;
do {
int nextevent;
if (CountN < left) nextevent = CountN;
else nextevent = left;
if ( (outn & 0x08) != 0) {
if (OutputA != 0) vola += CountA;
CountA -= nextevent;
/* PeriodA is the half period of the square wave. Here, in each */
/* loop I add PeriodA twice, so that at the end of the loop the */
/* square wave is in the same status (0 or 1) it was at the start. */
/* vola is also incremented by PeriodA, since the wave has been 1 */
/* exactly half of the time, regardless of the initial position. */
/* If we exit the loop in the middle, OutputA has to be inverted */
/* and vola incremented only if the exit status of the square */
/* wave is 1. */
while (CountA <= 0 && PeriodA > 0) {
CountA += PeriodA;
if (CountA > 0) {
OutputA ^= 1;
if (OutputA != 0) vola += PeriodA;
break;
}
CountA += PeriodA;
vola += PeriodA;
}
if (OutputA != 0) vola -= CountA;
} else {
CountA -= nextevent;
while (CountA <= 0 && PeriodA > 0) {
CountA += PeriodA;
if (CountA > 0) {
OutputA ^= 1;
break;
}
CountA += PeriodA;
}
}
if ((outn & 0x10) != 0) {
if (OutputB != 0) volb += CountB;
CountB -= nextevent;
while (CountB <= 0 && PeriodB > 0) {
CountB += PeriodB;
if (CountB > 0) {
OutputB ^= 1;
if (OutputB != 0) volb += PeriodB;
break;
}
CountB += PeriodB;
volb += PeriodB;
}
if (OutputB != 0) volb -= CountB;
} else {
CountB -= nextevent;
while (CountB <= 0 && PeriodB > 0) {
CountB += PeriodB;
if (CountB > 0) {
OutputB ^= 1;
break;
}
CountB += PeriodB;
}
}
if ( (outn & 0x20) != 0) {
if (OutputC != 0) volc += CountC;
CountC -= nextevent;
while (CountC <= 0 && PeriodC > 0) {
CountC += PeriodC;
if (CountC > 0) {
OutputC ^= 1;
if (OutputC != 0) volc += PeriodC;
break;
}
CountC += PeriodC;
volc += PeriodC;
}
if (OutputC != 0) volc -= CountC;
} else {
CountC -= nextevent;
while (CountC <= 0 && PeriodC > 0) {
CountC += PeriodC;
if (CountC > 0) {
OutputC ^= 1;
break;
}
CountC += PeriodC;
}
}
CountN -= nextevent;
if (CountN <= 0 && PeriodN > 0) {
/* Is noise output going to change? */
/* (bit0^bit1)? */
if (((RNG + 1) & 2) != 0) {
OutputN ^= 0x0FF;
outn = (OutputN | getReg(Reg.Enable));
}
/* The Random Number Generator of the 8910 is a 17-bit shift */
/* register. The input to the shift register is bit0 XOR bit3 */
/* (bit0 is the output). This was verified on AY-3-8910 and YM2149 chips. */
/* The following is a fast way to compute bit17 = bit0^bit3. */
/* Instead of doing all the logic operations, we only check */
/* bit0, relying on the fact that after three shifts of the */
/* register, what now is bit3 will become bit0, and will */
/* invert, if necessary, bit14, which previously was bit17. */
if ((RNG & 1) != 0) RNG ^= 0x0024000; /* This version is called the "Galois configuration". */
RNG >>= 1;
CountN += PeriodN;
}
left -= nextevent;
} while (left > 0);
// System.out.println("End left loop");
/* update envelope */
if (Holding == 0) {
CountE -= STEP;
if (CountE <= 0) {
do {
CountEnv--;
CountE += PeriodE;
} while (CountE <= 0);
/* check envelope current position */
if (CountEnv < 0) {
if (Hold != 0) {
if (Alternate != 0)
Attack ^= 0x1f;
Holding = 1;
CountEnv = 0;
} else {
/* if CountEnv has looped an odd number of times (usually 1), */
/* invert the output. */
if ( (Alternate != 0) && ((CountEnv & 0x20) != 0))
Attack ^= 0x1f;
CountEnv &= 0x1f;
}
}
VolE = VolTable[CountEnv ^ Attack];
/* reload volume */
if (EnvelopeA != 0) VolA = VolE;
if (EnvelopeB != 0) VolB = VolE;
if (EnvelopeC != 0) VolC = VolE;
}
}
// Output PCM wave [-32768...32767] instead of MAME's voltage level [0...32767]
// - This allows for better s/w mixing
buf1[index] = (vola * VolA) / STEP;
buf2[index] = (volb * VolB) / STEP;
buf3[index] = (volc * VolC) / STEP;
/*
if(VolA != 0) {
if (vola != 0) buf1[index] = (vola * VolA) / STEP;
else buf1[index] = -VolA;
} else {
buf1[index] = 0;
}
//
if(VolB != 0) {
if (volb != 0) buf2[index] = (volb * VolB) / STEP;
else buf2[index] = -VolB;
} else
buf2[index] = 0;
//
if(VolC != 0) {
if (volc != 0) buf3[index] = (volc * VolC) / STEP;
else buf3[index] = -VolC;
} else
buf3[index] = 0;
*/
index++;
length--;
}
}
};
public void writeReg(int chipNumber, int register, int value) {
Reg r = Reg.get(register);
writeReg(chipNumber, r, value);
}
public void writeReg(int chipNumber, Reg register, int value) {
chips.get(chipNumber).writeReg(register, value);
}
// /length/ is the number of samples we require
// NB. This should be called at twice the 6522 IRQ rate or (eg) 60Hz if no IRQ.
public void update(int chipNumber,int[][] buffer,int length) {
chips.get(chipNumber).update(buffer, length);
}
int[][] buffers;
int bufferLength = -1;
public int[][] getBuffers(int length) {
if (buffers == null || bufferLength != length) {
buffers = new int[3][length];
bufferLength = length;
}
return buffers;
}
public void playSound(int size, int[] left, int[] right) {
int[][] buffers = getBuffers(left.length);
update(0, buffers, size);
mixDown(left, buffers, size);
update(1, buffers, size);
mixDown(right, buffers, size);
}
public void mixDown(int[] out, int[][] in, int size) {
for (int i=0; i < size; i++) {
int sample = (in[0][i] + in[1][i] + in[2][i]) / 3;
out[i] = sample;
}
}
public void setClock(int chipNumber,int clock) {
chips.get(chipNumber).setClock(clock);
}
public void reset(int chipNumber) {
chips.get(chipNumber).reset();
}
public void initAll(int nClock, int nSampleRate) {
SampleRate = nSampleRate;
for (PSG p:chips) {
p.setClock(nClock);
p.reset();
}
}
public void initClock(int nClock) {
for (PSG p:chips) p.setClock(nClock);
}
static void buildMixerTable() {
VolTable = new int[32];
int SampleRate;
/* calculate the volume->voltage conversion table */
/* The AY-3-8910 has 16 levels, in a logarithmic scale (3dB per step) */
/* The YM2149 still has 16 levels for the tone generators, but 32 for */
/* the envelope generator (1.5dB per step). */
double out = MAX_OUTPUT;
for (int i = 31;i > 0;i--) {
VolTable[i] = (int) (out + 0.5); /* round to nearest */ // [TC: unsigned int cast]
out /= 1.188502227; /* = 10 ^ (1.5/20) = 1.5dB */
}
VolTable[0] = 0;
}
}