From 6c2796f8bd616b5378726a78b70e51470903abdf Mon Sep 17 00:00:00 2001 From: Daniel Hammer Date: Wed, 22 Apr 2026 07:45:33 +0200 Subject: [PATCH] feat: expose drive labels to userspace, render in Files --- kernel/src/Api/Filesystem.hpp | 4 + kernel/src/Api/Syscall.cpp | 4 + kernel/src/Api/Syscall.hpp | 3 + kernel/src/Fs/Boot.cpp | 1 + kernel/src/Fs/Ext2.cpp | 7 + kernel/src/Fs/Fat32.cpp | 10 + kernel/src/Fs/Ramdisk.cpp | 4 + kernel/src/Fs/Ramdisk.hpp | 1 + kernel/src/Fs/Vfs.cpp | 32 +++ kernel/src/Fs/Vfs.hpp | 2 + programs/include/Api/Syscall.hpp | 1 + programs/include/libc/montauk.h | 1 + programs/include/montauk/syscall.h | 3 + .../src/desktop/apps/filemanager/events.cpp | 14 +- .../apps/filemanager/filemanager_internal.hpp | 6 + .../desktop/apps/filemanager/filesystem.cpp | 6 + .../src/desktop/apps/filemanager/render.cpp | 195 +++++++++++++++--- template/sysroot/include/Api/Syscall.hpp | 1 + template/sysroot/include/libc/montauk.h | 1 + template/sysroot/include/montauk/syscall.h | 3 + 20 files changed, 261 insertions(+), 38 deletions(-) diff --git a/kernel/src/Api/Filesystem.hpp b/kernel/src/Api/Filesystem.hpp index 9613dbc..d6aef9c 100644 --- a/kernel/src/Api/Filesystem.hpp +++ b/kernel/src/Api/Filesystem.hpp @@ -122,4 +122,8 @@ namespace Montauk { static int Sys_DriveList(int* outDrives, int maxEntries) { return Fs::Vfs::VfsDriveList(outDrives, maxEntries); } + + static int Sys_DriveLabel(int driveNumber, char* outLabel, int maxLen) { + return Fs::Vfs::VfsDriveLabel(driveNumber, outLabel, maxLen); + } }; diff --git a/kernel/src/Api/Syscall.cpp b/kernel/src/Api/Syscall.cpp index 12a1b12..7b19f15 100644 --- a/kernel/src/Api/Syscall.cpp +++ b/kernel/src/Api/Syscall.cpp @@ -209,6 +209,10 @@ namespace Montauk { if ((int64_t)frame->arg2 < 0) return -1; if (!UserMemory::Range(frame->arg1, (uint64_t)frame->arg2 * sizeof(int), true)) return -1; return (int64_t)Sys_DriveList((int*)frame->arg1, (int)frame->arg2); + case SYS_DRIVELABEL: + if ((int64_t)frame->arg3 <= 0) return -1; + if (!UserMemory::Range(frame->arg2, frame->arg3, true)) return -1; + return (int64_t)Sys_DriveLabel((int)frame->arg1, (char*)frame->arg2, (int)frame->arg3); case SYS_TERMSCALE: return Sys_TermScale(frame->arg1, frame->arg2); case SYS_RESOLVE: diff --git a/kernel/src/Api/Syscall.hpp b/kernel/src/Api/Syscall.hpp index dae0846..3a8e4b9 100644 --- a/kernel/src/Api/Syscall.hpp +++ b/kernel/src/Api/Syscall.hpp @@ -222,6 +222,9 @@ namespace Montauk { /* Input.hpp */ static constexpr uint64_t SYS_INPUT_WAIT = 123; + /* Filesystem.hpp */ + static constexpr uint64_t SYS_DRIVELABEL = 124; + static constexpr uint32_t CLIPBOARD_MAX_TEXT_BYTES = 256 * 1024; static constexpr uint32_t IPC_SIGNAL_READABLE = 1u << 0; diff --git a/kernel/src/Fs/Boot.cpp b/kernel/src/Fs/Boot.cpp index 847526c..f67bf8b 100644 --- a/kernel/src/Fs/Boot.cpp +++ b/kernel/src/Fs/Boot.cpp @@ -65,6 +65,7 @@ namespace Fs { Ramdisk::Delete, Ramdisk::Mkdir, Ramdisk::Rename, + Ramdisk::GetLabel, }; } diff --git a/kernel/src/Fs/Ext2.cpp b/kernel/src/Fs/Ext2.cpp index 3a30dda..74d7d3c 100644 --- a/kernel/src/Fs/Ext2.cpp +++ b/kernel/src/Fs/Ext2.cpp @@ -1592,6 +1592,11 @@ namespace Fs::Ext2 { // Template thunks — generate unique function pointers per instance // ========================================================================= + static const char* GetLabelImpl(int inst) { + if (inst < 0 || inst >= g_instanceCount || !g_instances[inst].active) return nullptr; + return g_instances[inst].volumeLabel[0] ? g_instances[inst].volumeLabel : nullptr; + } + template struct Thunks { static int Open(const char* p) { return OpenImpl(N, p); } static int Read(int h, uint8_t* b, uint64_t o, uint64_t s) { return ReadImpl(N, h, b, o, s); } @@ -1603,6 +1608,7 @@ namespace Fs::Ext2 { static int Delete(const char* p) { return DeleteImpl(N, p); } static int Mkdir(const char* p) { return MkdirImpl(N, p); } static int Rename(const char* o, const char* n) { return RenameImpl(N, o, n); } + static const char* GetLabel() { return GetLabelImpl(N); } }; template @@ -1618,6 +1624,7 @@ namespace Fs::Ext2 { Thunks::Delete, Thunks::Mkdir, Thunks::Rename, + Thunks::GetLabel, }; } diff --git a/kernel/src/Fs/Fat32.cpp b/kernel/src/Fs/Fat32.cpp index e5d535f..bc81efb 100644 --- a/kernel/src/Fs/Fat32.cpp +++ b/kernel/src/Fs/Fat32.cpp @@ -1748,6 +1748,14 @@ namespace Fs::Fat32 { // Template thunks — generate unique function pointers per instance // ========================================================================= + static const char* GetLabelImpl(int inst) { + if (inst < 0 || inst >= g_instanceCount || !g_instances[inst].active) return nullptr; + + const char* label = g_instances[inst].volumeLabel; + if (label[0] == '\0' || StrEqualNoCase(label, "NO NAME")) return nullptr; + return label; + } + template struct Thunks { static int Open(const char* p) { return OpenImpl(N, p); } static int Read(int h, uint8_t* b, uint64_t o, uint64_t s) { return ReadImpl(N, h, b, o, s); } @@ -1759,6 +1767,7 @@ namespace Fs::Fat32 { static int Delete(const char* p) { return DeleteImpl(N, p); } static int Mkdir(const char* p) { return MkdirImpl(N, p); } static int Rename(const char* o, const char* n) { return RenameImpl(N, o, n); } + static const char* GetLabel() { return GetLabelImpl(N); } }; template @@ -1774,6 +1783,7 @@ namespace Fs::Fat32 { Thunks::Delete, Thunks::Mkdir, Thunks::Rename, + Thunks::GetLabel, }; } diff --git a/kernel/src/Fs/Ramdisk.cpp b/kernel/src/Fs/Ramdisk.cpp index d932b25..18129f6 100644 --- a/kernel/src/Fs/Ramdisk.cpp +++ b/kernel/src/Fs/Ramdisk.cpp @@ -38,6 +38,10 @@ namespace Fs::Ramdisk { return n; } + const char* GetLabel() { + return "Ramdisk"; + } + static bool StartsWith(const char* str, const char* prefix) { while (*prefix) { if (*str != *prefix) return false; diff --git a/kernel/src/Fs/Ramdisk.hpp b/kernel/src/Fs/Ramdisk.hpp index 49fa63d..1f4f0f6 100644 --- a/kernel/src/Fs/Ramdisk.hpp +++ b/kernel/src/Fs/Ramdisk.hpp @@ -35,6 +35,7 @@ namespace Fs::Ramdisk { int Delete(const char* path); int Mkdir(const char* path); int Rename(const char* oldPath, const char* newPath); + const char* GetLabel(); int GetFileCount(); } diff --git a/kernel/src/Fs/Vfs.cpp b/kernel/src/Fs/Vfs.cpp index 6ec881b..d94843e 100644 --- a/kernel/src/Fs/Vfs.cpp +++ b/kernel/src/Fs/Vfs.cpp @@ -208,6 +208,38 @@ namespace Fs::Vfs { return count; } + int VfsDriveLabel(int driveNumber, char* outLabel, int maxLen) { + if (outLabel == nullptr || maxLen <= 0) return -1; + outLabel[0] = '\0'; + + vfsLock.Acquire(); + if (driveNumber < 0 || driveNumber >= MaxDrives || driveTable[driveNumber] == nullptr) { + vfsLock.Release(); + return -1; + } + + if (driveTable[driveNumber]->GetLabel == nullptr) { + vfsLock.Release(); + return 0; + } + + const char* label = driveTable[driveNumber]->GetLabel(); + if (label == nullptr || label[0] == '\0') { + vfsLock.Release(); + return 0; + } + + int copied = 0; + while (label[copied] != '\0' && copied < maxLen - 1) { + outLabel[copied] = label[copied]; + copied++; + } + outLabel[copied] = '\0'; + + vfsLock.Release(); + return copied; + } + int VfsRename(const char* oldPath, const char* newPath) { int oldDrive, newDrive; const char* oldLocal; diff --git a/kernel/src/Fs/Vfs.hpp b/kernel/src/Fs/Vfs.hpp index 1f5c8b5..7f46594 100644 --- a/kernel/src/Fs/Vfs.hpp +++ b/kernel/src/Fs/Vfs.hpp @@ -28,6 +28,7 @@ namespace Fs::Vfs { int (*Delete)(const char* path); int (*Mkdir)(const char* path); int (*Rename)(const char* oldPath, const char* newPath); + const char* (*GetLabel)(); }; void Initialize(); @@ -48,5 +49,6 @@ namespace Fs::Vfs { // Returns number of registered drives, fills outDrives[] with their indices int VfsDriveList(int* outDrives, int maxEntries); + int VfsDriveLabel(int driveNumber, char* outLabel, int maxLen); } diff --git a/programs/include/Api/Syscall.hpp b/programs/include/Api/Syscall.hpp index da72ea1..06a0cb4 100644 --- a/programs/include/Api/Syscall.hpp +++ b/programs/include/Api/Syscall.hpp @@ -157,6 +157,7 @@ namespace Montauk { static constexpr uint64_t SYS_CLIPBOARD_GET_TEXT = 121; static constexpr uint64_t SYS_CLIPBOARD_CLEAR = 122; static constexpr uint64_t SYS_INPUT_WAIT = 123; + static constexpr uint64_t SYS_DRIVELABEL = 124; static constexpr uint32_t CLIPBOARD_MAX_TEXT_BYTES = 256 * 1024; diff --git a/programs/include/libc/montauk.h b/programs/include/libc/montauk.h index 8d44307..9afd213 100644 --- a/programs/include/libc/montauk.h +++ b/programs/include/libc/montauk.h @@ -92,6 +92,7 @@ extern "C" { #define MTK_SYS_FMKDIR 78 #define MTK_SYS_FRENAME 94 #define MTK_SYS_DRIVELIST 79 +#define MTK_SYS_DRIVELABEL 124 #define MTK_SYS_AUDIOOPEN 80 #define MTK_SYS_AUDIOCLOSE 81 #define MTK_SYS_AUDIOWRITE 82 diff --git a/programs/include/montauk/syscall.h b/programs/include/montauk/syscall.h index 7720276..383ac8a 100644 --- a/programs/include/montauk/syscall.h +++ b/programs/include/montauk/syscall.h @@ -161,6 +161,9 @@ namespace montauk { inline int drivelist(int* outDrives, int max) { return (int)syscall2(Montauk::SYS_DRIVELIST, (uint64_t)outDrives, (uint64_t)max); } + inline int drivelabel(int drive, char* outLabel, int maxLen) { + return (int)syscall3(Montauk::SYS_DRIVELABEL, (uint64_t)drive, (uint64_t)outLabel, (uint64_t)maxLen); + } // Memory inline void* alloc(uint64_t size) { return (void*)syscall1(Montauk::SYS_ALLOC, size); } diff --git a/programs/src/desktop/apps/filemanager/events.cpp b/programs/src/desktop/apps/filemanager/events.cpp index 5675519..a5d725f 100644 --- a/programs/src/desktop/apps/filemanager/events.cpp +++ b/programs/src/desktop/apps/filemanager/events.cpp @@ -117,11 +117,10 @@ void filemanager_on_mouse(Window* win, MouseEvent& ev) { if (local_y >= list_y && local_x < cw - FM_SCROLLBAR_W) { int cols = (cw - FM_SCROLLBAR_W) / FM_GRID_CELL_W; if (cols < 1) cols = 1; - int col = local_x / FM_GRID_CELL_W; - int row = (local_y - list_y + fm->scrollbar.scroll_offset) / FM_GRID_CELL_H; - int clicked_idx = row * cols + col; + int rel_y = local_y - list_y + fm->scrollbar.scroll_offset; + int clicked_idx = filemanager_grid_index_at(fm, cols, local_x, rel_y); - if (clicked_idx >= 0 && clicked_idx < fm->entry_count && col < cols) { + if (clicked_idx >= 0 && clicked_idx < fm->entry_count) { uint64_t now = montauk::get_milliseconds(); if (fm->last_click_item == clicked_idx && @@ -179,10 +178,9 @@ void filemanager_on_mouse(Window* win, MouseEvent& ev) { if (local_x < cw - FM_SCROLLBAR_W) { int cols = (cw - FM_SCROLLBAR_W) / FM_GRID_CELL_W; if (cols < 1) cols = 1; - int col = local_x / FM_GRID_CELL_W; - int row = (local_y - list_y + fm->scrollbar.scroll_offset) / FM_GRID_CELL_H; - int idx = row * cols + col; - if (idx >= 0 && idx < fm->entry_count && col < cols) { + int rel_y = local_y - list_y + fm->scrollbar.scroll_offset; + int idx = filemanager_grid_index_at(fm, cols, local_x, rel_y); + if (idx >= 0 && idx < fm->entry_count) { target_idx = idx; fm->selected = idx; } diff --git a/programs/src/desktop/apps/filemanager/filemanager_internal.hpp b/programs/src/desktop/apps/filemanager/filemanager_internal.hpp index c3b407d..00e3876 100644 --- a/programs/src/desktop/apps/filemanager/filemanager_internal.hpp +++ b/programs/src/desktop/apps/filemanager/filemanager_internal.hpp @@ -73,6 +73,7 @@ inline constexpr int FM_ITEM_H = 24; inline constexpr int FM_SCROLLBAR_W = 12; inline constexpr int FM_GRID_CELL_W = 80; inline constexpr int FM_GRID_CELL_H = 80; +inline constexpr int FM_GRID_CELL_H_WRAPPED = 92; inline constexpr int FM_GRID_ICON = 48; inline constexpr int FM_GRID_PAD = 4; @@ -151,6 +152,11 @@ void filemanager_commit_pathbar(FileManagerState* fm); void filemanager_open_entry(FileManagerState* fm, int idx); +int filemanager_grid_row_height(FileManagerState* fm, int row, int cols); +int filemanager_grid_row_y(FileManagerState* fm, int row, int cols); +int filemanager_grid_content_height(FileManagerState* fm, int cols); +int filemanager_grid_index_at(FileManagerState* fm, int cols, int x, int rel_y); + void filemanager_draw_header(Canvas& c, FileManagerState* fm, Color toolbar_color, Color btn_bg); void filemanager_on_draw(Window* win, Framebuffer& fb); void filemanager_on_mouse(Window* win, MouseEvent& ev); diff --git a/programs/src/desktop/apps/filemanager/filesystem.cpp b/programs/src/desktop/apps/filemanager/filesystem.cpp index bbcaab7..9feadc1 100644 --- a/programs/src/desktop/apps/filemanager/filesystem.cpp +++ b/programs/src/desktop/apps/filemanager/filesystem.cpp @@ -85,6 +85,12 @@ void filemanager_read_drives(FileManagerState* fm) { char label[64]; montauk::strcpy(label, "Drive "); str_append(label, probe, 64); + char volume_label[64]; + if (montauk::drivelabel(d, volume_label, 64) > 0 && volume_label[0] != '\0') { + str_append(label, " [", 64); + str_append(label, volume_label, 64); + str_append(label, "]", 64); + } montauk::strncpy(fm->entry_names[i], label, 63); fm->entry_types[i] = 3; // drive fm->entry_sizes[i] = 0; diff --git a/programs/src/desktop/apps/filemanager/render.cpp b/programs/src/desktop/apps/filemanager/render.cpp index 25dd923..145443d 100644 --- a/programs/src/desktop/apps/filemanager/render.cpp +++ b/programs/src/desktop/apps/filemanager/render.cpp @@ -8,6 +8,155 @@ namespace filemanager { +static bool label_break_char(char ch) { + return ch == ' ' || ch == '-' || ch == '_' || ch == '/'; +} + +static void copy_label_range(char* dst, int dst_max, const char* src, int start, int end) { + if (!dst || dst_max <= 0) return; + while (start < end && src[start] == ' ') start++; + while (end > start && src[end - 1] == ' ') end--; + + int out = 0; + for (int i = start; i < end && out < dst_max - 1; i++) { + dst[out++] = src[i]; + } + dst[out] = '\0'; +} + +static int fitted_prefix_len(const char* src, int max_w, int max_len) { + char tmp[128]; + int best = 0; + int limit = max_len < 127 ? max_len : 127; + for (int len = 1; len <= limit; len++) { + copy_label_range(tmp, sizeof(tmp), src, 0, len); + if (text_width(tmp) > max_w) break; + best = len; + } + return best > 0 ? best : 1; +} + +static void fit_label_with_ellipsis(char* dst, int dst_max, const char* src, int max_w) { + montauk::strncpy(dst, src, dst_max); + if (text_width(dst) <= max_w) return; + + int ellipsis_w = text_width("..."); + int len = montauk::slen(dst); + while (len > 0) { + dst[len] = '\0'; + if (text_width(dst) + ellipsis_w <= max_w) break; + len--; + } + + if (len > dst_max - 4) len = dst_max - 4; + if (len < 0) len = 0; + dst[len] = '.'; + dst[len + 1] = '.'; + dst[len + 2] = '.'; + dst[len + 3] = '\0'; +} + +static void build_grid_label_lines(const char* name, int max_w, + char* line1, int line1_max, + char* line2, int line2_max) { + line1[0] = '\0'; + line2[0] = '\0'; + + if (text_width(name) <= max_w) { + montauk::strncpy(line1, name, line1_max); + return; + } + + int nlen = montauk::slen(name); + int break_end = -1; + int break_next = -1; + + for (int i = 0; i < nlen - 1; i++) { + if (!label_break_char(name[i])) continue; + + int end = (name[i] == ' ') ? i : i + 1; + int next = i + 1; + + char candidate[128]; + copy_label_range(candidate, sizeof(candidate), name, 0, end); + if (candidate[0] != '\0' && text_width(candidate) <= max_w) { + break_end = end; + break_next = next; + } + } + + if (break_end < 0) { + break_end = fitted_prefix_len(name, max_w, nlen); + break_next = break_end; + } + + copy_label_range(line1, line1_max, name, 0, break_end); + fit_label_with_ellipsis(line2, line2_max, name + break_next, max_w); +} + +static void draw_centered_grid_label(Canvas& c, int cell_x, int y, const char* label, Color color) { + int tw = text_width(label); + int tx = cell_x + (FM_GRID_CELL_W - tw) / 2; + if (tx < cell_x + 2) tx = cell_x + 2; + c.text(tx, y, label, color); +} + +int filemanager_grid_row_height(FileManagerState* fm, int row, int cols) { + if (!fm || cols <= 0 || row < 0) return FM_GRID_CELL_H; + + int start = row * cols; + int end = start + cols; + if (end > fm->entry_count) end = fm->entry_count; + + int max_w = FM_GRID_CELL_W - 4; + for (int i = start; i < end; i++) { + if (text_width(fm->entry_names[i]) > max_w) { + return FM_GRID_CELL_H_WRAPPED; + } + } + + return FM_GRID_CELL_H; +} + +int filemanager_grid_row_y(FileManagerState* fm, int row, int cols) { + int y = 0; + for (int r = 0; r < row; r++) { + y += filemanager_grid_row_height(fm, r, cols); + } + return y; +} + +int filemanager_grid_content_height(FileManagerState* fm, int cols) { + if (!fm || cols <= 0) return 0; + + int rows = (fm->entry_count + cols - 1) / cols; + int h = 0; + for (int r = 0; r < rows; r++) { + h += filemanager_grid_row_height(fm, r, cols); + } + return h; +} + +int filemanager_grid_index_at(FileManagerState* fm, int cols, int x, int rel_y) { + if (!fm || cols <= 0 || x < 0 || rel_y < 0) return -1; + + int col = x / FM_GRID_CELL_W; + if (col < 0 || col >= cols) return -1; + + int rows = (fm->entry_count + cols - 1) / cols; + int row_y = 0; + for (int row = 0; row < rows; row++) { + int row_h = filemanager_grid_row_height(fm, row, cols); + if (rel_y < row_y + row_h) { + int idx = row * cols + col; + return idx < fm->entry_count ? idx : -1; + } + row_y += row_h; + } + + return -1; +} + void filemanager_draw_header(Canvas& c, FileManagerState* fm, Color toolbar_color, Color btn_bg) { DesktopState* ds = fm->desktop; @@ -133,8 +282,7 @@ void filemanager_on_draw(Window* win, Framebuffer& fb) { int list_h = c.h - list_y; int cols = (c.w - FM_SCROLLBAR_W) / FM_GRID_CELL_W; if (cols < 1) cols = 1; - int rows = (fm->entry_count + cols - 1) / cols; - int content_h = rows * FM_GRID_CELL_H; + int content_h = filemanager_grid_content_height(fm, cols); // Update scrollbar fm->scrollbar.bounds = {c.w - FM_SCROLLBAR_W, list_y, FM_SCROLLBAR_W, list_h}; @@ -145,15 +293,16 @@ void filemanager_on_draw(Window* win, Framebuffer& fb) { int col = i % cols; int row = i / cols; int cell_x = col * FM_GRID_CELL_W; - int cell_y = list_y + row * FM_GRID_CELL_H - fm->scrollbar.scroll_offset; + int row_h = filemanager_grid_row_height(fm, row, cols); + int cell_y = list_y + filemanager_grid_row_y(fm, row, cols) - fm->scrollbar.scroll_offset; // Skip if entirely off-screen - if (cell_y + FM_GRID_CELL_H <= list_y || cell_y >= c.h) continue; + if (cell_y + row_h <= list_y || cell_y >= c.h) continue; // Selection highlight if (i == fm->selected) { int sy = gui_max(cell_y, list_y); - int sh = gui_min(cell_y + FM_GRID_CELL_H, c.h) - sy; + int sh = gui_min(cell_y + row_h, c.h) - sy; int sw = gui_min(FM_GRID_CELL_W, c.w - FM_SCROLLBAR_W - cell_x); if (sh > 0 && sw > 0) c.fill_rect(cell_x, sy, sw, sh, colors::MENU_HOVER); @@ -217,35 +366,21 @@ void filemanager_on_draw(Window* win, Framebuffer& fb) { c.vline(cx, ty, system_font_height(), colors::ACCENT); } } else { - // Truncate by pixel width so names never overflow cells + // Prefer two grid label rows before truncating. int max_w = FM_GRID_CELL_W - 4; const char* name = fm->entry_names[i]; - int nlen = montauk::slen(name); - char label[64]; - montauk::strncpy(label, name, 63); + char line1[128]; + char line2[128]; + build_grid_label_lines(name, max_w, line1, sizeof(line1), line2, sizeof(line2)); - if (text_width(label) > max_w && nlen > 3) { - int ellipsis_w = text_width("..."); - int final_len = nlen; - while (final_len > 1) { - label[final_len] = '\0'; - int w = text_width(label); - if (w + ellipsis_w <= max_w) break; - final_len--; - } - if (final_len > 60) final_len = 60; - label[final_len] = '.'; - label[final_len + 1] = '.'; - label[final_len + 2] = '.'; - label[final_len + 3] = '\0'; - } - - int tw = text_width(label); - int tx = cell_x + (FM_GRID_CELL_W - tw) / 2; - if (tx < cell_x) tx = cell_x; int ty = icon_y + FM_GRID_ICON + 2; - if (ty >= list_y && ty + system_font_height() <= c.h) - c.text(tx, ty, label, colors::TEXT_COLOR); + int fh = system_font_height(); + if (ty >= list_y && ty + fh <= c.h) { + draw_centered_grid_label(c, cell_x, ty, line1, colors::TEXT_COLOR); + } + if (line2[0] != '\0' && ty + fh >= list_y && ty + fh * 2 <= c.h) { + draw_centered_grid_label(c, cell_x, ty + fh, line2, colors::TEXT_COLOR); + } } } } else { diff --git a/template/sysroot/include/Api/Syscall.hpp b/template/sysroot/include/Api/Syscall.hpp index 9423f6e..8d41e79 100644 --- a/template/sysroot/include/Api/Syscall.hpp +++ b/template/sysroot/include/Api/Syscall.hpp @@ -57,6 +57,7 @@ namespace Montauk { static constexpr uint64_t SYS_FDELETE = 77; static constexpr uint64_t SYS_FMKDIR = 78; static constexpr uint64_t SYS_DRIVELIST = 79; + static constexpr uint64_t SYS_DRIVELABEL = 124; static constexpr uint64_t SYS_TERMSCALE = 43; static constexpr uint64_t SYS_RESOLVE = 44; static constexpr uint64_t SYS_GETRANDOM = 45; diff --git a/template/sysroot/include/libc/montauk.h b/template/sysroot/include/libc/montauk.h index 2653efd..0e3b087 100644 --- a/template/sysroot/include/libc/montauk.h +++ b/template/sysroot/include/libc/montauk.h @@ -91,6 +91,7 @@ extern "C" { #define MTK_SYS_FMKDIR 78 #define MTK_SYS_FRENAME 94 #define MTK_SYS_DRIVELIST 79 +#define MTK_SYS_DRIVELABEL 124 #define MTK_SYS_AUDIOOPEN 80 #define MTK_SYS_AUDIOCLOSE 81 #define MTK_SYS_AUDIOWRITE 82 diff --git a/template/sysroot/include/montauk/syscall.h b/template/sysroot/include/montauk/syscall.h index 8ba7938..614afd1 100644 --- a/template/sysroot/include/montauk/syscall.h +++ b/template/sysroot/include/montauk/syscall.h @@ -152,6 +152,9 @@ namespace montauk { inline int drivelist(int* outDrives, int max) { return (int)syscall2(Montauk::SYS_DRIVELIST, (uint64_t)outDrives, (uint64_t)max); } + inline int drivelabel(int drive, char* outLabel, int maxLen) { + return (int)syscall3(Montauk::SYS_DRIVELABEL, (uint64_t)drive, (uint64_t)outLabel, (uint64_t)maxLen); + } // Memory inline void* alloc(uint64_t size) { return (void*)syscall1(Montauk::SYS_ALLOC, size); }