00001
00038 #include <dma.h>
00039 #include <hugemem.h>
00040 #include <physmem.h>
00041 #include <mainloop.h>
00042 #include <status_codes.h>
00043
00044 #include <board/physmem.h>
00045
00046 #include <fs/tsfs.h>
00047
00048 #include <gfx/gfx.h>
00049 #include <gfx/win.h>
00050 #include <gfx/wtk.h>
00051 #include <gfx/sysfont.h>
00052
00053 #include "file_loader.h"
00054
00061 #define MAX_LOAD_PIXELS 64
00062 #define MAX_LOAD_SIZE (MAX_LOAD_PIXELS * sizeof(gfx_color_t))
00063
00064 extern struct tsfs myfs;
00065
00066 struct file_loader {
00067 struct tsfs_file file;
00068 struct workqueue_task task;
00069 struct workqueue_task *done_task;
00070
00071
00072
00073
00074
00075
00076 union {
00077 hugemem_ptr_t hugemem_address;
00078 struct {
00079 gfx_coord_t current_x;
00080 gfx_coord_t current_y;
00081 };
00082 };
00083 union {
00084 uint32_t offset;
00085 struct {
00086 gfx_coord_t offset_x;
00087 gfx_coord_t offset_y;
00088 };
00089 };
00090
00091 gfx_coord_t width;
00092 gfx_coord_t height;
00093
00094 uint16_t load_size;
00095 uint8_t buffer[MAX_LOAD_SIZE];
00096 bool busy;
00097 };
00098
00099 static struct file_loader the_file_loader;
00100
00109 static void load_to_screen_worker(struct workqueue_task *task)
00110 {
00111 struct file_loader *floader = &the_file_loader;
00112 enum status_code result;
00113
00114 gfx_set_clipping(0, 0, gfx_get_width(), gfx_get_height());
00115
00116 gfx_put_pixmap((gfx_color_t *)floader->buffer,
00117 floader->load_size,
00118 0,
00119 0,
00120 floader->current_x + floader->offset_x,
00121 floader->current_y + floader->offset_y,
00122 floader->load_size,
00123 1);
00124
00125 floader->current_x += floader->load_size;
00126 if (floader->current_x >= floader->width) {
00127 floader->current_y++;
00128 floader->current_x = 0;
00129 }
00130
00131 floader->load_size = min_u((floader->width - floader->current_x),
00132 MAX_LOAD_PIXELS);
00133
00134 result = tsfs_read(&myfs, &floader->file, &floader->buffer,
00135 floader->load_size * sizeof(gfx_color_t),
00136 &floader->task);
00137
00138
00139 if ((result != STATUS_OK) || (floader->current_y > floader->height)) {
00140 floader->busy = false;
00141
00142 if (floader->done_task)
00143 workqueue_add_task(&main_workqueue, floader->done_task);
00144 }
00145 }
00146
00155 static void load_to_hugemem_worker(struct workqueue_task *task)
00156 {
00157 struct file_loader *floader = &the_file_loader;
00158 enum status_code result = STATUS_OK;
00159 uint32_t file_size;
00160
00161 file_size = floader->file.end - floader->file.start;
00162
00163 hugemem_write_block((hugemem_ptr_t)((uint32_t)floader->hugemem_address +
00164 floader->offset), floader->buffer, floader->load_size);
00165
00166 floader->offset += floader->load_size;
00167 floader->load_size = min_u(file_size - floader->offset,
00168 MAX_LOAD_SIZE);
00169
00170 if (floader->load_size) {
00171 result = tsfs_read(&myfs, &floader->file, &floader->buffer,
00172 floader->load_size, &floader->task);
00173 }
00174
00175 if (!floader->load_size || result != STATUS_OK) {
00176 floader->busy = false;
00177
00178 if (floader->done_task)
00179 workqueue_add_task(&main_workqueue,
00180 floader->done_task);
00181 }
00182 }
00183
00199 enum status_code load_file_to_screen(const char *filename, gfx_coord_t pos_x,
00200 gfx_coord_t pos_y, gfx_coord_t width, gfx_coord_t height,
00201 struct workqueue_task *done_task)
00202 {
00203 struct file_loader *floader = &the_file_loader;
00204 enum status_code result;
00205
00206 if (!tsfs_is_ready(&myfs))
00207 return ERR_IO_ERROR;
00208
00209 if (floader->busy)
00210 return ERR_BUSY;
00211
00212 floader->current_x = 0;
00213 floader->current_y = 0;
00214 floader->offset_x = pos_x;
00215 floader->offset_y = pos_y;
00216 floader->height = height;
00217 floader->width = width;
00218
00219 result = tsfs_open(&myfs, filename, &floader->file);
00220
00221 if (result != STATUS_OK)
00222 return ERR_INVALID_ARG;
00223
00224 floader->busy = true;
00225 floader->done_task = done_task;
00226
00227 floader->load_size = min_u(floader->width, MAX_LOAD_PIXELS);
00228
00229 workqueue_task_set_work_func(&floader->task, load_to_screen_worker);
00230
00231 result = tsfs_read(&myfs, &floader->file, &floader->buffer,
00232 floader->load_size * sizeof(gfx_color_t),
00233 &floader->task);
00234
00235 return result;
00236 }
00237
00250 hugemem_ptr_t load_file_to_hugemem(const char *filename,
00251 struct workqueue_task *task)
00252 {
00253 struct file_loader *floader = &the_file_loader;
00254 enum status_code status;
00255 hugemem_ptr_t retval;
00256 uint32_t file_size;
00257
00258 if (!tsfs_is_ready(&myfs) || floader->busy)
00259 return HUGEMEM_NULL;
00260
00261 status = tsfs_open(&myfs, filename, &floader->file);
00262 if (status != STATUS_OK)
00263 return HUGEMEM_NULL;
00264
00265 file_size = floader->file.end - floader->file.start;
00266
00267 retval = hugemem_alloc(&board_extram_pool, file_size, CPU_DMA_ALIGN);
00268 if (retval == HUGEMEM_NULL)
00269 return retval;
00270
00271 floader->busy = true;
00272 floader->done_task = task;
00273 floader->offset = 0;
00274 floader->hugemem_address = retval;
00275 floader->load_size = min_u(file_size, MAX_LOAD_SIZE);
00276
00277 workqueue_task_set_work_func(&floader->task, load_to_hugemem_worker);
00278
00279 status = tsfs_read(&myfs, &floader->file, &floader->buffer,
00280 floader->load_size, &floader->task);
00281 if (status != STATUS_OK)
00282 return HUGEMEM_NULL;
00283
00284 return retval;
00285 }
00286
00293 bool file_loader_busy()
00294 {
00295 struct file_loader *floader = &the_file_loader;
00296 return floader->busy;
00297 }
00298
00302 void file_loader_init()
00303 {
00304 struct file_loader *floader = &the_file_loader;
00305 workqueue_task_init(&floader->task, load_to_screen_worker);
00306 }
00307