streamtools: Backport newer x264 driver
[jpcrr.git] / lua / spam-bios-keyboard
blob0a4dcedf81827df06c61c5df00eaf23d112d3c2e
1 win = jpcrr.window.create("Generic watch");
3 y = 0;
5 fieldpair = function(fname, label)
6         win:create_component({gridx = 0, gridy = y, gridwidth = 1, gridheight = 1, name = fname .. "_LABEL", type = "label", text = label,
7                 fill = win:HORIZONTAL(), weightx = 0, weighty = 1});
8         win:create_component({gridx = 1, gridy = y, gridwidth = 1, gridheight = 1, name = fname, type = "label", text = "N/A",
9                 fill = win:HORIZONTAL(), weightx = 1, weighty = 1, insets_left = 16});
10         y = y + 1;
11 end
13 update_field = function(fname, newval)
14         win:set_text(fname, tostring(newval));
15 end
18 fieldnames = {};
19 fieldupdates = {};
21 add_field = function(name, update_fn)
22         fieldpair(name, name);
23         table.insert(fieldnames, name);
24         fieldupdates[name] = update_fn;
25 end
27 do_update = function()
28         for k, v in ipairs(fieldnames) do
29                 update_field(v, fieldupdates[v]());
30         end
31 end
34 add_field("System time: ", function()
35         return tostring(jpcrr.clock_time());
36 end);
38 add_field("Frame number: ", function()
39         return tostring(jpcrr.frame_number());
40 end);
42 add_field("0x41A: ", function()
43         return tostring(jpcrr.read_word(0x41A) - 30);
44 end);
46 add_field("0x41C: ", function()
47         return tostring(jpcrr.read_word(0x41C) - 30);
48 end);
50 add_field("In flight: ", function()
51         return tostring(chars_in_flight);
52 end);
54 for i = 0, 15 do
55         add_field("BUF" .. i .. ": ", function()
56                 return string.format("%04X", jpcrr.read_word(0x41E + 2 * i));
57         end);
58 end
61 win:show();
63 keys_held = {};
64 async_key_mask = {};
65 stopping_flag = false;
66 bios_delay = 100000000;   --Assume 20MHz machine with paired IDE drives. (NEW 78ms)
67 first_post_bios_stop = true;
68 keyboard_input_to_feed = {};
69 keyboard_input_pointer = 1;
70 last_nextchar = -1;
71 seen_first_char = false;
72 last_lastchar = -1;
73 chars_in_flight = 0;
75 --In case something needs to be done here... VGA unlock is automatically preformed after return.
76 redraw_handler = function()
78 end
80 --Handle stop post bios delay. PC is automatically started after this.
81 handle_stop_post_bios_delay = function()
82         local nextchar = jpcrr.read_word(0x41A) - 30;
83         local lastchar = jpcrr.read_word(0x41C) - 30;
84         local olastchar = lastchar;
85         if lastchar < nextchar then
86                         lastchar = lastchar + 32;
87         end
88         local keyboard_chars = (lastchar-nextchar)/2;
89         if keyboard_chars > 13 then
90                 print("WARNING: Keyboard buffer possibly overflowing!");
91         end
92         --Character appeared out of flight?
93         if seen_first_char and last_lastchar ~= olastchar then
94                 chars_in_flight = chars_in_flight - 1;
95                 do_update();
96         end
97         last_lastchar = olastchar;
98         seen_first_char = true;
99         --Only add more input if nextchar has changed.
100         if last_nextchar == nextchar then
101                 return nil;
102         end
103         last_nextchar = nextchar;
104         while keyboard_chars + chars_in_flight < 10 do
105                 --Feed more characters
106                 if not keyboard_input_to_feed[keyboard_input_pointer] then
107                         -- No more input. Exit.
108                         jpcrr.bios_kbd_trap(false);
109                         jpcrr.exit();
110                 end
111                 if keyboard_input_to_feed[keyboard_input_pointer] == 54 and not keys_held[54] and keyboard_chars + chars_in_flight > 0 then
112                         break;
113                 end
114                 if keyboard_input_to_feed[keyboard_input_pointer] == 42 and not keys_held[42] and keyboard_chars + chars_in_flight > 0 then
115                         break;
116                 end
117                 if not is_async(keyboard_input_to_feed[keyboard_input_pointer]) then
118                         chars_in_flight = chars_in_flight + 1;
119                         do_update();
120                 end
121                 press_or_release(keyboard_input_to_feed[keyboard_input_pointer]);
122                 keyboard_input_pointer = keyboard_input_pointer + 1;
123         end
127 async_key_mask[29] = true;      -- Left CTRL.
128 async_key_mask[42] = true;      -- Left shift.
129 async_key_mask[56] = true;      -- Left alt.
130 async_key_mask[58] = true;      -- Caps lock.
131 async_key_mask[69] = true;      -- Num lock.
132 async_key_mask[70] = true;      -- Scroll lock.
133 async_key_mask[54] = true;      -- Right shift
134 async_key_mask[95] = true;      -- Unknown key (delay);
135 async_key_mask[157] = true;     -- Right ctrl.
136 async_key_mask[184] = true;     -- Right alt.
137 async_key_mask[255] = true;     -- Pause.
139 -- Would this key be asynchronous now?
140 is_async = function(keynum)
141         -- Releases are always asynchronous.
142         if keys_held[keynum] then
143                 return true;
144         end
145         -- Some keys are always asynchronous.
146         if async_key_mask[keynum] then
147                 return true;
148         end
149         -- It is synchronous.
150         return false;
153 -- press or release specified key (255 = pause).
154 press_or_release = function(keynum)
155         if keynum == 255 then
156                 jpcrr.sendevent("org.jpc.emulator.peripheral.Keyboard", "PAUSE");
157         else
158                 jpcrr.sendevent("org.jpc.emulator.peripheral.Keyboard", "KEYEDGE", tostring(keynum));
159                 keys_held[keynum] = not keys_held[keynum];
160         end
164 --This is called after redraw_handler if machine is stopping.
165 stop_handler = function()
166         if jpcrr.clock_time() < bios_delay then
167                 --Just restart it...
168         else
169                 if first_post_bios_stop then
170                         --Set trap on keyboard and clear timed trap.
171                         jpcrr.bios_kbd_trap(true);
172                         jpcrr.timed_trap(nil);
173                         first_post_bios_stop = false;
174                 end
175                 handle_stop_post_bios_delay();
176         end
177         jpcrr.pc_start();
180 file, err = io.open_read("/select input file");
181 if not file then
182         error("Can't open file: " .. err);
184 file2, err = file:text();
185 if not file2 then
186         error("Can't cast file to text: " .. err);
189 while true do
190         line, err = file2:read();
191         if not line then
192                 if not err then
193                         break;
194                 else
195                         error("Can't read line: " .. err);
196                 end
197         end
198         local num = tonumber(line);
199         if not num then
200                 error("Bad line: " .. line);
201         end
202         table.insert(keyboard_input_to_feed, num);
204 file2:close();
206 --Wait for the initial BIOS delay.
207 jpcrr.timed_trap(bios_delay);
208 jpcrr.pc_start();
210 while true do
211         event, arg = jpcrr.wait_event();
212         if event == "stop" then
213                 stopping_flag = true;
214         end
215         if event == "lock" then
216                 do_update();
217                 redraw_handler();
218                 jpcrr.release_vga();
219                 if stopping_flag then
220                         stop_handler();
221                 end
222                 stopping_flag = false;
223         end