Subversion Repositories freemyipod

Rev

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