add support for loading .vgi and .tfi instruments

This commit is contained in:
tildearrow 2022-02-21 01:44:51 -05:00
parent 3f57cf0951
commit 57c4e22d70
1 changed files with 350 additions and 229 deletions

View File

@ -1196,8 +1196,24 @@ int DivEngine::addInstrument(int refChan) {
return insCount;
}
enum DivInsFormats {
DIV_INSFORMAT_DMP,
DIV_INSFORMAT_TFI,
DIV_INSFORMAT_VGI,
DIV_INSFORMAT_FTI,
DIV_INSFORMAT_BTI
};
bool DivEngine::addInstrumentFromFile(const char *path) {
warnings="";
const char* pathRedux=strrchr(path,DIR_SEPARATOR);
if (pathRedux==NULL) {
pathRedux="Instrument";
} else {
pathRedux++;
}
FILE* f=ps_fopen(path,"rb");
if (f==NULL) {
lastError=strerror(errno);
@ -1274,7 +1290,32 @@ bool DivEngine::addInstrumentFromFile(const char *path) {
delete[] buf;
return false;
}
} else { // read as .dmp
} else { // read as a different format
const char* ext=strrchr(path,'.');
DivInsFormats format=DIV_INSFORMAT_DMP;
if (ext!=NULL) {
String extS;
for (; *ext; ext++) {
char i=*ext;
if (i>='A' && i<='Z') {
i+='a'-'A';
}
extS+=i;
}
if (extS==String(".dmp")) {
format=DIV_INSFORMAT_DMP;
} else if (extS==String(".tfi")) {
format=DIV_INSFORMAT_TFI;
} else if (extS==String(".vgi")) {
format=DIV_INSFORMAT_VGI;
} else if (extS==String(".fti")) {
format=DIV_INSFORMAT_FTI;
} else if (extS==String(".bti")) {
format=DIV_INSFORMAT_BTI;
}
}
switch (format) {
case DIV_INSFORMAT_DMP: {
// this is a ridiculous mess
unsigned char version=0;
unsigned char sys=0;
@ -1296,6 +1337,8 @@ bool DivEngine::addInstrumentFromFile(const char *path) {
return false;
}
ins->name=pathRedux;
if (version>=11) { // 1.0
try {
sys=reader.readC();
@ -1520,6 +1563,84 @@ bool DivEngine::addInstrumentFromFile(const char *path) {
delete[] buf;
return false;
}
break;
}
case DIV_INSFORMAT_TFI:
try {
reader.seek(0,SEEK_SET);
ins->type=DIV_INS_FM;
ins->name=pathRedux;
ins->fm.alg=reader.readC();
ins->fm.fb=reader.readC();
for (int i=0; i<4; i++) {
DivInstrumentFM::Operator& op=ins->fm.op[i];
op.mult=reader.readC();
op.dt=reader.readC();
op.tl=reader.readC();
op.rs=reader.readC();
op.ar=reader.readC();
op.dr=reader.readC();
op.d2r=reader.readC();
op.rr=reader.readC();
op.sl=reader.readC();
op.ssgEnv=reader.readC();
}
} catch (EndOfFileException e) {
lastError="premature end of file";
logE("premature end of file!\n");
delete ins;
delete[] buf;
return false;
}
break;
case DIV_INSFORMAT_VGI:
try {
reader.seek(0,SEEK_SET);
ins->type=DIV_INS_FM;
ins->name=pathRedux;
ins->fm.alg=reader.readC();
ins->fm.fb=reader.readC();
unsigned char fmsams=reader.readC();
ins->fm.fms=fmsams&7;
ins->fm.ams=fmsams>>4;
for (int i=0; i<4; i++) {
DivInstrumentFM::Operator& op=ins->fm.op[i];
op.mult=reader.readC();
op.dt=reader.readC();
op.tl=reader.readC();
op.rs=reader.readC();
op.ar=reader.readC();
op.dr=reader.readC();
if (op.dr&0x80) {
op.am=1;
op.dr&=0x7f;
}
op.d2r=reader.readC();
op.rr=reader.readC();
op.sl=reader.readC();
op.ssgEnv=reader.readC();
}
} catch (EndOfFileException e) {
lastError="premature end of file";
logE("premature end of file!\n");
delete ins;
delete[] buf;
return false;
}
break;
case DIV_INSFORMAT_FTI:
break;
case DIV_INSFORMAT_BTI:
break;
}
if (reader.tell()<reader.size()) {
addWarning("https://github.com/tildearrow/furnace/issues/84");