add iPod and GRUB bootloader beeper tune export (#2441)
This commit is contained in:
parent
24b629c73c
commit
055266090a
11 changed files with 522 additions and 0 deletions
204
src/engine/export/grub.cpp
Normal file
204
src/engine/export/grub.cpp
Normal file
|
|
@ -0,0 +1,204 @@
|
|||
/**
|
||||
* Furnace Tracker - multi-system chiptune tracker
|
||||
* Copyright (C) 2021-2025 tildearrow and contributors
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "grub.h"
|
||||
#include "../engine.h"
|
||||
#include "../ta-log.h"
|
||||
#include <fmt/printf.h>
|
||||
#include <array>
|
||||
#include <vector>
|
||||
|
||||
void DivExportGRUB::run() {
|
||||
bool grubExportBin=conf.getBool("exportBin",false);
|
||||
|
||||
int BEEPER=-1;
|
||||
int IGNORED=0;
|
||||
|
||||
// Locate system index.
|
||||
for (int i=0; i<e->song.systemLen; i++) {
|
||||
if (e->song.system[i] == DIV_SYSTEM_PCSPKR) {
|
||||
if (BEEPER>=0) {
|
||||
IGNORED++;
|
||||
logAppendf("Ignoring duplicate Beeper id %d",i);
|
||||
break;
|
||||
}
|
||||
BEEPER=i;
|
||||
logAppendf("PC Speaker detected as chip id %d",i);
|
||||
break;
|
||||
} else {
|
||||
IGNORED++;
|
||||
logAppendf("Ignoring chip id %d, system id %d",i,(int)e->song.system[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (BEEPER<0) {
|
||||
logAppendf("ERROR: Could not find PC Speaker/Beeper");
|
||||
failed=true;
|
||||
running=false;
|
||||
return;
|
||||
}
|
||||
if (IGNORED>0) {
|
||||
logAppendf("WARNING: iPod .tone export ignoring %d unsupported system%c",IGNORED,IGNORED>1?'s':' ');
|
||||
}
|
||||
|
||||
size_t tickCount=0;
|
||||
|
||||
e->stop();
|
||||
e->repeatPattern=false;
|
||||
e->setOrder(0);
|
||||
|
||||
logAppend("playing and logging register writes...");
|
||||
|
||||
int oldFreq = 0;
|
||||
int freq = 0;
|
||||
|
||||
e->synchronizedSoft([&]() {
|
||||
double origRate = e->got.rate;
|
||||
double rate = MIN(e->curSubSong->hz,1000.0);
|
||||
logAppendf("export rate is %d hz",(int)rate);
|
||||
int tempo = (int)(60000.0/(1000.0/rate));
|
||||
e->got.rate=rate;
|
||||
|
||||
// Determine loop point.
|
||||
int loopOrder=0;
|
||||
int loopRow=0;
|
||||
int loopEnd=0;
|
||||
e->walkSong(loopOrder,loopRow,loopEnd);
|
||||
logAppendf("loop point: %d %d",loopOrder,loopRow);
|
||||
e->warnings="";
|
||||
|
||||
auto w = new SafeWriter;
|
||||
w->init();
|
||||
|
||||
// Reset the playback state.
|
||||
e->curOrder=0;
|
||||
e->freelance=false;
|
||||
e->playing=false;
|
||||
e->extValuePresent=false;
|
||||
e->remainingLoops=-1;
|
||||
|
||||
e->disCont[BEEPER].dispatch->toggleRegisterDump(true);
|
||||
|
||||
// Prepare to write song data.
|
||||
e->playSub(false);
|
||||
bool done=false;
|
||||
|
||||
logAppend("writing data...");
|
||||
progress[0].amount=0.15f;
|
||||
|
||||
int wait_tempo = 0;
|
||||
if (grubExportBin)
|
||||
w->writeI(tempo); // write tempo
|
||||
else
|
||||
w->writeText(fmt::sprintf("%d",tempo)); // write tempo
|
||||
|
||||
while (!done) {
|
||||
if (e->nextTick(false,true) || !e->playing) {
|
||||
done=true;
|
||||
}
|
||||
|
||||
// get register dumps
|
||||
uint8_t* regPool = e->disCont[BEEPER].dispatch->getRegisterPool();
|
||||
int chipClock = e->disCont[BEEPER].dispatch->chipClock;
|
||||
freq = (int)(regPool[0]|(regPool[1]<<8));
|
||||
if (freq > 0) freq = chipClock/freq;
|
||||
|
||||
// write wait
|
||||
tickCount++;
|
||||
int totalWait=e->cycles;
|
||||
if (totalWait>0 && !done) {
|
||||
while (totalWait) {
|
||||
wait_tempo++;
|
||||
if (freq != oldFreq || wait_tempo == 65535) {
|
||||
if (grubExportBin) {
|
||||
w->writeS(oldFreq); // pitch
|
||||
w->writeS(wait_tempo); // duration
|
||||
} else {
|
||||
w->writeText(fmt::sprintf(" %d %d", oldFreq, wait_tempo));
|
||||
}
|
||||
oldFreq = freq;
|
||||
wait_tempo = 0;
|
||||
}
|
||||
totalWait--;
|
||||
tickCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!grubExportBin) w->writeText(fmt::sprintf("\n")); // end song
|
||||
// end of song
|
||||
|
||||
// done - close out.
|
||||
e->got.rate=origRate;
|
||||
e->disCont[BEEPER].dispatch->getRegisterWrites().clear();
|
||||
e->disCont[BEEPER].dispatch->toggleRegisterDump(false);
|
||||
|
||||
e->remainingLoops=-1;
|
||||
e->playing=false;
|
||||
e->freelance=false;
|
||||
e->extValuePresent=false;
|
||||
|
||||
output.push_back(DivROMExportOutput(grubExportBin?"export.bin":"export.txt",w));
|
||||
});
|
||||
|
||||
|
||||
progress[0].amount=1.0f;
|
||||
|
||||
logAppend("finished!");
|
||||
|
||||
running=false;
|
||||
}
|
||||
|
||||
bool DivExportGRUB::go(DivEngine* eng) {
|
||||
progress[0].name="Progress";
|
||||
progress[0].amount=0.0f;
|
||||
|
||||
e=eng;
|
||||
running=true;
|
||||
failed=false;
|
||||
mustAbort=false;
|
||||
exportThread=new std::thread(&DivExportGRUB::run,this);
|
||||
return true;
|
||||
}
|
||||
|
||||
void DivExportGRUB::wait() {
|
||||
if (exportThread!=NULL) {
|
||||
logV("waiting for export thread...");
|
||||
exportThread->join();
|
||||
delete exportThread;
|
||||
}
|
||||
}
|
||||
|
||||
void DivExportGRUB::abort() {
|
||||
mustAbort=true;
|
||||
wait();
|
||||
}
|
||||
|
||||
bool DivExportGRUB::isRunning() {
|
||||
return running;
|
||||
}
|
||||
|
||||
bool DivExportGRUB::hasFailed() {
|
||||
return failed;
|
||||
}
|
||||
|
||||
DivROMExportProgress DivExportGRUB::getProgress(int index) {
|
||||
if (index<0 || index>1) return progress[1];
|
||||
return progress[index];
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue