⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mp3pc.c

📁 Frank s MP3 Player Source Files
💻 C
📖 第 1 页 / 共 4 页
字号:
    StreamFileC();

    FINDFILE_OFSET = ((u16)SEC_PER_CLUS)<<9;
    // Loop until we've counted through the required number of file records
    // Note that filecount can start at zero, whereas N and NN start at 1.
    while (filecount < N) {

        // If we're at the (N-1)th file directory entry, put its directory cluster number in FINDFILE_PREV_CLUS
        if (filecount == (NN-1)) 
            FINDFILE_PREV_CLUS = FINDFILE_CLUS;

        // if clusterbytecount == numberofbytespercluster, we need to read the 4-byte cluster number out of the data Q,
        // and reset the OffsetIntoCluster counter. FYI, a multiply by 512 is a left-shift of 9 bits.
        if (FINDFILE_OFSET == ((u16)SEC_PER_CLUS)<<9) {
            // wait until 4 bytes in data Q
            while ( Q_HowMuchDataC((u08*)&MP3DATAQ[0]) < 4 ) {
                StreamFileC();
                if ( (STREAMFILE_ST==StreamFile_St_Idle) && (Q_HowMuchDataC((u08*)&MP3DATAQ[0])<4) )
                    return FindFile_err;
            }            
            // extract cluster number low-byte first, reset OffsetIntoCluster counter, and continue along...
            FINDFILE_CLUS = ((u32)Q_read_C((u08*)&MP3DATAQ[0])) + (((u32)Q_read_C((u08*)&MP3DATAQ[0]))<<8) + \
                          + (((u32)Q_read_C((u08*)&MP3DATAQ[0]))<<16) + (((u32)Q_read_C((u08*)&MP3DATAQ[0]))<<24);
            FINDFILE_OFSET = 0;
        }

        // Wait until 32 bytes in queue. If StreamFileC goes idle, return with error, because we've run out
        // of directory data before we reached the required number of files. Possibly due to FAT corruption.
        while ( Q_HowMuchDataC((u08*)&MP3DATAQ[0]) < 32 ) {
            StreamFileC();
            if ( (STREAMFILE_ST==StreamFile_St_Idle) && (Q_HowMuchDataC((u08*)&MP3DATAQ[0])<32) )
                return FindFile_err;
        }

        // We now have 32 bytes in the queue; a directory entry's worth. Read them out of 
        // the queue, keeping a few of them for later review, discarding the rest. The first 12 bytes in 
        // the queue are the short filename (8.3) and the file attributes. If the first byte is zero,
        // return, also telling StreamFileC to stop, because there are no more files in this directory.
        firstchar = Q_read_C((u08*)&MP3DATAQ[0]);       // get first character of filename
        if (firstchar == 0x00 ) {
           	STREAMFILE_CMD = StreamFile_Cmd_Stop;                       // tell StreamFileC to stop, then
            while (STREAMFILE_ST!=StreamFile_St_Idle) StreamFileC();    // wait until it's idle               
            return FindFile_err;
        }
        // put the 8 characters of the short filename into the filename array
        FINDFILE_RET_NAME[0] = 12;                                      // first array element is length
        FINDFILE_RET_NAME[1] = firstchar;
        FINDFILE_RET_NAME[2] = Q_read_C((u08*)&MP3DATAQ[0]);            // get 2nd character of filename
        FINDFILE_RET_NAME[3] = Q_read_C((u08*)&MP3DATAQ[0]);            // get 3rd character of filename
        FINDFILE_RET_NAME[4] = Q_read_C((u08*)&MP3DATAQ[0]);            // get 4th character of filename
        FINDFILE_RET_NAME[5] = Q_read_C((u08*)&MP3DATAQ[0]);            // get 5th character of filename
        FINDFILE_RET_NAME[6] = Q_read_C((u08*)&MP3DATAQ[0]);            // get 6th character of filename
        FINDFILE_RET_NAME[7] = Q_read_C((u08*)&MP3DATAQ[0]);            // get 7th character of filename
        FINDFILE_RET_NAME[8] = Q_read_C((u08*)&MP3DATAQ[0]);            // get 8th character of filename

        extm = Q_read_C((u08*)&MP3DATAQ[0]);
        extp = Q_read_C((u08*)&MP3DATAQ[0]);
        ext3 = Q_read_C((u08*)&MP3DATAQ[0]);            // hopefully these 3 characters are "MP3"

        FINDFILE_RET_NAME[9] = '.';
        FINDFILE_RET_NAME[10] = extm;
        FINDFILE_RET_NAME[11] = extp;
        FINDFILE_RET_NAME[12] = ext3;
        FINDFILE_RET_NAME[13] = 0;                      // null-terminate file name array

        attr = Q_read_C((u08*)&MP3DATAQ[0]);            // get file attributes
        for (i=8;i;i--)
            Q_read_C((u08*)&MP3DATAQ[0]);               // throwaway next 8 bytes in directory structure

        // get 32-bit starting cluster number for file
        FINDFILE_RET_CLUS = (((u32)Q_read_C((u08*)&MP3DATAQ[0]))<<16) + (((u32)Q_read_C((u08*)&MP3DATAQ[0]))<<24);
        Q_read_C((u08*)&MP3DATAQ[0]);
        Q_read_C((u08*)&MP3DATAQ[0]);
        Q_read_C((u08*)&MP3DATAQ[0]);
        Q_read_C((u08*)&MP3DATAQ[0]);                   // toss time&date of last write 4 bytes
        FINDFILE_RET_CLUS += (((u32)Q_read_C((u08*)&MP3DATAQ[0]))) + (((u32)Q_read_C((u08*)&MP3DATAQ[0]))<<8);

        // get 32-bit file size
        FINDFILE_RET_SIZE = (((u32)Q_read_C((u08*)&MP3DATAQ[0]))) + (((u32)Q_read_C((u08*)&MP3DATAQ[0]))<<8) + \
                            (((u32)Q_read_C((u08*)&MP3DATAQ[0]))<<16) + (((u32)Q_read_C((u08*)&MP3DATAQ[0]))<<24);
        
        // Increment filecount if we've found an MP3 file
        if ( firstchar!=0xE5 && extm=='M' && extp=='P' && ext3=='3' && !(attr&0x1E) )
            filecount++;

        // increment OffsetIntoCluster by the number of bytes we've read
        FINDFILE_OFSET += 32;

        // give StreamFileC another chance to run, then loop back for the next directory entry
        StreamFileC();
    }
    STREAMFILE_CMD = StreamFile_Cmd_Stop;                       // command StreamFileC to STOP; we're all done now
    return FindFile_done;
}



