mirror of
https://github.com/tildearrow/furnace.git
synced 2024-11-30 08:23:01 +00:00
Amiga: better emulation, part 1
prepare to actually emulate DMA operation eventually poke() and register view will work
This commit is contained in:
parent
0f08c6e702
commit
c0b4cc0d63
4 changed files with 109 additions and 3 deletions
|
@ -20,6 +20,7 @@
|
||||||
#define _USE_MATH_DEFINES
|
#define _USE_MATH_DEFINES
|
||||||
#include "amiga.h"
|
#include "amiga.h"
|
||||||
#include "../engine.h"
|
#include "../engine.h"
|
||||||
|
#include "../../ta-log.h"
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#define AMIGA_DIVIDER 8
|
#define AMIGA_DIVIDER 8
|
||||||
|
@ -81,6 +82,10 @@ void DivPlatformAmiga::acquire(short** buf, size_t len) {
|
||||||
for (size_t h=0; h<len; h++) {
|
for (size_t h=0; h<len; h++) {
|
||||||
outL=0;
|
outL=0;
|
||||||
outR=0;
|
outR=0;
|
||||||
|
|
||||||
|
// NEW CODE
|
||||||
|
|
||||||
|
// OLD CODE
|
||||||
for (int i=0; i<4; i++) {
|
for (int i=0; i<4; i++) {
|
||||||
chan[i].volPos=(chan[i].volPos+1)&AMIGA_VPMASK;
|
chan[i].volPos=(chan[i].volPos+1)&AMIGA_VPMASK;
|
||||||
if (!chan[i].active) {
|
if (!chan[i].active) {
|
||||||
|
@ -457,6 +462,9 @@ void DivPlatformAmiga::setFlags(const DivConfig& flags) {
|
||||||
sep1=sep+127;
|
sep1=sep+127;
|
||||||
sep2=127-sep;
|
sep2=127-sep;
|
||||||
amigaModel=flags.getInt("chipType",0);
|
amigaModel=flags.getInt("chipType",0);
|
||||||
|
chipMem=flags.getInt("chipMem",21);
|
||||||
|
if (chipMem<18) chipMem=18;
|
||||||
|
if (chipMem>21) chipMem=21;
|
||||||
bypassLimits=flags.getBool("bypassLimits",false);
|
bypassLimits=flags.getBool("bypassLimits",false);
|
||||||
if (amigaModel) {
|
if (amigaModel) {
|
||||||
filtConstOff=4000;
|
filtConstOff=4000;
|
||||||
|
@ -467,6 +475,56 @@ void DivPlatformAmiga::setFlags(const DivConfig& flags) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const void* DivPlatformAmiga::getSampleMem(int index) {
|
||||||
|
return index == 0 ? sampleMem : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t DivPlatformAmiga::getSampleMemCapacity(int index) {
|
||||||
|
return index == 0 ? (1<<chipMem) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t DivPlatformAmiga::getSampleMemUsage(int index) {
|
||||||
|
return index == 0 ? sampleMemLen : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DivPlatformAmiga::isSampleLoaded(int index, int sample) {
|
||||||
|
if (index!=0) return false;
|
||||||
|
if (sample<0 || sample>255) return false;
|
||||||
|
return sampleLoaded[sample];
|
||||||
|
}
|
||||||
|
|
||||||
|
void DivPlatformAmiga::renderSamples(int sysID) {
|
||||||
|
memset(sampleMem,0,2097152);
|
||||||
|
memset(sampleOff,0,256*sizeof(unsigned int));
|
||||||
|
memset(sampleLoaded,0,256*sizeof(bool));
|
||||||
|
|
||||||
|
size_t memPos=0;
|
||||||
|
for (int i=0; i<parent->song.sampleLen; i++) {
|
||||||
|
DivSample* s=parent->song.sample[i];
|
||||||
|
if (!s->renderOn[0][sysID]) {
|
||||||
|
sampleOff[i]=0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memPos>=getSampleMemCapacity()) {
|
||||||
|
logW("out of Amiga memory for sample %d!",i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int length=s->getLoopEndPosition(DIV_SAMPLE_DEPTH_8BIT);
|
||||||
|
int actualLength=MIN((int)(getSampleMemCapacity()-memPos),length);
|
||||||
|
if (actualLength>0) {
|
||||||
|
sampleOff[i]=memPos;
|
||||||
|
memcpy(&sampleMem[memPos],s->data8,actualLength);
|
||||||
|
memPos+=actualLength;
|
||||||
|
}
|
||||||
|
// align memPos to short
|
||||||
|
if (memPos&1) memPos++;
|
||||||
|
sampleLoaded[i]=true;
|
||||||
|
}
|
||||||
|
sampleMemLen=memPos;
|
||||||
|
}
|
||||||
|
|
||||||
int DivPlatformAmiga::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) {
|
int DivPlatformAmiga::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) {
|
||||||
parent=p;
|
parent=p;
|
||||||
dumpWrites=false;
|
dumpWrites=false;
|
||||||
|
@ -487,12 +545,16 @@ int DivPlatformAmiga::init(DivEngine* p, int channels, int sugRate, const DivCon
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sampleMem=new unsigned char[2097152];
|
||||||
|
sampleMemLen=0;
|
||||||
|
|
||||||
setFlags(flags);
|
setFlags(flags);
|
||||||
reset();
|
reset();
|
||||||
return 6;
|
return 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivPlatformAmiga::quit() {
|
void DivPlatformAmiga::quit() {
|
||||||
|
delete[] sampleMem;
|
||||||
for (int i=0; i<4; i++) {
|
for (int i=0; i<4; i++) {
|
||||||
delete oscBuf[i];
|
delete oscBuf[i];
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,20 +29,26 @@ class DivPlatformAmiga: public DivDispatch {
|
||||||
unsigned int audLoc;
|
unsigned int audLoc;
|
||||||
unsigned short audLen;
|
unsigned short audLen;
|
||||||
unsigned int audPos;
|
unsigned int audPos;
|
||||||
|
unsigned int dmaLoc;
|
||||||
|
unsigned short dmaLen;
|
||||||
int audSub;
|
int audSub;
|
||||||
signed char audDat;
|
signed char audDat;
|
||||||
|
signed char audDat2;
|
||||||
unsigned char volPos;
|
unsigned char volPos;
|
||||||
int sample, wave;
|
int sample, wave;
|
||||||
int busClock;
|
int busClock;
|
||||||
bool useWave, setPos, useV, useP;
|
bool useWave, setPos, useV, useP, dmaOn, audDatClock;
|
||||||
DivWaveSynth ws;
|
DivWaveSynth ws;
|
||||||
Channel():
|
Channel():
|
||||||
SharedChannel<signed char>(64),
|
SharedChannel<signed char>(64),
|
||||||
audLoc(0),
|
audLoc(0),
|
||||||
audLen(0),
|
audLen(0),
|
||||||
audPos(0),
|
audPos(0),
|
||||||
|
dmaLoc(0),
|
||||||
|
dmaLen(0),
|
||||||
audSub(0),
|
audSub(0),
|
||||||
audDat(0),
|
audDat(0),
|
||||||
|
audDat2(0),
|
||||||
volPos(0),
|
volPos(0),
|
||||||
sample(-1),
|
sample(-1),
|
||||||
wave(-1),
|
wave(-1),
|
||||||
|
@ -50,7 +56,9 @@ class DivPlatformAmiga: public DivDispatch {
|
||||||
useWave(false),
|
useWave(false),
|
||||||
setPos(false),
|
setPos(false),
|
||||||
useV(false),
|
useV(false),
|
||||||
useP(false) {}
|
useP(false),
|
||||||
|
dmaOn(false),
|
||||||
|
audDatClock(false) {}
|
||||||
};
|
};
|
||||||
Channel chan[4];
|
Channel chan[4];
|
||||||
DivDispatchOscBuffer* oscBuf[4];
|
DivDispatchOscBuffer* oscBuf[4];
|
||||||
|
@ -62,9 +70,16 @@ class DivPlatformAmiga: public DivDispatch {
|
||||||
int filter[2][4];
|
int filter[2][4];
|
||||||
int filtConst;
|
int filtConst;
|
||||||
int filtConstOff, filtConstOn;
|
int filtConstOff, filtConstOn;
|
||||||
|
int chipMem;
|
||||||
|
|
||||||
unsigned char volTable[64][64];
|
unsigned char volTable[64][64];
|
||||||
|
|
||||||
|
unsigned int sampleOff[256];
|
||||||
|
bool sampleLoaded[256];
|
||||||
|
|
||||||
|
unsigned char* sampleMem;
|
||||||
|
size_t sampleMemLen;
|
||||||
|
|
||||||
int sep1, sep2;
|
int sep1, sep2;
|
||||||
|
|
||||||
friend void putDispatchChip(void*,int);
|
friend void putDispatchChip(void*,int);
|
||||||
|
@ -86,7 +101,12 @@ class DivPlatformAmiga: public DivDispatch {
|
||||||
void notifyInsChange(int ins);
|
void notifyInsChange(int ins);
|
||||||
void notifyWaveChange(int wave);
|
void notifyWaveChange(int wave);
|
||||||
void notifyInsDeletion(void* ins);
|
void notifyInsDeletion(void* ins);
|
||||||
|
void renderSamples(int chipID);
|
||||||
const char** getRegisterSheet();
|
const char** getRegisterSheet();
|
||||||
|
const void* getSampleMem(int index=0);
|
||||||
|
size_t getSampleMemCapacity(int index=0);
|
||||||
|
size_t getSampleMemUsage(int index=0);
|
||||||
|
bool isSampleLoaded(int index, int sample);
|
||||||
int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags);
|
int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags);
|
||||||
void quit();
|
void quit();
|
||||||
};
|
};
|
||||||
|
|
|
@ -446,7 +446,7 @@ void DivPlatformSegaPCM::reset() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivPlatformSegaPCM::renderSamples(int sysID) {
|
void DivPlatformSegaPCM::renderSamples(int sysID) {
|
||||||
size_t memPos=0;
|
size_t memPos=0;
|
||||||
|
|
||||||
memset(sampleMem,0,16777216);
|
memset(sampleMem,0,16777216);
|
||||||
|
|
|
@ -681,6 +681,7 @@ bool FurnaceGUI::drawSysConf(int chan, DivSystem type, DivConfig& flags, bool mo
|
||||||
case DIV_SYSTEM_AMIGA: {
|
case DIV_SYSTEM_AMIGA: {
|
||||||
bool clockSel=flags.getInt("clockSel",0);
|
bool clockSel=flags.getInt("clockSel",0);
|
||||||
int chipType=flags.getInt("chipType",0);
|
int chipType=flags.getInt("chipType",0);
|
||||||
|
int chipMem=flags.getInt("chipMem",21);
|
||||||
int stereoSep=flags.getInt("stereoSep",0);
|
int stereoSep=flags.getInt("stereoSep",0);
|
||||||
bool bypassLimits=flags.getBool("bypassLimits",false);
|
bool bypassLimits=flags.getBool("bypassLimits",false);
|
||||||
|
|
||||||
|
@ -690,6 +691,8 @@ bool FurnaceGUI::drawSysConf(int chan, DivSystem type, DivConfig& flags, bool mo
|
||||||
if (stereoSep>127) stereoSep=127;
|
if (stereoSep>127) stereoSep=127;
|
||||||
altered=true;
|
altered=true;
|
||||||
} rightClickable
|
} rightClickable
|
||||||
|
|
||||||
|
ImGui::Text("Model:");
|
||||||
if (ImGui::RadioButton("Amiga 500 (OCS)",chipType==0)) {
|
if (ImGui::RadioButton("Amiga 500 (OCS)",chipType==0)) {
|
||||||
chipType=0;
|
chipType=0;
|
||||||
altered=true;
|
altered=true;
|
||||||
|
@ -698,6 +701,26 @@ bool FurnaceGUI::drawSysConf(int chan, DivSystem type, DivConfig& flags, bool mo
|
||||||
chipType=1;
|
chipType=1;
|
||||||
altered=true;
|
altered=true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImGui::Text("Chip memory:");
|
||||||
|
if (ImGui::RadioButton("2MB (ECS/AGA max)",chipMem==21)) {
|
||||||
|
chipMem=21;
|
||||||
|
altered=true;
|
||||||
|
}
|
||||||
|
if (ImGui::RadioButton("1MB",chipMem==20)) {
|
||||||
|
chipMem=20;
|
||||||
|
altered=true;
|
||||||
|
}
|
||||||
|
if (ImGui::RadioButton("512KB (OCS max)",chipMem==19)) {
|
||||||
|
chipMem=19;
|
||||||
|
altered=true;
|
||||||
|
}
|
||||||
|
if (ImGui::RadioButton("256KB",chipMem==18)) {
|
||||||
|
chipMem=18;
|
||||||
|
altered=true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (ImGui::Checkbox("PAL",&clockSel)) {
|
if (ImGui::Checkbox("PAL",&clockSel)) {
|
||||||
altered=true;
|
altered=true;
|
||||||
}
|
}
|
||||||
|
@ -709,6 +732,7 @@ bool FurnaceGUI::drawSysConf(int chan, DivSystem type, DivConfig& flags, bool mo
|
||||||
e->lockSave([&]() {
|
e->lockSave([&]() {
|
||||||
flags.set("clockSel",(int)clockSel);
|
flags.set("clockSel",(int)clockSel);
|
||||||
flags.set("chipType",chipType);
|
flags.set("chipType",chipType);
|
||||||
|
flags.set("chipMem",chipMem);
|
||||||
flags.set("stereoSep",stereoSep);
|
flags.set("stereoSep",stereoSep);
|
||||||
flags.set("bypassLimits",bypassLimits);
|
flags.set("bypassLimits",bypassLimits);
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue