Subversion Repositories freemyipod

Rev

Rev 777 | Rev 808 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
660 theseven 1
//
2
//
3
//    Copyright 2011 TheSeven
4
//
5
//
6
//    This file is part of emCORE.
7
//
8
//    emCORE is free software: you can redistribute it and/or
9
//    modify it under the terms of the GNU General Public License as
10
//    published by the Free Software Foundation, either version 2 of the
11
//    License, or (at your option) any later version.
12
//
13
//    emCORE is distributed in the hope that it will be useful,
14
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
15
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
//    See the GNU General Public License for more details.
17
//
18
//    You should have received a copy of the GNU General Public License along
19
//    with emCORE.  If not, see <http://www.gnu.org/licenses/>.
20
//
21
//
22
 
23
 
528 theseven 24
#include "emcoreapp.h"
25
#include "libboot.h"
26
#include "libpng.h"
27
#include "libui.h"
660 theseven 28
#include "libmkfat32.h"
528 theseven 29
 
768 user890104 30
extern char background_png[];
31
extern uint32_t background_png_size;
32
extern char icons_png[];
33
extern uint32_t icons_png_size;
34
extern char rockbox_png[];
35
extern uint32_t rockbox_png_size;
36
 
660 theseven 37
struct libpng_api* png;
38
struct libboot_api* boot;
39
struct libui_api* ui;
40
void* framebuf;
41
void* bg;
42
void* icons;
43
void* rbxlogo;
528 theseven 44
 
660 theseven 45
static struct emcorelib_header* loadlib(uint32_t identifier, uint32_t version, char* filename)
528 theseven 46
{
660 theseven 47
    struct emcorelib_header* lib = get_library(identifier, version, LIBSOURCE_BOOTFLASH, filename);
48
    if (!lib) panicf(PANIC_KILLTHREAD, "Could not load %s", filename);
49
    return lib;
50
}
51
 
768 user890104 52
static void* loadpng(const char* buf, const uint32_t size, void* (*decoder)(struct png_info* handle))
660 theseven 53
{
768 user890104 54
    if (size == 0) panicf(PANIC_KILLTHREAD, "Could not load PNG at 0x%08X", buf);
660 theseven 55
    struct png_info* handle = png->png_open(buf, size);
768 user890104 56
    if (!handle) panicf(PANIC_KILLTHREAD, "Could not parse PNG at 0x%08X", buf);
660 theseven 57
    void* out = decoder(handle);
768 user890104 58
    if (!out) panicf(PANIC_KILLTHREAD, "Could not decode PNG at 0x%08X", buf);
660 theseven 59
    png->png_destroy(handle);
60
    return out;
61
}
62
 
63
static void message(int x, const char* line1, const char* line2)
64
{
65
    rendertext(framebuf, x, 140, 320, 0xff3333ff, 0xa0000000, line1);
66
    rendertext(framebuf, x, 148, 320, 0xff3333ff, 0xa0000000, line2);
806 theseven 67
    update_display(NULL);
660 theseven 68
    displaylcd(0, 0, 320, 240, framebuf, 0, 0, 320);
69
    sleep(5000000);
70
}
71
 
72
struct chooser_renderer_list_itemdata toolchooser_rparams_mainchooser =
73
{
74
    .size = LIBUI_POINT(260, 10),
75
    .fill_box = LIBUI_BOX(LIBUI_POINT(0, 0), LIBUI_POINT(260, 10)),
76
    .fill_color = 0xa0000000,
77
    .fill_color_selected = 0x60ffffff,
78
    .icon_pos = LIBUI_POINT(0, 0),
79
    .icon = LIBUI_SURFACE(LIBUI_LOCATION(LIBUI_BUFFER(NULL, 0), LIBUI_POINT(0, 0)),
80
                          LIBUI_POINT(0, 0)),
81
    .icon_opacity = 0,
82
    .icon_selected = LIBUI_SURFACE(LIBUI_LOCATION(LIBUI_BUFFER(NULL, 0), LIBUI_POINT(0, 0)),
83
                                   LIBUI_POINT(0, 0)),
84
    .icon_selected_opacity = 0,
85
    .text = "Return to main menu",
86
    .text_pos = LIBUI_POINT(1, 1),
87
    .text_color = 0xffffffff,
88
    .text_color_selected = 0xff7fffff
89
};
90
 