void GetLongFileName (void)
/* WARNING: DOES NOT RETURN UNTIL COMPLETED - VERY VERY SLOW */
// Here's the magic routine. It gets the long filename for the current file off the disk and
// writes that name into the FINDFILE_RET_NAME structure. It works by looking at three FindNthMP3 / FindNthDir
// global variables: FINDFILE_CLUS, FINDFILE_PREV_CLUS, and FINDFILE_OFSET. _CLUS and _OFSET
// provide the location (cluster number and byte offset into that cluster) of the NEXT directory
// entry. Subtract 1 from this and you have the location of the last byte of the 8.3 filename directory 
// entry for the current file. Directory entries are 32 bytes long; the entry before the 8.3 name is 
// potentially the first of possibly several long-filename directory entries for our current file.
// (Note the "potentially" and "possibly". There might not be any long filename directory entries for
// the current file, in which case we use the 8.3 name already provided by FindNthMP3. Or there might
// be one, two, or more long filename entries. We cannot make any assumptions what might be present.)
//
// So now that we know where the long filename directory entries begin (actually end), how do we get them? 
// By telling StreamFile to stream a bunch of directory entry data, and then reading that data out of the 
// queue backwards. StreamFile can stop streaming at _CLUS bytes _OFSET-32 (the -32 because we don't need
// the 8.3 name) but where to start? Start streaming from the previous cluster; the one before _CLUS,
// which is _PREV_CLUS. This is to ensure if the longname crosses a cluster boundary (which it can do
// and sometimes does) we'll still get it all. Often _CLUS and _PREV_CLUS are the same, which speeds
// things up.
{
	u16		i, DirCnt, StreamBytes;
	u08		r[15];
	u08		attr, temp;
	
    
    // Calculate how many bytes to tell StreamFile to stream from the disk directory data. This is 
    // dependant upon whether FINDFILE_PREV_CLUS and FINDFILE_CLUS are the same or not. If we need to
    // stream the previous cluster, there are SEC_PER_CLUS sectors in a cluster, and 512 bytes
    // in a sector.
    StreamBytes = FINDFILE_OFSET-32;                    // don't need the 8.3 directory entry
    if (FINDFILE_PREV_CLUS != FINDFILE_CLUS)
        StreamBytes += ((u16)SEC_PER_CLUS) << 9;        // stream previous cluster if required

	// Tell StreamFile to stream the directory data into the MP3 data queue.
	// if queue not large enough then do some dummy reads to make space
   	STREAMFILE_CMD = StreamFile_Cmd_Stop;
   	while (STREAMFILE_ST != StreamFile_St_Idle) StreamFileC();	/* ensure StreamFile is idle */
    STREAMFILE_FILESZ   = StreamBytes;			        /* stream this many directory bytes */
    STREAMFILE_CLUS     = FINDFILE_PREV_CLUS;			/* starting from this directory cluster */
    STREAMFILE_QPOINTER = &MP3DATAQ[0];					/* point StreamFile to the MP3 Data queue */
    Q_clear_C((u08*)&MP3DATAQ[0]);						/* ensure that Q is empty (yes I'm paranoid) */
    STREAMFILE_CMD      = StreamFile_Cmd_Stream;		/* tell StreamFile to stream the file to the Q */
	StreamFileC();										/* get StreamFile started */
	
	// determine how many dummy reads (i) we may have to do (if MP3 q too small to hold all the data)
    i = 0;
	if (StreamBytes > (MP3DATAQ_size - 10))
		i = StreamBytes - MP3DATAQ_size + 10;

	// stream directory into queue; do dummy reads if required
	while (STREAMFILE_ST != StreamFile_St_Idle) {		/* loop until StreamFile finished streaming */
		StreamFileC();
		if (i) {										/* if we need to do dummy read from queue... */
			Q_read_C ((u08*)&MP3DATAQ[0]);				/*   attempt dummy read */
			if (ReadQstatus == Q_OK) i--;				/*   if dummy read successful decrement dummy read counter */
		}				
	}

	// At this point the directory entries are in the queue. Now we can read them out. We need to 
	// define the maximum number of long filename directory entries (DirCnt) we'll permit, which is based 
    // upon the amount of memory space we allocated for the file name string. We read them out one
    // set of 32-bytes directory entry at a time, looping until we've done them all.
	DirCnt = FindFile_NumLongDirs;						
	
	while (DirCnt) {

		// read a 32-byte directory entry backwards out of the queue
		// note that characters are in 16-bit unicode; we only care about the first byte
		r[14] = 0;											// ensure r[] is null-terminated	
		Q_Read_FILO_C((u08*)&MP3DATAQ[0]);					// toss directory offset byte 31 
		r[13] = Q_Read_FILO_C((u08*)&MP3DATAQ[0]);			// character 13 in this directory entry 
		Q_Read_FILO_C((u08*)&MP3DATAQ[0]);					// toss directory offset byte 29 
		r[12] = Q_Read_FILO_C((u08*)&MP3DATAQ[0]);			// character 12 in this directory entry 	
		Q_Read_FILO_C((u08*)&MP3DATAQ[0]);					
		Q_Read_FILO_C((u08*)&MP3DATAQ[0]);					// offsets 26-27 should be zero - we'll ignore
		Q_Read_FILO_C((u08*)&MP3DATAQ[0]);					
		r[11] = Q_Read_FILO_C((u08*)&MP3DATAQ[0]);			// character 11 in this directory entry 	
		Q_Read_FILO_C((u08*)&MP3DATAQ[0]);
		r[10] = Q_Read_FILO_C((u08*)&MP3DATAQ[0]);			// character 10 in this directory entry 	
		Q_Read_FILO_C((u08*)&MP3DATAQ[0]);
		r[9] = Q_Read_FILO_C((u08*)&MP3DATAQ[0]);			// character 9 in this directory entry 	
		Q_Read_FILO_C((u08*)&MP3DATAQ[0]);
		r[8] = Q_Read_FILO_C((u08*)&MP3DATAQ[0]);			// character 8 in this directory entry 	
		Q_Read_FILO_C((u08*)&MP3DATAQ[0]);
		r[7] = Q_Read_FILO_C((u08*)&MP3DATAQ[0]);			// character 7 in this directory entry 	
		Q_Read_FILO_C((u08*)&MP3DATAQ[0]);
		r[6] = Q_Read_FILO_C((u08*)&MP3DATAQ[0]);			// character 6 in this directory entry 
		Q_Read_FILO_C((u08*)&MP3DATAQ[0]);					// ignore checksum in offset 13
		Q_Read_FILO_C((u08*)&MP3DATAQ[0]);					// should be zero in offset 12 - we'll ignore
		attr = Q_Read_FILO_C((u08*)&MP3DATAQ[0]);			// directory attributes in offset 11
		Q_Read_FILO_C((u08*)&MP3DATAQ[0]);	
		r[5] = Q_Read_FILO_C((u08*)&MP3DATAQ[0]);			// character 5 in this directory entry
		Q_Read_FILO_C((u08*)&MP3DATAQ[0]);	
		r[4] = Q_Read_FILO_C((u08*)&MP3DATAQ[0]);			// character 4 in this directory entry	
		Q_Read_FILO_C((u08*)&MP3DATAQ[0]);	
		r[3] = Q_Read_FILO_C((u08*)&MP3DATAQ[0]);			// character 3 in this directory entry	
		Q_Read_FILO_C((u08*)&MP3DATAQ[0]);	
		r[2] = Q_Read_FILO_C((u08*)&MP3DATAQ[0]);			// character 2 in this directory entry
		Q_Read_FILO_C((u08*)&MP3DATAQ[0]);	
		r[1] = Q_Read_FILO_C((u08*)&MP3DATAQ[0]);			// character 1 in this directory entry	
		r[0] = Q_Read_FILO_C((u08*)&MP3DATAQ[0]);			// offset zero is directory ordinal number	
		
		if ((attr & 0x0f) != 0x0f) return;					// finish if this not a long directory entry
		
        // If the first directory entry is a long filename entry, zero the filename byte count so that the
        // long filename can be entered. Otherwise leave it as it is, so the 8.3 name put in by FindNthMP3
        // remains. Note that if the code executes to this point, we do have a long filename entry, because
        // the test above (if... return) failed. Checking the value of DirCnt informs us if we're here for
        // the first time or not.      
        if (DirCnt == FindFile_NumLongDirs)
            FINDFILE_RET_NAME[0] = 0;                       // zero length byte - fill name from start of buffer

		// copy long filename characters into the filename buffer FINDFILE_RET_NAME[]
		// the first byte in that filename buffer is the length
		// note that longfilenames on the disk (now in r[]) are null-terminated. r[1] is the first character.
		// FINDFILE_RET_NAME[0] is the number of characters in array, not including length or NULL
		i = 1;
		temp = FINDFILE_RET_NAME[0];						// number of bytes already in filename buffer
		do
			FINDFILE_RET_NAME[temp+i] = r[i];
		while (r[i++]);
		FINDFILE_RET_NAME[0] = temp + i - 2;				// update length byte to reflect characters just added
		
		if (r[0] & 0x40) return;							// if this was last long filename dir entry then finish
		
		DirCnt--;											// else decrement directory count & loop again
	}
}




