8000 VGM Music Maker import by techmetx11 · Pull Request #2509 · tildearrow/furnace · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

VGM Music Maker import #2509

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 8 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -694,7 +694,9 @@ src/engine/fileOps/it.cpp
src/engine/fileOps/mod.cpp
src/engine/fileOps/s3m.cpp
src/engine/fileOps/text.cpp
src/engine/fileOps/tfmCommon.cpp
src/engine/fileOps/tfm.cpp
src/engine/fileOps/vge.cpp
src/engine/fileOps/xm.cpp

src/engine/fileOps/p.cpp
Expand Down
3 changes: 2 additions & 1 deletion src/engine/engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,7 @@ class DivEngine {
bool loadFC(unsigned char* file, size_t len);
bool loadTFMv1(unsigned char* file, size_t len);
bool loadTFMv2(unsigned char* file, size_t len);
bool loadVGE(unsigned char* file, size_t len);

void loadDMP(SafeReader& reader, std::vector<DivInstrument*>& ret, String& stripPath);
void loadTFI(SafeReader& reader, std::vector<DivInstrument*>& ret, String& stripPath);
Expand All @@ -623,7 +624,7 @@ class DivEngine {
void loadFF(SafeReader& reader, std::vector<DivInstrument*>& ret, String& stripPath);
void loadWOPL(SafeReader& reader, std::vector<DivInstrument*>& ret, String& stripPath);
void loadWOPN(SafeReader& reader, std::vector<DivInstrument*>& ret, String& stripPath);

//sample banks
void loadP(SafeReader& reader, std::vector<DivSample*>& ret, String& stripPath);
void loadPPC(SafeReader& reader, std::vector<DivSample*>& ret, String& stripPath);
Expand Down
6 changes: 4 additions & 2 deletions src/engine/fileOps/fileOpsCommon.cpp
10000
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ bool DivEngine::load(unsigned char* f, size_t slen, const char* nameHint) {

// step 2: try loading as .fur, .dmf, or another magic-ful format
if (memcmp(file,DIV_DMF_MAGIC,16)==0) {
return loadDMF(file,len);
return loadDMF(file,len);
} else if (memcmp(file,DIV_FTM_MAGIC,18)==0) {
return loadFTM(file,len,(extS==".dnm"),false,(extS==".eft"));
} else if (memcmp(file,DIV_DNM_MAGIC,21)==0) {
Expand All @@ -156,6 +156,8 @@ bool DivEngine::load(unsigned char* f, size_t slen, const char* nameHint) {
return loadTFMv2(file,len);
} else if (memcmp(file,DIV_IT_MAGIC,4)==0) {
return loadIT(file,len);
} else if (memcmp(file,DIV_VGEV3_MAGIC,7)==0) {
return loadVGE(file,len);
} else if (len>=48) {
if (memcmp(&file[0x2c],DIV_S3M_MAGIC,4)==0) {
return loadS3M(file,len);
Expand All @@ -171,7 +173,7 @@ bool DivEngine::load(unsigned char* f, size_t slen, const char* nameHint) {
delete[] f;
return true;
}

// step 4: not a valid file
logE("not a valid module!");
lastError="not a compatible song";
Expand Down
3 changes: 3 additions & 0 deletions src/engine/fileOps/fileOpsCommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ struct NotZlibException {
#define DIV_XM_MAGIC "Extended Module: "
#define DIV_IT_MAGIC "IMPM"
#define DIV_TFM_MAGIC "TFMfmtV2"
#define DIV_VGEV1_MAGIC "VGEfmtV1"
#define DIV_VGEV2_MAGIC "VGEfmtV2"
#define DIV_VGEV3_MAGIC "VGEfmtV3"

#define DIV_FUR_MAGIC_DS0 "Furnace-B module"

Expand Down
164 changes: 1 addition & 163 deletions src/engine/fileOps/tfm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,169 +17,7 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#include "fileOpsCommon.h"

class TFMRLEReader;

struct TFMEndOfFileException {
TFMRLEReader* reader;
size_t finalSize;
TFMEndOfFileException(TFMRLEReader* r, size_t fs):
reader(r),
finalSize(fs) {}
};


class TFMRLEReader {
const unsigned char* buf;
size_t len;
size_t curSeek;
bool inTag;
int tagLenLeft;
signed char tagChar;

void decodeRLE(unsigned char prevChar) {
int lenShift=0;
tagLenLeft=0;
unsigned char rleTag=0;

do {
rleTag=readCNoRLE();
tagLenLeft|=(rleTag&0x7F)<<lenShift;
lenShift+=7;
//logD("offset: %x, RLE tag: %X, len shift: %d, len left: %d",curSeek,rleTag,lenShift,tagLenLeft);
} while (!(rleTag&0x80));

if (tagLenLeft) {
// sync back since we've already read one character
inTag=true;
tagLenLeft--;
tagChar=prevChar;
} else {
tagChar=0x80;
}
//logD("tag finished: len left: %d, char: %X",tagLenLeft,tagChar);
}

public:
TFMRLEReader(const void* b, size_t l) :
buf((const unsigned char*)b),
len(l),
curSeek(0),
inTag(false),
tagLenLeft(0),
tagChar(0) {}

// these functions may throw TFMEndOfFileException
unsigned char readC() {
if (inTag) {
if (tagLenLeft<=0) {
inTag=false;
return readC();
}
tagLenLeft--;
//logD("one char RLE decompressed, tag left: %d, char: %d",tagLenLeft,tagChar);
return tagChar;
}
if (curSeek>len) throw TFMEndOfFileException(this,len);

unsigned char ret=buf[curSeek++];

// MISLEADING DOCUMENTATION: while TFM music maker's documentation says if the next byte
// is zero, then it's not a tag but just 0x80 (for example: 0x00 0x80 0x00 = 0x00 0x80)
// this is actually wrong
// through research and experimentation, there are times that TFM music maker
// will use 0x80 0x00 for actual tags (for example: 0x00 0x80 0x00 0x84 = 512 times 0x00
// in certain parts of the header and footer)
// TFM music maker actually uses double 0x80 to escape the 0x80
// for example: 0xDA 0x80 0x80 0x00 0x23 = 0xDA 0x80 0x00 0x23)
if (ret==0x80) {
decodeRLE(buf[curSeek-2]);
tagLenLeft--;
return tagChar;
}
return ret;
}

signed char readCNoRLE() {
if (curSeek>len) throw TFMEndOfFileException(this,len);
return buf[curSeek++];
}

void read(unsigned char* b, size_t l) {
int i=0;
while(l--) {
unsigned char nextChar=readC();
b[i++]=nextChar;
//logD("read next char: %x, index: %d",nextChar,i);
}
}

void readNoRLE(unsigned char *b, size_t l) {
int i=0;
while (l--) {
b[i++]=buf[curSeek++];
if (curSeek>len) throw TFMEndOfFileException(this,len);
}
}

short readS() {
return readC()|readC()<<8;
}

short readSNoRLE() {
if (curSeek+2>len) throw TFMEndOfFileException(this,len);
short ret=buf[curSeek]|buf[curSeek+1]<<8;
curSeek+=2;
return ret;
}

String readString(size_t l) {
String ret;
ret.reserve(l);
while (l--) {
unsigned char byte=readC();
if (!byte) {
skip(l);
break;
}
ret += byte;
}
return ret;
}
void skip(size_t l) {
// quick and dirty
while (l--) {
//logD("skipping l %d",l);
readC();
}
}

};

String TFMparseDate(short date) {
return fmt::sprintf("%02d.%02d.%02d",date>>11,(date>>7)&0xF,date&0x7F);
}

struct TFMSpeed {
unsigned char speedEven;
unsigned char speedOdd;
unsigned char interleaveFactor;

bool operator==(const TFMSpeed &s) const {
return speedEven==s.speedEven && speedOdd==s.speedOdd && interleaveFactor==s.interleaveFactor;
}
};

// to make it work with map
namespace std {
template<> struct hash<TFMSpeed>
{
size_t operator()(const TFMSpeed& s) const noexcept {
return s.speedEven<<16|s.speedOdd<<8|s.interleaveFactor;
}
};
}
#include "tfmCommon.h"

struct TFMParsePatternInfo {
TFMRLEReader* reader;
Expand Down
24 changes: 24 additions & 0 deletions src/engine/fileOps/tfmCommon.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* 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 "tfmCommon.h"

String TFMparseDate(short date) {
return fmt::sprintf("%02d.%02d.%02d",date>>11,(date>>7)&0xF,date&0x7F);
}
Loading
Loading
0