Example #1
1
int load_wav (
FIL *fp,			/* Pointer to the open file object to play */
const char *title,	/* Title (file name, etc...) */
void *work,			/* Pointer to working buffer (must be-4 byte aligned) */
UINT sz_work		/* Size of working buffer (must be power of 2) */
)
{
	UINT md, wi, br, tc, t, btr;
	DWORD sz, ssz, offw, szwav, wsmp, fsmp, eof;
	WAVFIFO fcb;
	BYTE k, *buff = work;
	char *p, nam[NBSIZE], art[NBSIZE];


	//xprintf(PSTR("%s\n"), title);	/* Put title */

	/* Is it a WAV file? */
	if (f_read(fp, buff, 12, &br) || br != 12) return -1;
	if (LD_DWORD(&buff[0]) != FCC('R','I','F','F')) return -1;
	if (LD_DWORD(&buff[8]) != FCC('W','A','V','E')) return -1;
	eof = LD_DWORD(&buff[4]) + 8;

	/* Analyze the RIFF-WAVE header and get properties */
	nam[0] = art[0] = 0;
	md = fsmp = wsmp = offw = szwav = 0;
	while (f_tell(fp) < eof) {
		if (f_read(fp, buff, 8, &br) || br != 8) return -1;
		sz = (LD_DWORD(&buff[4]) + 1) & ~1;
		switch (LD_DWORD(&buff[0])) {
			case FCC('f','m','t',' ') :
			if (sz > 1000 || sz < 16 || f_read(fp, buff, sz, &br) || sz != br) return -1;
			if (LD_WORD(&buff[0]) != 0x1) return -1;	/* Check if LPCM */
			if (LD_WORD(&buff[2]) == 2) {	/* Channels (1 or 2) */
				md = 1; wsmp = 2;
				} else {
				md = 0; wsmp = 1;
			}
			if (LD_WORD(&buff[14]) == 16) {	/* Resolution (8 or 16) */
				md |= 2; wsmp *= 2;
			}
			fsmp = LD_DWORD(&buff[4]);		/* Sampling rate */
			break;

			case FCC('f','a','c','t') :
			f_lseek(fp, f_tell(fp) + sz);
			break;

			case FCC('d','a','t','a') :
			offw = f_tell(fp);	/* Wave data start offset */
			szwav = sz;			/* Wave data length [byte] */
			f_lseek(fp, f_tell(fp) + sz);
			break;

			case FCC('L','I','S','T'):
			sz += f_tell(fp);
			if (f_read(fp, buff, 4, &br) || br != 4) return -1;
			if (LD_DWORD(buff) == FCC('I','N','F','O')) {	/* LIST/INFO chunk */
				while (f_tell(fp) < sz) {
					if (f_read(fp, buff, 8, &br) || br != 8) return -1;
					ssz = (LD_DWORD(&buff[4]) + 1) & ~1;
					p = 0;
					switch (LD_DWORD(buff)) {
						case FCC('I','N','A','M'):		/* INAM sub-chunk */
						p = nam; break;
						case FCC('I','A','R','T'):		/* IART sub-cnunk */
						p = art; break;
					}
					if (p && ssz <= NBSIZE) {
						if (f_read(fp, p, ssz, &br) || br != ssz) return -1;
						} else {
						if (f_lseek(fp, f_tell(fp) + ssz)) return -1;
					}
				}
				} else {
				if (f_lseek(fp, sz)) return -1;	/* Skip unknown sub-chunk type */
			}
			break;

			default :	/* Unknown chunk */
			return -1;
		}
	}
	if (!szwav || !fsmp) return -1;		/* Check if valid WAV file */
	if (f_lseek(fp, offw)) return -1;	/* Seek to top of wav data */
	tc = (UINT)(szwav / fsmp / wsmp);	/* Length (sec) */

	//xprintf(PSTR("IART=%s\nINAM=%s\n"), art, nam);
	//xprintf(PSTR("Sample=%u.%ukHz/%ubit/%S\nLength=%u:%02u\n"), (UINT)(fsmp / 1000), (UINT)(fsmp / 100) % 10, (md & 2) ? 16 : 8, (md & 1) ? PSTR("st") : PSTR("mo"), tc / 60, tc % 60);

	/* Initialize stream parameters and start sound streming */
	fcb.mode = md;
	fcb.buff = buff;
	fcb.sz_buff = sz_work;
	if (!sound_start(&fcb, fsmp)) return -1;

	k = 0; wi = 0;
	while (szwav || fcb.ct >= 4) {
		if (szwav && fcb.ct <= sz_work / 2) {	/* Refill FIFO when it gets half empty */
			btr = (szwav >= sz_work / 2) ? sz_work / 2 : szwav;
			f_read(fp, &buff[wi], btr, &br);
			if (br != btr) break;
			szwav -= br;
			wi = (wi + br) & (sz_work - 1);
			cli();
			fcb.ct += br;
			sei();
		}
		//if (uart_test()) {		/* Exit if a command arrived */
		//	k = uart_getc();
		//	break;
		//}
		
		if (btn_check_press() == BTN2)
		{
			sound_stop();
			break;
		}
		
		t = (f_tell(fp) - offw - fcb.ct) / fsmp / wsmp;	/* Refresh time display every 1 sec */
		if (t != tc) {
			tc = t;
			//xprintf(PSTR("\rTime=%u:%02u"), tc / 60, tc % 60);
		}
	}

	sound_stop();	/* Stop sound output */

	//xputc('\n');
	return k;	/* Terminated due to -1:error, 0:eot, >0:key code */
}
Example #2
0
static
void get_fileinfo (		/* No return code */
	DIR *dj,			/* Pointer to the directory object */
	BYTE *dir,			/* 32-byte working buffer */
	FILINFO *fno	 	/* Pointer to store the file information */
)
{
	BYTE i, c;
	char *p;


	p = fno->fname;
	if (dj->sect) {
		for (i = 0; i < 8; i++) {	/* Copy file name body */
			c = dir[i];
			if (c == ' ') break;
			if (c == 0x05) c = 0xE5;
			*p++ = c;
		}
		if (dir[8] != ' ') {		/* Copy file name extension */
			*p++ = '.';
			for (i = 8; i < 11; i++) {
				c = dir[i];
				if (c == ' ') break;
				*p++ = c;
			}
		}
		fno->fattrib = dir[DIR_Attr];				/* Attribute */
		fno->fsize = LD_DWORD(dir+DIR_FileSize);	/* Size */
		fno->fdate = LD_WORD(dir+DIR_WrtDate);		/* Date */
		fno->ftime = LD_WORD(dir+DIR_WrtTime);		/* Time */
	}
	*p = 0;
}
Example #3
0
FRESULT pf_open (
	const char *path	/* Pointer to the file name */
)
{
	FRESULT res;
	DIR dj;
	BYTE sp[12], dir[32];
	FATFS *fs = FatFs;


	if (!fs)						/* Check file system */
		return FR_NOT_ENABLED;

	fs->flag = 0;
	fs->buf = dir;
	dj.fn = sp;
	res = follow_path(&dj, path);	/* Follow the file path */
	if (res != FR_OK) return res;	/* Follow failed */
	if (!dir[0] || (dir[DIR_Attr] & AM_DIR))	/* It is a directory */
		return FR_NO_FILE;

	fs->org_clust =						/* File start cluster */
#if _FS_FAT32
		((DWORD)LD_WORD(dir+DIR_FstClusHI) << 16) |
#endif
		LD_WORD(dir+DIR_FstClusLO);
	fs->fsize = LD_DWORD(dir+DIR_FileSize);	/* File size */
	fs->fptr = 0;						/* File pointer */
	fs->flag = FA_READ;

	return FR_OK;
}
Example #4
0
static
BYTE check_fs (	/* 0:The FAT boot record, 1:Valid boot record but not an FAT, 2:Not a boot record, 3:Error */
	BYTE *buf,	/* Working buffer */
	DWORD sect	/* Sector# (lba) to check if it is an FAT boot record or not */
)
{
	if (disk_readp(buf, sect, 510, 2))		/* Read the boot sector */
		return 3;
	if (LD_WORD(buf) != 0xAA55)				/* Check record signature */
		return 2;
	if (!disk_readp(buf, sect, BS_FilSysType, 2) && LD_WORD(buf) == 0x4146)	/* Check FAT12/16 */
		return 0;
	if (_FS_FAT32 && !disk_readp(buf, sect, BS_FilSysType32, 2) && LD_WORD(buf) == 0x4146)	/* Check FAT32 */
		return 0;
	return 1;
}
Example #5
0
static
CLUST get_cluster (		/* 0,>=2: successful, 1: failed */
	CLUST clust			/* Cluster# to get the link information */
)
{
   WORD wc, bc;
   DWORD fatsect;
  FATFS *fs = FatFs;


	if (clust >= 2 && clust < fs->max_clust) {		/* Valid cluster# */
		fatsect = fs->fatbase;
		switch (fs->fs_type) {
		case FS_FAT12 :
			bc = (WORD)clust * 3 / 2;
			if (!move_window(fatsect + bc / 512)) break;
			wc = fs->win[bc % 512]; bc++;
			if (!move_window(fatsect + bc / 512)) break;
			wc |= (WORD)fs->win[bc % 512] << 8;
			return (clust & 1) ? (wc >> 4) : (wc & 0xFFF);

		case FS_FAT16 :
			if (!move_window(fatsect + clust / 256)) break;
			return LD_WORD(&fs->win[((WORD)clust * 2) % 512]);
#if _FAT32
		case FS_FAT32 :
			if (!move_window(fatsect + clust / 128)) break;
			return LD_DWORD(&fs->win[((WORD)clust * 4) % 512]) & 0x0FFFFFFF;
#endif
		}
	}
Example #6
0
File: ff.c Project: optixx/lm32
static
DWORD get_cluster (
	DWORD clust			/* Cluster# to get the link information */
)
{
	WORD wc, bc;
	DWORD fatsect;
	FATFS *fs = FatFs;


	if ((clust >= 2) && (clust < fs->max_clust)) {		/* Valid cluster# */
		fatsect = fs->fatbase;
		switch (fs->fs_type) {
		case FS_FAT12 :
			bc = (WORD)clust * 3 / 2;
			if (!move_window(fatsect + bc / 512)) break;
			wc = fs->win[bc % 512]; bc++;
			if (!move_window(fatsect + bc / 512)) break;
			wc |= (WORD)fs->win[bc % 512] << 8;
			return (clust & 1) ? (wc >> 4) : (wc & 0xFFF);

		case FS_FAT16 :
			if (!move_window(fatsect + clust / 256)) break;
			return LD_WORD(&(fs->win[((WORD)clust * 2) % 512]));

		case FS_FAT32 :
			if (!move_window(fatsect + clust / 128)) break;
			return LD_DWORD(&(fs->win[((WORD)clust * 4) % 512]));
		}
	}
Example #7
0
static
CLUST get_clust (
	BYTE* dir		/* Pointer to directory entry */
)
{
	FATFS *fs = FatFs;
	CLUST clst = 0;


	if (_FS_32ONLY || (_FS_FAT32 && fs->fs_type == FS_FAT32)) {
		clst = LD_WORD(dir+DIR_FstClusHI);
		clst <<= 16;
	}
	clst |= LD_WORD(dir+DIR_FstClusLO);

	return clst;
}
Example #8
0
static
CLUST get_clust (
        FATFS* fs,      /* Filesystem descriptor */
        BYTE* dir		/* Pointer to directory entry */
        )
{
    CLUST clst = 0;


    if (_FS_32ONLY || (_FS_FAT32 && fs->fs_type == FS_FAT32)) {
        clst = LD_WORD(dir+DIR_FstClusHI);
        clst <<= 16;
    }
    clst |= LD_WORD(dir+DIR_FstClusLO);

    return clst;
}
Example #9
0
static FRESULT follow_path (	/* FR_OK(0): successful, !=0: error code */
	DIR *dj,			/* Directory object to return last directory and found object */
	const char *path	/* Full-path string to find a file or directory */
)
{
	FRESULT res;
	u8 *dir;
	u8 t[15];

//	memcpypgm2ram(t, path, 15);

	while (*path == ' ') path++;		/* Skip leading spaces */
	if (*path == '/') path++;			/* Strip heading separator */
	dj->sclust = 0;						/* Set start directory (always root dir) */

//	memcpypgm2ram(t, path, 15);

	if ((u8)*path <= ' ') {			/* Null path means the root directory */
		res = dir_rewind(dj);
		FatFs->buf[0] = 0;

	} else {							/* Follow path */
		for (;;) {
			res = create_name(dj, &path);	/* Get a segment */
			if (res != FR_OK) break;
         res = dir_find(dj);
			if (res != FR_OK) {				/* Could not find the object */
				if (res == FR_NO_FILE && !*(dj->fn+11))
					res = FR_NO_PATH;
				break;
			}
			if (*(dj->fn+11)) break;		/* Last segment match. Function completed. */
			dir = FatFs->buf;				/* There is next segment. Follow the sub directory */
			if (!(dir[DIR_Attr] & AM_DIR)) { /* Cannot follow because it is a file */
				res = FR_NO_PATH; break;
			}
			dj->sclust =
#if _FS_FAT32
				((u32)LD_WORD(dir+DIR_FstClusHI) << 16) |
#endif
				LD_WORD(dir+DIR_FstClusLO);
		}
	}

	return res;
}
Example #10
0
static
CLUST get_fat (	/* 1:IO error, Else:Cluster status */
    CLUST clst	/* Cluster# to get the link information */
)
{
    BYTE buf[4];
    FATFS *fs = FatFs;

    if (clst < 2 || clst >= fs->n_fatent)	/* Range check */
        return 1;

    switch (fs->fs_type) {
#if _FS_FAT12
    case FS_FAT12 : {
        UINT wc, bc, ofs;

        bc = (UINT)clst;
        bc += bc / 2;
        ofs = bc % 512;
        bc /= 512;
        if (ofs != 511) {
            if (disk_readp(buf, fs->fatbase + bc, ofs, 2)) break;
        } else {
            if (disk_readp(buf, fs->fatbase + bc, 511, 1)) break;
            if (disk_readp(buf+1, fs->fatbase + bc + 1, 0, 1)) break;
        }
        wc = LD_WORD(buf);
        return (clst & 1) ? (wc >> 4) : (wc & 0xFFF);
    }
#endif
#if _FS_FAT16
    case FS_FAT16 :
        if (disk_readp(buf, fs->fatbase + clst / 256, ((UINT)clst % 256) * 2, 2)) break;
        return LD_WORD(buf);
#endif
#if _FS_FAT32
    case FS_FAT32 :
        if (disk_readp(buf, fs->fatbase + clst / 128, ((UINT)clst % 128) * 4, 4)) break;
        return LD_DWORD(buf) & 0x0FFFFFFF;
#endif
    }

    return 1;	/* An error occured at the disk I/O layer */
}
Example #11
0
void Excep_CMTU1_CMT3 (void)
{

	WAVFIFO *fcb;
	uint32_t ri, ct, ch_l, ch_r;
	uint8_t *buff;


	fcb = WavFifo;
	if (!fcb) return;	/* Spurious interrupt? */

	buff = fcb->buff;
	ct = fcb->ct; ri = fcb->ri;
		switch (fcb->mode) {
	case 0:		/* Mono, 8bit */
		if (ct < 1) return;
		ch_l = ch_r = buff[ri] << 8;
		ct -= 1; ri += 1;
		break;
	case 1:		/* Stereo, 8bit */
		if (ct < 2) return;
		ch_l = buff[ri] << 8;
		ch_r = buff[ri + 1] << 8;
		ct -= 2; ri += 2;
		break;
	case 2:		/* Mono, 16bit */
		if (ct < 2) return;
		ch_l = ch_r = LD_WORD(buff+ri) ^ 0x8000;
		ct -= 2; ri += 2;
		break;
	default:	/* Stereo, 16bit */
		if (ct < 4) return;
		ch_l = LD_WORD(buff+ri) ^ 0x8000;;
		ch_r = LD_WORD(buff+ri+2) ^ 0x8000;;
		ct -= 4; ri += 4;
	}
	fcb->ct = ct;
	fcb->ri = ri & (fcb->sz_buff - 1);

	DA.DADR0 = (uint16_t)ch_l;
	DA.DADR1 = (uint16_t)ch_r;
}
Example #12
0
FRESULT pf_opendir (
	DIR *dj,			/* Pointer to directory object to create */
	const char *path	/* Pointer to the directory path */
)
{
	FRESULT res;
	BYTE sp[12], dir[32];
	FATFS *fs = FatFs;


	if (!fs) {				/* Check file system */
		res = FR_NOT_ENABLED;
	} else {
		fs->buf = dir;
		dj->fn = sp;
		res = follow_path(dj, path);			/* Follow the path to the directory */
		if (res == FR_OK) {						/* Follow completed */
			if (dir[0]) {						/* It is not the root dir */
				if (dir[DIR_Attr] & AM_DIR) {	/* The object is a directory */
					dj->sclust =
#if _FS_FAT32
					((DWORD)LD_WORD(dir+DIR_FstClusHI) << 16) |
#endif
					LD_WORD(dir+DIR_FstClusLO);
				} else {						/* The object is not a directory */
					res = FR_NO_PATH;
				}
			}
			if (res == FR_OK) {
				res = dir_rewind(dj);			/* Rewind dir */
			}
		}
		if (res == FR_NO_FILE) res = FR_NO_PATH;
	}

	return res;
}
Example #13
0
static
DWORD load_header (void)	/* 0:Invalid format, 1:I/O error, >1:Number of samples */
{
	DWORD sz;


	if (pf_read(Buff1, 12, &rb)) return 1;	/* Load file header (12 bytes) */

	if (rb != 12 || LD_DWORD(Buff1+8) != FCC('W','A','V','E')) return 0;

	for (;;) {
		pf_read(Buff1, 8, &rb);			/* Get Chunk ID and size */
		if (rb != 8) return 0;
		sz = LD_DWORD(&Buff1[4]);		/* Chunk size */

		switch (LD_DWORD(&Buff1[0])) {	/* FCC */
		case FCC('f','m','t',' ') :					/* 'fmt ' chunk */
			if (sz > 100 || sz < 16) return 0;		/* Check chunk size */
			pf_read(Buff1, sz, &rb);					/* Get content */
			if (rb != sz) return 0;
			if (Buff1[0] != 1) return 0;				/* Check coding type (1) */
			if (Buff1[2] != 1 && Buff1[2] != 2) 		/* Check channels (1/2) */
				return 0;
			
			if (Buff1[14] != 8 && Buff1[14] != 16)	/* Check resolution (8/16) */
				return 0;
			
			OCR0A = (BYTE)(F_CPU/8/LD_WORD(&Buff1[4]))-1;	/* Sampling freq */
			
			break;

		case FCC('d','a','t','a') :				/* 'data' chunk (start to play) */
			return sz;

		case FCC('L','I','S','T') :				/* 'LIST' chunk (skip) */
		case FCC('f','a','c','t') :				/* 'fact' chunk (skip) */
			pf_lseek(Fs.fptr + sz);
			break;

		default :								/* Unknown chunk (error) */
			return 0;
		}
	}

	return 0;
}
Example #14
0
FRESULT pf_mount (
	FATFS *fs		/* Pointer to new file system object */
)
{
	BYTE fmt, buf[36] = {0};
	DWORD bsect, fsize, tsect, mclst;


	FatFs = 0;

	if (disk_initialize() & STA_NOINIT)	/* Check if the drive is ready or not */
		return FR_NOT_READY;

	/* Search FAT partition on the drive */
	bsect = 0;
	fmt = check_fs(buf, bsect);			/* Check sector 0 as an SFD format */
	if (fmt == 1) {						/* Not an FAT boot record, it may be FDISK format */
		/* Check a partition listed in top of the partition table */
		if (disk_readp(buf, bsect, MBR_Table, 16)) {	/* 1st partition entry */
			fmt = 3;
		} else {
			if (buf[4]) {					/* Is the partition existing? */
				bsect = LD_DWORD(&buf[8]);	/* Partition offset in LBA */
				fmt = check_fs(buf, bsect);	/* Check the partition */
			}
		}
	}
	if (fmt == 3) return FR_DISK_ERR;
	if (fmt) return FR_NO_FILESYSTEM;	/* No valid FAT patition is found */

	/* Initialize the file system object */
	if (disk_readp(buf, bsect, 13, sizeof (buf))) return FR_DISK_ERR;

	fsize = LD_WORD(buf+BPB_FATSz16-13);				/* Number of sectors per FAT */
	if (!fsize) fsize = LD_DWORD(buf+BPB_FATSz32-13);

	fsize *= buf[BPB_NumFATs-13];						/* Number of sectors in FAT area */
	fs->fatbase = bsect + LD_WORD(buf+BPB_RsvdSecCnt-13); /* FAT start sector (lba) */
	fs->csize = buf[BPB_SecPerClus-13];					/* Number of sectors per cluster */
	fs->n_rootdir = LD_WORD(buf+BPB_RootEntCnt-13);		/* Nmuber of root directory entries */
	tsect = LD_WORD(buf+BPB_TotSec16-13);				/* Number of sectors on the file system */
	if (!tsect) tsect = LD_DWORD(buf+BPB_TotSec32-13);
	mclst = (tsect						/* Last cluster# + 1 */
		- LD_WORD(buf+BPB_RsvdSecCnt-13) - fsize - fs->n_rootdir / 16
		) / fs->csize + 2;
	fs->n_fatent = (CLUST)mclst;

	fmt = 0;							/* Determine the FAT sub type */
	if (_FS_FAT12 && mclst < 0xFF7)
		fmt = FS_FAT12;
	if (_FS_FAT16 && mclst >= 0xFF8 && mclst < 0xFFF7)
		fmt = FS_FAT16;
	if (_FS_FAT32 && mclst >= 0xFFF7)
		fmt = FS_FAT32;
	if (!fmt) return FR_NO_FILESYSTEM;
	fs->fs_type = fmt;

	if (_FS_32ONLY || (_FS_FAT32 && fmt == FS_FAT32))
		fs->dirbase = LD_DWORD(buf+(BPB_RootClus-13));	/* Root directory start cluster */
	else
		fs->dirbase = fs->fatbase + fsize;				/* Root directory start sector (lba) */
	fs->database = fs->fatbase + fsize + fs->n_rootdir / 16;	/* Data start sector (lba) */

	fs->flag = 0;
	FatFs = fs;

	return FR_OK;
}
Example #15
0
int main (int argc, char* argv[])
{
	UINT csz;
	HANDLE wh;
	DWORD wb, szvol;
	int ai = 1, truncation = 0;
	const char *outfile;


	/* Initialize parameters */
	if (argc >= 2 && *argv[ai] == '-') {
		if (!strcmp(argv[ai], "-t")) {
			truncation = 1;
			ai++;
			argc--;
		} else {
			argc = 0;
		}
	}
	if (argc < 3) {
		printf("usage: mkfatimg [-t] <source node> <output file> <volume size> [<cluster size>]\n"
				"    -t: Truncate unused area for read only volume.\n"
				"    <source node>: Source node\n"
				"    <output file>: FAT volume image file\n"
				"    <volume size>: Size of temporary volume size in unit of KiB\n"
				"    <cluster size>: Size of cluster in unit of byte (default:512)\n"
			);
		return 1;
	}
	strcpy(SrcPath, argv[ai++]);
	outfile = argv[ai++];
	RamDiskSize = atoi(argv[ai++]) * 2;
	csz = (argc >= 5) ? atoi(argv[ai++]) : 512;

	/* Create an FAT volume */
	f_mount(&FatFs, "", 0);
	if (f_mkfs("", 1, csz)) {
		printf("Failed to create FAT volume. Adjust volume size or cluster size.\n");
		return 2;
	}

	/* Copy directory tree onto the FAT volume */
	if (!maketree()) return 3;
	if (!Files) { printf("No file in the source directory."); return 3; }
	szvol = LD_WORD(RamDisk + BPB_TotSec16);
	if (!szvol) szvol = LD_DWORD(RamDisk + BPB_TotSec32);

	if (truncation) {
		DWORD ent, nent;
		DWORD szf, szfp, edf, edfp;
		DWORD szd, szdp, edd, eddp;

		/* Truncate unused root directory entries */
		if (FatFs.fs_type != FS_FAT32) {
			printf("\nTruncating unused root directory area...");
			for (nent = ent = 0; ent < FatFs.n_rootdir; ent++) {
				if (RamDisk[FatFs.dirbase * 512 + ent * 32]) nent = ent + 1;
			}
			szd = (nent + 15) / 16;
			szdp = FatFs.n_rootdir / 16;
			if (szd < szdp) {
				edd = FatFs.dirbase + szd;
				eddp = FatFs.database;
				MoveMemory(RamDisk + (edd * 512), RamDisk + (eddp * 512), (szvol - eddp) * 512);
				szvol -= szdp - szd;
				FatFs.database -= szdp - szd;
				ST_WORD(RamDisk + BPB_RootEntCnt, szd * 16);
			}
		}

		/* Truncate unused data area and FAT */
		printf("\nTruncating unused data area...");
		for (nent = ent = 2; ent < FatFs.n_fatent; ent++) {
			if (get_fat(&FatFs, ent)) nent = ent + 1;
		}
		switch (FatFs.fs_type) {
		case FS_FAT12:
			szf = (nent * 3 / 2 + (nent & 1) + 511) / 512;
			break;
		case FS_FAT16:
			szf = (nent * 2 + 511) / 512;
			if (nent - 2 < MIN_FAT16) nent = 0;
			break;
		default:
			szf = (nent * 4 + 511) / 512;
			if (nent - 2 < MIN_FAT32) nent = 0;
			break;
		}
		if (!nent) {
			printf("different FAT sub-type is needed. Adjust volume size or cluster size.\n");
			return 3;
		}
		szfp = LD_WORD(RamDisk + BPB_FATSz16) * RamDisk[BPB_NumFATs];
		if (!szfp) szfp = LD_DWORD(RamDisk + BPB_FATSz32) * RamDisk[BPB_NumFATs];
		edf = FatFs.fatbase + szf;
		edfp = (FatFs.fs_type == FS_FAT32) ? FatFs.database : FatFs.dirbase;
		MoveMemory(RamDisk + (edf * 512), RamDisk + (edfp * 512), (szvol - edfp) * 512);
		szvol -= (szfp - szf) + FatFs.csize * (FatFs.n_fatent - nent);
		if (FatFs.fs_type == FS_FAT32) {
			ST_DWORD(RamDisk + BPB_FATSz32, szf);
		} else {
			ST_WORD(RamDisk + BPB_FATSz16, szf);
		}
		RamDisk[BPB_NumFATs] = 1;
		if (szvol < 0x10000) {
			ST_WORD(RamDisk + BPB_TotSec16, szvol);
			ST_DWORD(RamDisk + BPB_TotSec32, 0);
		} else {
			ST_WORD(RamDisk + BPB_TotSec16, 0);
			ST_DWORD(RamDisk + BPB_TotSec32, szvol);
		}
	}

	/* Output the FAT volume to the file */
	printf("\nWriting output file...");
	wh = CreateFile(outfile, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
	if (wh == INVALID_HANDLE_VALUE) {
		printf("Failed to create output file.\n");
		return 4;
	}
	szvol *= 512;
	WriteFile(wh, RamDisk, szvol, &wb, 0);
	CloseHandle(wh);
	if (szvol != wb) {
		DeleteFile(argv[2]);
		printf("Failed to write output file.\n");
		return 4;
	}

	printf("\n%u files and %u directories in a %u bytes of FAT volume.\n", Files, Dirs, szvol);

	return 0;
}
Example #16
0
int load_wav (
	FIL *fp,			/* Pointer to the open file object to play */
	const char *title,	/* Title (file name, etc...) */
	void *work,			/* Pointer to working buffer (must be-4 byte aligned) */
	uint32_t sz_work	/* Size of working buffer (must be power of 2) */
)
{
	UINT md, wi, br, tc, t, btr;
	DWORD sz, ssz, offw, szwav, wsmp, fsmp, eof;
	WAVFIFO fcb;
	BYTE k, *buff = work;
	char *p, nam[NBSIZE], art[NBSIZE];


	xprintf("**** RIFF-WAVE Player ****\nFile=%s\n", title);	/* Put title */

	/* Is this a WAV file? */
	if (f_read(fp, buff, 12, &br) || br != 12) return -1;
	if (LD_DWORD(&buff[0]) != FCC('R','I','F','F')) return -1;
	if (LD_DWORD(&buff[8]) != FCC('W','A','V','E')) return -1;
	eof = LD_DWORD(&buff[4]) + 8;

	/* Analyze the RIFF-WAVE header and get properties */
	nam[0] = art[0] = 0;
	md = fsmp = wsmp = offw = szwav = 0;
	while (f_tell(fp) < eof) {
		if (f_read(fp, buff, 8, &br) || br != 8) return -1;
		sz = (LD_DWORD(&buff[4]) + 1) & ~1;
		switch (LD_DWORD(&buff[0])) {
		case FCC('f','m','t',' ') :	/* fmt chunk */
			if (sz > 1000 || sz < 16 || f_read(fp, buff, sz, &br) || sz != br) return -1;
			if (LD_WORD(&buff[0]) != 0x1) return -1;	/* Check if LPCM or not */
			if (LD_WORD(&buff[2]) == 2) {	/* Check channels (1 or 2) */
				md = 1; wsmp = 2;
			} else {
				md = 0; wsmp = 1;
			}
			if (LD_WORD(&buff[14]) == 16) {	/* Resolution (8 or 16) */
				md |= 2; wsmp *= 2;
			}
			fsmp = LD_DWORD(&buff[4]);		/* Sampling rate */
			break;

		case FCC('f','a','c','t') :	/* fact chunk */
			f_lseek(fp, f_tell(fp) + sz);
			break;

		case FCC('d','a','t','a') :	/* data chunk */
			offw = f_tell(fp);	/* Wave data start offset */
			szwav = sz;			/* Size of wave data [byte] */
			f_lseek(fp, f_tell(fp) + sz);
			break;

		case FCC('L','I','S','T'):	/* LIST chunk */
			sz += f_tell(fp);
			if (f_read(fp, buff, 4, &br) || br != 4) return -1;
			if (LD_DWORD(buff) == FCC('I','N','F','O')) {	/* LIST/INFO sub-chunk */
				while (f_tell(fp) < sz) {
					if (f_read(fp, buff, 8, &br) || br != 8) return -1;
					ssz = (LD_DWORD(&buff[4]) + 1) & ~1;
					p = 0;
					switch (LD_DWORD(buff)) {
					case FCC('I','N','A','M'):		/* INAM (name) field */
						p = nam; break;
					case FCC('I','A','R','T'):		/* IART (artist) field */
						p = art; break;
					}
					if (p && ssz <= NBSIZE) {
						if (f_read(fp, p, ssz, &br) || br != ssz) return -1;
					} else {
						if (f_lseek(fp, f_tell(fp) + ssz)) return -1;
					}
				}
			} else {
				if (f_lseek(fp, sz)) return -1;	/* Skip unknown sub-chunk */
			}
			break;

		default :	/* Unknown chunk */
			return -1;
		}
	}
	if (!szwav || !fsmp) return -1;		/* Check if valid WAV file */
	if (f_lseek(fp, offw)) return -1;	/* Seek to top of wav data */
	tc = szwav / fsmp / wsmp;			/* Length (sec) */

	xprintf("IART=%s\nINAM=%s\n", art, nam);
	xprintf("Sample=%u.%ukHz/%ubit/%s\nLength=%u:%02u\n", fsmp / 1000, (fsmp / 100) % 10, (md & 2) ? 16 : 8, (md & 1) ? "Stereo" : "Mono", tc / 60, tc % 60);

	/* Initialize sound FIFO and start sound streming */
	fcb.mode = md;			/* Sampling: b0=mono(0)/stereo(1), b1=8bit(0)/16bit(1) */
	fcb.buff = buff;		/* Pointer to streaming buffer */
	fcb.sz_buff = sz_work;	/* Size of streaming buffer */
	if (!sound_start(&fcb, fsmp)) return -1;	/* Start sound streaming */

	k = 0; wi = 0;
	while (szwav || fcb.ct >= 4) {	/* Sount streaming loop */
		if (szwav && fcb.ct <= sz_work / 2) {	/* Refill FIFO when it gets half empty */
			btr = (szwav >= sz_work / 2) ? sz_work / 2 : szwav;
			f_read(fp, &buff[wi], btr, &br);
			if (br != btr) break;	/* Exit if illigal file termination or FS error */
			szwav -= br;
			wi = (wi + br) & (sz_work - 1);
			IEN(CMT3, CMI3) = 0;	/* Disable CMT3 compare match irq */
			fcb.ct += br;
			IEN(CMT3, CMI3) = 1;	/* Enable CMT3 compare match irq */
		}
		if (scif_test()) {		/* Exit if a user command arrived */
			k = scif_getc();
			break;
		}
		t = (f_tell(fp) - offw - fcb.ct) / fsmp / wsmp;	/* Refresh time display every 1 sec */
		if (t != tc) {
			tc = t;
			xprintf("\rTime=%u:%02u", tc / 60, tc % 60);
		}
	}

	sound_stop();	/* Stop sound streaming */

	xputc('\n');
	return k;	/* Terminated due to -1:error, 0:eot, >0:key code */
}