From c0b4cc0d6352552cba0b5c1e5c8c8335590b893a Mon Sep 17 00:00:00 2001 From: tildearrow Date: Thu, 9 Mar 2023 17:46:45 -0500 Subject: [PATCH] Amiga: better emulation, part 1 prepare to actually emulate DMA operation eventually poke() and register view will work --- src/engine/platform/amiga.cpp | 62 +++++++++++++++++++++++++++++++++ src/engine/platform/amiga.h | 24 +++++++++++-- src/engine/platform/segapcm.cpp | 2 +- src/gui/sysConf.cpp | 24 +++++++++++++ 4 files changed, 109 insertions(+), 3 deletions(-) diff --git a/src/engine/platform/amiga.cpp b/src/engine/platform/amiga.cpp index b05c5c30..b86beb19 100644 --- a/src/engine/platform/amiga.cpp +++ b/src/engine/platform/amiga.cpp @@ -20,6 +20,7 @@ #define _USE_MATH_DEFINES #include "amiga.h" #include "../engine.h" +#include "../../ta-log.h" #include #define AMIGA_DIVIDER 8 @@ -81,6 +82,10 @@ void DivPlatformAmiga::acquire(short** buf, size_t len) { for (size_t h=0; h21) chipMem=21; bypassLimits=flags.getBool("bypassLimits",false); if (amigaModel) { 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<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; isong.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) { parent=p; 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); reset(); return 6; } void DivPlatformAmiga::quit() { + delete[] sampleMem; for (int i=0; i<4; i++) { delete oscBuf[i]; } diff --git a/src/engine/platform/amiga.h b/src/engine/platform/amiga.h index 921d1294..f1da65d3 100644 --- a/src/engine/platform/amiga.h +++ b/src/engine/platform/amiga.h @@ -29,20 +29,26 @@ class DivPlatformAmiga: public DivDispatch { unsigned int audLoc; unsigned short audLen; unsigned int audPos; + unsigned int dmaLoc; + unsigned short dmaLen; int audSub; signed char audDat; + signed char audDat2; unsigned char volPos; int sample, wave; int busClock; - bool useWave, setPos, useV, useP; + bool useWave, setPos, useV, useP, dmaOn, audDatClock; DivWaveSynth ws; Channel(): SharedChannel(64), audLoc(0), audLen(0), audPos(0), + dmaLoc(0), + dmaLen(0), audSub(0), audDat(0), + audDat2(0), volPos(0), sample(-1), wave(-1), @@ -50,7 +56,9 @@ class DivPlatformAmiga: public DivDispatch { useWave(false), setPos(false), useV(false), - useP(false) {} + useP(false), + dmaOn(false), + audDatClock(false) {} }; Channel chan[4]; DivDispatchOscBuffer* oscBuf[4]; @@ -62,9 +70,16 @@ class DivPlatformAmiga: public DivDispatch { int filter[2][4]; int filtConst; int filtConstOff, filtConstOn; + int chipMem; unsigned char volTable[64][64]; + unsigned int sampleOff[256]; + bool sampleLoaded[256]; + + unsigned char* sampleMem; + size_t sampleMemLen; + int sep1, sep2; friend void putDispatchChip(void*,int); @@ -86,7 +101,12 @@ class DivPlatformAmiga: public DivDispatch { void notifyInsChange(int ins); void notifyWaveChange(int wave); void notifyInsDeletion(void* ins); + void renderSamples(int chipID); 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); void quit(); }; diff --git a/src/engine/platform/segapcm.cpp b/src/engine/platform/segapcm.cpp index b96e4452..0b02bb40 100644 --- a/src/engine/platform/segapcm.cpp +++ b/src/engine/platform/segapcm.cpp @@ -446,7 +446,7 @@ void DivPlatformSegaPCM::reset() { } } - void DivPlatformSegaPCM::renderSamples(int sysID) { +void DivPlatformSegaPCM::renderSamples(int sysID) { size_t memPos=0; memset(sampleMem,0,16777216); diff --git a/src/gui/sysConf.cpp b/src/gui/sysConf.cpp index 87b9baed..7bdb61de 100644 --- a/src/gui/sysConf.cpp +++ b/src/gui/sysConf.cpp @@ -681,6 +681,7 @@ bool FurnaceGUI::drawSysConf(int chan, DivSystem type, DivConfig& flags, bool mo case DIV_SYSTEM_AMIGA: { bool clockSel=flags.getInt("clockSel",0); int chipType=flags.getInt("chipType",0); + int chipMem=flags.getInt("chipMem",21); int stereoSep=flags.getInt("stereoSep",0); 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; altered=true; } rightClickable + + ImGui::Text("Model:"); if (ImGui::RadioButton("Amiga 500 (OCS)",chipType==0)) { chipType=0; altered=true; @@ -698,6 +701,26 @@ bool FurnaceGUI::drawSysConf(int chan, DivSystem type, DivConfig& flags, bool mo chipType=1; 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)) { altered=true; } @@ -709,6 +732,7 @@ bool FurnaceGUI::drawSysConf(int chan, DivSystem type, DivConfig& flags, bool mo e->lockSave([&]() { flags.set("clockSel",(int)clockSel); flags.set("chipType",chipType); + flags.set("chipMem",chipMem); flags.set("stereoSep",stereoSep); flags.set("bypassLimits",bypassLimits); });