91
struct chooser_renderer_list_itemdata toolchooser_rparams_umsboot =
92
{
93
    .size = LIBUI_POINT(260, 10),
94
    .fill_box = LIBUI_BOX(LIBUI_POINT(0, 0), LIBUI_POINT(260, 10)),
95
    .fill_color = 0xa0000000,
96
    .fill_color_selected = 0x60ffffff,
97
    .icon_pos = LIBUI_POINT(0, 0),
98
    .icon = LIBUI_SURFACE(LIBUI_LOCATION(LIBUI_BUFFER(NULL, 0), LIBUI_POINT(0, 0)),
99
                          LIBUI_POINT(0, 0)),
100
    .icon_opacity = 0,
101
    .icon_selected = LIBUI_SURFACE(LIBUI_LOCATION(LIBUI_BUFFER(NULL, 0), LIBUI_POINT(0, 0)),
102
                                   LIBUI_POINT(0, 0)),
103
    .icon_selected_opacity = 0,
104
    .text = "Run UMSboot",
105
    .text_pos = LIBUI_POINT(1, 1),
106
    .text_color = 0xffffffff,
107
    .text_color_selected = 0xff7fffff
108
};
109
 
110
void run_umsboot(void** firmware, void** app, int* size)
111
{
662 theseven 112
    boot->load_from_flash(firmware, size, false, "umsboot ", 0x10000);
660 theseven 113
    if (!*firmware)
114
    {
115
        memcpy(framebuf, bg, 320 * 240 * 3);
116
        message(91, "Loading UMSboot failed!", "Returning to main menu.");
117
    }
118
}
119
 
120
struct chooser_renderer_list_itemdata toolchooser_rparams_rockbox_fallback =
121
{
122
    .size = LIBUI_POINT(260, 10),
123
    .fill_box = LIBUI_BOX(LIBUI_POINT(0, 0), LIBUI_POINT(260, 10)),
124
    .fill_color = 0xa0000000,
125
    .fill_color_selected = 0x60ffffff,
126
    .icon_pos = LIBUI_POINT(0, 0),
127
    .icon = LIBUI_SURFACE(LIBUI_LOCATION(LIBUI_BUFFER(NULL, 0), LIBUI_POINT(0, 0)),
128
                          LIBUI_POINT(0, 0)),
129
    .icon_opacity = 0,
130
    .icon_selected = LIBUI_SURFACE(LIBUI_LOCATION(LIBUI_BUFFER(NULL, 0), LIBUI_POINT(0, 0)),
131
                                   LIBUI_POINT(0, 0)),
132
    .icon_selected_opacity = 0,
133
    .text = "Run Rockbox fallback image",
134
    .text_pos = LIBUI_POINT(1, 1),
135
    .text_color = 0xffffffff,
136
    .text_color_selected = 0xff7fffff
137
};
138
 
139
void run_rockbox_fallback(void** firmware, void** app, int* size)
140
{
141
    boot->load_from_flash(firmware, size, true, "rockbox ", 0x100000);
142
    if (!*firmware)
143
    {
144
        memcpy(framebuf, bg, 320 * 240 * 3);
145
        message(91, "Loading Rockbox failed!", "Returning to main menu.");
146
    }
147
}
148
 
149
struct chooser_renderer_list_itemdata toolchooser_rparams_clearcfg =
150
{
151
    .size = LIBUI_POINT(260, 10),
152
    .fill_box = LIBUI_BOX(LIBUI_POINT(0, 0), LIBUI_POINT(260, 10)),
153
    .fill_color = 0xa0000000,
154
    .fill_color_selected = 0x60ffffff,
155
    .icon_pos = LIBUI_POINT(0, 0),
156
    .icon = LIBUI_SURFACE(LIBUI_LOCATION(LIBUI_BUFFER(NULL, 0), LIBUI_POINT(0, 0)),
157
                          LIBUI_POINT(0, 0)),
158
    .icon_opacity = 0,
159
    .icon_selected = LIBUI_SURFACE(LIBUI_LOCATION(LIBUI_BUFFER(NULL, 0), LIBUI_POINT(0, 0)),
160
                                   LIBUI_POINT(0, 0)),
161
    .icon_selected_opacity = 0,
162
    .text = "Clear Rockbox configuration",
163
    .text_pos = LIBUI_POINT(1, 1),
164
    .text_color = 0xffffffff,
165
    .text_color_selected = 0xff7fffff
166
};
167
 