void FormatFileNameString (u08 TruncEnd)
// This routine formats the filename string to make the file name look better when displayed
// on the LCD. It tries to prevent words from breaking over two lines.
// Remember the format of the string: FINDFILE_RET_NAME[0] contains a length byte (which we don't 
// care about; the first character in the string is at FINDFILE_RET_NAME[1].
//
// There are three characters we're interested in: the space, the hyphen, and the period. Basically,
// a space at the end of a line is good; a hyphen at the end of a line is good, and a period at the
// beginning of the next line is good. If one of these 3 conditions doesn't exist for a given line,
// try and make it so. Additionally, we don't want a line to start with a space.
//
// TruncEnd says how many characters to remove from end of string; useful for removing .mp3 extensions
// from the filename. (ie set this to 4 to remove a .mp3 extension).
{
	u08		*tempptr;
	u08		freespace, backcount;
	
	// first we need to know how many characters we can insert; is the string already full?
	// freespace will end up containing number of free spaces in the string
	// max number of characters is 96 (24 chars x 4 lines)
	tempptr = (u08*)&FINDFILE_RET_NAME[1];
	freespace = 0;
	while (*tempptr) {
		freespace++;						// freespace counts number of characters to null
		tempptr++;
	}
	freespace = 96 - freespace;				// free string space equals 96 - number used characters
	
	// remove TruncEnd characters from end of filename string
	// note that tempptr is pointing to the null at the end of the string
	// ensure sufficient characters in string so we can perform truncation
	// number of characters in the string = 96 - freespace
	if (TruncEnd && ((96-freespace)>TruncEnd)) {
		tempptr = tempptr - TruncEnd;
		*tempptr = 0;						// new null TruncEnd characters back; string is now shortened
		freespace = freespace + TruncEnd;	// we have some extra free space in the string buffer now
	}
	
	
	// PROCESS THE FIRST LINE  (characters 1 - 24)
	
	// Remove any spaces at the beginning of the line
	while (FINDFILE_RET_NAME[1] == ' ') {					// if first char is a space...
		DeleteCharFromString((u08*)&FINDFILE_RET_NAME[1]);	//   then remove it
		freespace++;										//   and we now have an extra place free in the string
	}

	// Now deal with the end of the line. This switch statement only inserts spaces, so don't bother even
	// executing it if there's no free space in the string buffer.
	if (freespace) {
	switch (FINDFILE_RET_NAME[24]) {
	case ' ': case '-':									// space or hyphen at end of line is good
		break;											
	case '.':											// if period at end of line, move it to the next line
		InsertCharInString((u08*)&FINDFILE_RET_NAME[24], ' ');
		freespace--;
		break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -