├── .gitignore ├── EFI └── Boot │ └── .gitignore ├── screenshot.jpg ├── readme.md └── paint.zig /.gitignore: -------------------------------------------------------------------------------- 1 | zig-cache 2 | NvVars 3 | -------------------------------------------------------------------------------- /EFI/Boot/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /screenshot.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nrdmn/uefi-paint/HEAD/screenshot.jpg -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | Build with `zig build`, run on a device with a touchscreen. 2 | 3 | ![screenshot](screenshot.jpg) 4 | -------------------------------------------------------------------------------- /paint.zig: -------------------------------------------------------------------------------- 1 | const uefi = @import("std").os.uefi; 2 | const AbsolutePointerProtocol = uefi.protocols.AbsolutePointerProtocol; 3 | const AbsolutePointerState = uefi.protocols.AbsolutePointerState; 4 | const GraphicsOutputProtocol = uefi.protocols.GraphicsOutputProtocol; 5 | const GraphicsOutputBltPixel = uefi.protocols.GraphicsOutputBltPixel; 6 | const GraphicsOutputBltOperation = uefi.protocols.GraphicsOutputBltOperation; 7 | 8 | pub fn main() void { 9 | const boot_services = uefi.system_table.boot_services.?; 10 | var pointer: *AbsolutePointerProtocol = undefined; 11 | var graphics: *GraphicsOutputProtocol = undefined; 12 | var pointer_state = AbsolutePointerState{}; 13 | var selected: u4 = 0; 14 | const colors = [16]GraphicsOutputBltPixel{ 15 | GraphicsOutputBltPixel{ .blue = 0x00, .green = 0x00, .red = 0x00, .reserved = 0 }, // black 16 | GraphicsOutputBltPixel{ .blue = 0xaa, .green = 0x00, .red = 0x00, .reserved = 0 }, // blue 17 | GraphicsOutputBltPixel{ .blue = 0x00, .green = 0xaa, .red = 0x00, .reserved = 0 }, // green 18 | GraphicsOutputBltPixel{ .blue = 0xaa, .green = 0xaa, .red = 0x00, .reserved = 0 }, // cyan 19 | GraphicsOutputBltPixel{ .blue = 0x00, .green = 0x00, .red = 0xaa, .reserved = 0 }, // red 20 | GraphicsOutputBltPixel{ .blue = 0xaa, .green = 0x00, .red = 0xaa, .reserved = 0 }, // magenta 21 | GraphicsOutputBltPixel{ .blue = 0x00, .green = 0x55, .red = 0xaa, .reserved = 0 }, // brown 22 | GraphicsOutputBltPixel{ .blue = 0xaa, .green = 0xaa, .red = 0xaa, .reserved = 0 }, // gray 23 | GraphicsOutputBltPixel{ .blue = 0x55, .green = 0x55, .red = 0x55, .reserved = 0 }, // dark gray 24 | GraphicsOutputBltPixel{ .blue = 0xff, .green = 0x55, .red = 0x55, .reserved = 0 }, // bright blue 25 | GraphicsOutputBltPixel{ .blue = 0x55, .green = 0xff, .red = 0x55, .reserved = 0 }, // bright green 26 | GraphicsOutputBltPixel{ .blue = 0xff, .green = 0xff, .red = 0x55, .reserved = 0 }, // bright cyan 27 | GraphicsOutputBltPixel{ .blue = 0x55, .green = 0x55, .red = 0xff, .reserved = 0 }, // bright red 28 | GraphicsOutputBltPixel{ .blue = 0xff, .green = 0x55, .red = 0xff, .reserved = 0 }, // bright magenta 29 | GraphicsOutputBltPixel{ .blue = 0x55, .green = 0xff, .red = 0xff, .reserved = 0 }, // yellow 30 | GraphicsOutputBltPixel{ .blue = 0xff, .green = 0xff, .red = 0xff, .reserved = 0 }, // white 31 | }; 32 | 33 | // Disable watchdog 34 | _ = boot_services.setWatchdogTimer(0, 0, 0, null); 35 | 36 | // Set pointers to protocols 37 | _ = boot_services.locateProtocol(&AbsolutePointerProtocol.guid, null, @ptrCast(*?*c_void, &pointer)); 38 | _ = boot_services.locateProtocol(&GraphicsOutputProtocol.guid, null, @ptrCast(*?*c_void, &graphics)); 39 | 40 | // Draw color picker in the uppermost 16th of screen 41 | comptime var i = 0; 42 | inline while (i < 16) : (i += 1) { 43 | var c = [1]GraphicsOutputBltPixel{colors[i]}; 44 | _ = graphics.blt(&c, GraphicsOutputBltOperation.BltVideoFill, 0, 0, i * graphics.mode.info.horizontal_resolution / 16, 0, graphics.mode.info.horizontal_resolution / 16, graphics.mode.info.vertical_resolution / 16, 0); 45 | } 46 | 47 | var index: usize = undefined; 48 | while (boot_services.waitForEvent(1, @ptrCast([*]uefi.Event, &pointer.wait_for_input), &index) == 0) { 49 | _ = pointer.getState(&pointer_state); 50 | if (graphics.mode.info.vertical_resolution * pointer_state.current_y / (pointer.mode.absolute_max_y - pointer.mode.absolute_min_y) < graphics.mode.info.vertical_resolution / 16) { 51 | // If the color picker has been touched, set selected color 52 | selected = @truncate(u4, 16 * pointer_state.current_x / (pointer.mode.absolute_max_x - pointer.mode.absolute_min_x + 1)); 53 | } else if (graphics.mode.info.horizontal_resolution * pointer_state.current_x / (pointer.mode.absolute_max_x - pointer.mode.absolute_min_x) >= 2 and graphics.mode.info.horizontal_resolution * pointer_state.current_x / (pointer.mode.absolute_max_x - pointer.mode.absolute_min_x) < graphics.mode.info.horizontal_resolution - 2 and graphics.mode.info.vertical_resolution * pointer_state.current_y / (pointer.mode.absolute_max_y - pointer.mode.absolute_min_y) < graphics.mode.info.vertical_resolution - 2) { 54 | // Else if touch was at least 2 pixels into the drawing area, draw 55 | var c = [1]GraphicsOutputBltPixel{colors[selected]}; 56 | _ = graphics.blt(&c, GraphicsOutputBltOperation.BltVideoFill, 0, 0, graphics.mode.info.horizontal_resolution * pointer_state.current_x / (pointer.mode.absolute_max_x - pointer.mode.absolute_min_x) - 2, graphics.mode.info.vertical_resolution * pointer_state.current_y / (pointer.mode.absolute_max_y - pointer.mode.absolute_min_y) - 2, 5, 5, 0); 57 | } 58 | } 59 | } 60 | --------------------------------------------------------------------------------