168
void run_clearcfg(void** firmware, void** app, int* size)
169
{
170
    remove("/.rockbox/config.cfg");
171
    memcpy(framebuf, bg, 320 * 240 * 3);
172
    message(97, "Rockbox configuration", "  has been cleared.  ");
173
}
174
 
175
struct chooser_renderer_list_itemdata toolchooser_rparams_cleardb =
176
{
177
    .size = LIBUI_POINT(260, 10),
178
    .fill_box = LIBUI_BOX(LIBUI_POINT(0, 0), LIBUI_POINT(260, 10)),
179
    .fill_color = 0xa0000000,
180
    .fill_color_selected = 0x60ffffff,
181
    .icon_pos = LIBUI_POINT(0, 0),
182
    .icon = LIBUI_SURFACE(LIBUI_LOCATION(LIBUI_BUFFER(NULL, 0), LIBUI_POINT(0, 0)),
183
                          LIBUI_POINT(0, 0)),
184
    .icon_opacity = 0,
185
    .icon_selected = LIBUI_SURFACE(LIBUI_LOCATION(LIBUI_BUFFER(NULL, 0), LIBUI_POINT(0, 0)),
186
                                   LIBUI_POINT(0, 0)),
187
    .icon_selected_opacity = 0,
188
    .text = "Clear Rockbox database",
189
    .text_pos = LIBUI_POINT(1, 1),
190
    .text_color = 0xffffffff,
191
    .text_color_selected = 0xff7fffff
192
};
193
 
194
void run_cleardb(void** firmware, void** app, int* size)
195
{
196
    remove("/.rockbox/database_0.tcd");
197
    remove("/.rockbox/database_1.tcd");
198
    remove("/.rockbox/database_2.tcd");
199
    remove("/.rockbox/database_3.tcd");
200
    remove("/.rockbox/database_4.tcd");
201
    remove("/.rockbox/database_5.tcd");
202
    remove("/.rockbox/database_6.tcd");
203
    remove("/.rockbox/database_7.tcd");
204
    remove("/.rockbox/database_8.tcd");
205
    remove("/.rockbox/database_9.tcd");
206
    remove("/.rockbox/database_idx.tcd");
207
    remove("/.rockbox/database_tmp.tcd");
208
    remove("/.rockbox/database_state.tcd");
209
    remove("/.rockbox/database_changelog.txt");
210
    memcpy(framebuf, bg, 320 * 240 * 3);
211
    message(109, "Rockbox  database", "has been cleared.");
212
}
213
 
214
struct chooser_renderer_list_itemdata toolchooser_rparams_reformat =
215
{
216
    .size = LIBUI_POINT(260, 10),
217
    .fill_box = LIBUI_BOX(LIBUI_POINT(0, 0), LIBUI_POINT(260, 10)),
218
    .fill_color = 0xa0000000,
219
    .fill_color_selected = 0x60ffffff,
220
    .icon_pos = LIBUI_POINT(0, 0),
221
    .icon = LIBUI_SURFACE(LIBUI_LOCATION(LIBUI_BUFFER(NULL, 0), LIBUI_POINT(0, 0)),
222
                          LIBUI_POINT(0, 0)),
223
    .icon_opacity = 0,
224
    .icon_selected = LIBUI_SURFACE(LIBUI_LOCATION(LIBUI_BUFFER(NULL, 0), LIBUI_POINT(0, 0)),
225
                                   LIBUI_POINT(0, 0)),
226
    .icon_selected_opacity = 0,
227
    .text = "Reformat data partition",
228
    .text_pos = LIBUI_POINT(1, 1),
229
    .text_color = 0xffffffff,
230
    .text_color_selected = 0xff7fffff
231
};
232
 
233
void fat32_progressbar_init(void* user, int max)
234
{
235
    progressbar_init((struct progressbar_state*)user,
236
                     15, 304, 135, 159, 0x77ff, 0xe8, 0x125f, 0, max);
237
}
238
 
239
void fat32_progressbar_update(void* user, int current)
240
{
241
    progressbar_setpos((struct progressbar_state*)user, current, false);
242
}
243
 
