mirror of
https://github.com/tildearrow/furnace.git
synced 2025-01-05 23:21:22 +00:00
move the code a bit to load/save other formats
This commit is contained in:
parent
073703f8ba
commit
254bf18036
3 changed files with 134 additions and 115 deletions
|
@ -35,6 +35,7 @@ void process(void* u, float** in, float** out, int inChans, int outChans, unsign
|
||||||
|
|
||||||
#define DIV_READ_SIZE 131072
|
#define DIV_READ_SIZE 131072
|
||||||
#define DIV_DMF_MAGIC ".DelekDefleMask."
|
#define DIV_DMF_MAGIC ".DelekDefleMask."
|
||||||
|
#define DIV_FUR_MAGIC "-Furnace module-"
|
||||||
|
|
||||||
struct InflateBlock {
|
struct InflateBlock {
|
||||||
unsigned char* buf;
|
unsigned char* buf;
|
||||||
|
@ -399,117 +400,7 @@ int DivEngine::getMaxWave() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DivEngine::load(unsigned char* f, size_t slen) {
|
bool DivEngine::loadDMF(unsigned char* file, size_t len) {
|
||||||
unsigned char* file;
|
|
||||||
size_t len;
|
|
||||||
if (slen<16) {
|
|
||||||
logE("too small!");
|
|
||||||
lastError="file is too small";
|
|
||||||
delete[] f;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (memcmp(f,DIV_DMF_MAGIC,16)!=0) {
|
|
||||||
logD("loading as zlib...\n");
|
|
||||||
// try zlib
|
|
||||||
z_stream zl;
|
|
||||||
memset(&zl,0,sizeof(z_stream));
|
|
||||||
|
|
||||||
zl.avail_in=slen;
|
|
||||||
zl.next_in=(Bytef*)f;
|
|
||||||
zl.zalloc=NULL;
|
|
||||||
zl.zfree=NULL;
|
|
||||||
zl.opaque=NULL;
|
|
||||||
|
|
||||||
int nextErr;
|
|
||||||
nextErr=inflateInit(&zl);
|
|
||||||
if (nextErr!=Z_OK) {
|
|
||||||
if (zl.msg==NULL) {
|
|
||||||
logE("zlib error: unknown! %d\n",nextErr);
|
|
||||||
} else {
|
|
||||||
logE("zlib error: %s\n",zl.msg);
|
|
||||||
}
|
|
||||||
inflateEnd(&zl);
|
|
||||||
delete[] f;
|
|
||||||
lastError="not a .dmf song";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<InflateBlock*> blocks;
|
|
||||||
while (true) {
|
|
||||||
InflateBlock* ib=new InflateBlock(DIV_READ_SIZE);
|
|
||||||
zl.next_out=ib->buf;
|
|
||||||
zl.avail_out=ib->len;
|
|
||||||
|
|
||||||
nextErr=inflate(&zl,Z_SYNC_FLUSH);
|
|
||||||
if (nextErr!=Z_OK && nextErr!=Z_STREAM_END) {
|
|
||||||
if (zl.msg==NULL) {
|
|
||||||
logE("zlib error: unknown error! %d\n",nextErr);
|
|
||||||
lastError="unknown decompression error";
|
|
||||||
} else {
|
|
||||||
logE("zlib inflate: %s\n",zl.msg);
|
|
||||||
lastError=fmt::sprintf("decompression error: %s",zl.msg);
|
|
||||||
}
|
|
||||||
for (InflateBlock* i: blocks) delete i;
|
|
||||||
blocks.clear();
|
|
||||||
delete ib;
|
|
||||||
inflateEnd(&zl);
|
|
||||||
delete[] f;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
ib->blockSize=ib->len-zl.avail_out;
|
|
||||||
blocks.push_back(ib);
|
|
||||||
if (nextErr==Z_STREAM_END) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nextErr=inflateEnd(&zl);
|
|
||||||
if (nextErr!=Z_OK) {
|
|
||||||
if (zl.msg==NULL) {
|
|
||||||
logE("zlib end error: unknown error! %d\n",nextErr);
|
|
||||||
lastError="unknown decompression finish error";
|
|
||||||
} else {
|
|
||||||
logE("zlib end: %s\n",zl.msg);
|
|
||||||
lastError=fmt::sprintf("decompression finish error: %s",zl.msg);
|
|
||||||
}
|
|
||||||
for (InflateBlock* i: blocks) delete i;
|
|
||||||
blocks.clear();
|
|
||||||
delete[] f;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t finalSize=0;
|
|
||||||
size_t curSeek=0;
|
|
||||||
for (InflateBlock* i: blocks) {
|
|
||||||
finalSize+=i->blockSize;
|
|
||||||
}
|
|
||||||
if (finalSize<1) {
|
|
||||||
logE("compressed too small!\n");
|
|
||||||
lastError="file too small";
|
|
||||||
for (InflateBlock* i: blocks) delete i;
|
|
||||||
blocks.clear();
|
|
||||||
delete[] f;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
file=new unsigned char[finalSize];
|
|
||||||
for (InflateBlock* i: blocks) {
|
|
||||||
memcpy(&file[curSeek],i->buf,i->blockSize);
|
|
||||||
curSeek+=i->blockSize;
|
|
||||||
delete i;
|
|
||||||
}
|
|
||||||
blocks.clear();
|
|
||||||
len=finalSize;
|
|
||||||
delete[] f;
|
|
||||||
} else {
|
|
||||||
logD("loading as uncompressed\n");
|
|
||||||
file=(unsigned char*)f;
|
|
||||||
len=slen;
|
|
||||||
}
|
|
||||||
if (memcmp(file,DIV_DMF_MAGIC,16)!=0) {
|
|
||||||
logE("not a valid module!\n");
|
|
||||||
lastError="not a .dmf song";
|
|
||||||
delete[] file;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
SafeReader reader=SafeReader(file,len);
|
SafeReader reader=SafeReader(file,len);
|
||||||
try {
|
try {
|
||||||
DivSong ds;
|
DivSong ds;
|
||||||
|
@ -1006,7 +897,130 @@ bool DivEngine::load(unsigned char* f, size_t slen) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
SafeWriter* DivEngine::save() {
|
bool DivEngine::loadFur(unsigned char* file, size_t len) {
|
||||||
|
logE("not implemented!\n");
|
||||||
|
lastError="not implemented";
|
||||||
|
delete[] file;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DivEngine::load(unsigned char* f, size_t slen) {
|
||||||
|
unsigned char* file;
|
||||||
|
size_t len;
|
||||||
|
if (slen<16) {
|
||||||
|
logE("too small!");
|
||||||
|
lastError="file is too small";
|
||||||
|
delete[] f;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (memcmp(f,DIV_DMF_MAGIC,16)!=0 && memcmp(f,DIV_FUR_MAGIC,16)!=0) {
|
||||||
|
logD("loading as zlib...\n");
|
||||||
|
// try zlib
|
||||||
|
z_stream zl;
|
||||||
|
memset(&zl,0,sizeof(z_stream));
|
||||||
|
|
||||||
|
zl.avail_in=slen;
|
||||||
|
zl.next_in=(Bytef*)f;
|
||||||
|
zl.zalloc=NULL;
|
||||||
|
zl.zfree=NULL;
|
||||||
|
zl.opaque=NULL;
|
||||||
|
|
||||||
|
int nextErr;
|
||||||
|
nextErr=inflateInit(&zl);
|
||||||
|
if (nextErr!=Z_OK) {
|
||||||
|
if (zl.msg==NULL) {
|
||||||
|
logE("zlib error: unknown! %d\n",nextErr);
|
||||||
|
} else {
|
||||||
|
logE("zlib error: %s\n",zl.msg);
|
||||||
|
}
|
||||||
|
inflateEnd(&zl);
|
||||||
|
delete[] f;
|
||||||
|
lastError="not a .dmf song";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<InflateBlock*> blocks;
|
||||||
|
while (true) {
|
||||||
|
InflateBlock* ib=new InflateBlock(DIV_READ_SIZE);
|
||||||
|
zl.next_out=ib->buf;
|
||||||
|
zl.avail_out=ib->len;
|
||||||
|
|
||||||
|
nextErr=inflate(&zl,Z_SYNC_FLUSH);
|
||||||
|
if (nextErr!=Z_OK && nextErr!=Z_STREAM_END) {
|
||||||
|
if (zl.msg==NULL) {
|
||||||
|
logE("zlib error: unknown error! %d\n",nextErr);
|
||||||
|
lastError="unknown decompression error";
|
||||||
|
} else {
|
||||||
|
logE("zlib inflate: %s\n",zl.msg);
|
||||||
|
lastError=fmt::sprintf("decompression error: %s",zl.msg);
|
||||||
|
}
|
||||||
|
for (InflateBlock* i: blocks) delete i;
|
||||||
|
blocks.clear();
|
||||||
|
delete ib;
|
||||||
|
inflateEnd(&zl);
|
||||||
|
delete[] f;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ib->blockSize=ib->len-zl.avail_out;
|
||||||
|
blocks.push_back(ib);
|
||||||
|
if (nextErr==Z_STREAM_END) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nextErr=inflateEnd(&zl);
|
||||||
|
if (nextErr!=Z_OK) {
|
||||||
|
if (zl.msg==NULL) {
|
||||||
|
logE("zlib end error: unknown error! %d\n",nextErr);
|
||||||
|
lastError="unknown decompression finish error";
|
||||||
|
} else {
|
||||||
|
logE("zlib end: %s\n",zl.msg);
|
||||||
|
lastError=fmt::sprintf("decompression finish error: %s",zl.msg);
|
||||||
|
}
|
||||||
|
for (InflateBlock* i: blocks) delete i;
|
||||||
|
blocks.clear();
|
||||||
|
delete[] f;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t finalSize=0;
|
||||||
|
size_t curSeek=0;
|
||||||
|
for (InflateBlock* i: blocks) {
|
||||||
|
finalSize+=i->blockSize;
|
||||||
|
}
|
||||||
|
if (finalSize<1) {
|
||||||
|
logE("compressed too small!\n");
|
||||||
|
lastError="file too small";
|
||||||
|
for (InflateBlock* i: blocks) delete i;
|
||||||
|
blocks.clear();
|
||||||
|
delete[] f;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
file=new unsigned char[finalSize];
|
||||||
|
for (InflateBlock* i: blocks) {
|
||||||
|
memcpy(&file[curSeek],i->buf,i->blockSize);
|
||||||
|
curSeek+=i->blockSize;
|
||||||
|
delete i;
|
||||||
|
}
|
||||||
|
blocks.clear();
|
||||||
|
len=finalSize;
|
||||||
|
delete[] f;
|
||||||
|
} else {
|
||||||
|
logD("loading as uncompressed\n");
|
||||||
|
file=(unsigned char*)f;
|
||||||
|
len=slen;
|
||||||
|
}
|
||||||
|
if (memcmp(file,DIV_DMF_MAGIC,16)==0) {
|
||||||
|
return loadDMF(file,len);
|
||||||
|
} else if (memcmp(file,DIV_FUR_MAGIC,16)==0) {
|
||||||
|
return loadFur(file,len);
|
||||||
|
}
|
||||||
|
logE("not a valid module!\n");
|
||||||
|
lastError="not a compatible song";
|
||||||
|
delete[] file;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SafeWriter* DivEngine::saveDMF() {
|
||||||
// fail if this is an YMU759 song
|
// fail if this is an YMU759 song
|
||||||
if (song.system==DIV_SYSTEM_YMU759) {
|
if (song.system==DIV_SYSTEM_YMU759) {
|
||||||
logE("cannot save YMU759 song!\n");
|
logE("cannot save YMU759 song!\n");
|
||||||
|
|
|
@ -157,6 +157,9 @@ class DivEngine {
|
||||||
void reset();
|
void reset();
|
||||||
void playSub(bool preserveDrift);
|
void playSub(bool preserveDrift);
|
||||||
|
|
||||||
|
bool loadDMF(unsigned char* file, size_t len);
|
||||||
|
bool loadFur(unsigned char* file, size_t len);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DivSong song;
|
DivSong song;
|
||||||
void nextBuf(float** in, float** out, int inChans, int outChans, unsigned int size);
|
void nextBuf(float** in, float** out, int inChans, int outChans, unsigned int size);
|
||||||
|
@ -164,10 +167,12 @@ class DivEngine {
|
||||||
DivWavetable* getWave(int index);
|
DivWavetable* getWave(int index);
|
||||||
// start fresh
|
// start fresh
|
||||||
void createNew();
|
void createNew();
|
||||||
// load a .dmf.
|
// load a file.
|
||||||
bool load(unsigned char* f, size_t length);
|
bool load(unsigned char* f, size_t length);
|
||||||
// save as .dmf.
|
// save as .dmf.
|
||||||
SafeWriter* save();
|
SafeWriter* saveDMF();
|
||||||
|
// save as .fur.
|
||||||
|
SafeWriter* saveFur();
|
||||||
|
|
||||||
// save config
|
// save config
|
||||||
bool saveConf();
|
bool saveConf();
|
||||||
|
|
|
@ -2382,7 +2382,7 @@ int FurnaceGUI::save(String path) {
|
||||||
lastError=strerror(errno);
|
lastError=strerror(errno);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
SafeWriter* w=e->save();
|
SafeWriter* w=e->saveDMF();
|
||||||
if (w==NULL) {
|
if (w==NULL) {
|
||||||
lastError=e->getLastError();
|
lastError=e->getLastError();
|
||||||
fclose(outFile);
|
fclose(outFile);
|
||||||
|
|
Loading…
Reference in a new issue