Subversion Repositories freemyipod

Rev

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