mouse support (working in qemu, semi-working in virtualbox)
This commit is contained in:
parent
b1a912a8a6
commit
e60fa7740c
16 changed files with 365 additions and 67 deletions
|
@ -1,28 +1,120 @@
|
||||||
#include <daguerre.hpp>
|
#include <daguerre.hpp>
|
||||||
|
|
||||||
|
void overlay_encode(
|
||||||
|
daguerre::hilbert_color &dest, const daguerre::rgb24 &src) {
|
||||||
|
if (src.r != 0xff || src.g != 0x00 || src.b != 0xff)
|
||||||
|
daguerre::encode(dest, src);
|
||||||
|
}
|
||||||
|
|
||||||
|
void invert(daguerre::rgb24 &dest, const daguerre::rgb24 &src) {
|
||||||
|
dest.r = 255 - src.r;
|
||||||
|
dest.g = 255 - src.g;
|
||||||
|
dest.b = 255 - src.b;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int, char **) {
|
int main(int, char **) {
|
||||||
|
|
||||||
auto hfb = daguerre::get_hilbert_framebuffer();
|
auto framebuffer = daguerre::get_hilbert_framebuffer();
|
||||||
daguerre::image<daguerre::rgb24> bim;
|
|
||||||
|
|
||||||
std::FILE *burdon = std::fopen("/assets/burden.ppm", "r");
|
daguerre::image<daguerre::rgb24> burden;
|
||||||
daguerre::try_load_ppm(burdon, bim);
|
std::FILE *burden_file = std::fopen("/assets/burden.ppm", "r");
|
||||||
std::fclose(burdon);
|
daguerre::try_load_ppm(burden_file, burden);
|
||||||
|
std::fclose(burden_file);
|
||||||
|
|
||||||
unsigned width = bim.width < hfb.width ? bim.width : hfb.width;
|
daguerre::image<daguerre::rgb24> pointer;
|
||||||
unsigned height = bim.height < hfb.height ? bim.height : hfb.height;
|
std::FILE *pointer_file = std::fopen("/assets/pointer.ppm", "r");
|
||||||
unsigned x = (hfb.width - width) / 2;
|
daguerre::try_load_ppm(pointer_file, pointer);
|
||||||
unsigned y = (hfb.height - height) / 2;
|
std::fclose(pointer_file);
|
||||||
|
|
||||||
|
int32_t width = burden.width < framebuffer.width
|
||||||
|
? burden.width : framebuffer.width;
|
||||||
|
int32_t height = burden.height < framebuffer.height
|
||||||
|
? burden.height : framebuffer.height;
|
||||||
|
unsigned x = (framebuffer.width - width) / 2;
|
||||||
|
unsigned y = (framebuffer.height - height) / 2;
|
||||||
|
|
||||||
|
int32_t new_mouse_x = width / 2;
|
||||||
|
int32_t new_mouse_y = height / 2;
|
||||||
|
int32_t old_mouse_x = new_mouse_x;
|
||||||
|
int32_t old_mouse_y = new_mouse_y;
|
||||||
|
bool was_left_mouse_down = false;
|
||||||
|
|
||||||
|
daguerre::overlay_region<
|
||||||
|
daguerre::hilbert_color, daguerre::rgb24, daguerre::encode>(
|
||||||
|
framebuffer, x, y, burden, 0, 0, width, height);
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
daguerre::copy_region<>(hfb, bim, 0, 0, x, y, width, height);
|
|
||||||
while ((__euler_read_key_packet() & 0x0400ff) != 0x00005a)
|
__euler_mouse_buttons mouse_buttons;
|
||||||
;
|
int16_t mouse_change_x, mouse_change_y;
|
||||||
for (unsigned i = 0; i < bim.width * bim.height; ++i) {
|
uint32_t key_packet;
|
||||||
bim.buffer[i].r = 255 - bim.buffer[i].r;
|
__euler_input_packet_type packet_type = __euler_get_input_packet(
|
||||||
bim.buffer[i].g = 255 - bim.buffer[i].g;
|
mouse_buttons, mouse_change_x, mouse_change_y, key_packet);
|
||||||
bim.buffer[i].b = 255 - bim.buffer[i].b;
|
|
||||||
|
bool anything_changed = false;
|
||||||
|
bool should_invert = false;
|
||||||
|
|
||||||
|
if (packet_type == __EULER_IPT_MOUSE) {
|
||||||
|
|
||||||
|
if (mouse_change_x != 0 || mouse_change_y != 0) {
|
||||||
|
|
||||||
|
old_mouse_x = new_mouse_x;
|
||||||
|
old_mouse_y = new_mouse_y;
|
||||||
|
new_mouse_x += mouse_change_x;
|
||||||
|
new_mouse_y += mouse_change_y;
|
||||||
|
|
||||||
|
if (new_mouse_x < 0)
|
||||||
|
new_mouse_x = 0;
|
||||||
|
else if ((unsigned)new_mouse_x > width - pointer.width)
|
||||||
|
new_mouse_x = width - pointer.width;
|
||||||
|
|
||||||
|
if (new_mouse_y < 0)
|
||||||
|
new_mouse_y = 0;
|
||||||
|
else if ((unsigned)new_mouse_y > height - pointer.height)
|
||||||
|
new_mouse_y = height - pointer.height;
|
||||||
|
|
||||||
|
anything_changed = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!was_left_mouse_down && (mouse_buttons & __EULER_MB_LEFT))
|
||||||
|
should_invert = true;
|
||||||
|
|
||||||
|
was_left_mouse_down = mouse_buttons & __EULER_MB_LEFT;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (packet_type == __EULER_IPT_KEYBOARD)
|
||||||
|
if ((key_packet & 0x0400ff) == 0x00005a)
|
||||||
|
should_invert = true;
|
||||||
|
|
||||||
|
if (should_invert) {
|
||||||
|
|
||||||
|
//this works with the current implementation of overlay_region, but
|
||||||
|
//maybe it would be better to have a dedicated function for when the
|
||||||
|
//two regions are exactly the same, given the comment on overlay_region.
|
||||||
|
daguerre::overlay_region<daguerre::rgb24, daguerre::rgb24, invert>(
|
||||||
|
burden, 0, 0, burden, 0, 0, width, height);
|
||||||
|
|
||||||
|
daguerre::overlay_region<
|
||||||
|
daguerre::hilbert_color, daguerre::rgb24, daguerre::encode>(
|
||||||
|
framebuffer, x, y, burden, 0, 0, width, height);
|
||||||
|
|
||||||
|
anything_changed = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (anything_changed) {
|
||||||
|
daguerre::overlay_region<
|
||||||
|
daguerre::hilbert_color, daguerre::rgb24, daguerre::encode>(
|
||||||
|
framebuffer, old_mouse_x + x, old_mouse_y + y, burden,
|
||||||
|
old_mouse_x, old_mouse_y, pointer.width, pointer.height);
|
||||||
|
daguerre::overlay_region<
|
||||||
|
daguerre::hilbert_color, daguerre::rgb24, overlay_encode>(
|
||||||
|
framebuffer, new_mouse_x + x, new_mouse_y + y,
|
||||||
|
pointer, 0, 0, pointer.width, pointer.height);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,9 +63,19 @@ get new pages:
|
||||||
rax out: start of first page
|
rax out: start of first page
|
||||||
the allocated pages are next to each other, writable, and not executable.
|
the allocated pages are next to each other, writable, and not executable.
|
||||||
|
|
||||||
read key packet:
|
get input packet:
|
||||||
rax in: 5
|
rax in: 5
|
||||||
eax out: key packet
|
al out:
|
||||||
|
bit 7: was mouse packet
|
||||||
|
if bit 7:
|
||||||
|
bit 0: left mouse button down
|
||||||
|
bit 1: right mouse button down
|
||||||
|
bit 2: middle mouse button down
|
||||||
|
if bit 7:
|
||||||
|
di out: mouse x change (signed)
|
||||||
|
si out: mouse y change (signed)
|
||||||
|
else:
|
||||||
|
edi out: key packet
|
||||||
|
|
||||||
create private socket:
|
create private socket:
|
||||||
rax in: 6
|
rax in: 6
|
|
@ -58,4 +58,17 @@ extern "C" uint32_t *__euler_get_framebuffer(
|
||||||
|
|
||||||
extern "C" uint32_t __euler_encode_color(uint8_t r, uint8_t g, uint8_t b);
|
extern "C" uint32_t __euler_encode_color(uint8_t r, uint8_t g, uint8_t b);
|
||||||
|
|
||||||
extern "C" uint32_t __euler_read_key_packet();
|
enum __euler_mouse_buttons : uint8_t {
|
||||||
|
__EULER_MB_LEFT = 1,
|
||||||
|
__EULER_MB_RIGHT = 2,
|
||||||
|
__EULER_MB_MIDDLE = 4
|
||||||
|
};
|
||||||
|
|
||||||
|
enum __euler_input_packet_type : uint8_t {
|
||||||
|
__EULER_IPT_MOUSE = 1,
|
||||||
|
__EULER_IPT_KEYBOARD = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
extern "C" __euler_input_packet_type __euler_get_input_packet(
|
||||||
|
__euler_mouse_buttons &buttons_out, int16_t &x_change_out,
|
||||||
|
int16_t &y_change_out, uint32_t &keyboard_packet_out);
|
||||||
|
|
|
@ -11,7 +11,7 @@ global __euler_end_this_thread
|
||||||
global __euler_read_from_stream
|
global __euler_read_from_stream
|
||||||
global __euler_get_framebuffer
|
global __euler_get_framebuffer
|
||||||
global __euler_encode_color
|
global __euler_encode_color
|
||||||
global __euler_read_key_packet
|
global __euler_get_input_packet
|
||||||
|
|
||||||
section .text
|
section .text
|
||||||
|
|
||||||
|
@ -96,7 +96,31 @@ __euler_encode_color:
|
||||||
syscall
|
syscall
|
||||||
ret
|
ret
|
||||||
|
|
||||||
__euler_read_key_packet:
|
__euler_get_input_packet:
|
||||||
|
push rdi
|
||||||
|
push rsi
|
||||||
|
push rdx
|
||||||
|
push rcx
|
||||||
mov rax, 5
|
mov rax, 5
|
||||||
syscall
|
syscall
|
||||||
|
|
||||||
|
test al, 0x80
|
||||||
|
jnz .mouse_packet
|
||||||
|
|
||||||
|
pop rcx
|
||||||
|
mov dword [rcx], edi
|
||||||
|
add rsp, 24
|
||||||
|
mov al, 2
|
||||||
|
ret
|
||||||
|
|
||||||
|
.mouse_packet:
|
||||||
|
add rsp, 8
|
||||||
|
pop rdx
|
||||||
|
mov word [rdx], si
|
||||||
|
pop rdx
|
||||||
|
mov word [rdx], di
|
||||||
|
pop rdx
|
||||||
|
and al, 0x7f
|
||||||
|
mov byte [rdx], al
|
||||||
|
mov al, 1
|
||||||
ret
|
ret
|
||||||
|
|
|
@ -18,7 +18,26 @@ namespace hilbert::kernel::input {
|
||||||
BREAK = 1 << 18,
|
BREAK = 1 << 18,
|
||||||
};
|
};
|
||||||
|
|
||||||
extern utility::queue<uint32_t> *key_queue;
|
enum buttons_t : uint8_t {
|
||||||
|
LEFT_BUTTON = 1,
|
||||||
|
RIGHT_BUTTON = 2,
|
||||||
|
MIDDLE_BUTTON = 4
|
||||||
|
};
|
||||||
|
|
||||||
|
struct input_packet {
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
int16_t x_change;
|
||||||
|
int16_t y_change;
|
||||||
|
buttons_t buttons;
|
||||||
|
} mouse;
|
||||||
|
uint32_t keyboard;
|
||||||
|
};
|
||||||
|
bool is_mouse;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern utility::queue<input_packet> *input_queue;
|
||||||
|
|
||||||
//notify a process waiting for input
|
//notify a process waiting for input
|
||||||
void got_input();
|
void got_input();
|
||||||
|
|
||||||
|
|
|
@ -342,6 +342,11 @@ namespace hilbert::kernel::utility {
|
||||||
return move(ret);
|
return move(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//assumes not empty
|
||||||
|
value_t &last_inserted() const {
|
||||||
|
return buffer[(count - 1 + next_read_index) % buffer_len];
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,10 +5,10 @@
|
||||||
|
|
||||||
namespace hilbert::kernel::input {
|
namespace hilbert::kernel::input {
|
||||||
|
|
||||||
utility::queue<uint32_t> *key_queue;
|
utility::queue<input_packet> *input_queue;
|
||||||
|
|
||||||
void init_input() {
|
void init_input() {
|
||||||
key_queue = new utility::queue<uint32_t>();
|
input_queue = new utility::queue<input_packet>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void got_input() {
|
void got_input() {
|
||||||
|
|
|
@ -227,14 +227,6 @@ section .bss
|
||||||
|
|
||||||
section .text
|
section .text
|
||||||
|
|
||||||
write_keyboard_byte:
|
|
||||||
in al, 0x64
|
|
||||||
test al, 0x02
|
|
||||||
jnz write_keyboard_byte
|
|
||||||
mov al, dil
|
|
||||||
out 0x60, al
|
|
||||||
ret
|
|
||||||
|
|
||||||
extern on_keyboard_interrupt
|
extern on_keyboard_interrupt
|
||||||
|
|
||||||
keyboard_isr:
|
keyboard_isr:
|
||||||
|
@ -249,6 +241,7 @@ keyboard_isr:
|
||||||
push rcx
|
push rcx
|
||||||
push rax
|
push rax
|
||||||
|
|
||||||
|
call wait_read_ps2
|
||||||
in al, 0x60
|
in al, 0x60
|
||||||
mov dil, al
|
mov dil, al
|
||||||
|
|
||||||
|
@ -269,6 +262,54 @@ keyboard_isr:
|
||||||
|
|
||||||
iretq
|
iretq
|
||||||
|
|
||||||
|
extern on_mouse_interrupt
|
||||||
|
|
||||||
|
mouse_isr:
|
||||||
|
|
||||||
|
push r11
|
||||||
|
push r10
|
||||||
|
push r9
|
||||||
|
push r8
|
||||||
|
push rsi
|
||||||
|
push rdi
|
||||||
|
push rdx
|
||||||
|
push rcx
|
||||||
|
push rax
|
||||||
|
|
||||||
|
call wait_read_ps2
|
||||||
|
in al, 0x60
|
||||||
|
mov dil, al
|
||||||
|
|
||||||
|
call on_mouse_interrupt
|
||||||
|
|
||||||
|
mov al, 0x20
|
||||||
|
out 0x20, al
|
||||||
|
out 0xa0, al
|
||||||
|
|
||||||
|
pop rax
|
||||||
|
pop rcx
|
||||||
|
pop rdx
|
||||||
|
pop rdi
|
||||||
|
pop rsi
|
||||||
|
pop r8
|
||||||
|
pop r9
|
||||||
|
pop r10
|
||||||
|
pop r11
|
||||||
|
|
||||||
|
iretq
|
||||||
|
|
||||||
|
wait_send_ps2:
|
||||||
|
in al, 0x64
|
||||||
|
test al, 0x02
|
||||||
|
jnz wait_send_ps2
|
||||||
|
ret
|
||||||
|
|
||||||
|
wait_read_ps2:
|
||||||
|
in al, 0x64
|
||||||
|
test al, 0x01
|
||||||
|
jz wait_send_ps2
|
||||||
|
ret
|
||||||
|
|
||||||
load_gdt_and_idt:
|
load_gdt_and_idt:
|
||||||
|
|
||||||
;fill exception entries in idt
|
;fill exception entries in idt
|
||||||
|
@ -294,7 +335,7 @@ load_gdt_and_idt:
|
||||||
out 0x21, al
|
out 0x21, al
|
||||||
mov al, 0x01
|
mov al, 0x01
|
||||||
out 0x21, al
|
out 0x21, al
|
||||||
mov al, 0xfd ;mask all but irq 1
|
mov al, 0xf9 ;mask all but irq 1 and 2
|
||||||
out 0x21, al
|
out 0x21, al
|
||||||
|
|
||||||
mov al, 0x11
|
mov al, 0x11
|
||||||
|
@ -305,19 +346,54 @@ load_gdt_and_idt:
|
||||||
out 0xa1, al
|
out 0xa1, al
|
||||||
mov al, 0x01
|
mov al, 0x01
|
||||||
out 0xa1, al
|
out 0xa1, al
|
||||||
mov al, 0xff ;mask all
|
mov al, 0xef ;mask all but irq 12
|
||||||
out 0xa1, al
|
out 0xa1, al
|
||||||
|
|
||||||
|
;register keyboard and mouse interrupts
|
||||||
|
|
||||||
mov rdi, 0x21
|
mov rdi, 0x21
|
||||||
mov rsi, keyboard_isr
|
mov rsi, keyboard_isr
|
||||||
call set_isr
|
call set_isr
|
||||||
|
|
||||||
;set keyboard config
|
mov rdi, 0x2c
|
||||||
|
mov rsi, mouse_isr
|
||||||
|
call set_isr
|
||||||
|
|
||||||
|
;set ps2 config
|
||||||
|
|
||||||
|
call wait_send_ps2
|
||||||
mov al, 0x60
|
mov al, 0x60
|
||||||
out 0x64, al
|
out 0x64, al
|
||||||
mov dil, 0x01
|
|
||||||
call write_keyboard_byte
|
call wait_send_ps2
|
||||||
|
mov al, 0x03
|
||||||
|
out 0x60, al
|
||||||
|
|
||||||
|
;set mouse defaults
|
||||||
|
|
||||||
|
call wait_send_ps2
|
||||||
|
mov al, 0xd4
|
||||||
|
out 0x64, al
|
||||||
|
|
||||||
|
call wait_send_ps2
|
||||||
|
mov al, 0xf6
|
||||||
|
out 0x60, al
|
||||||
|
|
||||||
|
call wait_read_ps2
|
||||||
|
in al, 0x60
|
||||||
|
|
||||||
|
;enable mouse reporting
|
||||||
|
|
||||||
|
call wait_send_ps2
|
||||||
|
mov al, 0xd4
|
||||||
|
out 0x64, al
|
||||||
|
|
||||||
|
call wait_send_ps2
|
||||||
|
mov al, 0xf4
|
||||||
|
out 0x60, al
|
||||||
|
|
||||||
|
call wait_read_ps2
|
||||||
|
in al, 0x60
|
||||||
|
|
||||||
;make tss entry in gdt
|
;make tss entry in gdt
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include <hilbert/kernel/framebuffer.hpp>
|
||||||
#include <hilbert/kernel/input.hpp>
|
#include <hilbert/kernel/input.hpp>
|
||||||
#include <hilbert/kernel/panic.hpp>
|
#include <hilbert/kernel/panic.hpp>
|
||||||
|
|
||||||
|
@ -54,7 +55,9 @@ static uint32_t current_flags = 0;
|
||||||
|
|
||||||
static void got_key(uint32_t key) {
|
static void got_key(uint32_t key) {
|
||||||
|
|
||||||
input::key_queue->insert(current_flags | key);
|
input::input_queue->insert({
|
||||||
|
.keyboard = current_flags | key, .is_mouse = false});
|
||||||
|
|
||||||
input::got_input();
|
input::got_input();
|
||||||
|
|
||||||
if (key == (input::BREAK | 0x77))
|
if (key == (input::BREAK | 0x77))
|
||||||
|
@ -90,7 +93,7 @@ static void got_key(uint32_t key) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t key_so_far[8];
|
static uint8_t key_so_far[8];
|
||||||
uint8_t key_so_far_len = 0;
|
static uint8_t key_so_far_len = 0;
|
||||||
|
|
||||||
extern "C" void on_keyboard_interrupt(uint8_t byte) {
|
extern "C" void on_keyboard_interrupt(uint8_t byte) {
|
||||||
|
|
||||||
|
@ -150,3 +153,45 @@ extern "C" void on_keyboard_interrupt(uint8_t byte) {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint8_t mouse_packet_so_far[3];
|
||||||
|
static uint8_t mouse_packet_so_far_len = 0;
|
||||||
|
|
||||||
|
extern "C" void on_mouse_interrupt(uint8_t byte) {
|
||||||
|
|
||||||
|
if (mouse_packet_so_far_len == 0 && byte == 0xfa)
|
||||||
|
//dirty hack
|
||||||
|
return;
|
||||||
|
|
||||||
|
mouse_packet_so_far[mouse_packet_so_far_len++] = byte;
|
||||||
|
if (mouse_packet_so_far_len < 3)
|
||||||
|
return;
|
||||||
|
|
||||||
|
mouse_packet_so_far_len = 0;
|
||||||
|
|
||||||
|
int16_t x_change = mouse_packet_so_far[1];
|
||||||
|
int16_t y_change = -(int16_t)mouse_packet_so_far[2];
|
||||||
|
if (mouse_packet_so_far[0] & 0x10)
|
||||||
|
x_change -= 0x100;
|
||||||
|
if (mouse_packet_so_far[0] & 0x20)
|
||||||
|
y_change += 0x100;
|
||||||
|
|
||||||
|
input::input_packet packet = {
|
||||||
|
.mouse = {
|
||||||
|
.x_change = x_change, .y_change = y_change,
|
||||||
|
.buttons = (input::buttons_t)(mouse_packet_so_far[0] & 7) },
|
||||||
|
.is_mouse = true };
|
||||||
|
|
||||||
|
if (input::input_queue->count > 0 &&
|
||||||
|
input::input_queue->last_inserted().is_mouse &&
|
||||||
|
input::input_queue->last_inserted().mouse.buttons ==
|
||||||
|
packet.mouse.buttons) {
|
||||||
|
input::input_queue->last_inserted().mouse.x_change = packet.mouse.x_change;
|
||||||
|
input::input_queue->last_inserted().mouse.y_change = packet.mouse.y_change;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
input::input_queue->insert(packet);
|
||||||
|
|
||||||
|
input::got_input();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -157,7 +157,7 @@ namespace hilbert::kernel::syscall {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void read_key_packet_syscall(
|
void get_input_packet_syscall(
|
||||||
uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx
|
uint64_t &rax, uint64_t &rdi, uint64_t &rsi, uint64_t &rdx
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
@ -165,8 +165,17 @@ namespace hilbert::kernel::syscall {
|
||||||
auto *t = application::running_thread;
|
auto *t = application::running_thread;
|
||||||
|
|
||||||
do
|
do
|
||||||
if (input::key_queue->count > 0) {
|
if (input::input_queue->count > 0) {
|
||||||
rax = (uint64_t)input::key_queue->take();
|
input::input_packet packet = input::input_queue->take();
|
||||||
|
if (packet.is_mouse) {
|
||||||
|
rax = packet.mouse.buttons | 0x80;
|
||||||
|
rdi = (uint16_t)packet.mouse.x_change;
|
||||||
|
rsi = (uint16_t)packet.mouse.y_change;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
rax = 0;
|
||||||
|
rdi = packet.keyboard;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
while (application::save_thread_state(t->cpu));
|
while (application::save_thread_state(t->cpu));
|
||||||
|
@ -504,7 +513,7 @@ namespace hilbert::kernel::syscall {
|
||||||
&open_file_syscall,
|
&open_file_syscall,
|
||||||
&end_this_thread_syscall,
|
&end_this_thread_syscall,
|
||||||
&get_new_pages_syscall,
|
&get_new_pages_syscall,
|
||||||
&read_key_packet_syscall,
|
&get_input_packet_syscall,
|
||||||
&create_private_socket_syscall,
|
&create_private_socket_syscall,
|
||||||
&create_socket_listener_syscall,
|
&create_socket_listener_syscall,
|
||||||
&stop_socket_listener_syscall,
|
&stop_socket_listener_syscall,
|
||||||
|
@ -520,7 +529,7 @@ namespace hilbert::kernel::syscall {
|
||||||
&set_stream_length_syscall
|
&set_stream_length_syscall
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr int max_syscall_number = 18;
|
static constexpr int max_syscall_number = 19;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <cstring>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
namespace daguerre {
|
namespace daguerre {
|
||||||
|
@ -13,14 +14,6 @@ namespace daguerre {
|
||||||
uint8_t b;
|
uint8_t b;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class to_type, class from_type>
|
|
||||||
to_type convert_color(const from_type &from);
|
|
||||||
|
|
||||||
template <>
|
|
||||||
inline hilbert_color convert_color<hilbert_color, rgb24>(const rgb24 &from) {
|
|
||||||
return __euler_encode_color(from.r, from.g, from.b);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class color_t>
|
template <class color_t>
|
||||||
class image {
|
class image {
|
||||||
|
|
||||||
|
@ -88,15 +81,15 @@ namespace daguerre {
|
||||||
//from [from_x, from_x + width) x [from_y, from_y + height).
|
//from [from_x, from_x + width) x [from_y, from_y + height).
|
||||||
template <class color_t>
|
template <class color_t>
|
||||||
void copy_region(
|
void copy_region(
|
||||||
image<color_t> &to, const image<color_t> &from, unsigned from_x,
|
image<color_t> &to, unsigned to_x, unsigned to_y,
|
||||||
unsigned from_y, unsigned to_x, unsigned to_y, unsigned width,
|
const image<color_t> &from, unsigned from_x, unsigned from_y,
|
||||||
unsigned height) {
|
unsigned width, unsigned height) {
|
||||||
|
|
||||||
color_t *to_start = to.buffer + to.pitch * to_y + to_x;
|
color_t *to_start = to.buffer + to.pitch * to_y + to_x;
|
||||||
const color_t *from_start = from.buffer + from.pitch * from_y + from_x;
|
const color_t *from_start = from.buffer + from.pitch * from_y + from_x;
|
||||||
|
|
||||||
for (unsigned y = 0; y < height; ++y)
|
for (unsigned y = 0; y < height; ++y)
|
||||||
memcpy(
|
std::memcpy(
|
||||||
to_start + to.pitch * y, from_start + from.pitch * y,
|
to_start + to.pitch * y, from_start + from.pitch * y,
|
||||||
width * sizeof(color_t));
|
width * sizeof(color_t));
|
||||||
|
|
||||||
|
@ -107,12 +100,11 @@ namespace daguerre {
|
||||||
//from [from_x, from_x + width) x [from_y, from_y + height).
|
//from [from_x, from_x + width) x [from_y, from_y + height).
|
||||||
template <
|
template <
|
||||||
class to_color_t, class from_color_t,
|
class to_color_t, class from_color_t,
|
||||||
to_color_t converter(const from_color_t &) =
|
void overlay(to_color_t &dest, const from_color_t &src)>
|
||||||
convert_color<to_color_t, from_color_t>>
|
void overlay_region(
|
||||||
void copy_region(
|
image<to_color_t> &to, unsigned to_x, unsigned to_y,
|
||||||
image<to_color_t> &to, const image<from_color_t> &from, unsigned from_x,
|
const image<from_color_t> &from, unsigned from_x, unsigned from_y,
|
||||||
unsigned from_y, unsigned to_x, unsigned to_y, unsigned width,
|
unsigned width, unsigned height) {
|
||||||
unsigned height) {
|
|
||||||
|
|
||||||
to_color_t *to_start = to.buffer + to.pitch * to_y + to_x;
|
to_color_t *to_start = to.buffer + to.pitch * to_y + to_x;
|
||||||
const from_color_t *from_start =
|
const from_color_t *from_start =
|
||||||
|
@ -120,10 +112,14 @@ namespace daguerre {
|
||||||
|
|
||||||
for (unsigned y = 0; y < height; ++y)
|
for (unsigned y = 0; y < height; ++y)
|
||||||
for (unsigned x = 0; x < width; ++x)
|
for (unsigned x = 0; x < width; ++x)
|
||||||
to_start[to.pitch * y + x] = converter(from_start[from.pitch * y + x]);
|
overlay(to_start[to.pitch * y + x], from_start[from.pitch * y + x]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void encode(hilbert_color &dest, const rgb24 &src) {
|
||||||
|
dest = __euler_encode_color(src.r, src.g, src.b);
|
||||||
|
}
|
||||||
|
|
||||||
image<hilbert_color> get_hilbert_framebuffer();
|
image<hilbert_color> get_hilbert_framebuffer();
|
||||||
|
|
||||||
bool try_load_ppm(std::FILE *input, image<rgb24> &into);
|
bool try_load_ppm(std::FILE *input, image<rgb24> &into);
|
||||||
|
|
|
@ -8,15 +8,22 @@ namespace daguerre {
|
||||||
return image<hilbert_color>(ptr, width, height, pitch, false);
|
return image<hilbert_color>(ptr, width, height, pitch, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO: make this more robust
|
||||||
unsigned read_text_int(std::FILE *input) {
|
unsigned read_text_int(std::FILE *input) {
|
||||||
unsigned n = 0;
|
unsigned n = 0;
|
||||||
char ch;
|
char ch;
|
||||||
while (true) {
|
std::fread(&ch, 1, 1, input);
|
||||||
|
if (ch == '#') {
|
||||||
|
do
|
||||||
|
std::fread(&ch, 1, 1, input);
|
||||||
|
while (ch != '\n');
|
||||||
std::fread(&ch, 1, 1, input);
|
std::fread(&ch, 1, 1, input);
|
||||||
if (ch < '0' || ch > '9')
|
|
||||||
return n;
|
|
||||||
n = n * 10 + ch - '0';
|
|
||||||
}
|
}
|
||||||
|
do {
|
||||||
|
n = n * 10 + ch - '0';
|
||||||
|
std::fread(&ch, 1, 1, input);
|
||||||
|
} while (ch >= '0' && ch <= '9');
|
||||||
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool try_load_ppm(std::FILE *input, image<rgb24> &into) {
|
bool try_load_ppm(std::FILE *input, image<rgb24> &into) {
|
||||||
|
|
BIN
skeleton/assets/pointer.ppm
Normal file
BIN
skeleton/assets/pointer.ppm
Normal file
Binary file not shown.
|
@ -2,3 +2,5 @@ the photo in burden.ppm is "selective focus photography snowflakes" by aaron
|
||||||
burden. it can be found online at
|
burden. it can be found online at
|
||||||
https://unsplash.com/photos/selective-focus-photography-snowflakes-9yhy1FXlKwI.
|
https://unsplash.com/photos/selective-focus-photography-snowflakes-9yhy1FXlKwI.
|
||||||
its license can be found online at https://unsplash.com/license.
|
its license can be found online at https://unsplash.com/license.
|
||||||
|
|
||||||
|
the icon in pointer.ppm is by me :)
|
||||||
|
|
Reference in a new issue