installer interface

This commit is contained in:
nakst 2021-09-12 10:11:54 +01:00
parent 485dbc59e5
commit f53a980a65
18 changed files with 338 additions and 72 deletions

View File

@ -96,11 +96,3 @@ FileType *FolderEntryGetType(Folder *folder, FolderEntry *entry) {
return &knownFileTypes[index ? index : KNOWN_FILE_TYPE_UNKNOWN];
}
}
uint32_t IconFromDriveType(uint8_t driveType) {
if (driveType == ES_DRIVE_TYPE_HDD ) return ES_ICON_DRIVE_HARDDISK;
if (driveType == ES_DRIVE_TYPE_SSD ) return ES_ICON_DRIVE_HARDDISK_SOLIDSTATE;
if (driveType == ES_DRIVE_TYPE_CDROM ) return ES_ICON_MEDIA_OPTICAL;
if (driveType == ES_DRIVE_TYPE_USB_MASS_STORAGE) return ES_ICON_DRIVE_REMOVABLE_MEDIA_USB;
return ES_ICON_DRIVE_HARDDISK;
}

View File

@ -880,7 +880,7 @@ int PlacesViewCallback(EsElement *element, EsMessage *message) {
} else {
Drive *drive = &drives[index - 1];
EsBufferFormat(message->getContent.buffer, "%s", drive->information.labelBytes, drive->information.label);
message->getContent.icon = IconFromDriveType(drive->information.driveType);
message->getContent.icon = EsIconIDFromDriveType(drive->information.driveType);
}
} else if (group == PLACES_VIEW_GROUP_BOOKMARKS) {
if (index == 0) {

View File

@ -4,6 +4,7 @@
#include <essence.h>
#include <shared/hash.cpp>
#include <shared/strings.cpp>
#include <ports/lzma/LzmaDec.c>
#include <shared/array.cpp>
@ -15,7 +16,47 @@
#define exit(x) EsThreadTerminate(ES_CURRENT_THREAD)
#include <shared/esfs2.h>
// Assume an additional 64MB of storage capacity is needed on top of totalUncompressedBytes.
#define PARTITION_OVERHEAD (64 * 1024 * 1024)
struct InstallerMetadata {
uint64_t totalUncompressedBytes;
};
const EsStyle styleRoot = {
.metrics = {
.mask = ES_THEME_METRICS_GAP_MAJOR | ES_THEME_METRICS_INSETS,
.insets = ES_RECT_1(30),
.gapMajor = 20,
},
};
const EsStyle styleDrivesSelectHint = {
.inherit = ES_STYLE_TEXT_PARAGRAPH_SECONDARY,
.metrics = {
.mask = ES_THEME_METRICS_TEXT_ALIGN | ES_THEME_METRICS_INSETS,
.insets = ES_RECT_1(30),
.textAlign = ES_TEXT_H_CENTER | ES_TEXT_V_CENTER | ES_TEXT_WRAP,
},
};
const EsStyle styleButtonsRow = {
.metrics = {
.mask = ES_THEME_METRICS_GAP_MAJOR,
.gapMajor = 10,
},
};
InstallerMetadata *metadata;
Array<EsMessageDevice> connectedDrives;
EsListView *drivesList;
EsPanel *driveInformation;
EsObjectID selectedDriveID;
EsButton *installButton;
EsPanel *switcher;
EsPanel *panelInstallOptions;
EsPanel *panelLicenses;
/////////////////////////////////////////////
@ -126,6 +167,8 @@ EsError Extract(const char *pathIn, size_t pathInBytes, const char *pathOut, siz
return crc64 == actualCRC64 ? ES_SUCCESS : ES_ERROR_CORRUPT_DATA;
}
/////////////////////////////////////////////
void ReadBlock(uint64_t, uint64_t, void *) {
// TODO.
}
@ -138,33 +181,213 @@ void WriteBytes(uint64_t, uint64_t, void *) {
// TODO.
}
/////////////////////////////////////////////
EsBlockDeviceInformation ConnectedDriveGetInformation(EsHandle handle) {
EsBlockDeviceInformation information;
EsDeviceControl(handle, ES_DEVICE_CONTROL_BLOCK_GET_INFORMATION, 0, &information);
for (uintptr_t i = 0; i < information.modelBytes; i++) {
if (information.model[i] == 0) {
information.modelBytes = i;
break;
}
}
for (uintptr_t i = information.modelBytes; i > 0; i--) {
if (information.model[i - 1] == ' ') {
information.modelBytes--;
} else {
break;
}
}
return information;
}
void ConnectedDriveAdd(EsMessageDevice device) {
if (device.type != ES_DEVICE_BLOCK) {
return;
}
EsBlockDeviceInformation information;
EsDeviceControl(device.handle, ES_DEVICE_CONTROL_BLOCK_GET_INFORMATION, 0, &information);
EsBlockDeviceInformation information = ConnectedDriveGetInformation(device.handle);
if (information.nestLevel) {
if (information.nestLevel || information.driveType == ES_DRIVE_TYPE_CDROM) {
return;
}
// TODO EsObjectID might not necessarily fit in EsGeneric...
EsListViewFixedItemInsert(drivesList, information.model, information.modelBytes, device.id);
connectedDrives.Add(device);
}
void ConnectedDriveRemove(EsMessageDevice device) {
if (device.id == selectedDriveID) {
EsElementDestroyContents(driveInformation);
EsTextDisplayCreate(driveInformation, ES_CELL_H_FILL | ES_CELL_V_FILL, &styleDrivesSelectHint, INTERFACE_STRING(InstallerDriveRemoved));
selectedDriveID = 0;
EsElementSetDisabled(installButton, true);
}
for (uintptr_t i = 0; i < connectedDrives.Length(); i++) {
if (connectedDrives[i].id == device.id) {
EsListViewFixedItemRemove(drivesList, device.id);
connectedDrives.Delete(i);
return;
}
}
}
void ConnectedDriveSelect(uintptr_t index) {
EsMessageDevice device = connectedDrives[index];
if (selectedDriveID == device.id) return;
selectedDriveID = device.id;
EsElementSetDisabled(installButton, true);
EsBlockDeviceInformation information = ConnectedDriveGetInformation(device.handle);
EsElementDestroyContents(driveInformation);
EsPanel *nameRow = EsPanelCreate(driveInformation, ES_CELL_H_FILL | ES_PANEL_HORIZONTAL);
EsIconDisplayCreate(nameRow, ES_FLAGS_DEFAULT, 0, EsIconIDFromDriveType(information.driveType));
EsSpacerCreate(nameRow, ES_CELL_V_FILL, 0, 8, 0);
EsTextDisplayCreate(nameRow, ES_CELL_H_FILL, ES_STYLE_TEXT_HEADING2, information.model, information.modelBytes);
EsSpacerCreate(driveInformation, ES_CELL_H_FILL, 0, 0, 16);
EsPanel *messageRow = EsPanelCreate(driveInformation, ES_CELL_H_FILL | ES_PANEL_HORIZONTAL);
EsIconDisplay *statusIcon = EsIconDisplayCreate(messageRow, ES_CELL_V_TOP, ES_STYLE_ICON_DISPLAY_SMALL, ES_ICON_DIALOG_INFORMATION);
EsSpacerCreate(messageRow, ES_CELL_V_FILL, 0, 8, 0);
// TODO Check there are no file systems already on the drive.
bool showCapacity = true;
if (information.readOnly) {
EsIconDisplaySetIcon(statusIcon, ES_ICON_DIALOG_ERROR);
EsTextDisplayCreate(messageRow, ES_CELL_H_FILL, ES_STYLE_TEXT_PARAGRAPH, INTERFACE_STRING(InstallerDriveReadOnly));
showCapacity = false;
} else if (information.sectorSize * information.sectorCount < metadata->totalUncompressedBytes + PARTITION_OVERHEAD) {
EsIconDisplaySetIcon(statusIcon, ES_ICON_DIALOG_ERROR);
EsTextDisplayCreate(messageRow, ES_CELL_H_FILL, ES_STYLE_TEXT_PARAGRAPH, INTERFACE_STRING(InstallerDriveNotEnoughSpace));
} else {
EsTextDisplayCreate(messageRow, ES_CELL_H_FILL, ES_STYLE_TEXT_PARAGRAPH, INTERFACE_STRING(InstallerDriveOkay));
EsElementSetDisabled(installButton, false);
}
if (showCapacity) {
// TODO Localization.
char buffer[128];
size_t bytes = EsStringFormat(buffer, sizeof(buffer), "Minimum space required: %D", metadata->totalUncompressedBytes + PARTITION_OVERHEAD);
EsSpacerCreate(driveInformation, ES_CELL_H_FILL, 0, 0, 10);
EsTextDisplayCreate(driveInformation, ES_CELL_H_FILL, ES_STYLE_TEXT_PARAGRAPH, buffer, bytes);
bytes = EsStringFormat(buffer, sizeof(buffer), "Drive capacity: %D", information.sectorSize * information.sectorCount);
EsTextDisplayCreate(driveInformation, ES_CELL_H_FILL, ES_STYLE_TEXT_PARAGRAPH, buffer, bytes);
}
}
/////////////////////////////////////////////
int DrivesListMessage(EsElement *element, EsMessage *message) {
if (message->type == ES_MSG_LIST_VIEW_SELECT) {
EsGeneric deviceID;
if (EsListViewFixedItemGetSelected(((EsListView *) element), &deviceID)) {
for (uintptr_t i = 0; i < connectedDrives.Length(); i++) {
if (connectedDrives[i].id == deviceID.u) {
ConnectedDriveSelect(i);
break;
}
}
}
}
return 0;
}
void ButtonViewLicenses(EsInstance *, EsElement *, EsCommand *) {
EsPanelSwitchTo(switcher, panelLicenses, ES_TRANSITION_FADE_IN);
}
void ButtonInstallOptions(EsInstance *, EsElement *, EsCommand *) {
EsPanelSwitchTo(switcher, panelInstallOptions, ES_TRANSITION_FADE_IN);
}
void ButtonShutdown(EsInstance *, EsElement *, EsCommand *) {
EsSystemShowShutdownDialog();
}
void ButtonInstall(EsInstance *, EsElement *, EsCommand *) {
// TODO.
}
int SwitcherMessage(EsElement *, EsMessage *message) {
if (message->type == ES_MSG_GET_WIDTH || message->type == ES_MSG_GET_HEIGHT) {
return EsMessageSend(panelInstallOptions, message);
}
return 0;
}
void _start() {
_init();
metadata = (InstallerMetadata *) EsFileReadAll(EsLiteral("0:/installer_metadata.dat"), nullptr);
EsAssert(metadata);
{
EsWindow *window = EsWindowCreate(_EsInstanceCreate(sizeof(EsInstance), nullptr), ES_WINDOW_PLAIN);
EsHandle handle = EsWindowGetHandle(window);
window->instance->window = window;
EsRectangle screen;
EsSyscall(ES_SYSCALL_SCREEN_BOUNDS_GET, 0, (uintptr_t) &screen, 0, 0);
EsSyscall(ES_SYSCALL_WINDOW_MOVE, handle, (uintptr_t) &screen, 0, 0);
EsSyscall(ES_SYSCALL_WINDOW_SET_PROPERTY, handle, ES_WINDOW_SOLID_TRUE, 0, ES_WINDOW_PROPERTY_SOLID);
EsSyscall(ES_SYSCALL_WINDOW_SET_PROPERTY, handle, 0, 0, ES_WINDOW_PROPERTY_FOCUSED);
EsPanel *sheet = EsPanelCreate(window, ES_PANEL_VERTICAL | ES_CELL_PUSH | ES_CELL_CENTER, ES_STYLE_INSTALLER_ROOT);
switcher = EsPanelCreate(sheet, ES_CELL_H_FILL | ES_PANEL_SWITCHER);
switcher->messageUser = SwitcherMessage;
{
panelInstallOptions = EsPanelCreate(switcher, ES_CELL_H_FILL, &styleRoot);
EsPanelSwitchTo(switcher, panelInstallOptions, ES_TRANSITION_NONE);
EsTextDisplayCreate(panelInstallOptions, ES_CELL_H_FILL, ES_STYLE_TEXT_HEADING0, INTERFACE_STRING(InstallerTitle));
EsPanel *drivesPanel = EsPanelCreate(panelInstallOptions, ES_CELL_H_FILL, ES_STYLE_PANEL_INSET);
EsPanel *drivesSplit = EsPanelCreate(drivesPanel, ES_CELL_H_FILL | ES_PANEL_HORIZONTAL);
EsPanel *drivesLeft = EsPanelCreate(drivesSplit, ES_CELL_H_FILL);
EsTextDisplayCreate(drivesLeft, ES_CELL_H_FILL, ES_STYLE_TEXT_PARAGRAPH, INTERFACE_STRING(InstallerDrivesList));
EsSpacerCreate(drivesLeft, ES_CELL_H_FILL, 0, 0, 8);
drivesList = EsListViewCreate(drivesLeft, ES_CELL_H_FILL | ES_LIST_VIEW_CHOICE_SELECT | ES_LIST_VIEW_FIXED_ITEMS, ES_STYLE_LIST_CHOICE_BORDERED);
drivesList->messageUser = DrivesListMessage;
EsElementFocus(drivesList);
EsSpacerCreate(drivesSplit, ES_CELL_V_FILL, 0, 25, 0);
driveInformation = EsPanelCreate(drivesSplit, ES_CELL_H_FILL | ES_CELL_V_FILL);
EsTextDisplayCreate(driveInformation, ES_CELL_H_FILL | ES_CELL_V_FILL, &styleDrivesSelectHint, INTERFACE_STRING(InstallerDrivesSelectHint));
EsPanel *buttonsRow = EsPanelCreate(panelInstallOptions, ES_CELL_H_FILL | ES_PANEL_HORIZONTAL, &styleButtonsRow);
EsButtonOnCommand(EsButtonCreate(buttonsRow, ES_FLAGS_DEFAULT, 0, INTERFACE_STRING(InstallerViewLicenses)), ButtonViewLicenses);
EsButtonOnCommand(EsButtonCreate(buttonsRow, ES_FLAGS_DEFAULT, 0, INTERFACE_STRING(DesktopShutdownAction)), ButtonShutdown);
EsSpacerCreate(buttonsRow, ES_CELL_H_FILL);
installButton = EsButtonCreate(buttonsRow, ES_ELEMENT_DISABLED, 0, INTERFACE_STRING(InstallerInstall));
EsButtonOnCommand(installButton, ButtonInstall);
}
{
panelLicenses = EsPanelCreate(switcher, ES_CELL_FILL, &styleRoot);
EsTextbox *textbox = EsTextboxCreate(panelLicenses, ES_CELL_FILL | ES_TEXTBOX_MULTILINE);
EsElementSetDisabled(textbox);
size_t bytes;
char *data = (char *) EsFileReadAll(EsLiteral("0:/installer_licenses.txt"), &bytes);
EsTextboxInsert(textbox, data, bytes);
EsHeapFree(data);
EsButtonOnCommand(EsButtonCreate(panelLicenses, ES_CELL_H_LEFT, 0, INTERFACE_STRING(InstallerGoBack)), ButtonInstallOptions);
}
// EsWindowCreate(instance, ES_WINDOW_INSPECTOR);
}
EsDeviceEnumerate([] (EsMessageDevice device, EsGeneric) {
ConnectedDriveAdd(device);
}, 0);

View File

@ -2,7 +2,9 @@
name=Installer
permission_all_files=1
permission_all_devices=1
permission_shutdown=1
hidden=1
is_installer=1
[build]
source=apps/installer.cpp

View File

@ -168,7 +168,7 @@ void FormatPopupCreate(Instance *instance) {
EsListView *list = EsListViewCreate(column, ES_LIST_VIEW_CHOICE_SELECT | ES_LIST_VIEW_FIXED_ITEMS, ES_STYLE_LIST_CHOICE_BORDERED);
EsListViewFixedItemInsert(list, INTERFACE_STRING(CommonFormatPlainText), 0);
EsListViewFixedItemInsert(list, "C/C++", -1, ES_SYNTAX_HIGHLIGHTING_LANGUAGE_C);
EsListViewFixedItemInsert(list, "Ini file", -1, ES_SYNTAX_HIGHLIGHTING_LANGUAGE_INI);
EsListViewFixedItemInsert(list, "Ini", -1, ES_SYNTAX_HIGHLIGHTING_LANGUAGE_INI);
EsListViewFixedItemSelect(list, instance->syntaxHighlightingLanguage);
list->messageUser = [] (EsElement *element, EsMessage *message) {

View File

@ -758,15 +758,17 @@ EsInstance *_EsInstanceCreate(size_t bytes, EsMessage *message, const char *appl
}
}
apiInstance->mainWindowHandle = message->createInstance.window;
instance->window = EsWindowCreate(instance, ES_WINDOW_NORMAL);
EsWindowSetTitle(instance->window, nullptr, 0);
if (message) {
apiInstance->mainWindowHandle = message->createInstance.window;
instance->window = EsWindowCreate(instance, ES_WINDOW_NORMAL);
EsWindowSetTitle(instance->window, nullptr, 0);
if (apiInstance->startupInformation && apiInstance->startupInformation->readHandle) {
InstanceCreateFileStore(apiInstance, apiInstance->startupInformation->readHandle);
InstancePostOpenMessage(instance, false);
EsWindowSetTitle(instance->window, apiInstance->startupInformation->filePath, apiInstance->startupInformation->filePathBytes);
EsCommandSetDisabled(&apiInstance->commandShowInFileManager, false);
if (apiInstance->startupInformation && apiInstance->startupInformation->readHandle) {
InstanceCreateFileStore(apiInstance, apiInstance->startupInformation->readHandle);
InstancePostOpenMessage(instance, false);
EsWindowSetTitle(instance->window, apiInstance->startupInformation->filePath, apiInstance->startupInformation->filePathBytes);
EsCommandSetDisabled(&apiInstance->commandShowInFileManager, false);
}
}
return instance;
@ -1437,6 +1439,14 @@ double EsPerformanceTimerPop() {
return result;
}
uint32_t EsIconIDFromDriveType(uint8_t driveType) {
if (driveType == ES_DRIVE_TYPE_HDD ) return ES_ICON_DRIVE_HARDDISK;
if (driveType == ES_DRIVE_TYPE_SSD ) return ES_ICON_DRIVE_HARDDISK_SOLIDSTATE;
if (driveType == ES_DRIVE_TYPE_CDROM ) return ES_ICON_MEDIA_OPTICAL;
if (driveType == ES_DRIVE_TYPE_USB_MASS_STORAGE) return ES_ICON_DRIVE_REMOVABLE_MEDIA_USB;
return ES_ICON_DRIVE_HARDDISK;
}
uint32_t EsIconIDFromString(const char *string, ptrdiff_t stringBytes) {
if (!string) {
return 0;

View File

@ -177,6 +177,7 @@ struct {
Array<ContainerWindow *> allContainerWindows;
InstalledApplication *fileManager;
InstalledApplication *installer;
EsObjectID currentDocumentID;
HashStore<EsObjectID, OpenDocument> openDocuments;
@ -187,7 +188,7 @@ struct {
bool shutdownWindowOpen;
bool setupDesktopUIComplete;
int installationState;
uint8_t installationState;
EsHandle nextClipboardFile;
EsObjectID nextClipboardProcessID;
@ -1882,6 +1883,8 @@ void ConfigurationLoadApplications() {
if (EsSystemConfigurationGroupReadInteger(group, EsLiteral("is_file_manager"))) {
desktop.fileManager = application;
} else if (EsSystemConfigurationGroupReadInteger(group, EsLiteral("is_installer"))) {
desktop.installer = application;
}
}
@ -2160,23 +2163,25 @@ void DesktopSetup() {
EsButtonOnCommand(shutdownButton, [] (EsInstance *, EsElement *, EsCommand *) {
ShutdownModalCreate();
});
}
}
if (!desktop.setupDesktopUIComplete) {
// Launch the first application.
// Launch the first application.
char *firstApplication = EsSystemConfigurationReadString(EsLiteral("general"), EsLiteral("first_application"));
char *firstApplication = EsSystemConfigurationReadString(EsLiteral("general"), EsLiteral("first_application"));
if (firstApplication && firstApplication[0]) {
for (uintptr_t i = 0; i < desktop.installedApplications.Length(); i++) {
if (desktop.installedApplications[i]->cName && 0 == EsCRTstrcmp(desktop.installedApplications[i]->cName, firstApplication)) {
ApplicationInstanceCreate(desktop.installedApplications[i]->id, nullptr, nullptr);
if (firstApplication && firstApplication[0]) {
for (uintptr_t i = 0; i < desktop.installedApplications.Length(); i++) {
if (desktop.installedApplications[i]->cName && 0 == EsCRTstrcmp(desktop.installedApplications[i]->cName, firstApplication)) {
ApplicationInstanceCreate(desktop.installedApplications[i]->id, nullptr, nullptr);
}
}
}
}
EsHeapFree(firstApplication);
EsHeapFree(firstApplication);
}
} else if (desktop.installationState == INSTALLATION_STATE_INSTALLER) {
if (!desktop.setupDesktopUIComplete) {
ApplicationInstanceCreate(desktop.installer->id, nullptr, nullptr, true /* hidden */);
}
}
#ifdef CHECK_FOR_NOT_RESPONDING
@ -2186,37 +2191,6 @@ void DesktopSetup() {
}
#endif
if (desktop.setupDesktopUIComplete) {
} else if (desktop.installationState == INSTALLATION_STATE_NONE) {
#if 0
// Play the startup sound.
EsThreadCreate([] (EsGeneric) {
size_t pathBytes;
char *path = EsSystemConfigurationReadString(EsLiteral("general"), EsLiteral("startup_sound"), &pathBytes);
if (path) {
PlaySound(path, pathBytes);
EsHeapFree(path);
}
}, nullptr, 0);
#endif
} else if (desktop.installationState == INSTALLATION_STATE_INSTALLER) {
// Start the installer.
EsWindow *window = EsWindowCreate(nullptr, ES_WINDOW_PLAIN);
EsRectangle screen;
EsSyscall(ES_SYSCALL_SCREEN_BOUNDS_GET, 0, (uintptr_t) &screen, 0, 0);
EsSyscall(ES_SYSCALL_WINDOW_MOVE, window->handle, (uintptr_t) &screen, 0, ES_WINDOW_MOVE_ALWAYS_ON_TOP);
EsSyscall(ES_SYSCALL_WINDOW_SET_PROPERTY, window->handle, ES_WINDOW_SOLID_TRUE, 0, ES_WINDOW_PROPERTY_SOLID);
EsPanel *root = EsPanelCreate(window, ES_PANEL_VERTICAL | ES_CELL_PUSH | ES_CELL_CENTER, ES_STYLE_INSTALLER_ROOT);
EsTextDisplayCreate(root, ES_CELL_H_FILL, ES_STYLE_TEXT_HEADING0, EsLiteral("Essence Installation"));
// TODO.
}
desktop.setupDesktopUIComplete = true;
}

View File

@ -5130,6 +5130,11 @@ EsIconDisplay *EsIconDisplayCreate(EsElement *parent, uint64_t flags, const EsSt
return display;
}
void EsIconDisplaySetIcon(EsIconDisplay *display, uint32_t iconID) {
display->iconID = iconID;
EsElementRepaint(display);
}
// --------------------------------- Sliders.
struct EsSlider : EsElement {
@ -5461,6 +5466,10 @@ void EsWindowSetTitle(EsWindow *window, const char *title, ptrdiff_t titleBytes)
MessageDesktop(buffer, bytes, window->handle);
}
EsHandle EsWindowGetHandle(EsWindow *window) {
return window->handle;
}
EsError EsMouseSetPosition(EsWindow *relativeWindow, int x, int y) {
if (relativeWindow) {
EsRectangle bounds = EsWindowGetBounds(relativeWindow);

View File

@ -2437,6 +2437,28 @@ bool EsListViewFixedItemSelect(EsListView *view, EsGeneric data) {
return found;
}
bool EsListViewFixedItemRemove(EsListView *view, EsGeneric data) {
EsAssert(view->flags & ES_LIST_VIEW_FIXED_ITEMS);
EsMessageMutexCheck();
EsListViewIndex index;
bool found = EsListViewFixedItemFindIndex(view, data, &index);
if (found) {
EsListViewRemove(view, 0, index, 1);
ListViewFixedItem item = view->fixedItems[index];
for (uintptr_t i = 0; i < item.otherColumns.Length(); i++) {
EsHeapFree(item.otherColumns[i].string);
}
EsHeapFree(item.firstColumn.string);
item.otherColumns.Free();
view->fixedItems.Delete(index);
}
return found;
}
bool EsListViewFixedItemGetSelected(EsListView *view, EsGeneric *data) {
EsAssert(view->flags & ES_LIST_VIEW_FIXED_ITEMS);
EsMessageMutexCheck();

View File

@ -2082,6 +2082,7 @@ function void EsDrawTextLayers(EsPainter *painter, EsTextPlan *plan, EsRectangle
function void EsDrawVectorFile(EsPainter *painter, EsRectangle bounds, const void *data, size_t dataBytes);
function uint32_t EsIconIDFromString(STRING string = BLANK_STRING);
function uint32_t EsIconIDFromDriveType(uint8_t driveType);
function uint8_t *EsImageLoad(const void *file, size_t fileSize, uint32_t *width, uint32_t *height, int imageChannels);
@ -2335,6 +2336,7 @@ function void EsWindowSwitchToolbar(EsWindow *window, EsElement *toolbar, EsTran
function void EsWindowSetIcon(EsWindow *window, uint32_t iconID);
function void EsWindowSetTitle(EsWindow *window, STRING title = BLANK_STRING);
function void EsWindowAddSizeAlternative(EsWindow *window, EsElement *small, EsElement *big, int widthThreshold, int heightThreshold); // Switch between elements when the window size goes below a threshold.
function EsHandle EsWindowGetHandle(EsWindow *window); // For internal use only.
function EsMenu *EsMenuCreate(EsElement *source, uint64_t flags = ES_FLAGS_DEFAULT);
function EsElement *EsMenuGetSource(EsMenu *menu); // TODO Public property?
@ -2409,6 +2411,7 @@ function void EsPanelStartMovementAnimation(EsPanel *panel, float timeMultiplier
// Static displays.
function EsIconDisplay *EsIconDisplayCreate(EsElement *parent, uint64_t flags = ES_FLAGS_DEFAULT, const EsStyle *style = ES_NULL, uint32_t iconID = 0);
function void EsIconDisplaySetIcon(EsIconDisplay *display, uint32_t iconID);
function EsImageDisplay *EsImageDisplayCreate(EsElement *parent, uint64_t flags = ES_FLAGS_DEFAULT, const EsStyle *style = ES_NULL);
function void EsImageDisplayLoadBits(EsImageDisplay *display, const uint32_t *bits, size_t width, size_t height, size_t stride);
@ -2466,6 +2469,7 @@ function void EsListViewRemove(EsListView *view, EsListViewIndex group, EsListVi
function void EsListViewRemoveAll(EsListView *view, EsListViewIndex group);
// (Fixed items.)
function EsListViewIndex EsListViewFixedItemInsert(EsListView *view, STRING string = BLANK_STRING, EsGeneric data = ES_NULL, EsListViewIndex index = -1, uint32_t iconID = 0);
function bool EsListViewFixedItemRemove(EsListView *view, EsGeneric data); // Returns false if the item was not found.
function void EsListViewFixedItemAddString(EsListView *view, EsListViewIndex index, STRING string = BLANK_STRING); // For additional columns.
function bool EsListViewFixedItemFindIndex(EsListView *view, EsGeneric data, EsListViewIndex *index); // Returns false if the item was not found.
function bool EsListViewFixedItemSelect(EsListView *view, EsGeneric data); // Returns false if the item was not found.

View File

@ -55,6 +55,7 @@ define ES_STYLE_PANEL_DIALOG_ROOT (ES_STYLE_CAST(1311))
define ES_STYLE_PANEL_DOCUMENT (ES_STYLE_CAST(1547))
define ES_STYLE_PANEL_FILLED (ES_STYLE_CAST(1313))
define ES_STYLE_PANEL_GROUP_BOX (ES_STYLE_CAST(1315))
define ES_STYLE_PANEL_INSET (ES_STYLE_CAST(1641))
define_private ES_STYLE_PANEL_INSPECTOR_WINDOW_CONTAINER (ES_STYLE_CAST(1317))
define_private ES_STYLE_PANEL_INSPECTOR_WINDOW_ROOT (ES_STYLE_CAST(1319))
define_private ES_STYLE_PANEL_MENU_COLUMN (ES_STYLE_CAST(1321))

View File

@ -46,6 +46,7 @@ struct NVMeController : KDevice {
uint64_t maximumDataTransferBytes;
uint32_t rtd3EntryLatencyUs;
uint16_t maximumOutstandingCommands;
char model[40];
uint8_t *adminCompletionQueue, *adminSubmissionQueue;
uint32_t adminCompletionQueueHead, adminSubmissionQueueTail;
@ -610,6 +611,7 @@ void NVMeController::Initialise() {
maximumDataTransferBytes = identifyData[77] ? (1 << (12 + identifyData[77] + (((capabilities >> 48) & 0xF)))) : 0;
rtd3EntryLatencyUs = *(uint32_t *) (identifyData + 88);
maximumOutstandingCommands = *(uint16_t *) (identifyData + 514);
EsMemoryCopy(model, &identifyData[24], sizeof(model));
if (rtd3EntryLatencyUs > 250 * 1000) {
rtd3EntryLatencyUs = 250 * 1000; // Maximum shutdown delay: 250ms.
@ -624,7 +626,7 @@ void NVMeController::Initialise() {
KernelLog(LOG_INFO, "NVMe", "controller identify data", "Controller identify reported the following information: "
"serial number - '%s', model number - '%s', firmware revision - '%s', "
"maximum data transfer - %D, RTD3 entry latency - %dus, maximum outstanding commands - %d.\n",
20, identifyData + 4, 40, identifyData + 24, 8, identifyData + 64,
20, identifyData + 4, sizeof(model), model, 8, identifyData + 64,
maximumDataTransferBytes, rtd3EntryLatencyUs, maximumOutstandingCommands);
if (maximumDataTransferBytes == 0 || maximumDataTransferBytes >= 2097152) {
@ -788,7 +790,7 @@ void NVMeController::Initialise() {
bool readOnly = identifyData[4096 + 99] & (1 << 0);
KernelLog(LOG_INFO, "NVMe", "namespace identified", "Identifier namespace %d with sectors of size %D, and a capacity of %D.%z\n",
KernelLog(LOG_INFO, "NVMe", "namespace identified", "Identified namespace %d with sectors of size %D, and a capacity of %D.%z\n",
nsid, sectorBytes, capacity, readOnly ? " The namespace is read-only." : "");
NVMeDrive *device = (NVMeDrive *) KDeviceCreate("NVMe namespace", this, sizeof(NVMeDrive));
@ -801,11 +803,15 @@ void NVMeController::Initialise() {
device->controller = this;
device->nsid = nsid;
device->maxAccessSectorCount = maximumDataTransferBytes / sectorBytes;
device->information.sectorSize = sectorBytes;
device->information.sectorCount = capacity / sectorBytes;
device->maxAccessSectorCount = maximumDataTransferBytes / sectorBytes;
device->information.readOnly = readOnly;
device->information.driveType = ES_DRIVE_TYPE_SSD;
EsAssert(sizeof(device->information.model) >= sizeof(model));
device->information.modelBytes = sizeof(model);
EsMemoryCopy(device->information.model, model, 40);
device->access = [] (KBlockDeviceAccessRequest request) {
NVMeDrive *drive = (NVMeDrive *) request.device;

Binary file not shown.

Binary file not shown.

View File

@ -5,6 +5,7 @@
#define ELLIPSIS "…"
#define HYPHENATION_POINT "‧"
#define SYSTEM_BRAND_SHORT "Essence"
// Common.
@ -52,7 +53,7 @@ DEFINE_INTERFACE_STRING(CommonDriveSSD, "SSD");
DEFINE_INTERFACE_STRING(CommonDriveCDROM, "CD-ROM");
DEFINE_INTERFACE_STRING(CommonDriveUSBMassStorage, "USB drive");
DEFINE_INTERFACE_STRING(CommonSystemBrand, "Essence Alpha v0.1");
DEFINE_INTERFACE_STRING(CommonSystemBrand, SYSTEM_BRAND_SHORT " Alpha v0.1");
DEFINE_INTERFACE_STRING(CommonListViewType, "List view");
DEFINE_INTERFACE_STRING(CommonListViewTypeThumbnails, "Thumbnails");
@ -276,6 +277,19 @@ DEFINE_INTERFACE_STRING(Game2048NewGame, "New game");
DEFINE_INTERFACE_STRING(Game2048HighScore, "High score: \aw6]%d\a]");
DEFINE_INTERFACE_STRING(Game2048NewHighScore, "You reached a new high score!");
// Installer.
DEFINE_INTERFACE_STRING(InstallerTitle, SYSTEM_BRAND_SHORT " Installer");
DEFINE_INTERFACE_STRING(InstallerDrivesList, "Select the drive to install on:");
DEFINE_INTERFACE_STRING(InstallerDrivesSelectHint, "Choose a drive from the list on the left.");
DEFINE_INTERFACE_STRING(InstallerDriveRemoved, "The drive was disconnected.");
DEFINE_INTERFACE_STRING(InstallerDriveReadOnly, "This drive is read-only. You cannot install " SYSTEM_BRAND_SHORT " on this drive.");
DEFINE_INTERFACE_STRING(InstallerDriveNotEnoughSpace, "This drive does not have enough space to install " SYSTEM_BRAND_SHORT ".");
DEFINE_INTERFACE_STRING(InstallerDriveOkay, SYSTEM_BRAND_SHORT " can be installed on this drive.");
DEFINE_INTERFACE_STRING(InstallerInstall, "Install");
DEFINE_INTERFACE_STRING(InstallerViewLicenses, "Licenses");
DEFINE_INTERFACE_STRING(InstallerGoBack, "Back");
// TODO System Monitor.
#pragma GCC diagnostic pop

View File

@ -446,3 +446,7 @@ EsBufferReadInt32Endian=444
EsBufferWriteInt32Endian=445
EsSystemGetOptimalWorkQueueThreadCount=446
EsDeviceControl=447
EsWindowGetHandle=448
EsListViewFixedItemRemove=449
EsIconIDFromDriveType=450
EsIconDisplaySetIcon=451

View File

@ -1002,7 +1002,7 @@ void AddressToLine(const char *symbolFile) {
}
}
void GatherFilesForInstallerArchive(FILE *file, const char *path1, const char *path2, uint64_t *crc64) {
void GatherFilesForInstallerArchive(FILE *file, const char *path1, const char *path2, uint64_t *crc64, uint64_t *totalUncompressedSize) {
char path[4096], path3[4096];
snprintf(path, sizeof(path), "%s%s", path1, path2);
@ -1021,7 +1021,7 @@ void GatherFilesForInstallerArchive(FILE *file, const char *path1, const char *p
lstat(path, &s);
if (S_ISDIR(s.st_mode)) {
GatherFilesForInstallerArchive(file, path1, path3, crc64);
GatherFilesForInstallerArchive(file, path1, path3, crc64, totalUncompressedSize);
} else if (S_ISREG(s.st_mode)) {
size_t _length;
void *data = LoadFile(path, &_length);
@ -1033,6 +1033,7 @@ void GatherFilesForInstallerArchive(FILE *file, const char *path1, const char *p
fwrite(path3, 1, pathBytes, file);
fwrite(data, 1, length, file);
*crc64 = CalculateCRC64(data, length, *crc64);
*totalUncompressedSize += length;
free(data);
} else {
printf("skipping: %s\n", path3);
@ -1105,8 +1106,8 @@ void DoCommand(const char *l) {
"ports/lzma/7zStream.c ports/lzma/Threads.c ports/lzma/LzFindMt.c ports/lzma/LzFind.c "
"ports/lzma/7zFile.c ports/lzma/Alloc.c ports/lzma/CpuArch.c -pthread");
FILE *f = fopen("bin/temp.dat", "wb");
uint64_t crc64 = 0;
GatherFilesForInstallerArchive(f, "root", "", &crc64);
uint64_t crc64 = 0, uncompressed = 0;
GatherFilesForInstallerArchive(f, "root", "", &crc64, &uncompressed);
fwrite(&crc64, 1, sizeof(crc64), f);
uint32_t sizeMB = ftell(f) / 1000000;
fclose(f);
@ -1116,6 +1117,9 @@ void DoCommand(const char *l) {
lstat("bin/installer_archive.dat", &s);
printf("Compressed to %d MB.\n", (uint32_t) (s.st_size / 1000000));
unlink("bin/temp.dat");
f = fopen("bin/installer_metadata.dat", "ab");
fwrite(&uncompressed, 1, sizeof(uncompressed), f);
fclose(f);
} else if (0 == strcmp(l, "config")) {
BuildUtilities();
CallSystem("bin/config_editor");

View File

@ -305,6 +305,7 @@ Option options[] = {
{ "Emulator.SecondaryDriveMB", OPTION_TYPE_STRING, { .s = NULL } },
{ "General.first_application", OPTION_TYPE_STRING, { .s = NULL } },
{ "General.wallpaper", OPTION_TYPE_STRING, { .s = NULL } },
{ "General.installation_state", OPTION_TYPE_STRING, { .s = "0" } },
};
char *previousOptionsBuffer;