A Y P C M
This commit is contained in:
parent
e82374fcde
commit
b72b5bf0e6
|
@ -81,16 +81,39 @@ const char** DivPlatformAY8910::getRegisterSheet() {
|
|||
return intellivision?regCheatSheetAY8914:regCheatSheetAY;
|
||||
}
|
||||
|
||||
void DivPlatformAY8910::acquire(short* bufL, short* bufR, size_t start, size_t len) {
|
||||
if (ayBufLen<len) {
|
||||
ayBufLen=len;
|
||||
for (int i=0; i<3; i++) {
|
||||
delete[] ayBuf[i];
|
||||
ayBuf[i]=new short[ayBufLen];
|
||||
}
|
||||
/* C program to generate this table:
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
for (int i=0; i<256; i++) {
|
||||
if ((i&15)==0) printf("\n ");
|
||||
printf(" %d,",(int)round(pow((double)i/255.0,0.36)*15.0));
|
||||
}
|
||||
// TODO: try to fit this into the actual loop
|
||||
// PCM part
|
||||
}
|
||||
*/
|
||||
|
||||
const unsigned char dacLogTableAY[256]={
|
||||
0, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||
9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10,
|
||||
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11,
|
||||
11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
|
||||
11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12,
|
||||
12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
|
||||
12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13,
|
||||
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
|
||||
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14,
|
||||
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
|
||||
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
|
||||
14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15
|
||||
};
|
||||
|
||||
void DivPlatformAY8910::runDAC() {
|
||||
for (int i=0; i<3; i++) {
|
||||
if (chan[i].psgMode.dac && chan[i].dac.sample!=-1) {
|
||||
chan[i].dac.period+=chan[i].dac.rate;
|
||||
|
@ -105,9 +128,8 @@ void DivPlatformAY8910::acquire(short* bufL, short* bufR, size_t start, size_t l
|
|||
end=true;
|
||||
break;
|
||||
}
|
||||
// Partially
|
||||
unsigned char dacData=(((unsigned char)s->data8[chan[i].dac.pos]^0x80)>>4);
|
||||
chan[i].dac.out=MAX(0,MIN(15,(dacData*chan[i].outVol)/15));
|
||||
unsigned char dacData=dacLogTableAY[(unsigned char)s->data8[chan[i].dac.pos]^0x80];
|
||||
chan[i].dac.out=MAX(0,dacData-(15-chan[i].outVol));
|
||||
if (prevOut!=chan[i].dac.out) {
|
||||
prevOut=chan[i].dac.out;
|
||||
changed=true;
|
||||
|
@ -130,7 +152,9 @@ void DivPlatformAY8910::acquire(short* bufL, short* bufR, size_t start, size_t l
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DivPlatformAY8910::checkWrites() {
|
||||
while (!writes.empty()) {
|
||||
QueuedWrite w=writes.front();
|
||||
if (intellivision) {
|
||||
|
@ -143,8 +167,22 @@ void DivPlatformAY8910::acquire(short* bufL, short* bufR, size_t start, size_t l
|
|||
regPool[w.addr&0x0f]=w.val;
|
||||
writes.pop();
|
||||
}
|
||||
}
|
||||
|
||||
void DivPlatformAY8910::acquire(short* bufL, short* bufR, size_t start, size_t len) {
|
||||
if (ayBufLen<len) {
|
||||
ayBufLen=len;
|
||||
for (int i=0; i<3; i++) {
|
||||
delete[] ayBuf[i];
|
||||
ayBuf[i]=new short[ayBufLen];
|
||||
}
|
||||
}
|
||||
|
||||
if (sunsoft) {
|
||||
for (size_t i=0; i<len; i++) {
|
||||
runDAC();
|
||||
checkWrites();
|
||||
|
||||
ay->sound_stream_update(ayBuf,1);
|
||||
bufL[i+start]=ayBuf[0][0];
|
||||
bufR[i+start]=bufL[i+start];
|
||||
|
@ -154,22 +192,22 @@ void DivPlatformAY8910::acquire(short* bufL, short* bufR, size_t start, size_t l
|
|||
oscBuf[2]->data[oscBuf[2]->needle++]=sunsoftVolTable[31-((ay->lastIndx>>10)&31)]>>3;
|
||||
}
|
||||
} else {
|
||||
ay->sound_stream_update(ayBuf,len);
|
||||
if (stereo) {
|
||||
for (size_t i=0; i<len; i++) {
|
||||
bufL[i+start]=ayBuf[0][i]+ayBuf[1][i]+((ayBuf[2][i]*stereoSep)>>8);
|
||||
bufR[i+start]=((ayBuf[0][i]*stereoSep)>>8)+ayBuf[1][i]+ayBuf[2][i];
|
||||
}
|
||||
} else {
|
||||
for (size_t i=0; i<len; i++) {
|
||||
bufL[i+start]=ayBuf[0][i]+ayBuf[1][i]+ayBuf[2][i];
|
||||
for (size_t i=0; i<len; i++) {
|
||||
runDAC();
|
||||
checkWrites();
|
||||
|
||||
ay->sound_stream_update(ayBuf,1);
|
||||
if (stereo) {
|
||||
bufL[i+start]=ayBuf[0][0]+ayBuf[1][0]+((ayBuf[2][0]*stereoSep)>>8);
|
||||
bufR[i+start]=((ayBuf[0][0]*stereoSep)>>8)+ayBuf[1][0]+ayBuf[2][0];
|
||||
} else {
|
||||
bufL[i+start]=ayBuf[0][0]+ayBuf[1][0]+ayBuf[2][0];
|
||||
bufR[i+start]=bufL[i+start];
|
||||
}
|
||||
}
|
||||
for (int ch=0; ch<3; ch++) {
|
||||
for (size_t i=0; i<len; i++) {
|
||||
oscBuf[ch]->data[oscBuf[ch]->needle++]=ayBuf[ch][i]<<2;
|
||||
}
|
||||
|
||||
oscBuf[0]->data[oscBuf[0]->needle++]=ayBuf[0][0]<<2;
|
||||
oscBuf[1]->data[oscBuf[1]->needle++]=ayBuf[1][0]<<2;
|
||||
oscBuf[2]->data[oscBuf[2]->needle++]=ayBuf[2][0]<<2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -291,7 +329,7 @@ void DivPlatformAY8910::tick(bool sysTick) {
|
|||
off=8363.0/(double)s->centerRate;
|
||||
}
|
||||
}
|
||||
chan[i].dac.rate=((double)chipClock*4096.0)/(double)(MAX(1,off*chan[i].freq));
|
||||
chan[i].dac.rate=((double)rate*16.0)/(double)(MAX(1,off*chan[i].freq));
|
||||
if (dumpWrites) addWrite(0xffff0001+(i<<8),chan[i].dac.rate);
|
||||
}
|
||||
if (chan[i].freq>4095) chan[i].freq=4095;
|
||||
|
|
|
@ -145,6 +145,8 @@ class DivPlatformAY8910: public DivDispatch {
|
|||
short* ayBuf[3];
|
||||
size_t ayBufLen;
|
||||
|
||||
void runDAC();
|
||||
void checkWrites();
|
||||
void updateOutSel(bool immediate=false);
|
||||
|
||||
friend void putDispatchChip(void*,int);
|
||||
|
|
|
@ -77,22 +77,45 @@ const char** DivPlatformAY8930::getRegisterSheet() {
|
|||
return regCheatSheetAY8930;
|
||||
}
|
||||
|
||||
void DivPlatformAY8930::acquire(short* bufL, short* bufR, size_t start, size_t len) {
|
||||
if (ayBufLen<len) {
|
||||
ayBufLen=len;
|
||||
for (int i=0; i<3; i++) {
|
||||
delete[] ayBuf[i];
|
||||
ayBuf[i]=new short[ayBufLen];
|
||||
}
|
||||
/* C program to generate this table:
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
for (int i=0; i<256; i++) {
|
||||
if ((i&15)==0) printf("\n ");
|
||||
printf(" %d,",(int)round(pow((double)i/255.0,0.3)*31.0));
|
||||
}
|
||||
// TODO: try to fit this into the actual loop
|
||||
// PCM part
|
||||
for (int i=0; i<3; i++) {
|
||||
}
|
||||
*/
|
||||
|
||||
const unsigned char dacLogTableAY8930[256]={
|
||||
0, 6, 7, 8, 9, 10, 10, 11, 11, 11, 12, 12, 12, 13, 13, 13,
|
||||
14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16,
|
||||
17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19,
|
||||
19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20,
|
||||
20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
|
||||
22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
|
||||
23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
||||
24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
|
||||
25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
|
||||
26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
|
||||
27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28,
|
||||
28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
|
||||
28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
|
||||
29, 29, 29, 29, 29, 29, 29, 29, 29, 30, 30, 30, 30, 30, 30, 30,
|
||||
30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
|
||||
30, 30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31
|
||||
};
|
||||
|
||||
void DivPlatformAY8930::runDAC() {
|
||||
for (int i=0; i<3; i++) {
|
||||
if (chan[i].psgMode.dac && chan[i].dac.sample!=-1) {
|
||||
chan[i].dac.period+=chan[i].dac.rate;
|
||||
bool end=false;
|
||||
bool changed=false;
|
||||
int prev_out = chan[i].dac.out;
|
||||
int prevOut=chan[i].dac.out;
|
||||
while (chan[i].dac.period>rate && !end) {
|
||||
DivSample* s=parent->getSample(chan[i].dac.sample);
|
||||
if (s->samples<=0) {
|
||||
|
@ -101,11 +124,10 @@ void DivPlatformAY8930::acquire(short* bufL, short* bufR, size_t start, size_t l
|
|||
end=true;
|
||||
break;
|
||||
}
|
||||
// Partially
|
||||
unsigned char dacData=(((unsigned char)s->data8[chan[i].dac.pos]^0x80)>>3);
|
||||
chan[i].dac.out=MAX(0,MIN(31,(dacData*chan[i].outVol)/31));
|
||||
if (prev_out!=chan[i].dac.out) {
|
||||
prev_out=chan[i].dac.out;
|
||||
unsigned char dacData=dacLogTableAY8930[(unsigned char)s->data8[chan[i].dac.pos]^0x80];
|
||||
chan[i].dac.out=MAX(0,dacData-(31-chan[i].outVol));
|
||||
if (prevOut!=chan[i].dac.out) {
|
||||
prevOut=chan[i].dac.out;
|
||||
changed=true;
|
||||
}
|
||||
chan[i].dac.pos++;
|
||||
|
@ -126,7 +148,9 @@ void DivPlatformAY8930::acquire(short* bufL, short* bufR, size_t start, size_t l
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DivPlatformAY8930::checkWrites() {
|
||||
while (!writes.empty()) {
|
||||
QueuedWrite w=writes.front();
|
||||
ay->address_w(w.addr);
|
||||
|
@ -138,23 +162,33 @@ void DivPlatformAY8930::acquire(short* bufL, short* bufR, size_t start, size_t l
|
|||
}
|
||||
writes.pop();
|
||||
}
|
||||
ay->sound_stream_update(ayBuf,len);
|
||||
if (stereo) {
|
||||
for (size_t i=0; i<len; i++) {
|
||||
bufL[i+start]=ayBuf[0][i]+ayBuf[1][i]+((ayBuf[2][i]*stereoSep)>>8);
|
||||
bufR[i+start]=((ayBuf[0][i]*stereoSep)>>8)+ayBuf[1][i]+ayBuf[2][i];
|
||||
}
|
||||
} else {
|
||||
for (size_t i=0; i<len; i++) {
|
||||
bufL[i+start]=ayBuf[0][i]+ayBuf[1][i]+ayBuf[2][i];
|
||||
bufR[i+start]=bufL[i+start];
|
||||
}
|
||||
|
||||
void DivPlatformAY8930::acquire(short* bufL, short* bufR, size_t start, size_t len) {
|
||||
if (ayBufLen<len) {
|
||||
ayBufLen=len;
|
||||
for (int i=0; i<3; i++) {
|
||||
delete[] ayBuf[i];
|
||||
ayBuf[i]=new short[ayBufLen];
|
||||
}
|
||||
}
|
||||
|
||||
for (int ch=0; ch<3; ch++) {
|
||||
for (size_t i=0; i<len; i++) {
|
||||
oscBuf[ch]->data[oscBuf[ch]->needle++]=ayBuf[ch][i]<<2;
|
||||
for (size_t i=0; i<len; i++) {
|
||||
runDAC();
|
||||
checkWrites();
|
||||
|
||||
ay->sound_stream_update(ayBuf,1);
|
||||
if (stereo) {
|
||||
bufL[i+start]=ayBuf[0][0]+ayBuf[1][0]+((ayBuf[2][0]*stereoSep)>>8);
|
||||
bufR[i+start]=((ayBuf[0][0]*stereoSep)>>8)+ayBuf[1][0]+ayBuf[2][0];
|
||||
} else {
|
||||
bufL[i+start]=ayBuf[0][0]+ayBuf[1][0]+ayBuf[2][0];
|
||||
bufR[i+start]=bufL[i+start];
|
||||
}
|
||||
|
||||
oscBuf[0]->data[oscBuf[0]->needle++]=ayBuf[0][0]<<2;
|
||||
oscBuf[1]->data[oscBuf[1]->needle++]=ayBuf[1][0]<<2;
|
||||
oscBuf[2]->data[oscBuf[2]->needle++]=ayBuf[2][0]<<2;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -294,7 +328,7 @@ void DivPlatformAY8930::tick(bool sysTick) {
|
|||
off=8363.0/(double)s->centerRate;
|
||||
}
|
||||
}
|
||||
chan[i].dac.rate=((double)chipClock*16384.0)/(double)(MAX(1,off*chan[i].freq));
|
||||
chan[i].dac.rate=((double)chipClock*4.0)/(double)(MAX(1,off*chan[i].freq));
|
||||
if (dumpWrites) addWrite(0xffff0001+(i<<8),chan[i].dac.rate);
|
||||
}
|
||||
if (chan[i].freq>65535) chan[i].freq=65535;
|
||||
|
|
|
@ -148,6 +148,8 @@ class DivPlatformAY8930: public DivDispatch {
|
|||
short* ayBuf[3];
|
||||
size_t ayBufLen;
|
||||
|
||||
void runDAC();
|
||||
void checkWrites();
|
||||
void updateOutSel(bool immediate=false);
|
||||
void immWrite(unsigned char a, unsigned char v);
|
||||
|
||||
|
|
Loading…
Reference in a new issue