Subversion Repositories freemyipod

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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