244
void run_reformat(void** firmware, void** app, int* size)
245
{
246
    memcpy(framebuf, bg, 320 * 240 * 3);
247
    rendertext(framebuf, 70, 125, 320, 0xff7fffff, 0, "Reformatting data partition...");
806 theseven 248
    update_display(NULL);
660 theseven 249
    displaylcd(0, 0, 320, 240, framebuf, 0, 0, 320);
250
    struct emcorelib_header* libmkfat32 = loadlib(LIBMKFAT32_IDENTIFIER,
251
                                                  LIBMKFAT32_API_VERSION, "libmkf32");
252
    struct libmkfat32_api* mf32 = (struct libmkfat32_api*)libmkfat32->api;
253
    struct storage_info storageinfo;
254
    storage_get_info(0, &storageinfo);
255
    struct progressbar_state progressbar;
256
    int rc = mf32->mkfat32(0, 0, storageinfo.num_sectors, 4096, 1, "iPodClassic",
257
                           &progressbar, fat32_progressbar_init, fat32_progressbar_update);
258
    if (rc < 0) panicf(PANIC_KILLTHREAD, "Error formatting hard drive: %08X", rc);
259
    release_library(libmkfat32);
260
    library_unload(libmkfat32);
261
    memcpy(framebuf, bg, 320 * 240 * 3);
262
    message(106, "Data partition has", "been  reformatted.");
263
}
264
 
765 user890104 265
bool update_display(struct chooser_data* data)
266
{
267
    char buf[6];
268
    struct rtc_datetime dt;
269
    rtc_read_datetime(&dt);
270
    snprintf(buf, sizeof(buf), "%02d:%02d", dt.hour, dt.minute);
271
    // clock
272
    rendertext(framebuf, 287, 4, 320, 0xffffcccc, 0, buf);
273
    unsigned int batt_level = 22 * read_battery_mwh_current(0) / read_battery_mwh_full(0);
274
    // remaining battery level
275
    ui->blendcolor(batt_level, 6, 0xc0ffcccc, framebuf, 5, 5, 320, framebuf, 5, 5, 320);
276
    // background of the rest space
277
    ui->blendcolor(22 - batt_level, 6, 0x40000000, framebuf, 5 + batt_level, 5, 320, framebuf, 5 + batt_level, 5, 320);
278
    return false;
279
}
280
 
660 theseven 281
struct chooser_renderer_list_params toolchooser_rparams =
282
{
283
    .version = CHOOSER_RENDERER_LIST_PARAMS_VERSION,
284
    .copy_dest = LIBUI_LOCATION(LIBUI_BUFFER(NULL, 320), LIBUI_POINT(0, 0)),
285
    .copy_src = LIBUI_SURFACE(LIBUI_LOCATION(LIBUI_BUFFER(NULL, 320), LIBUI_POINT(0, 0)),
286
                              LIBUI_POINT(320, 240)),
287
    .bg_dest = LIBUI_LOCATION(LIBUI_BUFFER(NULL, 0), LIBUI_POINT(0, 0)),
288
    .bg_src = LIBUI_SURFACE(LIBUI_LOCATION(LIBUI_BUFFER(NULL, 0), LIBUI_POINT(0, 0)),
289
                            LIBUI_POINT(0, 0)),
290
    .bg_opacity = 0,
291
    .fill_dest = LIBUI_SURFACE(LIBUI_LOCATION(LIBUI_BUFFER(NULL, 0), LIBUI_POINT(0, 0)),
292
                               LIBUI_POINT(0, 0)),
293
    .fill_color = 0,
294
    .viewport = LIBUI_SURFACE(LIBUI_LOCATION(LIBUI_BUFFER(NULL, 320), LIBUI_POINT(30, 50)),
295
                              LIBUI_POINT(260, 160)),
296
    .blit_dest = LIBUI_POINT(0, 0),
297
    .blit_src = LIBUI_SURFACE(LIBUI_LOCATION(LIBUI_BUFFER(NULL, 320), LIBUI_POINT(0, 0)),
298
                              LIBUI_POINT(320, 240)),
765 user890104 299
    .preblit = update_display,
660 theseven 300
    .postblit = NULL
301
};
302
 
