258 lines · 5.3 KB · C
RawDownload
/* DIGI Booster (non-Pro) module loader**** Note: Data sanitation is done in the last stage** of module loading, so you don't need to do that here.*/ #include <stdio.h>#include <stdint.h>#include <stdbool.h>#include "../ft2_header.h"#include "../ft2_module_loader.h"#include "../ft2_sample_ed.h"#include "../ft2_tables.h"#include "../ft2_sysreqs.h" #ifdef _MSC_VER  // please don't mess with this struct!#pragma pack(push)#pragma pack(1)#endiftypedef struct digiHdr_t{	char ID[20];	char verStr[4];	uint8_t version;	uint8_t numChannels;	uint8_t packedPatternsFlag;	char reserved[19];	uint8_t numPatterns;	uint8_t numOrders;	uint8_t orders[128];	uint32_t smpLength[31];	uint32_t smpLoopStart[31];	uint32_t smpLoopLength[31];	uint8_t smpVolume[31];	uint8_t smpFinetune[31];	char name[32];	char smpName[31][30];}#ifdef __GNUC____attribute__ ((packed))#endifdigiHdr_t;#ifdef _MSC_VER#pragma pack(pop)#endif static void readPatternNote(FILE *f, note_t *p); bool loadDIGI(FILE *f, uint32_t filesize){	int16_t i, j, k;	sample_t *s;	digiHdr_t hdr; 	tmpLinearPeriodsFlag = false; // use Amiga periods 	if (filesize < sizeof (hdr))	{		loaderMsgBox("Error: This file is either not a module, or is not supported.");		return false;	} 	memset(&hdr, 0, sizeof (hdr));	if (fread(&hdr, 1, sizeof (hdr), f) != sizeof (hdr))	{		loaderMsgBox("Error: This file is either not a module, or is not supported.");		return false;	} 	if (hdr.numChannels < 1 || hdr.numChannels > 8)	{		loaderMsgBox("Error: This file is either not a module, or is not supported.");		return false;	} 	hdr.numOrders++;	hdr.numPatterns++; 	if (hdr.numOrders < 1 || hdr.numOrders > 128)	{		loaderMsgBox("Error: This file is either not a module, or is not supported.");		return false;	} 	memcpy(songTmp.orders, hdr.orders, 128);	memcpy(songTmp.name, hdr.name, 20);	songTmp.numChannels = hdr.numChannels;	songTmp.songLength = hdr.numOrders;	songTmp.BPM = 125;	songTmp.speed = 6; 	// load pattern data	for (i = 0; i < hdr.numPatterns; i++)	{		if (!allocateTmpPatt(i, 64))		{			loaderMsgBox("Not enough memory!");			return false;		} 		if (hdr.packedPatternsFlag)		{			uint16_t pattSize;			uint8_t bitMasks[64]; 			fread(&pattSize, 2, 1, f); pattSize = SWAP16(pattSize);			fread(bitMasks, 1, 64, f); 			for (j = 0; j < 64; j++)			{				uint8_t bit = 128;				for (k = 0; k < songTmp.numChannels; k++, bit >>= 1)				{					note_t *p = &patternTmp[i][(j * MAX_CHANNELS) + k];					if (bitMasks[j] & bit)						readPatternNote(f, p);				}			}		}		else		{			for (j = 0; j < songTmp.numChannels; j++)			{				for (k = 0; k < 64; k++)					readPatternNote(f, &patternTmp[i][(k * MAX_CHANNELS) + j]);			}		} 		if (tmpPatternEmpty(i))		{			if (patternTmp[i] != NULL)			{				free(patternTmp[i]);				patternTmp[i] = NULL;			}		}	} 	// pattern command handling	for (i = 0; i < hdr.numPatterns; i++)	{		if (patternTmp[i] == NULL)			continue; 		for (j = 0; j < 64; j++)		{			for (k = 0; k < songTmp.numChannels; k++)			{				note_t *p = &patternTmp[i][(j * MAX_CHANNELS) + k]; 				if (p->efx == 0x8) // Robot effect (not supported)				{					p->efx = 0;					p->efxData = 0;				}				else if (p->efx == 0xE)				{					switch (p->efxData >> 4)					{						case 0x3: p->efx = p->efxData = 0;    break; // backwards play (not supported)						case 0x4:          p->efxData = 0xC0; break; // stop sample (convert to EC0)						case 0x8: p->efx = p->efxData = 0;    break; // high sample offset (not supported)						case 0x9: p->efx = p->efxData = 0;    break; // retrace (not supported)						default: break;					}				}			}		}	} 	// load sample data	for (i = 0; i < 31; i++)	{		memcpy(songTmp.instrName[1+i], hdr.smpName[i], 22);		if (hdr.smpLength[i] == 0)			continue; 		if (!allocateTmpInstr(1+i))		{			loaderMsgBox("Not enough memory!");			return false;		} 		setNoEnvelope(instrTmp[1+i]); 		s = &instrTmp[1+i]->smp[0];		memcpy(s->name, hdr.smpName[i], 22); 		s->length = SWAP32(hdr.smpLength[i]);		s->finetune = FINETUNE_MOD2XM(hdr.smpFinetune[i]);		s->volume = hdr.smpVolume[i];		s->loopStart = SWAP32(hdr.smpLoopStart[i]);		s->loopLength = SWAP32(hdr.smpLoopLength[i]); 		if (s->loopLength < 2)			s->loopLength = 2; 		// fix overflown loop		if (s->loopStart+s->loopLength > s->length)		{			if (s->loopStart >= s->length)			{				s->loopStart = 0;				s->loopLength = 0;			}			else			{				s->loopLength = s->length - s->loopStart;			}		} 		if (s->loopStart+s->loopLength > 2)		{			s->flags |= LOOP_FWD; // enable loop		}		else		{			s->loopStart = 0;			s->loopLength = 0;		} 		if (!allocateSmpData(s, s->length, false))		{			loaderMsgBox("Not enough memory!");			return false;		} 		int32_t bytesRead = (int32_t)fread(s->dataPtr, 1, s->length, f);		if (bytesRead < s->length)		{			int32_t bytesToClear = s->length - bytesRead;			memset(&s->dataPtr[bytesRead], 0, bytesToClear);		}	} 	return true;} static void readPatternNote(FILE *f, note_t *p){	uint8_t bytes[4];	fread(bytes, 1, 4, f); 	// period to note	uint16_t period = ((bytes[0] & 0x0F) << 8) | bytes[1];	for (uint8_t i = 0; i < 3*12; i++)	{		if (period >= ptPeriods[i])		{			p->note = 1 + (3*12) + i;			break;		}	} 	p->instr = (bytes[0] & 0xF0) | (bytes[2] >> 4);	p->efx = bytes[2] & 0x0F;	p->efxData = bytes[3];}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t