add a save function

and it loads on DefleMask!
This commit is contained in:
tildearrow 2021-12-09 02:38:55 -05:00
parent d395abe47f
commit daed339e07
2 changed files with 202 additions and 0 deletions

View File

@ -1,4 +1,5 @@
#include "engine.h"
#include "instrument.h"
#include "safeReader.h"
#include "../ta-log.h"
#include "../audio/sdl.h"
@ -70,6 +71,38 @@ DivSystem systemFromFile(unsigned char val) {
return DIV_SYSTEM_NULL;
}
unsigned char systemToFile(DivSystem val) {
switch (val) {
case DIV_SYSTEM_YMU759:
return 0x01;
case DIV_SYSTEM_GENESIS:
return 0x02;
case DIV_SYSTEM_SMS:
return 0x03;
case DIV_SYSTEM_GB:
return 0x04;
case DIV_SYSTEM_PCE:
return 0x05;
case DIV_SYSTEM_NES:
return 0x06;
case DIV_SYSTEM_C64_8580:
return 0x07;
case DIV_SYSTEM_ARCADE:
return 0x08;
case DIV_SYSTEM_YM2610:
return 0x09;
case DIV_SYSTEM_GENESIS_EXT:
return 0x42;
case DIV_SYSTEM_C64_6581:
return 0x47;
case DIV_SYSTEM_YM2610_EXT:
return 0x49;
case DIV_SYSTEM_NULL:
return 0;
}
return 0;
}
int getChannelCount(DivSystem sys) {
switch (sys) {
case DIV_SYSTEM_NULL:
@ -631,6 +664,168 @@ bool DivEngine::load(void* f, size_t slen) {
return true;
}
#define ERR_CHECK(x) x; if (ferror(f)) return false;
bool DivEngine::save(FILE* f) {
// write magic
ERR_CHECK(fwrite(DIV_DMF_MAGIC,1,16,f));
// version
ERR_CHECK(fputc(24,f));
ERR_CHECK(fputc(systemToFile(song.system),f));
// song info
ERR_CHECK(fputc(song.name.size(),f));
ERR_CHECK(fwrite(song.name.c_str(),1,song.name.size(),f));
ERR_CHECK(fputc(song.author.size(),f));
ERR_CHECK(fwrite(song.author.c_str(),1,song.author.size(),f));
ERR_CHECK(fputc(song.hilightA,f));
ERR_CHECK(fputc(song.hilightB,f));
ERR_CHECK(fputc(song.timeBase,f));
ERR_CHECK(fputc(song.speed1,f));
ERR_CHECK(fputc(song.speed2,f));
ERR_CHECK(fputc(song.pal,f));
ERR_CHECK(fputc(song.customTempo,f));
char customHz[4];
memset(customHz,0,4);
snprintf(customHz,4,"%d",song.hz);
ERR_CHECK(fwrite(customHz,1,3,f));
ERR_CHECK(fwrite(&song.patLen,4,1,f));
ERR_CHECK(fputc(song.ordersLen,f));
for (int i=0; i<getChannelCount(song.system); i++) {
for (int j=0; j<song.ordersLen; j++) {
ERR_CHECK(fputc(song.orders.ord[i][j],f));
}
}
ERR_CHECK(fputc(song.ins.size(),f));
for (DivInstrument* i: song.ins) {
ERR_CHECK(fputc(i->name.size(),f));
ERR_CHECK(fwrite(i->name.c_str(),1,i->name.size(),f));
ERR_CHECK(fputc(i->mode,f));
if (i->mode) { // FM
ERR_CHECK(fputc(i->fm.alg,f));
ERR_CHECK(fputc(i->fm.fb,f));
ERR_CHECK(fputc(i->fm.fms,f));
ERR_CHECK(fputc(i->fm.ams,f));
for (int j=0; j<4; j++) {
DivInstrumentFM::Operator& op=i->fm.op[j];
ERR_CHECK(fputc(op.am,f));
ERR_CHECK(fputc(op.ar,f));
ERR_CHECK(fputc(op.dr,f));
ERR_CHECK(fputc(op.mult,f));
ERR_CHECK(fputc(op.rr,f));
ERR_CHECK(fputc(op.sl,f));
ERR_CHECK(fputc(op.tl,f));
ERR_CHECK(fputc(op.dt2,f));
ERR_CHECK(fputc(op.rs,f));
ERR_CHECK(fputc(op.dt,f));
ERR_CHECK(fputc(op.d2r,f));
ERR_CHECK(fputc(op.ssgEnv,f));
}
} else { // STD
if (song.system!=DIV_SYSTEM_GB) {
ERR_CHECK(fputc(i->std.volMacroLen,f));
ERR_CHECK(fwrite(i->std.volMacro,4,i->std.volMacroLen,f));
if (i->std.volMacroLen>0) {
ERR_CHECK(fputc(i->std.volMacroLoop,f));
}
}
ERR_CHECK(fputc(i->std.arpMacroLen,f));
ERR_CHECK(fwrite(i->std.arpMacro,4,i->std.arpMacroLen,f));
if (i->std.arpMacroLen>0) {
ERR_CHECK(fputc(i->std.arpMacroLoop,f));
}
ERR_CHECK(fputc(i->std.arpMacroMode,f));
ERR_CHECK(fputc(i->std.dutyMacroLen,f));
ERR_CHECK(fwrite(i->std.dutyMacro,4,i->std.dutyMacroLen,f));
if (i->std.dutyMacroLen>0) {
ERR_CHECK(fputc(i->std.dutyMacroLoop,f));
}
ERR_CHECK(fputc(i->std.waveMacroLen,f));
ERR_CHECK(fwrite(i->std.waveMacro,4,i->std.waveMacroLen,f));
if (i->std.waveMacroLen>0) {
ERR_CHECK(fputc(i->std.waveMacroLoop,f));
}
if (song.system==DIV_SYSTEM_C64_6581 || song.system==DIV_SYSTEM_C64_8580) {
ERR_CHECK(fputc(i->c64.triOn,f));
ERR_CHECK(fputc(i->c64.sawOn,f));
ERR_CHECK(fputc(i->c64.pulseOn,f));
ERR_CHECK(fputc(i->c64.noiseOn,f));
ERR_CHECK(fputc(i->c64.a,f));
ERR_CHECK(fputc(i->c64.d,f));
ERR_CHECK(fputc(i->c64.s,f));
ERR_CHECK(fputc(i->c64.r,f));
ERR_CHECK(fputc(i->c64.duty,f));
ERR_CHECK(fputc(i->c64.ringMod,f));
ERR_CHECK(fputc(i->c64.oscSync,f));
ERR_CHECK(fputc(i->c64.toFilter,f));
ERR_CHECK(fputc(i->c64.volIsCutoff,f));
ERR_CHECK(fputc(i->c64.initFilter,f));
ERR_CHECK(fputc(i->c64.res,f));
ERR_CHECK(fputc(i->c64.cut,f));
ERR_CHECK(fputc(i->c64.hp,f));
ERR_CHECK(fputc(i->c64.bp,f));
ERR_CHECK(fputc(i->c64.lp,f));
ERR_CHECK(fputc(i->c64.ch3off,f));
}
if (song.system==DIV_SYSTEM_GB) {
ERR_CHECK(fputc(i->gb.envVol,f));
ERR_CHECK(fputc(i->gb.envDir,f));
ERR_CHECK(fputc(i->gb.envLen,f));
ERR_CHECK(fputc(i->gb.soundLen,f));
}
}
}
ERR_CHECK(fputc(song.wave.size(),f));
for (DivWavetable* i: song.wave) {
ERR_CHECK(fwrite(&i->len,4,1,f));
ERR_CHECK(fwrite(&i->data,4,i->len,f));
}
for (int i=0; i<song.pat.size(); i++) {
ERR_CHECK(fputc(song.pat[i]->effectRows,f));
for (int j=0; j<song.ordersLen; j++) {
DivPattern* pat=song.pat[i]->getPattern(song.orders.ord[i][j],false);
for (int k=0; k<song.patLen; k++) {
ERR_CHECK(fwrite(&pat->data[k][0],2,1,f)); // note
ERR_CHECK(fwrite(&pat->data[k][1],2,1,f)); // octave
ERR_CHECK(fwrite(&pat->data[k][3],2,1,f)); // volume
ERR_CHECK(fwrite(&pat->data[k][4],2,song.pat[i]->effectRows*2,f)); // volume
ERR_CHECK(fwrite(&pat->data[k][2],2,1,f)); // instrument
}
}
}
ERR_CHECK(fputc(song.sample.size(),f));
for (DivSample* i: song.sample) {
ERR_CHECK(fwrite(&i->length,4,1,f));
ERR_CHECK(fputc(i->name.size(),f));
ERR_CHECK(fwrite(i->name.c_str(),1,i->name.size(),f));
ERR_CHECK(fputc(i->rate,f));
ERR_CHECK(fputc(i->pitch,f));
ERR_CHECK(fputc(i->vol,f));
ERR_CHECK(fputc(i->depth,f));
ERR_CHECK(fwrite(i->data,2,i->length,f));
}
return true;
}
static double samplePitches[11]={
0.1666666666, 0.2, 0.25, 0.333333333, 0.5,
1,

View File

@ -260,6 +260,13 @@ int main(int argc, char** argv) {
logE("could not open file!\n");
return 1;
}
/*FILE* outFile=fopen("testout.dmf","wb");
if (outFile!=NULL) {
if (!e.save(outFile)) {
logE("could not save file!\n");
}
fclose(outFile);
}*/
if (!e.init(outName)) {
logE("could not initialize engine!\n");
return 1;