303
struct chooser_action_handler_wheel_params toolchooser_aparams =
304
{
305
    .version = CHOOSER_ACTION_HANDLER_WHEEL_PARAMS_VERSION,
306
    .stepsperitem = 128,
307
    .eventfilter = NULL,
308
    .timeout_initial = TIMEOUT_BLOCK,
309
    .timeout_idle = TIMEOUT_BLOCK,
310
    .timeout_item = 0,
311
    .tick_force_redraw = false,
312
    .buttoncount = 5,
313
    .buttonmap =
314
    {
315
        CHOOSER_ACTION_HANDLER_WHEEL_ACTION_SELECT,
316
        CHOOSER_ACTION_HANDLER_WHEEL_ACTION_NEXT,
317
        CHOOSER_ACTION_HANDLER_WHEEL_ACTION_PREV,
318
        CHOOSER_ACTION_HANDLER_WHEEL_ACTION_NEXT,
319
        CHOOSER_ACTION_HANDLER_WHEEL_ACTION_PREV
320
    }
321
};
322
 
323
struct chooser_info toolchooser =
324
{
325
    .version = CHOOSER_INFO_VERSION,
326
    .actionhandler = NULL,
327
    .actionhandlerparams = &toolchooser_aparams,
328
    .renderer = NULL,
329
    .rendererparams = &toolchooser_rparams,
330
    .userparams = NULL,
331
    .tickinterval = 10000000,
332
    .itemcount = 6,
333
    .defaultitem = 0,
334
    .items =
335
    {
336
        {
337
            .user = NULL,
338
            .actionparams = NULL,
339
            .renderparams = &toolchooser_rparams_mainchooser
340
        },
341
        {
342
            .user = run_umsboot,
343
            .actionparams = NULL,
344
            .renderparams = &toolchooser_rparams_umsboot
345
        },
346
        {
347
            .user = run_rockbox_fallback,
348
            .actionparams = NULL,
349
            .renderparams = &toolchooser_rparams_rockbox_fallback
350
        },
351
        {
352
            .user = run_clearcfg,
353
            .actionparams = NULL,
354
            .renderparams = &toolchooser_rparams_clearcfg
355
        },
356
        {
357
            .user = run_cleardb,
358
            .actionparams = NULL,
359
            .renderparams = &toolchooser_rparams_cleardb
360
        },
361
        {
362
            .user = run_reformat,
363
            .actionparams = NULL,
364
            .renderparams = &toolchooser_rparams_reformat
365
        }
366
    }
367
};
368
 
369
bool mainchooser_preblit(struct chooser_data* data)
370
{
765 user890104 371
    char buf[4];
528 theseven 372
    struct chooser_action_handler_wheel_data* adata;
373
    adata = (struct chooser_action_handler_wheel_data*)(data->actionhandlerdata);
374
    snprintf(buf, sizeof(buf), "%3d", adata->timeout_remaining / 1000000);
764 user890104 375
    rendertext(framebuf, 299, 229, 320, 0xffffcccc, 0, buf);
765 user890104 376
    update_display(data);
528 theseven 377
    return false;
378
}
379
 
660 theseven 380
struct chooser_renderer_iconflow_itemdata mainchooser_rparams_powerdown =
528 theseven 381
{
777 user890104 382
    .icon = LIBUI_SURFACE(LIBUI_LOCATION(LIBUI_BUFFER(NULL, 80), LIBUI_POINT(0, 0)),
383
                          LIBUI_POINT(80, 80)),
384
    .icon_selected = LIBUI_SURFACE(LIBUI_LOCATION(LIBUI_BUFFER(NULL, 80), LIBUI_POINT(0, 0)),
385
                                   LIBUI_POINT(80, 80)),
528 theseven 386
    .text = "Power off",
387
    .text_color = 0xffffcccc,
388
};
389
 
660 theseven 390
void run_powerdown(void** firmware, void** app, int* size)
528 theseven 391
{
660 theseven 392
    shutdown(true);
393
    power_off();
394
}
395
 
396
struct chooser_renderer_iconflow_itemdata mainchooser_rparams_rockbox =
397
{
777 user890104 398
    .icon = LIBUI_SURFACE(LIBUI_LOCATION(LIBUI_BUFFER(NULL, 80), LIBUI_POINT(0, 80)),
399
                          LIBUI_POINT(80, 80)),
400
    .icon_selected = LIBUI_SURFACE(LIBUI_LOCATION(LIBUI_BUFFER(NULL, 80), LIBUI_POINT(0, 80)),
401
                                   LIBUI_POINT(80, 80)),
528 theseven 402
    .text = "Rockbox",
403
    .text_color = 0xffffcccc,
404
};
405
 
