Index: apps/misc.h
===================================================================
--- apps/misc.h	(revision 18241)
+++ apps/misc.h	(working copy)
@@ -111,6 +111,7 @@
 #endif
 
 int open_utf8(const char* pathname, int flags);
+bool file_copy(const char* src, const char* target);
 
 #ifdef BOOTFILE
 #if !defined(USB_NONE) && !defined(USB_IPODSTYLE)
Index: apps/playlist.c
===================================================================
--- apps/playlist.c	(revision 18242)
+++ apps/playlist.c	(working copy)
@@ -1854,6 +1854,11 @@
 
     mutex_lock(&playlist->control_mutex);
 
+    if (playlist->bmark_fd >= 0)
+    {
+        close(playlist->bmark_fd); 
+        playlist->bmark_fd = -1;
+    }
     cache = &(playlist->control_cache[playlist->num_cached++]);
 
     cache->command = command;
@@ -1936,6 +1941,7 @@
         "%s", PLAYLIST_CONTROL_FILE);
     playlist->fd = -1;
     playlist->control_fd = -1;
+    playlist->bmark_fd = -1;
     playlist->max_playlist_size = global_settings.max_files_in_playlist;
     playlist->indices = buffer_alloc(
         playlist->max_playlist_size * sizeof(int));
@@ -2291,6 +2297,9 @@
                     case '#':
                         current_command = PLAYLIST_COMMAND_COMMENT;
                         break;
+                    case 'B':
+                        current_command = PLAYLIST_COMMAND_RESUMEPOINT;
+                        break;
                     default:
                         result = -1;
                         exit_loop = true;
@@ -3608,3 +3617,73 @@
 
     return result;
 }
+
+
+bool playlist_add_bookmark(char *bmark_filename, bool createnew)
+{
+    struct playlist_info *pl = &current_playlist;
+    struct playlist_resume_point resume_pt;
+    /* grab the currently playing track */
+    struct mp3entry *id3 = audio_current_track();
+    if(!id3)
+        return false;
+    resume_pt.track_position = id3->offset;
+    playlist_get_resume_info(&resume_pt.playlist_index);
+    sync_control(pl, true);
+    if (createnew || pl->bmark_fd < 0)
+    {
+        if (pl->bmark_fd >= 0)
+            close(pl->bmark_fd);
+        if (file_copy(PLAYLIST_CONTROL_FILE, bmark_filename) == false)
+            return false;
+        pl->bmark_fd = open(bmark_filename, O_RDWR|O_APPEND);
+        if (pl->bmark_fd < 0)
+            return false;
+    }
+    fdprintf(pl->bmark_fd, "B:%d:%ld\n", resume_pt.playlist_index, resume_pt.track_position);
+    return true;
+}
+
+/* setup the playlist from a bmark file and find any resume points in the bmark
+   if successful *resumes_count will be set to the number of available resumes
+   current_playlist.bmark_fd will also be set the to correct file and at the end
+   and ready to add new points if the playlist isnt changed */
+bool playlist_resume_bookmark(char *bmark_filename, struct playlist_resume_point *resumes, int *resumes_count)
+{
+    int maxresumes = *resumes_count;
+    struct playlist_info *pl = &current_playlist;
+    char buf[MAX_PATH];
+    *resumes_count = 0;
+    playlist_close(pl); /* may not be the best way to do this */
+    if (file_copy(bmark_filename, PLAYLIST_CONTROL_FILE) == false)
+        return false;
+    if (playlist_resume() >= 0)
+    {
+        /* playlist is loaded, open the origional bmark file and find any resume points */
+        pl->bmark_fd = open(bmark_filename, O_RDWR);
+        if (pl->bmark_fd < 0)
+            return false;
+        while (read_line(pl->bmark_fd, buf, MAX_PATH) > 0 &&
+               *resumes_count < maxresumes)
+        {
+            if (buf[0] == 'B')
+            {
+                struct playlist_resume_point *r = &resumes[*resumes_count];
+                if (sscanf(buf, "B:%d:%ld", &r->playlist_index, &r->track_position) == 2)
+                    (*resumes_count)++;
+            }
+        }
+        lseek(pl->bmark_fd, SEEK_END, 0);
+        return true;
+    }
+    return false;
+}
+    
+    
+    
+    
+    
+    
+    
+    
+        
\ No newline at end of file
Index: apps/playlist.h
===================================================================
--- apps/playlist.h	(revision 18241)
+++ apps/playlist.h	(working copy)
@@ -42,7 +42,8 @@
     PLAYLIST_COMMAND_SHUFFLE,
     PLAYLIST_COMMAND_UNSHUFFLE,
     PLAYLIST_COMMAND_RESET,
