Amiga: better emulation, part 4

This commit is contained in:
tildearrow 2023-03-10 13:45:46 -05:00
parent 12a1d2ff3d
commit 452846936f
2 changed files with 53 additions and 12 deletions

View file

@ -82,26 +82,64 @@ const char** DivPlatformAmiga::getRegisterSheet() {
void DivPlatformAmiga::acquire(short** buf, size_t len) { void DivPlatformAmiga::acquire(short** buf, size_t len) {
static int outL, outR, output; static int outL, outR, output;
for (size_t h=0; h<len; h++) { for (size_t h=0; h<len; h++) {
bool hsync=bypassLimits;
outL=0; outL=0;
outR=0; outR=0;
// NEW CODE // NEW CODE
amiga.volPos=(amiga.volPos+1)&AMIGA_VPMASK; amiga.volPos=(amiga.volPos+1)&AMIGA_VPMASK;
if (!bypassLimits) {
amiga.hPos+=AMIGA_DIVIDER;
if (amiga.hPos>=228) {
amiga.hPos-=228;
hsync=true;
}
}
for (int i=0; i<4; i++) { for (int i=0; i<4; i++) {
// run DMA // run DMA
if (amiga.dmaEn && amiga.audEn[i]) { if (amiga.dmaEn && amiga.audEn[i]) {
amiga.audTick[i]-=AMIGA_DIVIDER; amiga.audTick[i]-=AMIGA_DIVIDER;
if (amiga.audTick[i]<0) { if (amiga.audTick[i]<0) {
if (bypassLimits) {
amiga.audTick[i]+=MAX(AMIGA_DIVIDER,amiga.audPer[i]); amiga.audTick[i]+=MAX(AMIGA_DIVIDER,amiga.audPer[i]);
} else {
amiga.audTick[i]+=MAX(114,amiga.audPer[i]);
}
if (amiga.audByte[i]) { if (amiga.audByte[i]) {
// read next samples // read next samples
amiga.audDat[0][i]=sampleMem[(amiga.dmaLoc[i]++)&chipMask]; if (!amiga.incLoc[i]) {
amiga.audDat[1][i]=sampleMem[(amiga.dmaLoc[i]++)&chipMask]; amiga.audDat[0][i]=sampleMem[(amiga.dmaLoc[i])&chipMask];
amiga.audDat[1][i]=sampleMem[(amiga.dmaLoc[i]+1)&chipMask];
amiga.incLoc[i]=true;
} else {
amiga.audDat[0][i]=0;
amiga.audDat[1][i]=0;
}
amiga.audWord[i]=!amiga.audWord[i];
}
amiga.audByte[i]=!amiga.audByte[i];
if (!amiga.audByte[i] && (amiga.useV[i] || amiga.useP[i])) {
amiga.nextOut2[i]=((unsigned char)amiga.audDat[0][i])<<8|((unsigned char)amiga.audDat[1][i]);
if (i<3) {
if (amiga.useV[i] && amiga.useP[i]) {
if (amiga.audWord[i]) {
amiga.audPer[i+1]=amiga.nextOut2[i];
} else {
amiga.audVol[i+1]=amiga.nextOut2[i];
}
} else if (amiga.useV[i]) {
amiga.audVol[i+1]=amiga.nextOut2[i];
} else {
amiga.audPer[i+1]=amiga.nextOut2[i];
}
}
} else {
amiga.nextOut[i]=amiga.audDat[amiga.audByte[i]][i];
}
}
if (hsync) {
if (amiga.incLoc[i]) {
amiga.incLoc[i]=false;
amiga.dmaLoc[i]+=2;
// check for length // check for length
if ((--amiga.dmaLen[i])==0) { if ((--amiga.dmaLen[i])==0) {
if (amiga.audInt[i]) irq(i); if (amiga.audInt[i]) irq(i);
@ -109,19 +147,17 @@ void DivPlatformAmiga::acquire(short** buf, size_t len) {
amiga.dmaLen[i]=amiga.audLen[i]; amiga.dmaLen[i]=amiga.audLen[i];
} }
} }
amiga.audByte[i]=!amiga.audByte[i];
} }
} }
// output // output
if (!isMuted[i]) { if (!isMuted[i]) {
if (amiga.audVol[i]>=64) { if (amiga.audVol[i]>=64) {
output=amiga.audDat[amiga.audByte[i]][i]<<6; output=amiga.nextOut[i]<<6;
} else if (amiga.audVol[i]<=0) { } else if (amiga.audVol[i]<=0) {
output=0; output=0;
} else { } else {
output=amiga.audDat[amiga.audByte[i]][i]*volTable[amiga.audVol[i]][amiga.volPos]; output=amiga.nextOut[i]*volTable[amiga.audVol[i]][amiga.volPos];
} }
if (i==0 || i==3) { if (i==0 || i==3) {
outL+=(output*sep1)>>7; outL+=(output*sep1)>>7;
@ -130,7 +166,7 @@ void DivPlatformAmiga::acquire(short** buf, size_t len) {
outL+=(output*sep2)>>7; outL+=(output*sep2)>>7;
outR+=(output*sep1)>>7; outR+=(output*sep1)>>7;
} }
oscBuf[i]->data[oscBuf[i]->needle++]=amiga.audDat[amiga.audByte[i]][i]*MIN(64,amiga.audVol[i]); oscBuf[i]->data[oscBuf[i]->needle++]=amiga.nextOut[i]*MIN(64,amiga.audVol[i]);
} else { } else {
oscBuf[i]->data[oscBuf[i]->needle++]=0; oscBuf[i]->data[oscBuf[i]->needle++]=0;
} }

View file

@ -82,6 +82,8 @@ class DivPlatformAmiga: public DivDispatch {
unsigned short audPer[4]; // period unsigned short audPer[4]; // period
unsigned char audVol[4]; // volume unsigned char audVol[4]; // volume
signed char audDat[2][4]; // data signed char audDat[2][4]; // data
signed char nextOut[4];
unsigned short nextOut2[4];
// internal state // internal state
@ -90,7 +92,10 @@ class DivPlatformAmiga: public DivDispatch {
unsigned short dmaLen[4]; // position unsigned short dmaLen[4]; // position
bool audByte[4]; // which byte of audDat to output bool audByte[4]; // which byte of audDat to output
bool audWord[4]; // for P/V
bool incLoc[4]; // whether dmaLoc/dmaLen should be updated
unsigned char volPos; // position of volume PWM unsigned char volPos; // position of volume PWM
unsigned short hPos; // horizontal position of beam
Amiga() { Amiga() {
memset(this,0,sizeof(*this)); memset(this,0,sizeof(*this));