660 theseven 406
void run_rockbox(void** firmware, void** app, int* size)
528 theseven 407
{
660 theseven 408
    int i;
409
    for (i = 1; i <= 96; i += 19)
410
    {
411
        if (i < 96)
412
            ui->blend(320, 240, 50, framebuf, 0, 0, 320,
413
                        framebuf, 0, 0, 320, bg, 0, 0, 320);
414
        else memcpy(framebuf, bg, 320 * 240 * 3);
415
        ui->blit(280, MIN(86, i), 3, framebuf, 20, MAX(0, i - 86), 320,
416
                    rbxlogo, 0, MAX(0, 86 - i), 280);
806 theseven 417
        update_display(NULL);
660 theseven 418
        displaylcd(0, 0, 320, 240, framebuf, 0, 0, 320);
419
    }
420
    boot->load_from_file(firmware, size, true, "/.rockbox/rockbox.ipod", 0);
421
    if (!*firmware)
422
    {
423
        message(76, "Loading rockbox.ipod failed!", "  Trying fallback image...  ");
424
        boot->load_from_flash(firmware, size, true, "rockbox ", 0x100000);
425
    }
426
    if (!*firmware)
427
    {
428
        memcpy(framebuf, bg, 320 * 240 * 3);
429
        message(91, "Loading Rockbox failed!", "Returning to main menu.");
430
    }
431
}
432
 
433
struct chooser_renderer_iconflow_itemdata mainchooser_rparams_console =
434
{
777 user890104 435
    .icon = LIBUI_SURFACE(LIBUI_LOCATION(LIBUI_BUFFER(NULL, 80), LIBUI_POINT(0, 160)),
436
                          LIBUI_POINT(80, 80)),
437
    .icon_selected = LIBUI_SURFACE(LIBUI_LOCATION(LIBUI_BUFFER(NULL, 80), LIBUI_POINT(0, 160)),
438
                                   LIBUI_POINT(80, 80)),
528 theseven 439
    .text = "emCORE console",
440
    .text_color = 0xffffcccc,
441
};
442
 
660 theseven 443
struct chooser_renderer_iconflow_itemdata mainchooser_rparams_toolchooser =
528 theseven 444
{
777 user890104 445
    .icon = LIBUI_SURFACE(LIBUI_LOCATION(LIBUI_BUFFER(NULL, 80), LIBUI_POINT(0, 240)),
446
                          LIBUI_POINT(80, 80)),
447
    .icon_selected = LIBUI_SURFACE(LIBUI_LOCATION(LIBUI_BUFFER(NULL, 80), LIBUI_POINT(0, 240)),
448
                                   LIBUI_POINT(80, 80)),
660 theseven 449
    .text = "Tools",
528 theseven 450
    .text_color = 0xffffcccc,
451
};
452
 
660 theseven 453
static void run_toolchooser(void** firmware, void** app, int* size)
528 theseven 454
{
660 theseven 455
    const struct chooser_item* result = ui->chooser_run(&toolchooser);
456
    if (!result->user) return;
457
    void (*selected_function)(void** firmware, void** app, int* size);
458
    selected_function = (void(*)(void** firmware, void** app, int* size))(result->user);
459
    selected_function(firmware, app, size);
460
}
461
 