-    PLAYLIST_COMMAND_COMMENT
+    PLAYLIST_COMMAND_COMMENT,
+    PLAYLIST_COMMAND_RESUMEPOINT
 };
 
 enum {
@@ -76,6 +77,8 @@
     int  fd;             /* descriptor of the open playlist file    */
     int  control_fd;     /* descriptor of the open control file     */
     bool control_created; /* has control file been created?         */
+    int  bmark_fd;       /* fd of the bmark file if it exists. set to -1 if
+                            the control changes and it exists       */
     int  dirlen;         /* Length of the path to the playlist file */
     unsigned long *indices; /* array of indices                     */
     const struct dircache_entry **filenames; /* Entries from dircache */
@@ -113,6 +116,12 @@
     int  display_index;      /* index of track for display          */
 };
 
+struct playlist_resume_point
+{
+    int playlist_index; /* index into the playlist for the current track */
+    long track_position; /* position in the current song to resume from */
+};
+
 /* Exported functions only for current playlist. */
 void playlist_init(void);
 void playlist_shutdown(void);
Index: apps/onplay.c
===================================================================
--- apps/onplay.c	(revision 18241)
+++ apps/onplay.c	(working copy)
@@ -684,77 +684,10 @@
 /* Paste a file to a new directory. Will overwrite always. */
 static bool clipboard_pastefile(const char *src, const char *target, bool copy)
 {
-    int src_fd, target_fd;
-    size_t buffersize;
-    ssize_t size, bytesread, byteswritten;
-    char *buffer;
     bool result = false;
 
     if (copy) {
-        /* See if we can get the plugin buffer for the file copy buffer */
-        buffer = (char *) plugin_get_buffer(&buffersize);
-        if (buffer == NULL || buffersize < 512) {
-            /* Not large enough, try for a disk sector worth of stack
-               instead */
-            buffersize = 512;
-            buffer = (char *) __builtin_alloca(buffersize);
-        }
-
-        if (buffer == NULL) {
-            return false;
-        }
-
-        buffersize &= ~0x1ff;  /* Round buffer size to multiple of sector
-                                  size */
-
-        src_fd = open(src, O_RDONLY);
-
-        if (src_fd >= 0) {
-            target_fd = creat(target);
-
-            if (target_fd >= 0) {
-                result = true;
-
-                size = filesize(src_fd);
-
-                if (size == -1) {
-                    result = false;
-                }
-
-                while(size > 0) {
-                    bytesread = read(src_fd, buffer, buffersize);
-
-                    if (bytesread == -1) {
-                        result = false;
-                        break;
-                    }
-
-                    size -= bytesread;
-
-                    while(bytesread > 0) {
-                        byteswritten = write(target_fd, buffer, bytesread);
-
-                        if (byteswritten == -1) {
-                            result = false;
-                            size = 0;
-                            break;
-                        }
-
-                        bytesread -= byteswritten;
-                        draw_slider();
-                    }
-                }
-
-                close(target_fd);
-
-                /* Copy failed. Cleanup. */
-                if (!result) {
-                    remove(target);
-                }
-            }
-
-            close(src_fd);
-        }
+        result = file_copy(src, target);
     } else {
         result = rename(src, target) == 0;
 #ifdef HAVE_MULTIVOLUME
Index: apps/filetree.c
===================================================================
--- apps/filetree.c	(revision 18241)
+++ apps/filetree.c	(working copy)
@@ -381,6 +381,7 @@
         int seed = current_tick;
         bool play = false;
         int start_index=0;
+        long track_offset = 0;
 
         switch ( file->attr & FILE_ATTR_MASK ) {
             case FILE_ATTR_M3U:
@@ -491,7 +492,10 @@
 
             case FILE_ATTR_BMARK:
                 gui_syncsplash(0, ID2P(LANG_WAIT));
-                bookmark_load(buf, false);
+                if (bookmark_load(buf, false) == true)
+                {
+                    start_wps = true;
+                }
                 reload_dir = true;
                 break;
 
Index: apps/bookmark.c
===================================================================
--- apps/bookmark.c	(revision 18241)
+++ apps/bookmark.c	(working copy)
@@ -110,7 +110,10 @@
 /* ----------------------------------------------------------------------- */
 bool bookmark_create_menu(void)
 {
-    write_bookmark(true, create_bookmark());
+//    write_bookmark(true, create_bookmark());
+    char buffer[MAX_PATH];
+    if (!playlist_add_bookmark("/dummy.bmark", false))
+        gui_syncsplash(HZ, "FAiled!");
     return false;
 }
 
@@ -415,10 +418,85 @@
 
 /* ----------------------------------------------------------------------- */
 /* This function loads the bookmark information into the resume memory.    */
-/* This is an interface function.                                          */
 /* ------------------------------------------------------------------------*/
+#define PREVIOUS_BMARK_FILE ROCKBOX_DIR "/previous.bmark"
+static char bookmark_resume_points[MAX_BOOKMARKS][MAX_BOOKMARK_SIZE];
+static int selection = -1;
+char * bmark_get_name(int selected_item, void * data,
+                     char * buffer, size_t buffer_len)
+{
+    return bookmark_resume_points[selected_item];
+}
+int bmark_action_callback(int action, struct gui_synclist *lists)
+{
+    if (action == ACTION_STD_OK)
+    {
+        selection = lists->selected_item;
+        return ACTION_STD_CANCEL;
+    }
+    if (action == ACTION_STD_CANCEL)
+        selection = -1;
+    return action;
+}
 bool bookmark_load(const char* file, bool autoload)
 {
+    struct playlist_resume_point resumes[MAX_BOOKMARKS];
+    int resume_count = MAX_BOOKMARKS;
+    int i;
+    bool load_previous = !strcmp(file, PREVIOUS_BMARK_FILE);
+    struct playlist_track_info info;
+    int audio_playing = audio_status();
+    /* dump the current playlist and position incase the user wants to cancel */
+    if (load_previous)
+    {
+        if (playlist_resume_bookmark(PREVIOUS_BMARK_FILE, resumes, &resume_count)
+            && resume_count > 0)
+        {
+            remove(PREVIOUS_BMARK_FILE);
+            playlist_start(resumes[0].playlist_index,resumes[0].track_position);
+        }
+        return false;
+    }
+    
+    playlist_add_bookmark(PREVIOUS_BMARK_FILE, true);
+    if (playlist_resume_bookmark(file, resumes, &resume_count) && resume_count > 0)
+    {
+        if (resume_count > 1)
+        {
+            for (i=0;i<resume_count;i++)
+            {
+                if (playlist_get_track_info(NULL, resumes[i].playlist_index, &info) > -1)
+                {
+                    snprintf(bookmark_resume_points[i], MAX_BOOKMARK_SIZE, "%s: %d",
+                             info.filename, resumes[i].track_position);
+                }
+            }
+            struct simplelist_info list;
+            simplelist_info_init(&list, "Bookmark", resume_count, NULL);
+            list.action_callback = bmark_action_callback;
+            list.get_name = bmark_get_name;
+            selection = -1;
+            simplelist_show_list(&list);
+            if (selection == -1)
+            {
+                if (audio_playing)
+                    return bookmark_load(PREVIOUS_BMARK_FILE, true);
+                return false;
+            }
+        }
+        else
+            selection = 0;
+        
+        playlist_start(resumes[selection].playlist_index,
+                       resumes[selection].track_position);
+        return true;
+    }
+    else 
+        return bookmark_load(PREVIOUS_BMARK_FILE, true);
+        
+    return false;
+
+#if 0
     int  fd;
     char* bookmark = NULL;
 
@@ -451,8 +529,7 @@
             return false;
         }
     }
-
-    return true;
+#endif
 }
 
 
Index: apps/misc.c
===================================================================
--- apps/misc.c	(revision 18241)
+++ apps/misc.c	(working copy)
@@ -1208,7 +1208,79 @@
     return fd;
 }
 
