reduce the size of ppage by 8 bytes using signly linked list
[lunaix-os.git] / lunaix-os / hal / char / chargame.c
1 #include <klibc/string.h>
2 #include <lunaix/device.h>
3 #include <lunaix/input.h>
4 #include <lunaix/ioctl.h>
5 #include <lunaix/keyboard.h>
6 #include <lunaix/mm/pmm.h>
7 #include <lunaix/mm/valloc.h>
8 #include <lunaix/mm/vmm.h>
9 #include <lunaix/sched.h>
10 #include <lunaix/signal.h>
11 #include <lunaix/tty/tty.h>
12 #include <lunaix/ds/fifo.h>
13 #include <lunaix/owloysius.h>
14
15 #include <hal/term.h>
16
17 struct console
18 {
19     struct lx_timer* flush_timer;
20     struct fifo_buf output;
21     struct fifo_buf input;
22     size_t wnd_start;
23     size_t lines;
24 };
25
26 typedef struct write_cmd {
27     int x;
28     int y;
29     char data[1024];
30 }write_cmd;
31
32 static struct console game_console;
33
34 static waitq_t lx_reader;
35
36 int
37 __game_listener(struct input_device* dev)
38 {
39     u32_t key = dev->current_pkt.sys_code;
40     u32_t type = dev->current_pkt.pkt_type;
41     kbd_kstate_t state = key >> 16;
42     u8_t ttychr = key & 0xff;
43     key = key & 0xffff;
44
45     if (type == PKT_RELEASE) {
46         goto done;
47     }
48
49     if ((state & KBD_KEY_FLCTRL_HELD)) {
50         char cntrl = (char)(ttychr | 0x20);
51         if ('a' > cntrl || cntrl > 'z') {
52             goto done;
53         }
54         ttychr = cntrl - 'a' + 1;
55     } else if ((key & 0xff00) <= KEYPAD) {
56         ttychr = key;
57     } else {
58         goto done;
59     }
60
61     fifo_putone(&game_console.input, ttychr);
62     pwake_all(&lx_reader);
63
64 done:
65     return INPUT_EVT_NEXT;
66 }
67
68 int
69 __game_write(struct device* dev, void* buf, size_t offset, size_t len);
70
71 int
72 __game_read(struct device* dev, void* buf, size_t offset, size_t len);
73
74 int
75 __game_write_pg(struct device* dev, void* buf, size_t offset)
76 {
77     return __game_write(dev, buf, offset, 0x1000);
78 }
79
80 int
81 __game_read_pg(struct device* dev, void* buf, size_t offset)
82 {
83     return __game_read(dev, buf, offset, 0x1000);
84 }
85
86 int
87 __game_write(struct device* dev, void* buf, size_t offset, size_t len)
88 {
89     static bool first = 1;
90     if (first)
91     {
92         for (int i = 0; i < TTY_HEIGHT; i++)
93         {
94             tty_clear_line(i);
95         }
96         first = 0;
97         tty_set_cursor(TTY_WIDTH-1, TTY_HEIGHT-1);
98     }
99
100     write_cmd *cmd = (write_cmd *)buf;
101     if (cmd->x==0x0a0d) {
102         cmd->x= 0x0a;
103         memcpy(cmd->data, cmd->data+1, TTY_WIDTH+1);
104     }else if (cmd->y==0x0a0d) {
105         cmd->y = 0xa;
106         memcpy(cmd->data, cmd->data+1, TTY_WIDTH+1);
107     }
108     
109     tty_put_str_at((char*)&(cmd->data), cmd->x, cmd->y);
110     
111     return len;
112 }
113
114 int
115 __game_read(struct device* dev, void* buf, size_t offset, size_t len)
116 {
117     struct console* console = (struct console*)dev->underlay;
118     size_t count = fifo_read(&console->input, buf, len);
119
120     if (count > 0) {
121         return count;
122     }
123
124     pwait(&lx_reader);
125
126     return count + fifo_read(&console->input, buf + count, len - count);
127 }
128
129 static int
130 chargame_init(struct device_def* devdef)
131 {
132     struct device* tty_dev = device_allocseq(NULL, &game_console);
133     tty_dev->ops.write = __game_write;
134     tty_dev->ops.write_page = __game_write_pg;
135     tty_dev->ops.read = __game_read;
136     tty_dev->ops.read_page = __game_read_pg;
137     tty_dev->ops.read_async = __game_read;
138
139     waitq_init(&lx_reader);
140     input_add_listener(__game_listener);
141
142     register_device(tty_dev, &devdef->class, "game");
143
144     term_create(tty_dev, "G");
145
146     memset(&game_console, 0, sizeof(game_console));
147     fifo_init(&game_console.output, valloc(8192), 8192, 0);
148     fifo_init(&game_console.input, valloc(4096), 4096, 0);
149
150     game_console.flush_timer = NULL;
151
152     return 0;
153 }
154
155 static struct device_def chargame_def = {
156     .name = "Character Game Console",
157     .class = DEVCLASS(DEVIF_NON, DEVFN_TTY, DEV_BUILTIN),
158     .init = chargame_init,
159 };
160 // FIXME
161 EXPORT_DEVICE(chargame, &chargame_def, load_onboot);