462
struct chooser_renderer_iconflow_params mainchooser_rparams =
463
{
464
    .version = CHOOSER_RENDERER_ICONFLOW_PARAMS_VERSION,
528 theseven 465
    .copy_dest = LIBUI_LOCATION(LIBUI_BUFFER(NULL, 320), LIBUI_POINT(0, 0)),
466
    .copy_src = LIBUI_SURFACE(LIBUI_LOCATION(LIBUI_BUFFER(NULL, 320), LIBUI_POINT(0, 0)),
467
                              LIBUI_POINT(320, 240)),
468
    .bg_dest = LIBUI_LOCATION(LIBUI_BUFFER(NULL, 0), LIBUI_POINT(0, 0)),
469
    .bg_src = LIBUI_SURFACE(LIBUI_LOCATION(LIBUI_BUFFER(NULL, 0), LIBUI_POINT(0, 0)),
470
                            LIBUI_POINT(0, 0)),
471
    .bg_opacity = 0,
472
    .fill_dest = LIBUI_SURFACE(LIBUI_LOCATION(LIBUI_BUFFER(NULL, 0), LIBUI_POINT(0, 0)),
473
                               LIBUI_POINT(0, 0)),
474
    .fill_color = 0,
475
    .viewport = LIBUI_SURFACE(LIBUI_LOCATION(LIBUI_BUFFER(NULL, 320), LIBUI_POINT(0, 30)),
476
                              LIBUI_POINT(320, 130)),
477
    .text_pos = LIBUI_POINT(160, 215),
478
    .blit_dest = LIBUI_POINT(0, 0),
479
    .blit_src = LIBUI_SURFACE(LIBUI_LOCATION(LIBUI_BUFFER(NULL, 320), LIBUI_POINT(0, 0)),
480
                              LIBUI_POINT(320, 240)),
481
    .smoothness = 500000,
482
    .startposition = -3,
483
    .iconsinview = 4,
660 theseven 484
    .preblit = mainchooser_preblit,
528 theseven 485
    .postblit = NULL
486
};
487
 
660 theseven 488
struct chooser_action_handler_wheel_params mainchooser_aparams =
528 theseven 489
{
490
    .version = CHOOSER_ACTION_HANDLER_WHEEL_PARAMS_VERSION,
491
    .stepsperitem = 512,
492
    .eventfilter = NULL,
493
    .timeout_initial = 30500000,
494
    .timeout_idle = 300500000,
495
    .timeout_item = 0,
496
    .tick_force_redraw = true,
497
    .buttoncount = 3,
498
    .buttonmap =
499
    {
500
        CHOOSER_ACTION_HANDLER_WHEEL_ACTION_SELECT,
501
        CHOOSER_ACTION_HANDLER_WHEEL_ACTION_NEXT,
502
        CHOOSER_ACTION_HANDLER_WHEEL_ACTION_PREV
503
    }
504
};
505
 
660 theseven 506
struct chooser_info mainchooser =
528 theseven 507
{
508
    .version = CHOOSER_INFO_VERSION,
509
    .actionhandler = NULL,
660 theseven 510
    .actionhandlerparams = &mainchooser_aparams,
528 theseven 511
    .renderer = NULL,
660 theseven 512
    .rendererparams = &mainchooser_rparams,
528 theseven 513
    .userparams = NULL,
514
    .tickinterval = 990000,
515
    .itemcount = 4,
516
    .defaultitem = 1,
517
    .items =
518
    {
519
        {
667 theseven 520
            .user = run_powerdown,
528 theseven 521
            .actionparams = NULL,
660 theseven 522
            .renderparams = &mainchooser_rparams_powerdown
528 theseven 523
        },
524
        {
667 theseven 525
            .user = run_rockbox,
528 theseven 526
            .actionparams = NULL,
660 theseven 527
            .renderparams = &mainchooser_rparams_rockbox
528 theseven 528
        },
529
        {
660 theseven 530
            .user = NULL,
528 theseven 531
            .actionparams = NULL,
660 theseven 532
            .renderparams = &mainchooser_rparams_console
528 theseven 533
        },
534
        {
660 theseven 535
            .user = run_toolchooser,
528 theseven 536
            .actionparams = NULL,
660 theseven 537
            .renderparams = &mainchooser_rparams_toolchooser
528 theseven 538
        }
539
    }
540
};
541
 
660 theseven 542
static void run_mainchooser(void** firmware, void** app, int* size)
543
{
544
    while (!*firmware && !*app)
545
    {
546
        const struct chooser_item* result = ui->chooser_run(&mainchooser);
547
        if (!result->user) return;
548
        void (*selected_function)(void** firmware, void** app, int* size);
549
        selected_function = (void(*)(void** firmware, void** app, int* size))(result->user);
550
        selected_function(firmware, app, size);
551
    }
552
}
528 theseven 553
 
