test

Dependencies:   SDFileSystem mbed-dev

Fork of Nucleo_Ex06_EMU by woodstock .

Committer:
charliex
Date:
Sat May 27 02:17:37 2017 +0000
Revision:
4:53ef91c87d74
test

Who changed what in which revision?

UserRevisionLine numberNew contents of line
charliex 4:53ef91c87d74 1 /*===================================================================*/
charliex 4:53ef91c87d74 2 /* */
charliex 4:53ef91c87d74 3 /* pNesX_Filer.cpp : ROM selection screen */
charliex 4:53ef91c87d74 4 /* */
charliex 4:53ef91c87d74 5 /* 2016/1/20 Racoon */
charliex 4:53ef91c87d74 6 /* */
charliex 4:53ef91c87d74 7 /*===================================================================*/
charliex 4:53ef91c87d74 8
charliex 4:53ef91c87d74 9 #include "mbed.h"
charliex 4:53ef91c87d74 10 #include "SDFileSystem.h"
charliex 4:53ef91c87d74 11 #include "tft.h"
charliex 4:53ef91c87d74 12
charliex 4:53ef91c87d74 13 #include "pNesX_Types.h"
charliex 4:53ef91c87d74 14
charliex 4:53ef91c87d74 15 extern void pNesX_PadState( DWORD *pdwPad1, DWORD *pdwPad2, DWORD *pdwSystem );
charliex 4:53ef91c87d74 16 extern const unsigned char pNesX_logo[];
charliex 4:53ef91c87d74 17 extern const unsigned char Racoon_logo[];
charliex 4:53ef91c87d74 18
charliex 4:53ef91c87d74 19 #define LOGO_BACKCOLOR 0x86fd
charliex 4:53ef91c87d74 20
charliex 4:53ef91c87d74 21 #define FOLDER_FILE_MAX 100
charliex 4:53ef91c87d74 22 #define LIST_ROWS 20
charliex 4:53ef91c87d74 23 #define LIST_TOP 40
charliex 4:53ef91c87d74 24 #define LIST_LEFT 4
charliex 4:53ef91c87d74 25
charliex 4:53ef91c87d74 26 static int DispTop; // Top of the list
charliex 4:53ef91c87d74 27 static int SelIdx; // Cursor index
charliex 4:53ef91c87d74 28 static int FileCount; // Number of files in the folder
charliex 4:53ef91c87d74 29
charliex 4:53ef91c87d74 30 // file information
charliex 4:53ef91c87d74 31 typedef struct tagLISTITEM{
charliex 4:53ef91c87d74 32 char filename[33];
charliex 4:53ef91c87d74 33 bool isDir;
charliex 4:53ef91c87d74 34 long size;
charliex 4:53ef91c87d74 35 } LISTITEM;
charliex 4:53ef91c87d74 36
charliex 4:53ef91c87d74 37 // folder file list
charliex 4:53ef91c87d74 38 LISTITEM *flist;
charliex 4:53ef91c87d74 39
charliex 4:53ef91c87d74 40 char szRomFolder[32];
charliex 4:53ef91c87d74 41 char szPrevFolder[32];
charliex 4:53ef91c87d74 42 char szRomFilename[33];
charliex 4:53ef91c87d74 43 char szRomPath[256];
charliex 4:53ef91c87d74 44
charliex 4:53ef91c87d74 45 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 46 /* Get file extension */
charliex 4:53ef91c87d74 47 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 48 char *get_ext(char *filename)
charliex 4:53ef91c87d74 49 {
charliex 4:53ef91c87d74 50 int i;
charliex 4:53ef91c87d74 51 for (i = strlen(filename) - 1; i >= 0; --i) {
charliex 4:53ef91c87d74 52 if (filename[i] == '.') {
charliex 4:53ef91c87d74 53 return &filename[i + 1];
charliex 4:53ef91c87d74 54 }
charliex 4:53ef91c87d74 55 }
charliex 4:53ef91c87d74 56 return NULL;
charliex 4:53ef91c87d74 57 }
charliex 4:53ef91c87d74 58
charliex 4:53ef91c87d74 59 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 60 /* Get file path */
charliex 4:53ef91c87d74 61 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 62 char *get_filepath(char *path, char *filename)
charliex 4:53ef91c87d74 63 {
charliex 4:53ef91c87d74 64 static char filepath[256];
charliex 4:53ef91c87d74 65
charliex 4:53ef91c87d74 66 if (strncmp(path, "/sd", 3) != 0)
charliex 4:53ef91c87d74 67 {
charliex 4:53ef91c87d74 68 filepath[0] = 0;
charliex 4:53ef91c87d74 69 return filepath;
charliex 4:53ef91c87d74 70 }
charliex 4:53ef91c87d74 71
charliex 4:53ef91c87d74 72 int len = strlen(path);
charliex 4:53ef91c87d74 73 if (len < 4) {
charliex 4:53ef91c87d74 74 strcpy(filepath, filename);
charliex 4:53ef91c87d74 75 } else {
charliex 4:53ef91c87d74 76 sprintf(filepath, "%s/%s", &path[4], filename);
charliex 4:53ef91c87d74 77 }
charliex 4:53ef91c87d74 78
charliex 4:53ef91c87d74 79 return filepath;
charliex 4:53ef91c87d74 80 }
charliex 4:53ef91c87d74 81
charliex 4:53ef91c87d74 82 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 83 /* Get file list in the folder */
charliex 4:53ef91c87d74 84 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 85 int get_filelist(char *path)
charliex 4:53ef91c87d74 86 {
charliex 4:53ef91c87d74 87 DIR *dir = opendir(path);
charliex 4:53ef91c87d74 88 if ( dir == NULL ) {
charliex 4:53ef91c87d74 89 return 0;
charliex 4:53ef91c87d74 90 }
charliex 4:53ef91c87d74 91
charliex 4:53ef91c87d74 92 dirent *entry;
charliex 4:53ef91c87d74 93 FILINFO fi;
charliex 4:53ef91c87d74 94 fi.lfname = NULL;
charliex 4:53ef91c87d74 95 fi.lfsize = 0;
charliex 4:53ef91c87d74 96 int i = 0;
charliex 4:53ef91c87d74 97
charliex 4:53ef91c87d74 98 // not root
charliex 4:53ef91c87d74 99 if (strcmp(path, "/sd") != 0) {
charliex 4:53ef91c87d74 100 strcpy(flist[i].filename, "..");
charliex 4:53ef91c87d74 101 flist[i].isDir = true;
charliex 4:53ef91c87d74 102 i++;
charliex 4:53ef91c87d74 103 }
charliex 4:53ef91c87d74 104
charliex 4:53ef91c87d74 105 // folder
charliex 4:53ef91c87d74 106 while ((entry = readdir(dir)) != NULL && i < FOLDER_FILE_MAX) {
charliex 4:53ef91c87d74 107 if (f_stat(get_filepath(path, entry->d_name), &fi) == FR_OK) {
charliex 4:53ef91c87d74 108 int len = strlen(entry->d_name);
charliex 4:53ef91c87d74 109 len = len > 32 ? 32 : len;
charliex 4:53ef91c87d74 110 if (entry->d_name[0] == '.') continue;
charliex 4:53ef91c87d74 111
charliex 4:53ef91c87d74 112 memcpy(flist[i].filename, entry->d_name, len);
charliex 4:53ef91c87d74 113 flist[i].filename[len] = 0;
charliex 4:53ef91c87d74 114 flist[i].isDir = fi.fattrib & AM_DIR;
charliex 4:53ef91c87d74 115 flist[i].size = fi.fsize;
charliex 4:53ef91c87d74 116 ++i;
charliex 4:53ef91c87d74 117 }
charliex 4:53ef91c87d74 118 }
charliex 4:53ef91c87d74 119
charliex 4:53ef91c87d74 120 closedir(dir);
charliex 4:53ef91c87d74 121
charliex 4:53ef91c87d74 122 return i;
charliex 4:53ef91c87d74 123 }
charliex 4:53ef91c87d74 124
charliex 4:53ef91c87d74 125
charliex 4:53ef91c87d74 126 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 127 /* Get file information string */
charliex 4:53ef91c87d74 128 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 129 char* filedata(int idx)
charliex 4:53ef91c87d74 130 {
charliex 4:53ef91c87d74 131 static char disptext[41];
charliex 4:53ef91c87d74 132
charliex 4:53ef91c87d74 133 if (flist[idx].isDir) {
charliex 4:53ef91c87d74 134 sprintf(disptext, "%-32s <DIR>", flist[idx].filename);
charliex 4:53ef91c87d74 135 } else {
charliex 4:53ef91c87d74 136 sprintf(disptext, "%-32s %6d", flist[idx].filename, flist[idx].size);
charliex 4:53ef91c87d74 137 }
charliex 4:53ef91c87d74 138
charliex 4:53ef91c87d74 139 return disptext;
charliex 4:53ef91c87d74 140 }
charliex 4:53ef91c87d74 141
charliex 4:53ef91c87d74 142 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 143 /* Draw file list */
charliex 4:53ef91c87d74 144 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 145 void draw_list()
charliex 4:53ef91c87d74 146 {
charliex 4:53ef91c87d74 147 int i,y;
charliex 4:53ef91c87d74 148
charliex 4:53ef91c87d74 149 for (y = 0, i = DispTop; y < LIST_ROWS && i < FileCount; ++y, ++i) {
charliex 4:53ef91c87d74 150 tft_text( LIST_LEFT, LIST_TOP + y * 8, filedata(i), TFT_WHITE, TFT_BLACK );
charliex 4:53ef91c87d74 151 }
charliex 4:53ef91c87d74 152
charliex 4:53ef91c87d74 153 if (y < LIST_ROWS) {
charliex 4:53ef91c87d74 154 tft_boxfill( 0, LIST_TOP + y * 8, 319, LIST_TOP + LIST_ROWS * 8 - 1, TFT_BLACK);
charliex 4:53ef91c87d74 155 }
charliex 4:53ef91c87d74 156 }
charliex 4:53ef91c87d74 157
charliex 4:53ef91c87d74 158 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 159 /* Draw cursor */
charliex 4:53ef91c87d74 160 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 161 void draw_cursor(bool clear = false)
charliex 4:53ef91c87d74 162 {
charliex 4:53ef91c87d74 163 int y = SelIdx - DispTop;
charliex 4:53ef91c87d74 164 if (clear) {
charliex 4:53ef91c87d74 165 tft_box( LIST_LEFT - 1, LIST_TOP + y * 8 - 1, LIST_LEFT + 39 * 8, LIST_TOP + y * 8 + 7, TFT_BLACK);
charliex 4:53ef91c87d74 166 tft_text( LIST_LEFT, LIST_TOP + y * 8, filedata(SelIdx), TFT_WHITE, TFT_BLACK );
charliex 4:53ef91c87d74 167 } else {
charliex 4:53ef91c87d74 168 tft_box( LIST_LEFT - 1, LIST_TOP + y * 8 - 1, LIST_LEFT + 39 * 8, LIST_TOP + y * 8 + 7, TFT_YELLOW);
charliex 4:53ef91c87d74 169 tft_text( LIST_LEFT, LIST_TOP + y * 8, filedata(SelIdx), TFT_BLACK, TFT_YELLOW );
charliex 4:53ef91c87d74 170 }
charliex 4:53ef91c87d74 171 }
charliex 4:53ef91c87d74 172
charliex 4:53ef91c87d74 173 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 174 /* Draw back ground */
charliex 4:53ef91c87d74 175 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 176 void draw_frame()
charliex 4:53ef91c87d74 177 {
charliex 4:53ef91c87d74 178 tft_boxfill( 0, 0, 319, 31, LOGO_BACKCOLOR);
charliex 4:53ef91c87d74 179 tft_boxfill(0, 32, 319, 223, TFT_BLACK);
charliex 4:53ef91c87d74 180 tft_boxfill( 0, 224, 319, 239, LOGO_BACKCOLOR);
charliex 4:53ef91c87d74 181
charliex 4:53ef91c87d74 182 draw_bmp_4bpp(pNesX_logo, 8, 6);
charliex 4:53ef91c87d74 183 tft_text( 100, 225, "layerOne 2017", TFT_BLACK, LOGO_BACKCOLOR );
charliex 4:53ef91c87d74 184 //tft_text( 200, 233, "R1+R2:Reset", TFT_BLACK, LOGO_BACKCOLOR );
charliex 4:53ef91c87d74 185 // draw_bmp_4bpp(Racoon_logo, 0, 224);
charliex 4:53ef91c87d74 186 }
charliex 4:53ef91c87d74 187
charliex 4:53ef91c87d74 188 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 189 /* Dialog window */
charliex 4:53ef91c87d74 190 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 191 void dialog(char *msg)
charliex 4:53ef91c87d74 192 {
charliex 4:53ef91c87d74 193 if (msg)
charliex 4:53ef91c87d74 194 {
charliex 4:53ef91c87d74 195 tft_boxfill(0, 100, 319, 139, TFT_NAVY);
charliex 4:53ef91c87d74 196 int len = strlen(msg);
charliex 4:53ef91c87d74 197 len = len > 38 ? 38 : len;
charliex 4:53ef91c87d74 198 msg[len] = 0;
charliex 4:53ef91c87d74 199 int x = (40 - len) * 4;
charliex 4:53ef91c87d74 200 tft_text(x, 116, msg, TFT_WHITE, TFT_NAVY);
charliex 4:53ef91c87d74 201 }
charliex 4:53ef91c87d74 202 else
charliex 4:53ef91c87d74 203 {
charliex 4:53ef91c87d74 204 tft_boxfill(0, 100, 319, 139, TFT_BLACK);
charliex 4:53ef91c87d74 205 }
charliex 4:53ef91c87d74 206 }
charliex 4:53ef91c87d74 207
charliex 4:53ef91c87d74 208
charliex 4:53ef91c87d74 209 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 210 /* Rom selection */
charliex 4:53ef91c87d74 211 /*-------------------------------------------------------------------*/
charliex 4:53ef91c87d74 212 // return code:
charliex 4:53ef91c87d74 213 // 0 : File selected
charliex 4:53ef91c87d74 214 // 1 : Return to Emu
charliex 4:53ef91c87d74 215 // 2 : Reset
charliex 4:53ef91c87d74 216 // -1: Error
charliex 4:53ef91c87d74 217 int pNesX_Filer()
charliex 4:53ef91c87d74 218 {
charliex 4:53ef91c87d74 219 DWORD dwPad1=0, dwPad2=0, dwSystem=0;
charliex 4:53ef91c87d74 220 DWORD prev_dwPad1 = 0;
charliex 4:53ef91c87d74 221
charliex 4:53ef91c87d74 222 bool loadFolder;
charliex 4:53ef91c87d74 223 int keyrepeat = 1;
charliex 4:53ef91c87d74 224
charliex 4:53ef91c87d74 225 // Draw back ground
charliex 4:53ef91c87d74 226 draw_frame();
charliex 4:53ef91c87d74 227
charliex 4:53ef91c87d74 228 // init
charliex 4:53ef91c87d74 229 flist = (LISTITEM *)malloc(sizeof(LISTITEM) * FOLDER_FILE_MAX);
charliex 4:53ef91c87d74 230 if (flist == NULL) {
charliex 4:53ef91c87d74 231 return -1;
charliex 4:53ef91c87d74 232 }
charliex 4:53ef91c87d74 233
charliex 4:53ef91c87d74 234 loadFolder = true;
charliex 4:53ef91c87d74 235 int ret;
charliex 4:53ef91c87d74 236
charliex 4:53ef91c87d74 237 while(1) {
charliex 4:53ef91c87d74 238 if (loadFolder) {
charliex 4:53ef91c87d74 239 // Drawing of the files in the folder
charliex 4:53ef91c87d74 240 FileCount = get_filelist(szRomFolder);
charliex 4:53ef91c87d74 241
charliex 4:53ef91c87d74 242 if (FileCount > 0) {
charliex 4:53ef91c87d74 243 if (strcmp(szRomFolder, szPrevFolder) != 0)
charliex 4:53ef91c87d74 244 {
charliex 4:53ef91c87d74 245 DispTop = 0;
charliex 4:53ef91c87d74 246 SelIdx = 0;
charliex 4:53ef91c87d74 247 strcpy( szPrevFolder, szRomFolder);
charliex 4:53ef91c87d74 248 }
charliex 4:53ef91c87d74 249 draw_list();
charliex 4:53ef91c87d74 250 draw_cursor();
charliex 4:53ef91c87d74 251 }
charliex 4:53ef91c87d74 252 loadFolder = false;
charliex 4:53ef91c87d74 253 }
charliex 4:53ef91c87d74 254
charliex 4:53ef91c87d74 255 pNesX_PadState( &dwPad1, &dwPad2, &dwSystem );
charliex 4:53ef91c87d74 256
charliex 4:53ef91c87d74 257 if (dwPad1 != prev_dwPad1) {
charliex 4:53ef91c87d74 258 keyrepeat = 0;
charliex 4:53ef91c87d74 259 }
charliex 4:53ef91c87d74 260
charliex 4:53ef91c87d74 261 if (keyrepeat == 0 || keyrepeat >= 10) {
charliex 4:53ef91c87d74 262 // Down
charliex 4:53ef91c87d74 263 if (dwPad1 & KEYPAD_DOWN) {
charliex 4:53ef91c87d74 264 if (SelIdx < FileCount - 1) {
charliex 4:53ef91c87d74 265 // clear cursor
charliex 4:53ef91c87d74 266 draw_cursor(true);
charliex 4:53ef91c87d74 267
charliex 4:53ef91c87d74 268 if (SelIdx - DispTop == LIST_ROWS - 1) {
charliex 4:53ef91c87d74 269 DispTop++;
charliex 4:53ef91c87d74 270 draw_list();
charliex 4:53ef91c87d74 271 }
charliex 4:53ef91c87d74 272
charliex 4:53ef91c87d74 273 // draw new cursor
charliex 4:53ef91c87d74 274 SelIdx++;
charliex 4:53ef91c87d74 275 draw_cursor();
charliex 4:53ef91c87d74 276 }
charliex 4:53ef91c87d74 277 }
charliex 4:53ef91c87d74 278
charliex 4:53ef91c87d74 279 // Up
charliex 4:53ef91c87d74 280 if (dwPad1 & KEYPAD_UP) {
charliex 4:53ef91c87d74 281 if (SelIdx > 0) {
charliex 4:53ef91c87d74 282 // clear cursor
charliex 4:53ef91c87d74 283 draw_cursor(true);
charliex 4:53ef91c87d74 284
charliex 4:53ef91c87d74 285 if (SelIdx - DispTop == 0) {
charliex 4:53ef91c87d74 286 DispTop--;
charliex 4:53ef91c87d74 287 draw_list();
charliex 4:53ef91c87d74 288 }
charliex 4:53ef91c87d74 289
charliex 4:53ef91c87d74 290 // draw new cursor
charliex 4:53ef91c87d74 291 SelIdx--;
charliex 4:53ef91c87d74 292 draw_cursor();
charliex 4:53ef91c87d74 293 }
charliex 4:53ef91c87d74 294 }
charliex 4:53ef91c87d74 295
charliex 4:53ef91c87d74 296 // Select
charliex 4:53ef91c87d74 297 if (dwPad1 == KEYPAD_SELECT) {
charliex 4:53ef91c87d74 298 // clear cursor
charliex 4:53ef91c87d74 299 draw_cursor(true);
charliex 4:53ef91c87d74 300
charliex 4:53ef91c87d74 301 if (flist[SelIdx].isDir) {
charliex 4:53ef91c87d74 302 // folder
charliex 4:53ef91c87d74 303 if (strcmp(flist[SelIdx].filename, "..") != 0) {
charliex 4:53ef91c87d74 304 sprintf(szRomFolder, "%s/%s", szRomFolder, flist[SelIdx].filename);
charliex 4:53ef91c87d74 305 } else {
charliex 4:53ef91c87d74 306 // upper folder
charliex 4:53ef91c87d74 307 char *upper = strrchr(szRomFolder, '/');
charliex 4:53ef91c87d74 308 if (upper) {
charliex 4:53ef91c87d74 309 *upper = 0;
charliex 4:53ef91c87d74 310 }
charliex 4:53ef91c87d74 311 }
charliex 4:53ef91c87d74 312
charliex 4:53ef91c87d74 313 loadFolder = true;
charliex 4:53ef91c87d74 314 } else {
charliex 4:53ef91c87d74 315 char *ext = get_ext(flist[SelIdx].filename);
charliex 4:53ef91c87d74 316 if (ext != NULL && strcasecmp(ext, "nes") == 0)
charliex 4:53ef91c87d74 317 {
charliex 4:53ef91c87d74 318 strcpy(szRomFilename, flist[SelIdx].filename);
charliex 4:53ef91c87d74 319
charliex 4:53ef91c87d74 320
charliex 4:53ef91c87d74 321 strcpy(szRomPath, get_filepath(szRomFolder, szRomFilename));
charliex 4:53ef91c87d74 322
charliex 4:53ef91c87d74 323 ret = 0;
charliex 4:53ef91c87d74 324 break;
charliex 4:53ef91c87d74 325 }
charliex 4:53ef91c87d74 326 else
charliex 4:53ef91c87d74 327 {
charliex 4:53ef91c87d74 328 dialog("not a rom file!!");
charliex 4:53ef91c87d74 329 wait(1);
charliex 4:53ef91c87d74 330 dialog(NULL);
charliex 4:53ef91c87d74 331 draw_list();
charliex 4:53ef91c87d74 332 draw_cursor();
charliex 4:53ef91c87d74 333 }
charliex 4:53ef91c87d74 334 }
charliex 4:53ef91c87d74 335 }
charliex 4:53ef91c87d74 336
charliex 4:53ef91c87d74 337 // Return to Emu
charliex 4:53ef91c87d74 338 if (dwSystem & 0x01) {
charliex 4:53ef91c87d74 339 if ( szRomFilename[0] != 0 ) {
charliex 4:53ef91c87d74 340 do {
charliex 4:53ef91c87d74 341 wait(0.08);
charliex 4:53ef91c87d74 342 pNesX_PadState( &dwPad1, &dwPad2, &dwSystem );
charliex 4:53ef91c87d74 343
charliex 4:53ef91c87d74 344 } while (dwSystem & 0x01);
charliex 4:53ef91c87d74 345
charliex 4:53ef91c87d74 346 ret = 1;
charliex 4:53ef91c87d74 347 break;
charliex 4:53ef91c87d74 348 }
charliex 4:53ef91c87d74 349 }
charliex 4:53ef91c87d74 350
charliex 4:53ef91c87d74 351 // Reset
charliex 4:53ef91c87d74 352 if (dwSystem & 0x02) {
charliex 4:53ef91c87d74 353 if ( szRomFilename[0] != 0 ) {
charliex 4:53ef91c87d74 354 do {
charliex 4:53ef91c87d74 355 wait(0.08);
charliex 4:53ef91c87d74 356 pNesX_PadState( &dwPad1, &dwPad2, &dwSystem );
charliex 4:53ef91c87d74 357 } while (dwSystem & 0x02);
charliex 4:53ef91c87d74 358
charliex 4:53ef91c87d74 359 ret = 2;
charliex 4:53ef91c87d74 360 break;
charliex 4:53ef91c87d74 361 }
charliex 4:53ef91c87d74 362 }
charliex 4:53ef91c87d74 363 }
charliex 4:53ef91c87d74 364
charliex 4:53ef91c87d74 365 keyrepeat++;
charliex 4:53ef91c87d74 366
charliex 4:53ef91c87d74 367 prev_dwPad1 = dwPad1;
charliex 4:53ef91c87d74 368
charliex 4:53ef91c87d74 369 wait(0.08);
charliex 4:53ef91c87d74 370 }
charliex 4:53ef91c87d74 371
charliex 4:53ef91c87d74 372 // release memory
charliex 4:53ef91c87d74 373 free(flist);
charliex 4:53ef91c87d74 374
charliex 4:53ef91c87d74 375 return ret;
charliex 4:53ef91c87d74 376 }
charliex 4:53ef91c87d74 377