Skip to content

Commit 7fe7381

Browse files
committed
Updater: Some more work on the UI, still no flashing
1 parent fc1bcf9 commit 7fe7381

File tree

5 files changed

+151
-26
lines changed

5 files changed

+151
-26
lines changed

components/retro-go/rg_gui.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1041,7 +1041,7 @@ static int file_picker_cb(const rg_scandir_t *entry, void *arg)
10411041
return RG_SCANDIR_CONTINUE;
10421042
}
10431043

1044-
char *rg_gui_file_picker(const char *title, const char *path, bool (*validator)(const char *path), bool none_option)
1044+
char *rg_gui_file_picker(const char *title, const char *path, bool (*validator)(const char *path), bool browse_tree, bool none_option)
10451045
{
10461046
file_picker_opts_t options = {
10471047
.options = calloc(8, sizeof(rg_gui_option_t)),
@@ -1056,6 +1056,9 @@ char *rg_gui_file_picker(const char *title, const char *path, bool (*validator)(
10561056
if (none_option)
10571057
options.options[options.count++] = (rg_gui_option_t){0, _("<None>"), NULL, RG_DIALOG_FLAG_NORMAL, NULL};
10581058

1059+
// if (browse_tree)
1060+
// options.options[options.count++] = (rg_gui_option_t){0, "...", NULL, RG_DIALOG_FLAG_NORMAL, NULL};
1061+
10591062
if (!rg_storage_scandir(path, file_picker_cb, &options, 0) || options.count < 1)
10601063
{
10611064
rg_gui_alert(title, _("Folder is empty."));
@@ -1070,6 +1073,9 @@ char *rg_gui_file_picker(const char *title, const char *path, bool (*validator)(
10701073
if (filename)
10711074
snprintf(buffer, RG_PATH_MAX, "%s/%s", path, filename);
10721075
filepath = strdup(buffer);
1076+
// if (browse_tree && rg_storage_stat(filepath).is_dir)
1077+
// {
1078+
// }
10731079
}
10741080

10751081
cleanup:
@@ -1667,7 +1673,7 @@ static rg_gui_event_t theme_cb(rg_gui_option_t *option, rg_gui_event_t event)
16671673
{
16681674
if (event == RG_DIALOG_ENTER)
16691675
{
1670-
char *path = rg_gui_file_picker("Theme", RG_BASE_PATH_THEMES, NULL, true);
1676+
char *path = rg_gui_file_picker("Theme", RG_BASE_PATH_THEMES, NULL, false, true);
16711677
if (path != NULL)
16721678
{
16731679
const char *theme = strlen(path) > 0 ? rg_basename(path) : NULL;
@@ -1713,7 +1719,7 @@ static rg_gui_event_t border_update_cb(rg_gui_option_t *option, rg_gui_event_t e
17131719
{
17141720
if (event == RG_DIALOG_ENTER)
17151721
{
1716-
char *path = rg_gui_file_picker("Border", RG_BASE_PATH_BORDERS, NULL, true);
1722+
char *path = rg_gui_file_picker("Border", RG_BASE_PATH_BORDERS, NULL, false, true);
17171723
if (path != NULL)
17181724
{
17191725
rg_display_set_border(strlen(path) ? path : NULL);

components/retro-go/rg_gui.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ void rg_gui_draw_message(const char *format, ...);
132132
intptr_t rg_gui_dialog(const char *title, const rg_gui_option_t *options, int selected_index);
133133
bool rg_gui_confirm(const char *title, const char *message, bool default_yes);
134134
void rg_gui_alert(const char *title, const char *message);
135-
char *rg_gui_file_picker(const char *title, const char *path, bool (*validator)(const char *path), bool none_option);
135+
char *rg_gui_file_picker(const char *title, const char *path, bool (*validator)(const char *path), bool browse_tree, bool none_option);
136136
char *rg_gui_input_str(const char *title, const char *message, const char *default_value);
137137
int rg_gui_input_char(const rg_keyboard_layout_t *map);
138138

prboom-go/main/main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -559,7 +559,7 @@ void app_main()
559559

560560
if (!iwad)
561561
{
562-
iwad = rg_gui_file_picker("Select IWAD file", I_DoomExeDir(), is_iwad, false) ?: "";
562+
iwad = rg_gui_file_picker("Select IWAD file", I_DoomExeDir(), is_iwad, false, false) ?: "";
563563
rg_gui_draw_hourglass(); // Redraw hourglass to indicate loading...
564564
}
565565

rg_tool.py

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
import sys
88
import re
99
import os
10+
import struct
11+
import time
12+
import zlib
1013

1114
DEFAULT_TARGET = os.getenv("RG_TOOL_TARGET", "odroid-go")
1215
DEFAULT_BAUD = os.getenv("RG_TOOL_BAUD", "1152000")
@@ -58,6 +61,7 @@
5861
ESPTOOL_PY = "esptool.py"
5962
PARTTOOL_PY = "parttool.py"
6063
GEN_ESP32PART_PY = "gen_esp32part.py"
64+
MKIMG_PY = os.path.join("tools", "mkimg.py")
6165
MKFW_PY = os.path.join("tools", "mkfw.py")
6266

6367

@@ -68,9 +72,9 @@ def run(cmd, cwd=None, check=True):
6872
return subprocess.run(cmd, shell=False, cwd=cwd, check=check)
6973

7074

71-
def build_firmware(output_file, apps, fw_format="odroid-go", fatsize=0):
75+
def build_firmware(output_file, apps, fw_format="odroid-go", fatsize=0, info_target="unknown", info_version="unknown"):
7276
print("Building firmware with: %s\n" % " ".join(apps))
73-
args = [MKFW_PY, output_file, f"{PROJECT_NAME} {PROJECT_VER}", PROJECT_ICON]
77+
args = [MKFW_PY, output_file, f"{PROJECT_NAME} {info_version}", PROJECT_ICON]
7478

7579
if fw_format == "esplay":
7680
args.append("--esplay")
@@ -82,7 +86,7 @@ def build_firmware(output_file, apps, fw_format="odroid-go", fatsize=0):
8286
run(args)
8387

8488

85-
def build_image(output_file, apps, img_format="esp32", fatsize=0):
89+
def build_image(output_file, apps, img_format="esp32", fatsize=0, info_target="unknown", info_version="unknown"):
8690
print("Building image with: %s\n" % " ".join(apps))
8791
image_data = bytearray(b"\xFF" * 0x10000)
8892
table_ota = 0
@@ -128,6 +132,17 @@ def build_image(output_file, apps, img_format="esp32", fatsize=0):
128132
image_data[0x1000:0x1000+len(bootloader_bin)] = bootloader_bin
129133
image_data[0x8000:0x8000+len(table_bin)] = table_bin
130134

135+
# Append the information structure used by retro-go's updater.
136+
image_data += struct.pack(
137+
"<III32s32s180s",
138+
0x31304752, # Magic number "RG01"
139+
zlib.crc32(image_data), # CRC of the image not including this footer
140+
int(time.time()), # Unix timestamp
141+
info_target.encode(), # Name of the target device
142+
info_version.encode(), # Version
143+
b"\xFF" * 256, # 0xFF padding of the reserved area
144+
)
145+
131146
with open(output_file, "wb") as f:
132147
f.write(image_data)
133148

@@ -259,14 +274,14 @@ def monitor_app(app, port, baudrate=115200):
259274
print("=== Step: Packing ===\n")
260275
if FW_FORMAT in ["odroid", "esplay"]:
261276
fw_file = ("%s_%s_%s.fw" % (PROJECT_NAME, PROJECT_VER, args.target)).lower()
262-
build_firmware(fw_file, apps, FW_FORMAT, args.fatsize)
277+
build_firmware(fw_file, apps, FW_FORMAT, args.fatsize, args.target, PROJECT_VER)
263278
else:
264279
print("Device doesn't support fw format, try build-img!")
265280

266281
if command in ["build-img", "release", "install"]:
267282
print("=== Step: Packing ===\n")
268283
img_file = ("%s_%s_%s.img" % (PROJECT_NAME, PROJECT_VER, args.target)).lower()
269-
build_image(img_file, apps, IDF_TARGET, args.fatsize)
284+
build_image(img_file, apps, IDF_TARGET, args.fatsize, args.target, PROJECT_VER)
270285

271286
if command in ["install"]:
272287
print("=== Step: Flashing entire image to device ===\n")

updater/main/main.c

Lines changed: 120 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44
#include <stdio.h>
55
#include <stdlib.h>
66
#include <string.h>
7+
#include <strings.h>
78

8-
#include <esp_spi_flash.h>
9+
#include <esp_flash_partitions.h>
910
#include <esp_partition.h>
11+
#include <esp_spi_flash.h>
1012

1113
#ifdef RG_UPDATER_DOWNLOAD_LOCATION
1214
#define DOWNLOAD_LOCATION RG_UPDATER_DOWNLOAD_LOCATION
@@ -20,28 +22,130 @@
2022
#define CAN_UPDATE_PARTITION_TABLE 0
2123
#endif
2224

25+
#define RETRO_GO_IMG_MAGIC 0x31304752 // "RG01"
26+
typedef struct
27+
{
28+
uint32_t magic;
29+
uint32_t crc32;
30+
uint32_t timestamp;
31+
char target[32];
32+
char version[32];
33+
char reserved[180];
34+
} img_info_t;
35+
36+
#define CONFIRM(title, message...) \
37+
{ \
38+
snprintf(message_buffer, sizeof(message_buffer), message); \
39+
if (!rg_gui_confirm(_(title), message_buffer, false)) \
40+
return false; \
41+
rg_display_clear(C_BLACK); \
42+
}
43+
#define ALERT(title, message...) \
44+
{ \
45+
snprintf(message_buffer, sizeof(message_buffer), message); \
46+
rg_gui_alert(_(title), message_buffer); \
47+
rg_display_clear(C_BLACK); \
48+
}
49+
#define ERROR(message...) \
50+
{ \
51+
ALERT("Error", message); \
52+
return false; \
53+
}
54+
#define TRY(cond, error_message) \
55+
if (!(cond)) \
56+
ERROR(error_message);
57+
58+
static rg_app_t *app;
59+
static esp_partition_info_t device_partition_table[ESP_PARTITION_TABLE_MAX_ENTRIES];
60+
static char message_buffer[256];
61+
62+
static bool do_update(const char *filename)
63+
{
64+
esp_partition_info_t partition_table[16]; // ESP_PARTITION_TABLE_MAX_ENTRIES
65+
int num_partitions = 0;
66+
img_info_t img_info;
67+
int filesize = 0;
68+
FILE *fp;
69+
70+
RG_LOGI("Filename: %s", filename);
71+
rg_display_clear(C_BLACK);
72+
73+
TRY(fp = fopen(filename, "rb"), "File open failed");
74+
TRY(fseek(fp, 0, SEEK_END) == 0, "File seek failed");
75+
TRY(fseek(fp, -sizeof(img_info_t), SEEK_CUR) == 0, "File seek failed");
76+
filesize = ftell(fp); // Size without the footer
77+
TRY(fread(&img_info, sizeof(img_info), 1, fp), "File read failed");
78+
79+
img_info.target[sizeof(img_info.target) - 1] = 0; // Just in case
80+
img_info.version[sizeof(img_info.version) - 1] = 0; // Just in case
81+
82+
if (img_info.magic != RETRO_GO_IMG_MAGIC) // Invalid image
83+
{
84+
CONFIRM("Warning", "File is not a valid Retro-Go image.\nContinue anyway?");
85+
}
86+
else if (strcasecmp(img_info.target, RG_TARGET_NAME) != 0) // Wrong target
87+
{
88+
CONFIRM("Warning",
89+
"The file appears to be for a different device.\n"
90+
"Current device: %s\n"
91+
"Image device: %s\n\n"
92+
"Do you want to continue anyway?",
93+
RG_TARGET_NAME,
94+
img_info.target);
95+
}
96+
else // Valid image
97+
{
98+
CONFIRM("Version", "Current version: %s\nNew version: %s\n\nContinue?", app->version, img_info.version);
99+
}
100+
101+
// TODO: Also support images that truncate the first 0x1000, just in case
102+
TRY(fseek(fp, ESP_PARTITION_TABLE_OFFSET, SEEK_SET) == 0, "File seek failed");
103+
TRY(fread(&partition_table, sizeof(partition_table), 1, fp), "File read failed");
104+
105+
if (esp_partition_table_verify(partition_table, true, &num_partitions) != ESP_OK)
106+
ERROR("File is not a valid esp32 image.\nCannot continue.");
107+
108+
ALERT("Info", "Image contains %d partitions.", num_partitions);
109+
110+
// We can work around this, this is for debugging purposes
111+
if (memcmp(&device_partition_table, &partition_table, sizeof(partition_table)))
112+
ALERT("Error", "Partition table mismatch.");
113+
114+
return true;
115+
}
116+
23117
void app_main(void)
24118
{
25-
rg_app_t *app = rg_system_init(32000, NULL, NULL);
119+
app = rg_system_init(32000, NULL, NULL);
120+
// This is a hack to hide the status bar with bogus speed info. A better solution will be
121+
// needed as we still want the battery icon!
122+
app->isLauncher = true;
26123

27124
if (!rg_storage_ready())
28125
{
29-
rg_display_clear(C_SKY_BLUE);
30-
rg_gui_alert(_("SD Card Error"), _("Storage mount failed.\nMake sure the card is FAT32."));
31-
// What do at this point? Reboot? Switch back to launcher?
32-
goto launcher;
126+
ALERT("Error", "Storage mount failed.\nMake sure the card is FAT32.");
127+
rg_system_exit();
33128
}
34129

35-
// Hopefully we'll receive the filename from the launcher which has a nicer file browser
36-
const char *filename = app->romPath;
37-
38-
if (!filename || !rg_storage_exists(filename))
39-
filename = rg_gui_file_picker(_("Select update"), DOWNLOAD_LOCATION, NULL, true);
40-
if (!filename)
41-
goto launcher;
130+
if (spi_flash_read(ESP_PARTITION_TABLE_OFFSET, &device_partition_table, sizeof(device_partition_table)) != ESP_OK)
131+
{
132+
ALERT("Error", "Failed to read device's partition table!");
133+
rg_system_exit();
134+
}
42135

43-
RG_LOGI("Filename: %s", filename);
136+
const char *filename = app->romPath;
137+
while (true)
138+
{
139+
if (!filename || !*filename)
140+
{
141+
filename = rg_gui_file_picker("Select update", DOWNLOAD_LOCATION, NULL, true, true);
142+
if (!filename || !*filename)
143+
break;
144+
}
145+
if (do_update(filename))
146+
break;
147+
filename = NULL;
148+
}
44149

45-
launcher:
46-
rg_system_switch_app(RG_APP_LAUNCHER, 0, 0, 0, 0);
150+
rg_system_exit();
47151
}

0 commit comments

Comments
 (0)