554
static void main()
555
{
660 theseven 556
    struct emcorelib_header* libpng = loadlib(LIBPNG_IDENTIFIER, LIBPNG_API_VERSION, "libpng  ");
557
    png = (struct libpng_api*)libpng->api;
768 user890104 558
    bg = loadpng(background_png, background_png_size, (void* (*)(struct png_info*))(png->png_decode_rgb));
559
    icons = loadpng(icons_png, icons_png_size, (void* (*)(struct png_info*))(png->png_decode_rgba));
560
    rbxlogo = loadpng(rockbox_png, rockbox_png_size, (void* (*)(struct png_info*))(png->png_decode_rgb));
660 theseven 561
    release_library(libpng);
562
    library_unload(libpng);
563
    struct emcorelib_header* libboot = loadlib(LIBBOOT_IDENTIFIER,
564
                                               LIBBOOT_API_VERSION, "libboot ");
565
    boot = (struct libboot_api*)libboot->api;
566
    struct emcorelib_header* libui = loadlib(LIBUI_IDENTIFIER, LIBUI_API_VERSION, "libui   ");
567
    ui = (struct libui_api*)libui->api;
764 user890104 568
    // draw the battery meter box
569
    // top line
570
    ui->blendcolor(24, 1, 0xffffcccc, bg, 4, 4, 320, bg, 4, 4, 320);
571
    // bottom line
572
    ui->blendcolor(24, 1, 0xffffcccc, bg, 4, 11, 320, bg, 4, 11, 320);
573
    // left line
574
    ui->blendcolor(1, 6, 0xffffcccc, bg, 4, 5, 320, bg, 4, 5, 320);
575
    // right line
576
    ui->blendcolor(1, 6, 0xffffcccc, bg, 27, 5, 320, bg, 27, 5, 320);
577
    // tip - right
578
    ui->blendcolor(1, 4, 0xffffcccc, bg, 28, 6, 320, bg, 28, 6, 320);
528 theseven 579
    framebuf = malloc(320 * 240 * 3);
580
    if (!framebuf) panicf(PANIC_KILLTHREAD, "Could not allocate framebuffer!");
660 theseven 581
 
582
    mainchooser.actionhandler = ui->chooser_action_handler_wheel;
583
    mainchooser.renderer = ui->chooser_renderer_iconflow;
584
    mainchooser_rparams.copy_dest.buf.addr = framebuf;
585
    mainchooser_rparams.copy_src.loc.buf.addr = bg;
586
    mainchooser_rparams.viewport.loc.buf.addr = framebuf;
587
    mainchooser_rparams.blit_src.loc.buf.addr = framebuf;
588
    mainchooser_rparams_powerdown.icon.loc.buf.addr = icons;
589
    mainchooser_rparams_powerdown.icon_selected.loc.buf.addr = icons;
590
    mainchooser_rparams_rockbox.icon.loc.buf.addr = icons;
591
    mainchooser_rparams_rockbox.icon_selected.loc.buf.addr = icons;
592
    mainchooser_rparams_console.icon.loc.buf.addr = icons;
593
    mainchooser_rparams_console.icon_selected.loc.buf.addr = icons;
594
    mainchooser_rparams_toolchooser.icon.loc.buf.addr = icons;
595
    mainchooser_rparams_toolchooser.icon_selected.loc.buf.addr = icons;
596
 
597
    toolchooser.actionhandler = ui->chooser_action_handler_wheel;
598
    toolchooser.renderer = ui->chooser_renderer_list;
599
    toolchooser_rparams.copy_dest.buf.addr = framebuf;
600
    toolchooser_rparams.copy_src.loc.buf.addr = bg;
601
    toolchooser_rparams.viewport.loc.buf.addr = framebuf;
602
    toolchooser_rparams.blit_src.loc.buf.addr = framebuf;
603
 
528 theseven 604
    void* firmware = NULL;
660 theseven 605
    void* app = NULL;
606
    int size;
607
    run_mainchooser(&firmware, &app, &size);
608
 
528 theseven 609
    free(framebuf);
610
    free(rbxlogo);
611
    free(icons);
612
    free(bg);
613
    release_library(libui);
551 theseven 614
    release_library(libboot);
528 theseven 615
    library_unload(libui);
616
    library_unload(libboot);
660 theseven 617
 
528 theseven 618
    if (firmware)
619
    {
620
        shutdown(false);
621
        execfirmware((void*)0x08000000, firmware, size);
622
    }
660 theseven 623
    else if (app) execimage(app, false);
528 theseven 624
    else cputs(3, "Dropped into emCORE console.\n");
625
}
626
 
627
EMCORE_APP_HEADER("Boot menu", main, 127)