+/** Copy a file from src to dst **/
+bool file_copy(const char* src, const char* target)
+{
+    int src_fd, target_fd;
+    size_t buffersize;
+    ssize_t size, bytesread, byteswritten;
+    char *buffer;
+    bool result = false;
+    /* See if we can get the plugin buffer for the file copy buffer */
+    buffer = (char *) plugin_get_buffer(&buffersize);
+    if (buffer == NULL || buffersize < 512) {
+            /* Not large enough, try for a disk sector worth of stack
+        instead */
+        buffersize = 512;
+        buffer = (char *) __builtin_alloca(buffersize);
+    }
 
+    if (buffer == NULL) {
+        return false;
+    }
+
+    buffersize &= ~0x1ff;  /* Round buffer size to multiple of sector
+    size */
+
+    src_fd = open(src, O_RDONLY);
+
+    if (src_fd >= 0) {
+        target_fd = creat(target);
+
+        if (target_fd >= 0) {
+            result = true;
+
+            size = filesize(src_fd);
+
+            if (size == -1) {
+                result = false;
+            }
+
+            while(size > 0) {
+                bytesread = read(src_fd, buffer, buffersize);
+
+                if (bytesread == -1) {
+                    result = false;
+                    break;
+                }
+
+                size -= bytesread;
+
+                while(bytesread > 0) {
+                    byteswritten = write(target_fd, buffer, bytesread);
+
+                    if (byteswritten == -1) {
+                        result = false;
+                        size = 0;
+                        break;
+                    }
+
+                    bytesread -= byteswritten;
+         //          draw_slider();
+                }
+            }
+
+            close(target_fd);
+
+            /* Copy failed. Cleanup. */
+            if (!result) {
+                remove(target);
+            }
+        }
+        close(src_fd);
+    }
+    return result;
+}
 #ifdef HAVE_LCD_COLOR
 /*
  * Helper function to convert a string of 6 hex digits to a native colour
