S3M import: we load samples
This commit is contained in:
		
							parent
							
								
									b9e14e8b1f
								
							
						
					
					
						commit
						7ffbaf65b7
					
				|  | @ -139,7 +139,7 @@ bool DivEngine::load(unsigned char* f, size_t slen, const char* nameHint) { | |||
|     len=slen; | ||||
|   } | ||||
| 
 | ||||
|   // step 2: try loading as .fur or .dmf
 | ||||
|   // step 2: try loading as .fur, .dmf, or another magic-ful format
 | ||||
|   if (memcmp(file,DIV_DMF_MAGIC,16)==0) { | ||||
|     return loadDMF(file,len);  | ||||
|   } else if (memcmp(file,DIV_FTM_MAGIC,18)==0) { | ||||
|  | @ -154,6 +154,10 @@ bool DivEngine::load(unsigned char* f, size_t slen, const char* nameHint) { | |||
|     return loadFC(file,len); | ||||
|   } else if (memcmp(file,DIV_TFM_MAGIC,8)==0) { | ||||
|     return loadTFMv2(file,len); | ||||
|   } else if (len>=48) { | ||||
|     if (memcmp(&file[0x2c],DIV_S3M_MAGIC,4)==0) { | ||||
|       return loadS3M(file,len); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   // step 3: try loading as .mod or TFEv1 (if the file extension matches)
 | ||||
|  |  | |||
|  | @ -28,8 +28,8 @@ bool DivEngine::loadS3M(unsigned char* file, size_t len) { | |||
| 
 | ||||
|   unsigned char chanSettings[32]; | ||||
|   unsigned char ord[256]; | ||||
|   unsigned short insPtr[256]; | ||||
|   unsigned short patPtr[256]; | ||||
|   unsigned int insPtr[256]; | ||||
|   unsigned int patPtr[256]; | ||||
|   unsigned char chanPan[16]; | ||||
|   unsigned char defVol[256]; | ||||
| 
 | ||||
|  | @ -42,6 +42,8 @@ bool DivEngine::loadS3M(unsigned char* file, size_t len) { | |||
|     ds.rowResetsArpPos=true; | ||||
|     ds.ignoreJumpAtEnd=false; | ||||
| 
 | ||||
|     logV("Scream Tracker 3 module"); | ||||
| 
 | ||||
|     // load here
 | ||||
|     if (!reader.seek(0x2c,SEEK_SET)) { | ||||
|       logE("premature end of file!"); | ||||
|  | @ -74,6 +76,9 @@ bool DivEngine::loadS3M(unsigned char* file, size_t len) { | |||
|     unsigned short ordersLen=reader.readS(); | ||||
|     ds.insLen=reader.readS(); | ||||
| 
 | ||||
|     logV("orders: %d",ordersLen); | ||||
|     logV("instruments: %d",ds.insLen); | ||||
| 
 | ||||
|     if (ds.insLen<0 || ds.insLen>256) { | ||||
|       logE("invalid instrument count!"); | ||||
|       lastError="invalid instrument count!"; | ||||
|  | @ -83,10 +88,20 @@ bool DivEngine::loadS3M(unsigned char* file, size_t len) { | |||
| 
 | ||||
|     unsigned short patCount=reader.readS(); | ||||
| 
 | ||||
|     logV("patterns: %d",patCount); | ||||
| 
 | ||||
|     unsigned short flags=reader.readS(); | ||||
|     unsigned short version=reader.readS(); | ||||
|     bool signedSamples=(reader.readS()==1); | ||||
| 
 | ||||
|     logV("flags: %x",flags); | ||||
|     logV("version: %x",flags); | ||||
|     if (signedSamples) { | ||||
|       logV("signed samples: yes"); | ||||
|     } else { | ||||
|       logV("signed samples: no"); | ||||
|     } | ||||
| 
 | ||||
|     if ((flags&64) || version==0x1300) { | ||||
|       ds.noSlidesOnFirstTick=false; | ||||
|     } | ||||
|  | @ -96,6 +111,7 @@ bool DivEngine::loadS3M(unsigned char* file, size_t len) { | |||
|     unsigned char globalVol=reader.readC(); | ||||
| 
 | ||||
|     ds.subsong[0]->speeds.val[0]=(unsigned char)reader.readC(); | ||||
|     ds.subsong[0]->speeds.len=1; | ||||
|     ds.subsong[0]->hz=((double)reader.readC())/2.5; | ||||
| 
 | ||||
|     unsigned char masterVol=reader.readC(); | ||||
|  | @ -105,7 +121,9 @@ bool DivEngine::loadS3M(unsigned char* file, size_t len) { | |||
|     logV("globalVol: %d",globalVol); | ||||
| 
 | ||||
|     reader.readC(); // UC
 | ||||
|     bool defaultPan=(((unsigned char)reader.readC())==252); | ||||
|     unsigned char defaultPan=(unsigned char)reader.readC(); | ||||
| 
 | ||||
|     logV("defaultPan: %d",defaultPan); | ||||
| 
 | ||||
|     reader.readS(); // reserved
 | ||||
|     reader.readI(); | ||||
|  | @ -113,6 +131,11 @@ bool DivEngine::loadS3M(unsigned char* file, size_t len) { | |||
| 
 | ||||
|     reader.read(chanSettings,32); | ||||
| 
 | ||||
|     logD("channel settings:"); | ||||
|     for (int i=0; i<32; i++) { | ||||
|       logV("%d. %x",i,chanSettings[i]); | ||||
|     } | ||||
| 
 | ||||
|     logD("reading orders..."); | ||||
|     for (int i=0; i<ordersLen; i++) { | ||||
|       ord[i]=reader.readC(); | ||||
|  | @ -123,19 +146,21 @@ bool DivEngine::loadS3M(unsigned char* file, size_t len) { | |||
| 
 | ||||
|     logD("reading ins pointers..."); | ||||
|     for (int i=0; i<ds.insLen; i++) { | ||||
|       insPtr[i]=reader.readS(); | ||||
|       insPtr[i]=reader.readS()*16; | ||||
|       logV("- %.2x",insPtr[i]); | ||||
|     } | ||||
| 
 | ||||
|     logD("reading pat pointers..."); | ||||
|     for (int i=0; i<patCount; i++) { | ||||
|       patPtr[i]=reader.readS(); | ||||
|       patPtr[i]=reader.readS()*16; | ||||
|       logV("- %.2x",patPtr[i]); | ||||
|     } | ||||
| 
 | ||||
|     if (defaultPan) { | ||||
|     if (defaultPan==252) { | ||||
|       logV("reading channel panning settings"); | ||||
|       reader.read(chanPan,16); | ||||
|     } else { | ||||
|       logV("default channel pan"); | ||||
|       memset(chanPan,0,16); | ||||
|     } | ||||
| 
 | ||||
|  | @ -146,7 +171,7 @@ bool DivEngine::loadS3M(unsigned char* file, size_t len) { | |||
|     bool hasFM=false; | ||||
| 
 | ||||
|     for (int i=0; i<32; i++) { | ||||
|       if (!(chanSettings[i]&128)) continue; | ||||
|       if (chanSettings[i]==255) continue; | ||||
|       if ((chanSettings[i]&127)>=32) continue; | ||||
|       if ((chanSettings[i]&127)>=16) { | ||||
|         hasFM=true; | ||||
|  | @ -174,8 +199,9 @@ bool DivEngine::loadS3M(unsigned char* file, size_t len) { | |||
|     // load instruments/samples
 | ||||
|     ds.ins.reserve(ds.insLen); | ||||
|     for (int i=0; i<ds.insLen; i++) { | ||||
|       logV("reading instrument %d...",i); | ||||
|       DivInstrument* ins=new DivInstrument; | ||||
|       if (!reader.seek(0x4c+insPtr[i]*16,SEEK_SET)) { | ||||
|       if (!reader.seek(insPtr[i]+0x4c,SEEK_SET)) { | ||||
|         logE("premature end of file!"); | ||||
|         lastError="incomplete file"; | ||||
|         delete ins; | ||||
|  | @ -195,7 +221,7 @@ bool DivEngine::loadS3M(unsigned char* file, size_t len) { | |||
|         continue; | ||||
|       } | ||||
| 
 | ||||
|       if (!reader.seek(insPtr[i]*16,SEEK_SET)) { | ||||
|       if (!reader.seek(insPtr[i],SEEK_SET)) { | ||||
|         logE("premature end of file!"); | ||||
|         lastError="incomplete file"; | ||||
|         delete ins; | ||||
|  | @ -210,10 +236,14 @@ bool DivEngine::loadS3M(unsigned char* file, size_t len) { | |||
|         memSeg=(unsigned char)reader.readC(); | ||||
|         memSeg|=((unsigned short)reader.readS())<<8; | ||||
| 
 | ||||
|         logV("memSeg: %d",memSeg); | ||||
|         memSeg>>=4; // ???
 | ||||
| 
 | ||||
|         logV("memSeg: %x",memSeg); | ||||
| 
 | ||||
|         unsigned int length=reader.readI(); | ||||
| 
 | ||||
|         logV("length: %x",length); | ||||
| 
 | ||||
|         DivSample* s=new DivSample; | ||||
|         s->depth=DIV_SAMPLE_DEPTH_8BIT; | ||||
|         s->init(length); | ||||
|  | @ -225,13 +255,81 @@ bool DivEngine::loadS3M(unsigned char* file, size_t len) { | |||
|         logV("defVol: %d",defVol[i]); | ||||
| 
 | ||||
|         reader.readC(); // x
 | ||||
| 
 | ||||
|         bool isPacked=reader.readC(); | ||||
|         unsigned char flags=reader.readC(); | ||||
| 
 | ||||
|         s->centerRate=reader.readI(); | ||||
| 
 | ||||
|         // reserved
 | ||||
|         reader.readI(); // x
 | ||||
|         reader.readI(); | ||||
|         reader.readI(); | ||||
| 
 | ||||
|         String name=reader.readString(28); | ||||
|         s->name=name; | ||||
|         ins->name=name; | ||||
| 
 | ||||
|         // "SCRS"
 | ||||
|         reader.readI(); | ||||
| 
 | ||||
|         // read sample data
 | ||||
|         if (!reader.seek(memSeg,SEEK_SET)) { | ||||
|           logE("premature end of file!"); | ||||
|           lastError="incomplete file"; | ||||
|           delete ins; | ||||
|           delete s; | ||||
|           delete[] file; | ||||
|           return false; | ||||
|         } | ||||
| 
 | ||||
|         s->loop=flags&1; | ||||
|         s->depth=(flags&4)?DIV_SAMPLE_DEPTH_16BIT:DIV_SAMPLE_DEPTH_8BIT; | ||||
|         s->init(length>>(s->depth==DIV_SAMPLE_DEPTH_16BIT?1:0)); | ||||
| 
 | ||||
|         if (flags&2) { | ||||
|           logE("stereo sample!"); | ||||
|           lastError="stereo sample"; | ||||
|           delete ins; | ||||
|           delete s; | ||||
|           delete[] file; | ||||
|           return false; | ||||
|         } | ||||
| 
 | ||||
|         if (isPacked) { | ||||
|           logE("ADPCM not supported!"); | ||||
|           lastError="ADPCM sample"; | ||||
|           delete ins; | ||||
|           delete s; | ||||
|           delete[] file; | ||||
|           return false; | ||||
|         } | ||||
| 
 | ||||
|         reader.read(s->getCurBuf(),length); | ||||
| 
 | ||||
|         if (!signedSamples) { | ||||
|           if (s->depth==DIV_SAMPLE_DEPTH_16BIT) { | ||||
|             for (unsigned int i=0; i<s->samples; i++) { | ||||
|               s->data16[i]^=0x8000; | ||||
|             } | ||||
|           } else { | ||||
|             for (unsigned int i=0; i<s->samples; i++) { | ||||
|               s->data8[i]^=0x80; | ||||
|             } | ||||
|           } | ||||
|         } | ||||
| 
 | ||||
|         ins->amiga.initSample=ds.sample.size(); | ||||
|         ds.sample.push_back(s); | ||||
|       } else { | ||||
|          | ||||
|         // TODO: OPL
 | ||||
|       } | ||||
| 
 | ||||
|       ds.ins.push_back(ins); | ||||
|     } | ||||
| 
 | ||||
|     ds.sampleLen=ds.sample.size(); | ||||
| 
 | ||||
|     if (active) quitDispatch(); | ||||
|     BUSY_BEGIN_SOFT; | ||||
|     saveLock.lock(); | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 tildearrow
						tildearrow