📄 dirlist.c
字号:
#include <8051.h>#include <string.h>#include "as31glue.h"#include "printf.h"#include "paulmon2.h"#include "dirlist.h"#include "malloc.h"#include "playlist.h"#include "display.h"#include "stricmp.h"// #define VERBOSE_DEBUGsimm_id /* dirlist_t * */ root; // The root dirent_structstatic xdata struct dirent_struct dl_fileinfo;static dirlist_t * dl_parent;static dirlist_t * data dl_struct;static filelist_t * data fl_struct; data simm_id temp_id;// Limit Directory Depth (See dirlist.h for max depth define)static xdata unsigned char subdir_depth;/* static*/ xdata unsigned long dirlist_time_count;/* static*/ xdata unsigned int mp3_file_count;/* static*/ xdata unsigned int m3u_file_count;/* static*/ xdata unsigned int total_file_count;/* static*/ xdata unsigned int directory_count;static simm_id m3u_list_start=0;static simm_id m3u_list_end=0;static xdata char pathname_buffer[320];#pragma CALLEE-SAVES test_file_extension;char test_file_extension(void);void dirlist_read_dir(dirlist_t *this_dir);void filelist_show(simm_id /* dirlist_t */ dir);// m3u stuffxdata char *this_dirname;#pragma SAVE#pragma NOGCSEvoid dirlist_add_dir(simm_id /* dirlist_t * */ directory) reentrant{ simm_id sub_directory; // DO NOT add any non-static local variables here, as they // will rapidly overflow the 8051's limited stack space! if(++subdir_depth > MAX_SUBDIR_DEPTH) { print("Maximum subdir depth reached\r\n"); subdir_depth--; return; } dirlist_read_dir(addr5(directory)); //filelist_show(directory); sub_directory = ((dirlist_t *)addr5(directory))->subdir_start; while(sub_directory != 0) { // playlist names are full pathname full_pathname(sub_directory); temp_id = simm_malloc(strlen_asm(pathname_buffer) + 1); strcpy(addr7(temp_id), pathname_buffer); print("\\[\\B \""); print_str_n(pathname_buffer, 24); print("\\]\r\n"); playlist_create(temp_id); dirlist_add_dir(sub_directory); sub_directory = ((dirlist_t *)addr5(sub_directory))->next; } subdir_depth--; // on return from this function the next directory in the queue is processed}/* read a directory from the disk drive into a dirlist_struct *//* and populate all the dirlist_struct and filelist_struct's *//* that it points to. The "this_dir" will be passed using *//* addr5, so this function must not contain any calls to *//* the addr5 function! */static xdata simm_id fl_struct_id_state;/* this bit is set by file_cache_work when it is waiting *//* for a FAT sector and can not continue to process the file *//* until that sector is transfered. The bit is cleared by the *//* IDE driver every time a sector group is transfered. This *//* ugly hack allows us to avoid calling file_cache_work when *//* it is useless to do so. */static bit at 0x18 fcw_is_waiting;static bit fl_struct_already_allocated;static bit caching_dir;static bit seek_needed;static bit this_dir_filelist_started;void dirlist_read_dir(dirlist_t *this_dir){ xdata char r; xdata char dir_fd; //xdata char *bu; //data simm_id temp_dl; xdata char *filename;#ifdef VERBOSE_DEBUG r = SP; print("Entered dirlist_read_dir, dir "); print_str(Addr6(this_dir->long_name)); print("(depth="); print_uint8(subdir_depth); print("sp="); print_uint8(r); print(")\r\n");#endif fl_struct_already_allocated = 0; directory_count++; dir_fd = file_open_by_1st_cluster(this_dir->cluster); file_cache(dir_fd, 0, 0xFFFFFFFF); // request entire directory cached caching_dir = 1; seek_needed = 1;#if 1 do { r = file_cache_work(dir_fd); if (r == 2) pm2_exit(); do_ide_loop(4); } while (r == 0); do_ide_loop(8); file_seek(dir_fd, 0);#endif /* a minor speedup... use a fast "bit" instead of checking */ /* this 32 bit value indirectly accessed in xdata (slow) */ if (this_dir->filelist_start == 0) { this_dir_filelist_started = 0; } else { this_dir_filelist_started = 1; } while(1) {#if 0 /* this crazy idea is to be reading the directory and parsing */ /* it at the same time. It does not work yet... :( */ if (caching_dir && !fcw_is_waiting) { r = file_cache_work(dir_fd); if (r == 2) pm2_exit(); if (r) caching_dir = 0; } if (seek_needed) { r = file_seek(dir_fd, 0); if (r == 0) { seek_needed = 0; } else { continue; } }#endif if (fl_struct_already_allocated) { temp_id = fl_struct_id_state; fl_struct_already_allocated = 0; } else { temp_id = simm_malloc(sizeof(filelist_t)); } fl_struct = addr7(temp_id); // common case: files rather than directories r = dir_read_fast(dir_fd, fl_struct); if (r == 1) { // print("dir_read_fast returned 1 (xfer pending)\r\n"); do_ide_loop(4); // data wasn't in cache yet. continue; } if (r) break; // all other errors, stop reading this directory#ifdef VERBOSE_DEBUG print("attrib="); print_hex16(fl_struct->attrib); print(": "); /* printf("a=%x, len=%d, ", fl_struct->attrib, fl_struct->name_length); */ /* printf("ext=%c%c%c, ", (char)fl_struct->extension[0], (char)fl_struct->extension[1], (char)fl_struct->extension[2]); */ /* printf("clust=%lx, ", fl_struct->cluster); */ /* printf("size=%lx: ", fl_struct->size); */#endif if (fl_struct->attrib == 0x17) { print("Skipping RECYCLED directory\r\n"); continue; } if ((fl_struct->attrib & 0x0C) != 0) { print("Skipping system/hidden file\r\n"); continue; } // allocate memory and read filename. Initial length is rounded // up to nearest entry boundary (13) - length is adjusted upon // reading of actual entry. fl_struct->long_name = simm_malloc(fl_struct->name_length); filename = Addr6(fl_struct->long_name); dir_read_fast_name(filename);#ifdef VERBOSE_DEBUG print_str(filename); print_crlf();#endif if(fl_struct->attrib & 0x10) { if (*filename != '.') { // abnormal case - copy data from fl_struct to dl_struct;#ifdef VERBOSE_DEBUG print("Processing directory: "); print_str(filename); print_crlf();#endif fl_struct_id_state = temp_id; // save id of allocated fl_struct fl_struct_already_allocated = 1; temp_id = simm_malloc(sizeof(dirlist_t)); dl_struct = addr6(temp_id); // TODO: replace with a fast memcpy memcpy(dl_struct, fl_struct, 17); // copy first 6 items between structs if(this_dir->subdir_start == 0) { this_dir->subdir_start = temp_id; this_dir->subdir_end = temp_id; dl_struct = addr6(temp_id); dl_struct->prev = 0; } else { dl_struct = Addr6(this_dir->subdir_end); dl_struct->next = temp_id; dl_struct = addr6(temp_id); dl_struct->prev = this_dir->subdir_end; this_dir->subdir_end = temp_id; } dl_struct->next = 0; dl_struct->subdir_start = 0; dl_struct->subdir_end = 0; dl_struct->filelist_start = 0; dl_struct->filelist_end = 0; dl_struct->parent_dir = simm_id_from_pointer(this_dir); dl_struct->open = 1; dl_struct->treedir_expand = 0;// directory not expanded } } else { total_file_count++; switch (test_file_extension()) { case 1: /* MP3 extension */ //if(this_dir->filelist_start == 0) { if (!this_dir_filelist_started) { this_dir->filelist_start = temp_id; this_dir->filelist_end = temp_id; fl_struct->prev = 0; this_dir_filelist_started = 1; } else { fl_struct = Addr7(this_dir->filelist_end); fl_struct->next = temp_id; fl_struct = addr7(temp_id); fl_struct->prev = this_dir->filelist_end; this_dir->filelist_end = temp_id; } fl_struct->next = 0; playlist_add_file(temp_id); // TODO, move this someday mp3_file_count++; break; case 2: /* M3U extension */ // add m3u file to list to process later if(m3u_list_start == 0) { m3u_list_start = temp_id; m3u_list_end = temp_id; fl_struct->prev=0; } else { fl_struct = Addr7(m3u_list_end); fl_struct->next = temp_id; fl_struct = addr7(temp_id); fl_struct->prev = m3u_list_end; m3u_list_end = temp_id; } fl_struct->next=0; print("Playlist "); print_str(filename); print(" queued\r\n"); m3u_file_count++; break; default: // this really slows things down if there are a lot of // non-mp3 files on the hard drive //print("Unknown file extension, ignoring: "); //print_str(filename); //print_crlf(); ; } } } file_close(dir_fd); free_fat_memory();}void m3u_list_show() { temp_id = m3u_list_start; print("M3U files found:\r\n"); while (temp_id != 0) { fl_struct = addr6(temp_id); print_str(Addr7(fl_struct->long_name)); print("cluster="); print_hex32(fl_struct->cluster); print("size="); print_hex32(fl_struct->size); printf("ext=%c%c%c\r\n", (char) fl_struct->extension[0], (char) fl_struct->extension[1], (char) fl_struct->extension[2]); temp_id = fl_struct->next; }}// allow for leading /, dirs, and filename parts #define MAX_M3U_PATH_PARTS (MAX_SUBDIR_DEPTH+2)static volatile xdata char * data m3u_ptr;static unsigned long m3u_size;static xdata char * m3u_pathname[MAX_M3U_PATH_PARTS];static unsigned char num_path_parts;volatile static xdata at 0xFF08 unsigned int block_4000_mapping;volatile static xdata at 0xFF0A unsigned int block_5000_mapping;//volatile static xdata at 0xFF0C unsigned int block_6000_mapping;//volatile static xdata at 0xFF0E unsigned int block_7000_mapping;unsigned char parse_next_m3u_line(xdata char fd){ //print("parse next line"); //print_crlf(); if(m3u_ptr > (xdata char *)0x4FFF) { block_4000_mapping = block_5000_mapping; // remap 0x5000 block to 0x4000 m3u_size-=4096; if(m3u_size>4096) // load new 0x5000 block in if necessary file_mem_map(fd, 5); // map next 4k of file to 'address block' 5 m3u_ptr-=4096; // change m3u_ptr to point to same position within 0x4000 } num_path_parts = 0; m3u_pathname[0] = m3u_ptr; //printf("m3u_ptr=%d\r\n", m3u_ptr); //print("m3u_size = "); //print_hex32(m3u_size); //print_crlf(); while (m3u_size>4096 || (m3u_ptr < (xdata char *)(0x4000 + m3u_size))) { switch (*m3u_ptr) { case '\\': case '/': //if(start_of_line) // ignore leading / if present // break; // hmmm, are .m3u files specified relative to the directory // in which they are in? if so, we need to take account of // leading slashes to indicate start searching from root dir // and store a ptr to the 'current' directory (where the .m3u // file is stored as a baseline // TODO: store a ptr to the base directory, then if leading / // go to root (in m3u_add_file) *m3u_ptr = 0; if(++num_path_parts<MAX_M3U_PATH_PARTS) { m3u_pathname[num_path_parts]=m3u_ptr+1; } else { print("Too many parts in m3u path name"); print_crlf(); // return num_path_parts (not -1) so accesible data is returned, // even if of no use, but also so it still tries next line return num_path_parts; } break; // unused code case 10: case 13: *m3u_ptr = 0; m3u_ptr++; if (*m3u_ptr == 10 || *m3u_ptr == 13) { *m3u_ptr = 0; m3u_ptr++; } return (num_path_parts + 1); default: break; // do nothing } m3u_ptr++; } *m3u_ptr = 0; //print("end of file"); //print_crlf(); return 0; // hit end of file...}void m3u_add_file() {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -