diff options
Diffstat (limited to 'tfmx')
-rw-r--r-- | tfmx/module.mk | 8 | ||||
-rw-r--r-- | tfmx/tfmxdebug.cpp | 200 | ||||
-rw-r--r-- | tfmx/tfmxdebug.h | 14 | ||||
-rw-r--r-- | tfmx/tfmxplayer.cpp | 170 |
4 files changed, 392 insertions, 0 deletions
diff --git a/tfmx/module.mk b/tfmx/module.mk new file mode 100644 index 0000000000..41d114bfb0 --- /dev/null +++ b/tfmx/module.mk @@ -0,0 +1,8 @@ +MODULE := tfmx + +MODULE_OBJS := \ + tfmxplayer.o \ + tfmxdebug.o + +# Include common rules +include $(srcdir)/rules.mk diff --git a/tfmx/tfmxdebug.cpp b/tfmx/tfmxdebug.cpp new file mode 100644 index 0000000000..95bad15a96 --- /dev/null +++ b/tfmx/tfmxdebug.cpp @@ -0,0 +1,200 @@ +#include "common/scummsys.h" +#include "common/endian.h" +#include "common/debug.h" +#include "common/stream.h" +#include "common/util.h" + +#include "sound/mods/tfmx.h" + +#include "tfmx/tfmxdebug.h" + + +const char *pattcmds[]={ + "End --Next track step--", + "Loop[count / step.w]", + "Cont[patternno./ step.w]", + "Wait[count 00-FF--------", + "Stop--Stop this pattern-", + "Kup^-Set key up/channel]", + "Vibr[speed / rate.b]", + "Enve[speed /endvolume.b]", + "GsPt[patternno./ step.w]", + "RoPt-Return old pattern-", + "Fade[speed /endvolume.b]", + "PPat[patt./track+transp]", + "Lock---------ch./time.b]", + "Cue [number.b/ value.w]", + "Stop-Stop custompattern-", + "NOP!-no operation-------" +}; + +const char *macrocmds[]={ + "DMAoff+Resetxx/xx/xx flag/addset/vol ", + "DMAon (start sample at selected begin) ", + "SetBegin xxxxxx sample-startadress", + "SetLen ..xxxx sample-length ", + "Wait ..xxxx count (VBI''s) ", + "Loop xx/xxxx count/step ", + "Cont xx/xxxx macro-number/step ", + "-------------STOP----------------------", + "AddNote xx/xxxx note/detune ", + "SetNote xx/xxxx note/detune ", + "Reset Vibrato-Portamento-Envelope ", + "Portamento xx/../xx count/speed ", + "Vibrato xx/../xx speed/intensity ", + "AddVolume ....xx volume 00-3F ", + "SetVolume ....xx volume 00-3F ", + "Envelope xx/xx/xx speed/count/endvol", + "Loop key up xx/xxxx count/step ", + "AddBegin xx/xxxx count/add to start", + "AddLen ..xxxx add to sample-len ", + "DMAoff stop sample but no clear ", + "Wait key up ....xx count (VBI''s) ", + "Go submacro xx/xxxx macro-number/step ", + "--------Return to old macro------------", + "Setperiod ..xxxx DMA period ", + "Sampleloop ..xxxx relative adress ", + "-------Set one shot sample-------------", + "Wait on DMA ..xxxx count (Wavecycles)", + "Random play xx/xx/xx macro/speed/mode ", + "Splitkey xx/xxxx key/macrostep ", + "Splitvolume xx/xxxx volume/macrostep ", + "Addvol+note xx/fe/xx note/CONST./volume", + "SetPrevNote xx/xxxx note/detune ", + "Signal xx/xxxx signalnumber/value", + "Play macro xx/.x/xx macro/chan/detune ", + "SID setbeg xxxxxx sample-startadress", + "SID setlen xx/xxxx buflen/sourcelen ", + "SID op3 ofs xxxxxx offset ", + "SID op3 frq xx/xxxx speed/amplitude ", + "SID op2 ofs xxxxxx offset ", + "SID op2 frq xx/xxxx speed/amplitude ", + "SID op1 xx/xx/xx speed/amplitude/TC", + "SID stop xx.... flag (1=clear all)" +}; + +const char *const trackstepFmt[] = { + "---Stop Player----", + "Loop step/count ", + "Tempo tempo/ciaDiv", + "Timeshare ?/? ", + "Fade start/end " +}; + +void displayPatternstep(const void *const vptr) { + const byte *const patData = (const byte *const)vptr; + + const byte command = patData[0]; + + if (command < 0xF0) { // Playnote + const byte flags = command >> 6; // 0-1 means note+detune, 2 means wait, 3 means portamento? + char *flagsSt[] = {"Note ", "Note ", "Wait ", "Porta"}; + debug("%s %02X%02X%02X%02X", flagsSt[flags], patData[0], patData[1], patData[2], patData[3]); + } else { + debug("%s %02X%02X%02X",pattcmds[command&0xF], patData[1], patData[2], patData[3]); + } + +} + +void displayTrackstep(const void *const vptr) { + const uint16 *const trackData = (const uint16 *const)vptr; + + if (trackData[0] == FROM_BE_16(0xEFFE)) { + // 16 byte Trackstep Command + const uint16 command = READ_BE_UINT16(&trackData[1]); + const uint16 param1 = READ_BE_UINT16(&trackData[2]); + const uint16 param2 = READ_BE_UINT16(&trackData[3]); + + + if (command >= ARRAYSIZE(trackstepFmt)) + debug("Unknown (%04X) : %04X %04X", command, param1, param2); + else + debug("%s: %04X %04X", trackstepFmt[command], param1, param2); + } else { + const byte *const ptr = (const byte *const)vptr; + // 8 commands for Patterns + debug("%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X", + ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6], ptr[7], + ptr[8], ptr[9], ptr[10], ptr[11], ptr[12], ptr[13], ptr[14], ptr[15]); + } +} + +void displayMacroStep(const void *const vptr, int chan, int index) { + const byte *const macroData = (const byte *const)vptr; + + if (macroData[0] < ARRAYSIZE(macrocmds)) + debug("%02X %02X %s %02X%02X%02X", chan, index, macrocmds[macroData[0]], macroData[1], macroData[2], macroData[3]); + else + debug("%02X %02X Unkown Macro #%02X %02X%02X%02X", chan, index, macroData[0], macroData[1], macroData[2], macroData[3]); +} + +void displayMacroStep(const void *const vptr) { + const byte *const macroData = (const byte *const)vptr; + + if (macroData[0] < ARRAYSIZE(macrocmds)) + debug("%s %02X%02X%02X", macrocmds[macroData[0]], macroData[1], macroData[2], macroData[3]); + else + debug("Unkown Macro #%02X %02X%02X%02X", macroData[0], macroData[1], macroData[2], macroData[3]); +} + +void dumpTracksteps(Audio::Tfmx &player, uint16 first, uint16 last) { + for ( ; first <= last; ++first) { + displayTrackstep(player._resource.getTrackPtr(first)); + } +} + +void dumpTrackstepsBySong(Audio::Tfmx &player, int song) { + debug("Song %02X: Pos %02X - %02X. Tempo: %02X", song, player._subsong[song].songstart, player._subsong[song].songend, player._subsong[song].tempo); + dumpTracksteps(player, player._subsong[song].songstart, player._subsong[song].songend); + debug(""); +} + +void dumpMacro(Audio::Tfmx &player, uint16 macroIndex, uint16 len, uint16 start) { + const uint32 * macroPtr = player._resource.getMacroPtr(player._macroOffset[macroIndex]); + bool untilMacroStop = (len == 0); + while (len--) { + displayMacroStep(macroPtr++); + } + while (untilMacroStop) { + untilMacroStop = *(const byte *)macroPtr != 7; + displayMacroStep(macroPtr++); + } +} + +void dumpPattern(Audio::Tfmx &player, uint16 pattIndex, uint16 len, uint16 start) { + const uint32 * pattPtr = player._resource.getPatternPtr(player._patternOffset[pattIndex]); + if (len == 0) + len = (player._patternOffset[pattIndex+1] - player._patternOffset[pattIndex])/4; + bool untilMacroStop = (len == 0); + while (len--) { + displayPatternstep(pattPtr++); + } + while (untilMacroStop) { + byte cmd = *(const byte *)pattPtr; + untilMacroStop = cmd != 0 && cmd != 4; + displayPatternstep(pattPtr++); + } +} + +void countAllMacros1(Audio::Tfmx &player, uint16 macroIndex, int *list) { + const uint32 * macroPtr = player._resource.getMacroPtr(player._macroOffset[macroIndex]); + bool untilMacroStop = true; + while (untilMacroStop) { + const int type = *(const byte *)macroPtr++; + untilMacroStop = type != 7; + list[type]++; + } +} + +void countAllMacros(Audio::Tfmx &player) { + int list[256] = {0}; + for (int i = 0; i < 128; ++i) + countAllMacros1(player, i, list); + byte fakeMacro[4] = {0}; + for (int i = 0; i < 256; ++i) { + fakeMacro[0] = (byte)i; + if (list[i] > 0) + displayMacroStep(fakeMacro); + } + +} diff --git a/tfmx/tfmxdebug.h b/tfmx/tfmxdebug.h new file mode 100644 index 0000000000..e849e561a9 --- /dev/null +++ b/tfmx/tfmxdebug.h @@ -0,0 +1,14 @@ +#ifndef TFMXDEBUG_H +#define TFMXDEBUG_H + +void displayTrackstep(const void *const vptr); +void displayPatternstep(const void *const vptr); +void displayMacroStep(const void *const vptr); +void displayMacroStep(const void *const vptr, int chan, int index); +void dumpTracksteps(Audio::Tfmx &player, uint16 first, uint16 last); +void dumpTrackstepsBySong(Audio::Tfmx &player, int song); +void dumpMacro(Audio::Tfmx &player, uint16 macroIndex, uint16 len = 0, uint16 start = 0); +void dumpPattern(Audio::Tfmx &player, uint16 pattIndex, uint16 len = 0, uint16 start = 0); +void countAllMacros(Audio::Tfmx &player); + +#endif // TFMXDEBUG_H
\ No newline at end of file diff --git a/tfmx/tfmxplayer.cpp b/tfmx/tfmxplayer.cpp new file mode 100644 index 0000000000..efc3ce68b1 --- /dev/null +++ b/tfmx/tfmxplayer.cpp @@ -0,0 +1,170 @@ +#include "common/scummsys.h" +#include "common/system.h" +#include "common/stream.h" +#include "common/file.h" +#include "common/fs.h" +#include "common/endian.h" +#include "common/debug.h" + +#include "sound/mixer.h" +#include "sound/mods/protracker.h" +#include "sound/mods/tfmx.h" + +#include "tfmx/tfmxdebug.h" + +#define FILEDIR "" + +using namespace Common; + +#define MUSICFILE "mdat.monkey" +#define SAMPLEFILE "smpl.monkey" + +Audio::Tfmx *loadTfmxfile(const char *mdatName, const char *sampleName) { + FSNode fileDir(FILEDIR); + FSNode musicNode = fileDir.getChild(mdatName); + FSNode sampleNode = fileDir.getChild(sampleName); + SeekableReadStream *musicIn = musicNode.createReadStream(); + if (0 == musicIn) { + debug("Couldnt load file %s", MUSICFILE); + return 0; + } + + SeekableReadStream *sampleIn = sampleNode.createReadStream(); + if (0 == sampleIn) { + debug("Couldnt load file %s", SAMPLEFILE); + delete musicIn; + return 0; + } + + Audio::Tfmx *player = new Audio::Tfmx(44100, true); + player->load(*musicIn, *sampleIn); + delete musicIn; + delete sampleIn; + + return player; +} + +void runFlac(int chan, int bits, int sr, const char *fileName); + +void tfmxmain(const int argc, const char *const argv[]) { + debug("Started Scumm&VM"); + debug("Sound celebrating utility for monkey melodies & Various Malfunctions"); + debug(""); + + //simplePlaybacktest(argc, argv); + + Audio::Tfmx *player = loadTfmxfile(MUSICFILE, SAMPLEFILE); + if (!player) { + debug("couldnt create TFMX-Player"); + return; + } + + int i = 1; + int playflag = 1; + bool hasCmd = false; + + + while (i < argc && argv[i][0] == '-') { + int param; + if (!strcmp("-m", argv[i])) { + if (i + 1 < argc) { + param = atoi(argv[++i]); + debug( "play Macro %02X", param); + dumpMacro(*player, param); + player->doMacro(0x1B, param); + hasCmd = true; + } + } else if (!strcmp("-s", argv[i])) { + if (i + 1 < argc) { + param = atoi(argv[++i]); + debug( "play Song %02X", param); + dumpTrackstepsBySong(*player, param); + player->doSong(param); + hasCmd = true; + } + } else if (!strcmp("-c", argv[i])) { + if (i + 1 < argc) { + param = atoi(argv[++i]); + debug( "play custom %02X", param); + if (player->getSongIndex() < 0) + player->doSong(0x18); + player->doSfx(param); + hasCmd = true; + } + } else if (!strcmp("-flac", argv[i])) { + playflag = 2; + } else if (!strcmp("-hack-patternstop", argv[i])) + player->_playerCtx.stopWithLastPattern = true; + ++i; + } + + if (!hasCmd) { + player->doSong(4); + dumpTrackstepsBySong(*player, 4); + } + + + + +#if 0 + int16 buf[2 * 1024]; + + while( true) + player->readBuffer(buf, ARRAYSIZE(buf)); +#endif + int maxsecs = 10 * 60; + if (playflag == 1) { + // get Mixer, assume this never fails + Audio::Mixer *mixer = g_system->getMixer(); + + Audio::SoundHandle soundH; + + mixer->playInputStream(Audio::Mixer::kMusicSoundType, &soundH, player); + while (mixer->isSoundHandleActive(soundH) && --maxsecs) + g_system->delayMillis(1000); +// player->AllOff(); + +// while (mixer->isSoundHandleActive(soundH)); + + mixer->stopHandle(soundH); + player = 0; + } + + if (playflag == 2) { + Common::FSNode file("out.raw"); + WriteStream *wav = file.createWriteStream(); + int16 buf[2 * 1024]; + int32 maxsamples = (maxsecs <= 0) ? 0 : maxsecs * 44100; + while (!player->endOfData() && maxsamples > 0) { + int read = player->readBuffer(buf, ARRAYSIZE(buf)); + wav->write(buf, read * 2); + maxsamples -= read/2; + } + delete wav; + + runFlac(2, 16, 44100, "out.raw"); + } + +#ifdef _MSC_VER + printf("\npress a key"); + getc(stdin); +#endif + + delete player; +} + +void runFlac( int chan, int bits, int sr, const char *fileName) { + const char *format = "flac --endian=" +#ifdef SCUMM_BIG_ENDIAN + "big" +#else + "little" +#endif + " --channels=%d -f --bps=%d --sample-rate=%d --sign=signed --force-raw-format %s"; + char cmd[1024]; + sprintf(cmd, format, chan, bits, sr, fileName); + debug(cmd); + system(cmd); +} + + |