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
					
				| 
						 | 
				
			
			@ -20,6 +20,7 @@
 | 
			
		|||
#define _USE_MATH_DEFINES
 | 
			
		||||
#include "amiga.h"
 | 
			
		||||
#include "../engine.h"
 | 
			
		||||
#include "../../ta-log.h"
 | 
			
		||||
#include <math.h>
 | 
			
		||||
 | 
			
		||||
#define AMIGA_DIVIDER 8
 | 
			
		||||
| 
						 | 
				
			
			@ -81,6 +82,10 @@ void DivPlatformAmiga::acquire(short** buf, size_t len) {
 | 
			
		|||
  for (size_t h=0; h<len; h++) {
 | 
			
		||||
    outL=0;
 | 
			
		||||
    outR=0;
 | 
			
		||||
 | 
			
		||||
    // NEW CODE
 | 
			
		||||
 | 
			
		||||
    // OLD CODE
 | 
			
		||||
    for (int i=0; i<4; i++) {
 | 
			
		||||
      chan[i].volPos=(chan[i].volPos+1)&AMIGA_VPMASK;
 | 
			
		||||
      if (!chan[i].active) {
 | 
			
		||||
| 
						 | 
				
			
			@ -457,6 +462,9 @@ void DivPlatformAmiga::setFlags(const DivConfig& flags) {
 | 
			
		|||
  sep1=sep+127;
 | 
			
		||||
  sep2=127-sep;
 | 
			
		||||
  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);
 | 
			
		||||
  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<<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) {
 | 
			
		||||
  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];
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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<signed char>(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();
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
        });
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue