allow running GUI without loaded module

This commit is contained in:
tildearrow 2021-12-13 14:40:03 -05:00
parent 6b499fbc79
commit 285cc9b766
6 changed files with 122 additions and 111 deletions

View File

@ -707,19 +707,19 @@ bool DivEngine::load(void* f, size_t slen) {
logI("reading patterns (%d channels, %d orders)...\n",getChannelCount(ds.system),ds.ordersLen);
for (int i=0; i<getChannelCount(ds.system); i++) {
DivChannelData* chan=new DivChannelData;
DivChannelData& chan=ds.pat[i];
if (ds.version<0x0a) {
chan->effectRows=1;
chan.effectRows=1;
} else {
chan->effectRows=reader.readC();
chan.effectRows=reader.readC();
}
logD("%d fx rows: %d\n",i,chan->effectRows);
if (chan->effectRows>4 || chan->effectRows<1) {
logE("invalid effect row count %d. are you sure everything is ok?\n",chan->effectRows);
logD("%d fx rows: %d\n",i,chan.effectRows);
if (chan.effectRows>4 || chan.effectRows<1) {
logE("invalid effect row count %d. are you sure everything is ok?\n",chan.effectRows);
return false;
}
for (int j=0; j<ds.ordersLen; j++) {
DivPattern* pat=chan->getPattern(ds.orders.ord[i][j],true);
DivPattern* pat=chan.getPattern(ds.orders.ord[i][j],true);
for (int k=0; k<ds.patLen; k++) {
// note
pat->data[k][0]=reader.readS();
@ -742,7 +742,7 @@ bool DivEngine::load(void* f, size_t slen) {
pat->data[k][3]>>=1;
}
}
for (int l=0; l<chan->effectRows; l++) {
for (int l=0; l<chan.effectRows; l++) {
// effect
pat->data[k][4+(l<<1)]=reader.readS();
pat->data[k][5+(l<<1)]=reader.readS();
@ -751,7 +751,6 @@ bool DivEngine::load(void* f, size_t slen) {
pat->data[k][2]=reader.readS();
}
}
ds.pat.push_back(chan);
}
ds.sampleLen=reader.readC();
@ -947,16 +946,16 @@ bool DivEngine::save(FILE* 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 i=0; i<getChannelCount(song.system); 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);
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][4],2,song.pat[i].effectRows*2,f)); // volume
ERR_CHECK(fwrite(&pat->data[k][2],2,1,f)); // instrument
}
}
@ -1192,6 +1191,58 @@ void DivEngine::setView(DivStatusView which) {
view=which;
}
void DivEngine::initDispatch() {
if (dispatch!=NULL) return;
isBusy.lock();
switch (song.system) {
case DIV_SYSTEM_GENESIS:
dispatch=new DivPlatformGenesis;
break;
case DIV_SYSTEM_GENESIS_EXT:
dispatch=new DivPlatformGenesisExt;
break;
case DIV_SYSTEM_SMS:
dispatch=new DivPlatformSMS;
break;
case DIV_SYSTEM_GB:
dispatch=new DivPlatformGB;
break;
case DIV_SYSTEM_PCE:
dispatch=new DivPlatformPCE;
break;
case DIV_SYSTEM_NES:
dispatch=new DivPlatformNES;
break;
case DIV_SYSTEM_C64_6581:
dispatch=new DivPlatformC64;
((DivPlatformC64*)dispatch)->setChipModel(true);
break;
case DIV_SYSTEM_C64_8580:
dispatch=new DivPlatformC64;
((DivPlatformC64*)dispatch)->setChipModel(false);
break;
case DIV_SYSTEM_ARCADE:
dispatch=new DivPlatformArcade;
break;
case DIV_SYSTEM_YM2610:
dispatch=new DivPlatformYM2610;
break;
default:
logW("this system is not supported yet! using dummy platform.\n");
dispatch=new DivPlatformDummy;
break;
}
dispatch->init(this,getChannelCount(song.system),got.rate,(!song.pal) || (song.customTempo!=0 && song.hz<53));
blip_set_rates(bb[0],dispatch->rate,got.rate);
blip_set_rates(bb[1],dispatch->rate,got.rate);
isBusy.unlock();
}
void DivEngine::quitDispatch() {
if (dispatch==NULL) return;
}
bool DivEngine::init(String outName) {
SNDFILE* outFile;
SF_INFO outInfo;
@ -1266,49 +1317,7 @@ bool DivEngine::init(String outName) {
vibTable[i]=127*sin(((double)i/64.0)*(2*M_PI));
}
switch (song.system) {
case DIV_SYSTEM_GENESIS:
dispatch=new DivPlatformGenesis;
break;
case DIV_SYSTEM_GENESIS_EXT:
dispatch=new DivPlatformGenesisExt;
break;
case DIV_SYSTEM_SMS:
dispatch=new DivPlatformSMS;
break;
case DIV_SYSTEM_GB:
dispatch=new DivPlatformGB;
break;
case DIV_SYSTEM_PCE:
dispatch=new DivPlatformPCE;
break;
case DIV_SYSTEM_NES:
dispatch=new DivPlatformNES;
break;
case DIV_SYSTEM_C64_6581:
dispatch=new DivPlatformC64;
((DivPlatformC64*)dispatch)->setChipModel(true);
break;
case DIV_SYSTEM_C64_8580:
dispatch=new DivPlatformC64;
((DivPlatformC64*)dispatch)->setChipModel(false);
break;
case DIV_SYSTEM_ARCADE:
dispatch=new DivPlatformArcade;
break;
case DIV_SYSTEM_YM2610:
dispatch=new DivPlatformYM2610;
break;
default:
logW("this system is not supported yet! using dummy platform.\n");
dispatch=new DivPlatformDummy;
break;
}
dispatch->init(this,getChannelCount(song.system),got.rate,(!song.pal) || (song.customTempo!=0 && song.hz<53));
blip_set_rates(bb[0],dispatch->rate,got.rate);
blip_set_rates(bb[1],dispatch->rate,got.rate);
initDispatch();
reset();
if (outName!="") {

View File

@ -3,7 +3,7 @@
static DivPattern emptyPat;
DivPattern::DivPattern() {
memset(data,0,256*16);
memset(data,-1,256*16);
}
DivPattern* DivChannelData::getPattern(int index, bool create) {

View File

@ -307,9 +307,9 @@ bool DivEngine::perSystemPostEffect(int ch, unsigned char effect, unsigned char
void DivEngine::processRow(int i, bool afterDelay) {
int whatOrder=afterDelay?chan[i].delayOrder:curOrder;
int whatRow=afterDelay?chan[i].delayRow:curRow;
DivPattern* pat=song.pat[i]->getPattern(song.orders.ord[i][whatOrder],false);
DivPattern* pat=song.pat[i].getPattern(song.orders.ord[i][whatOrder],false);
// pre effects
if (!afterDelay) for (int j=0; j<song.pat[i]->effectRows; j++) {
if (!afterDelay) for (int j=0; j<song.pat[i].effectRows; j++) {
short effect=pat->data[whatRow][4+(j<<1)];
short effectVal=pat->data[whatRow][5+(j<<1)];
@ -369,7 +369,7 @@ void DivEngine::processRow(int i, bool afterDelay) {
}
// effects
for (int j=0; j<song.pat[i]->effectRows; j++) {
for (int j=0; j<song.pat[i].effectRows; j++) {
short effect=pat->data[whatRow][4+(j<<1)];
short effectVal=pat->data[whatRow][5+(j<<1)];
@ -526,7 +526,7 @@ void DivEngine::processRow(int i, bool afterDelay) {
chan[i].nowYouCanStop=true;
// post effects
for (int j=0; j<song.pat[i]->effectRows; j++) {
for (int j=0; j<song.pat[i].effectRows; j++) {
short effect=pat->data[whatRow][4+(j<<1)];
short effectVal=pat->data[whatRow][5+(j<<1)];
@ -547,7 +547,7 @@ void DivEngine::nextRow() {
snprintf(pb,4095," %.2x",song.orders.ord[i][curOrder]);
strcat(pb1,pb);
DivPattern* pat=song.pat[i]->getPattern(song.orders.ord[i][curOrder],false);
DivPattern* pat=song.pat[i].getPattern(song.orders.ord[i][curOrder],false);
snprintf(pb2,4095,"\x1b[37m %s",
formatNote(pat->data[curRow][0],pat->data[curRow][1]));
strcat(pb3,pb2);
@ -563,7 +563,7 @@ void DivEngine::nextRow() {
snprintf(pb2,4095,"\x1b[0;36m%.2x",pat->data[curRow][2]);
strcat(pb3,pb2);
}
for (int j=0; j<song.pat[i]->effectRows; j++) {
for (int j=0; j<song.pat[i].effectRows; j++) {
if (pat->data[curRow][4+(j<<1)]==-1) {
strcat(pb3,"\x1b[m--");
} else {
@ -621,7 +621,7 @@ void DivEngine::nextRow() {
// post row details
for (int i=0; i<chans; i++) {
DivPattern* pat=song.pat[i]->getPattern(song.orders.ord[i][curOrder],false);
DivPattern* pat=song.pat[i].getPattern(song.orders.ord[i][curOrder],false);
if (!(pat->data[curRow][0]==0 && pat->data[curRow][1]==0)) {
if (pat->data[curRow][0]!=100) {
dispatchCmd(DivCommand(DIV_CMD_PRE_NOTE,i,ticks));

View File

@ -91,7 +91,7 @@ struct DivSong {
DivOrders orders;
std::vector<DivInstrument*> ins;
std::vector<DivChannelData*> pat;
DivChannelData pat[17];
std::vector<DivWavetable*> wave;
std::vector<DivSample*> sample;
@ -99,8 +99,8 @@ struct DivSong {
DivWavetable nullWave;
DivSong():
version(0),
system(DIV_SYSTEM_NULL),
version(24),
system(DIV_SYSTEM_GENESIS),
name(""),
author(""),
carrier(""),
@ -123,8 +123,8 @@ struct DivSong {
pal(false),
customTempo(false),
hz(60),
patLen(0),
ordersLen(0),
patLen(64),
ordersLen(1),
insLen(0),
waveLen(0),
sampleLen(0) {

View File

@ -492,7 +492,7 @@ bool FurnaceGUI::loop() {
ImGui::TableNextColumn();
ImGui::Text("%3d ",i);
for (int j=0; j<chans; j++) {
DivPattern* pat=e->song.pat[j]->getPattern(e->song.orders.ord[j][ord],true);
DivPattern* pat=e->song.pat[j].getPattern(e->song.orders.ord[j][ord],true);
ImGui::TableNextColumn();
sprintf(id,"%s##PN_%d_%d",noteName(pat->data[i][0],pat->data[i][1]),i,j);
@ -514,7 +514,7 @@ bool FurnaceGUI::loop() {
ImGui::SameLine(0.0f,0.0f);
ImGui::Selectable(id,false,ImGuiSelectableFlags_NoPadWithHalfSpacing,twoChars);
for (int k=0; k<e->song.pat[j]->effectRows; k++) {
for (int k=0; k<e->song.pat[j].effectRows; k++) {
int index=4+(k<<1);
if (pat->data[i][index]==-1) {
sprintf(id,"..##PE%d_%d_%d",k,i,j);

View File

@ -235,52 +235,54 @@ int main(int argc, char** argv) {
}
}
if (fileName.empty()) {
if (fileName.empty() && consoleMode) {
logI("usage: %s file\n",argv[0]);
return 1;
}
logI("Furnace version " DIV_VERSION ".\n");
logI("loading module...\n");
FILE* f=fopen(fileName.c_str(),"rb");
if (f==NULL) {
perror("error");
return 1;
}
if (fseek(f,0,SEEK_END)<0) {
perror("size error");
fclose(f);
return 1;
}
ssize_t len=ftell(f);
if (len==0x7fffffffffffffff) {
perror("could not get file length");
fclose(f);
return 1;
}
if (len<1) {
if (len==0) {
printf("that file is empty!\n");
} else {
perror("tell error");
if (!fileName.empty()) {
logI("loading module...\n");
FILE* f=fopen(fileName.c_str(),"rb");
if (f==NULL) {
perror("error");
return 1;
}
if (fseek(f,0,SEEK_END)<0) {
perror("size error");
fclose(f);
return 1;
}
ssize_t len=ftell(f);
if (len==0x7fffffffffffffff) {
perror("could not get file length");
fclose(f);
return 1;
}
if (len<1) {
if (len==0) {
printf("that file is empty!\n");
} else {
perror("tell error");
}
fclose(f);
return 1;
}
unsigned char* file=new unsigned char[len];
if (fseek(f,0,SEEK_SET)<0) {
perror("size error");
fclose(f);
return 1;
}
if (fread(file,1,(size_t)len,f)!=(size_t)len) {
perror("read error");
fclose(f);
return 1;
}
fclose(f);
return 1;
}
unsigned char* file=new unsigned char[len];
if (fseek(f,0,SEEK_SET)<0) {
perror("size error");
fclose(f);
return 1;
}
if (fread(file,1,(size_t)len,f)!=(size_t)len) {
perror("read error");
fclose(f);
return 1;
}
fclose(f);
if (!e.load((void*)file,(size_t)len)) {
logE("could not open file!\n");
return 1;
if (!e.load((void*)file,(size_t)len)) {
logE("could not open file!\n");
return 1;
}
}
/*FILE* outFile=fopen("testout.dmf","wb");
if (outFile!=NULL) {