Fix deadlock in PC attach wait vs. Lua VM termination
[jpcrr.git] / luakernel.lua
bloba23845343825f74edac6703ce191dbf28b22e767
1 --
2 -- Copyright 2009 Ilari Liusvaara
3 --
4 -- Licenced under GNU GPL v2.
5 --
7 -- Exported tables:
8 -- - args
9 -- Contains user-level arguments.
11 -- Exported functions:
12 -- - All lua standard functions in tables main, "coroutine", "string" and "table".
13 -- - modulus_split(number num, number...)
14 -- Returns quotents and quotent remainders of number divided by given dividers.
15 -- The number of results returned is equal to number of numbers passed. The
16 -- dividers must be in decreasing order and all dividers must be nonzero and
17 -- should be >1.
18 -- - assert(object ret, object err)
19 -- If ret is considered true, return ret. Otherwise raise err as error. Exception
20 -- if err is nil too, then ret is returned anyway.
21 -- - bit.none(number...)
22 -- Returns 48-bit number that has those bits set that are set in none of its
23 -- arguments.
24 -- - bit.any(number...)
25 -- Returns 48-bit number that has those bits set that are set in any of its
26 -- arguments.
27 -- - bit.parity(number...)
28 -- Returns 48-bit number that has those bits set that are set in even number
29 -- of its arguments.
30 -- - bit.any(number...)
31 -- Returns 48-bit number that has those bits set that are set in all of its
32 -- arguments.
33 -- - bit.lshift(number num, number shift)
34 -- Returns 48 rightmost bits of num shifted by shift places left. Going outside
35 -- shift range 0-47 produces unpredicatable results.
36 -- - bit.rshift(number num, number shift)
37 -- Returns 48 rightmost bits of num shifted by shift places right. Going outside
38 -- shift range 0-47 produces unpredicatable results.
39 -- - bit.arshift(number num, number shift)
40 -- Returns 48 rightmost bits of num shifted by shift places right and bit 47
41 -- value copied to all incoming bits. Going outside shift range 0-47 produces
42 -- unpredicatable results.
43 -- - bit.add(number...)
44 -- Returns sum of all passed numbers modulo 2^48.
45 -- - bit.addneg(number...)
46 -- Returns 0 minus sum of all passed numbers modulo 2^48.
47 -- - bit.addalt(number...)
48 -- Returns sum of odd arguments (first is odd) minus sum of even arguments modulo
49 -- 2^48.
50 -- - bit.tohex(number num)
51 -- Returns hexadecimal string representation of number.
52 -- - jpcrr.pc_running()
53 -- Returns true if PC is running.
54 -- - jpcrr.clock_time()
55 -- Returns current time or nil if no PC.
56 -- - jpcrr.pc_connected()
57 -- Returns true if PC is connected.
58 -- - jpcrr.wait_pc_attach()
59 -- Wait for PC to attach.
60 -- - jpcrr.next_frame()
61 -- Wait for next frame output hold.
62 -- - jpcrr.in_frame_hold()
63 -- Returns true if in frame hold, false otherwise.
64 -- - jpcrr.keypressed(number key)
65 -- Return true if key is pressed, else false.
66 -- - jpcrr.wait_vga()
67 -- Waits for VGA to enter frame hold mode. Frame hold happens once per frame.
68 -- - jpcrr.release_vga()
69 -- Allow VGA to exit frame hold mode. Wait for frame hold first.
70 -- - jpcrr.vga_resolution()
71 -- Return VGA x and y resolutions. -1x-1 or 0x0 is returned if no valid resolution.
72 -- Should only be called during frame hold.
73 -- - jpcrr.hud.left_gap(number flags, number gap)
74 -- Set left gap for HUD. If flags has bit 0 (1) set, draw on screen, if bit
75 -- 1 (2) is set, dump to video dump.
76 -- - jpcrr.hud.right_gap(number flags, number gap)
77 -- Set right gap for HUD. If flags has bit 0 (1) set, draw on screen, if bit
78 -- 1 (2) is set, dump to video dump.
79 -- - jpcrr.hud.top_gap(number flags, number gap)
80 -- Set top gap for HUD. If flags has bit 0 (1) set, draw on screen, if bit
81 -- 1 (2) is set, dump to video dump.
82 -- - jpcrr.hud.bottom_gap(number flags, number gap)
83 -- Set bottom gap for HUD. If flags has bit 0 (1) set, draw on screen, if bit
84 -- 1 (2) is set, dump to video dump.
85 -- - jpcrr.hud.white_solid_box(number flags, number x, number y, number w, number h)
86 -- Draw with solid opaque box.
87 -- - jpcrr.hud.box(number flags, number x, number y, number w, number h, number linethick,
88 -- number lineRed, number lineGreen, number lineBlue, number lineAlpha,
89 -- number fillRed, number fillGreen, number fillBlue, number fillAlpha)
90 -- Draw box with specified size, border line thickness, line color and fill color.
91 -- - jpcrr.hud.bitmap(number flags, number x, number y, string bmap,
92 -- number fgRed, number fgGreen, number fgBlue, number fgAlpha,
93 -- number bgRed, number bgGreen, number bgBlue, number bgAlpha)
94 -- Draw bitmal with specified foreground color and background color.
95 -- - jpcrr.component_encode(table components)
96 -- Return component encoding for specified components.
97 -- - jpcrr.component_decode(string line)
98 -- Return component decoding for specified line, nil/nil if it doesn't encode
99 -- anything, nil/string if parse error occurs (the error is the second return).
100 -- - jpcrr.save_state(string name)
101 -- Savestate into specified file. Returns name used.
102 -- - jpcrr.save_movie(string name)
103 -- Save movie into specified file. Returns name used.
104 -- - jpcrr.load_state_normal(string name)
105 -- Load specified savestate. Returns name used.
106 -- - jpcrr.load_state_preserve_events(string name)
107 -- Load specified savestate, preserving events. Returns name used.
108 -- - jpcrr.load_state_movie(string name)
109 -- Load specified savestate as movie. Returns name used.
110 -- - jpcrr.assemble()
111 -- Open system settings dialog.
112 -- - jpcrr.change_authors()
113 -- Open change authors dialog.
114 -- - jpcrr.exit = function()
115 -- Exit the Lua VM.
116 -- - jpcrr.ram_dump(string name, boolean binary)
117 -- Dump PC memory to specified file. If binary is true, dump is binary, otherwise
118 -- textual hexadecimal dump.
119 -- - jpcrr.write_byte(number addr, number value)
120 -- Write byte to specified physical address.
121 -- - jpcrr.write_word(number addr, number value)
122 -- Write word to specified physical address (little endian).
123 -- - jpcrr.write_dword(number addr, number value)
124 -- Write dword to specified physical address (little endian).
125 -- - jpcrr.read_byte(number addr)
126 -- Return byte from specified physical address.
127 -- - jpcrr.read_word(number addr)
128 -- Return word from specified physical address (little endian).
129 -- - jpcrr.read_dword(number addr)
130 -- Return dword from specified physical address (little endian).
131 -- - jpcrr.timed_trap(number nsecs)
132 -- Set trap after specified number of nanoseconds. Use nil as nsecs to disable.
133 -- - jpcrr.vretrace_start_trap(boolean is_on)
134 -- Set trap on vretrace start on/off.
135 -- - jpcrr.vretrace_end_trap(boolean is_on)
136 -- Set trap on vretrace end on/off.
137 -- - jpcrr.pc_start()
138 -- Start PC execution.
139 -- - jpcrr.pc_stop()
140 -- Stop PC execution.
141 -- - jpcrr.set_pccontrol_pos(number x, number y)
142 -- Set position of PCControl window.
143 -- - jpcrr.set_luaplugin_pos(number x, number y)
144 -- Set position of LuaPlugin window.
145 -- - jpcrr.set_pcmonitor_pos(number x, number y)
146 -- Set position of PCMonitor window.
147 -- - jpcrr.set_pcstartstoptest_pos(number x, number y)
148 -- Set position of PCStartStopTest window.
149 -- - jpcrr.set_virtualkeyboard_pos(number x, number y)
150 -- Set position of VirtualKeyboard window.
152 -- I/O functions have the following conventions. If function returns any real data, the first
153 -- return value returns this data or is nil. Otherwise first return value is true or false.
154 -- If first return value is nil or false, then the second return value gives textual error
155 -- message for failed operation, or is nil if EOF occured before anything was read.
157 -- Unlink, rename and mkdir don't follow this pattern. They just return true/false to signal
158 -- success or failure.
160 -- Specifying nil as name of file results random filename being used (it even works with unlink,
161 -- mkdir, rename and read-only access, but doesn't make any sense there).
163 -- Class: BinaryFile:
164 -- Binary file for RO or RW access. Methods are as follows:
165 -- - name()
166 -- Return name of file.
167 -- - length()
168 -- Return length of file.
169 -- - set_length(number length)
170 -- Truncate file to specified length
171 -- - read(number offset, number length)
172 -- Read up to length bytes from offset.
173 -- - write(number offset, string content)
174 -- Write content to specified offset.
175 -- - close()
176 -- Close the file.
177 -- Class: BinaryInput:
178 -- Binary file for sequential input. Methods are as follows:
179 -- - name()
180 -- Return name of file.
181 -- - four_to_five()
182 -- Return BinaryInput that is four to five decoding of this stream.
183 -- - text()
184 -- Return stream as TextInput.
185 -- - inflate()
186 -- Return BinaryInput that is inflate of this stream.
187 -- - read(number bytes)
188 -- Read up to bytes bytes from file.
189 -- - read()
190 -- Read the entiere file at once.
191 -- - close()
192 -- Close the file.
193 -- Character set for binary files is Latin-1.
195 -- Class: BinaryOutput:
196 -- Binary file for sequential output. Methods are as follows:
197 -- - name()
198 -- Return name of file.
199 -- - four_to_five()
200 -- Return BinaryOutput that writes four to five encoded output to this stream.
201 -- - text()
202 -- Return stream as TextOutput.
203 -- - deflate()
204 -- Return BinaryOutput that writes deflate output to this stream.
205 -- - write(string content)
206 -- Write string to file.
207 -- - close()
208 -- Close the file.
209 -- Character set for binary files is Latin-1.
211 -- Class: TextInput:
212 -- - name()
213 -- Return name of file.
214 -- - read()
215 -- Read line from file.
216 -- - read_component()
217 -- Read next componented line into array.
218 -- - lines()
219 -- Line iterator function.
220 -- - close()
221 -- Close the file.
222 -- Character set for text files is UTF-8.
224 -- Class: TextOutput:
225 -- - name()
226 -- Return name of file.
227 -- - write(string line)
228 -- Write line line to file.
229 -- - write_component(table components)
230 -- Write componented line.
231 -- - close()
232 -- Close the file.
233 -- Character set for text files is UTF-8.
235 -- Class ArchiveIn:
236 -- - member(string name)
237 -- Open substream for member name. The methods are the same as for io.opentextin.
238 -- - member_binary(string name)
239 -- Open binary (four to five) substream for member name. The methods are the same as
240 -- for io.openbinaryin.
241 -- - close()
242 -- Close the file. Any opened substreams are invalidated.
244 -- Class ArchiveOut:
245 -- - member(string name)
246 -- Open substream for member name. The methods are the same as for io.opentextout. Note that
247 -- previous member must be closed before next can open.
248 -- - member_binary(string name)
249 -- Open binary (four to five) substream for member name. The methods are the same as
250 -- for io.openbinaryout. Note that previous substream must be closed before next can open.
251 -- - commit()
252 -- Commit the file. No substream may be open. Closes the file.
253 -- - rollback()
254 -- Rollback the file. No substream may be open. Closes the file.
256 -- - io.open(string name, string mode) -> BinaryFile
257 -- Open file named @name in specified mode. The mode can be 'r' (read only) or 'rw' (read and
258 -- write).
259 -- - io.open_read(string name) -> BinaryInput
260 -- Open file named @name as binary input stream.
261 -- - io.open_write(string name) -> BinaryOutput
262 -- Open file named @name as binary input stream.
263 -- - io.open_arch_read(string name) -> ArchiveIn
264 -- Open file named @name as input archive.
265 -- - io.open_arch_write(string name) -> ArchiveOut
266 -- Open file named @name as output archive.
267 -- - io.mkdir(string name)
268 -- Create directory name. Returns name created on success, nil on failure.
269 -- - io.unlink(string name)
270 -- Delete file/directory name. Returns name deleted on success, nil on failure.
271 -- - io.rename(string old, string new)
272 -- Rename file old -> new. Returns old, new on success, nil on failure.
281 local handle, err, chunk, indication, k, v;
283 local loadmod = loadmodule;
284 loadmodule = nil;
286 local export_module_in = function(tab, modname, prefix)
287 local fun = loadmod(modname);
288 for k, v in pairs(fun) do
289 tab[(prefix or "") .. k] = v;
293 jpcrr = {};
294 jpcrr.hud = {};
295 bit = {};
296 io = {};
298 export_module_in(jpcrr, "org.jpc.luaextensions.Base");
299 export_module_in(jpcrr, "org.jpc.luaextensions.ComponentCoding", "component_");
300 export_module_in(bit, "org.jpc.luaextensions.Bitops");
302 -- Few misc functions.
303 assert = function(val, err)
304 if (not val) and err then
305 error(err);
307 return val;
310 modulus_split = function(number, ...)
311 local dividers = {...};
312 local results = {};
313 local rem;
315 for k, v in ipairs(dividers) do
316 rem = number % v;
317 table.insert(results, (number - rem) / v);
318 number = rem;
321 table.insert(results, number);
322 return unpack(results);
325 local getmtable = getmetatable;
326 local toString = tostring;
327 local inject_binary_file;
328 local inject_binary_input;
329 local inject_binary_output;
330 local inject_text_input;
331 local inject_text_output;
332 local inject_archive_input;
333 local inject_archive_output;
335 -- Class member injectors.
336 inject_binary_file = function(obj, name)
337 local _name = name;
338 getmtable(obj).name = function(obj)
339 return _name;
341 getmtable(obj).__index = function(tab, name)
342 local x = getmtable(obj)[name];
343 if x then
344 return x;
346 error("Invalid method " .. name .. " for BinaryFile");
348 return obj;
351 inject_binary_input = function(obj, name)
352 local _name = name;
353 local old_four_to_five = getmtable(obj).four_to_five;
354 local old_inflate = getmtable(obj).inflate;
355 local old_text = getmtable(obj).text;
356 local old_read = getmtable(obj).read;
358 getmtable(obj).name = function(obj)
359 return _name;
361 getmtable(obj).four_to_five = function(obj)
362 local res, err;
363 res, err = old_four_to_five(obj);
364 if not res then
365 return res, err;
367 return inject_binary_input(res, "four-to-five<" .. _name .. ">");
369 getmtable(obj).inflate = function(obj)
370 local res, err;
371 res, err = old_inflate(obj);
372 if not res then
373 return res, err;
375 return inject_binary_input(res, "inflate<" .. _name .. ">");
377 getmtable(obj).text = function(obj)
378 local res, err;
379 res, err = old_text(obj);
380 if not res then
381 return res, err;
383 return inject_text_input(res, "text<" .. _name .. ">");
385 getmtable(obj).read = function(obj, toread)
386 if toread then
387 return old_read(obj, toread);
388 else
389 local res = "";
390 local ret, err;
391 while true do
392 ret, err = old_read(obj, 16384);
393 if not ret then
394 if not err then
395 return res;
397 return nil, err;
399 res = res .. ret;
403 getmtable(obj).__index = function(tab, name)
404 local x = getmtable(obj)[name];
405 if x then
406 return x;
408 error("Invalid method " .. name .. " for BinaryInput");
410 return obj;
413 inject_binary_output = function(obj, name)
414 local _name = name;
415 local old_four_to_five = getmtable(obj).four_to_five;
416 local old_deflate = getmtable(obj).deflate;
417 local old_text = getmtable(obj).text;
419 getmtable(obj).name = function(obj)
420 return _name;
422 getmtable(obj).four_to_five = function(obj)
423 local res, err;
424 res, err = old_four_to_five(obj);
425 if not res then
426 return res, err;
428 return inject_binary_output(res, "four-to-five<" .. _name .. ">");
430 getmtable(obj).deflate = function(obj)
431 local res, err;
432 res, err = old_deflate(obj);
433 if not res then
434 return res, err;
436 return inject_binary_output(res, "deflate<" .. _name .. ">");
438 getmtable(obj).text = function(obj)
439 local res, err;
440 res, err = old_text(obj);
441 if not res then
442 return res, err;
444 return inject_text_output(res, "text<" .. _name .. ">");
446 getmtable(obj).__index = function(tab, name)
447 local x = getmtable(obj)[name];
448 if x then
449 return x;
451 error("Invalid method " .. name .. " for BinaryOutput");
453 return obj;
456 inject_text_input = function(obj, name)
457 local _name = name;
458 getmtable(obj).lines = function(obj)
459 return function(state, prevline)
460 return state:read();
461 end, obj, nil;
463 getmtable(obj).name = function(obj)
464 return _name;
466 getmtable(obj).__index = function(tab, name)
467 local x = getmtable(obj)[name];
468 if x then
469 return x;
471 error("Invalid method " .. name .. " for TextInput");
473 return obj;
476 inject_text_output = function(obj, name)
477 local _name = name;
478 getmtable(obj).name = function(obj)
479 return _name;
481 getmtable(obj).__index = function(tab, name)
482 local x = getmtable(obj)[name];
483 if x then
484 return x;
486 error("Invalid method " .. name .. " for TextOutput");
488 return obj;
491 inject_archive_input = function(obj, name)
492 local _name = name;
493 local old_member = getmtable(obj).member;
494 getmtable(obj).member = function(obj, member)
495 local res, err;
496 res, err = old_member(obj, member);
497 if not res then
498 return res, err;
500 return inject_binary_input(res, _name .. "[" .. member .. "]");
502 getmtable(obj).name = function(obj)
503 return _name;
505 getmtable(obj).__index = function(tab, name)
506 local x = getmtable(obj)[name];
507 if x then
508 return x;
510 error("Invalid method " .. name .. " for ArchiveInput");
512 return obj;
515 inject_archive_output = function(obj, name)
516 local _name = name;
517 local old_member = getmtable(obj).member;
518 getmtable(obj).member = function(obj, member)
519 local res, err;
520 res, err = old_member(obj, member);
521 if not res then
522 return res, err;
524 return inject_binary_output(res, _name .. "[" .. member .. "]");
526 getmtable(obj).name = function(obj)
527 return _name;
529 getmtable(obj).__index = function(tab, name)
530 local x = getmtable(obj)[name];
531 if x then
532 return x;
534 error("Invalid method " .. name .. " for ArchiveOutput");
536 return obj;
540 -- Redefined print.
542 local rprint = print_console_msg;
543 print_console_msg = nil;
544 print = function(...)
545 local x = "";
546 local y = {...};
547 local i;
548 for i = 1,#y do
549 if i > 1 then
550 x = x .. "\t" .. toString(y[i]);
551 else
552 x = toString(y[i]);
555 rprint(x);
557 print_console_msg = nil;
560 -- I/O routines.
561 local stringfind = string.find;
562 local randname = loadmod("org.jpc.luaextensions.DelayedDelete").random_temp_name;
563 local path = args["luapath"] or ".";
564 local toresourcename = function(resname)
565 if not resname then
566 return randname(path .. "/", "luatemp-");
569 if not stringfind(resname, "[%d%l%u_%-]") then
570 error("Bad resource name (case 1): " .. resname);
572 if stringfind(resname, "^/") then
573 error("Bad resource name (case 2): " .. resname);
575 if stringfind(resname, "%.%.") then
576 error("Bad resource name (case 3): " .. resname);
578 if stringfind(resname, "\\") then
579 error("Bad resource name (case 4): " .. resname);
582 return resname, path .. "/" .. resname;
587 local openbinin = loadmod("org.jpc.luaextensions.BinaryInFile").open;
588 local openbinout = loadmod("org.jpc.luaextensions.BinaryOutFile").open;
589 local openarchin = loadmod("org.jpc.luaextensions.ArchiveIn").open;
590 local openarchout = loadmod("org.jpc.luaextensions.ArchiveOut").open;
591 local openbinary = loadmod("org.jpc.luaextensions.BinaryFile").open;
593 local baseFS = loadmod("org.jpc.luaextensions.BaseFSOps");
594 local mkdir = baseFS.mkdir;
595 local unlink = baseFS.unlink;
596 local rename = baseFS.rename;
598 local getmtable = getmetatable;
600 loadfile = function(_script)
601 local file, file2, err, content;
602 local x, y;
603 x, y = toresourcename(_script);
604 file, err = openbinin(y, "r");
605 if not file then
606 return nil, "Can't open " .. _script .. ": " .. err;
608 file2, err = file:text();
609 if not file2 then
610 return nil, "Can't transform " .. _script .. ": " .. err;
612 content = "";
613 line = file2:read();
614 while line do
615 content = content .. line .. "\n";
616 line = file2:read();
618 file2:close();
619 file:close();
620 return loadstring(content, _script);
623 io.open = function(name, mode)
624 local _name;
625 local res, err;
626 local y;
627 _name, y = toresourcename(name);
628 res, err = openbinary(y, mode);
629 if not res then
630 return res, err;
632 return inject_binary_file(res, _name);
635 io.open_arch_read = function(name)
636 local _name = name;
637 local res, err;
638 local y;
639 _name, y = toresourcename(name);
640 res, err = openarchin(y);
641 if not res then
642 return res, err;
644 return inject_archive_input(res, _name);
647 io.open_arch_write = function(name)
648 local _name = name;
649 local res, err;
650 local y;
651 _name, y = toresourcename(name);
652 res, err = openarchout(y);
653 if not res then
654 return res, err;
656 return inject_archive_output(res, _name);
659 io.open_read = function(name)
660 local _name = name;
661 local res, err;
662 local y;
663 _name, y = toresourcename(name);
664 res, err = openbinin(y);
665 if not res then
666 return res, err;
668 return inject_binary_input(res, _name);
671 io.open_write = function(name)
672 local _name = name;
673 local res, err;
674 local y;
675 _name, y = toresourcename(name);
676 res, err = openbinout(y);
677 if not res then
678 return res, err;
680 return inject_binary_output(res, _name);
683 io.mkdir = function(name)
684 local _name, y;
685 _name, y = toresourcename(name);
686 if mkdir(y) then
687 return _name;
688 else
689 return nil;
693 io.unlink = function(name)
694 local _name, y;
695 _name, y = toresourcename(name);
696 if unlink(y) then
697 return _name;
698 else
699 return nil;
703 io.rename = function(name1, name2)
704 local _name, y;
705 local _name2, y2;
706 _name, y = toresourcename(name1);
707 _name2, y2 = toresourcename(name2);
708 if rename(y, y2) then
709 return _name, _name2;
710 else
711 return nil;
716 jpcrr.next_frame = function(name)
717 while true do
718 if not jpcrr.pc_connected() then
719 jpcrr.wait_pc_attach();
721 if jpcrr.in_frame_hold() then
722 jpcrr.release_vga();
724 if jpcrr.wait_vga() then
725 return;
731 -- Various stuff built on top of ECI.
732 local invoke = jpcrr.invoke;
733 local invokecall = jpcrr.call;
734 local invokesync = jpcrr.invoke_synchronous;
736 jpcrr.save_state = function(name)
737 local _name, _fname;
738 _name, _fname = toresourcename(name);
739 invokesync("state-save", {_fname});
740 return _name;
743 jpcrr.save_movie = function(name)
744 local _name, _fname;
745 _name, _fname = toresourcename(name);
746 invokesync("movie-save", {_name});
747 return _name;
750 jpcrr.load_state_normal = function(name)
751 local _name, _fname;
752 _name, _fname = toresourcename(name);
753 invokesync("state-load", {_name});
754 return _name;
757 jpcrr.load_state_preserve_events = function(name)
758 local _name, _fname;
759 _name, _fname = toresourcename(name);
760 invokesync("state-load-noevents", {_name});
761 return _name;
764 jpcrr.load_state_movie = function(name)
765 local _name, _fname;
766 _name, _fname = toresourcename(name);
767 invokesync("state-load-movie", {_name});
768 return _name;
771 jpcrr.assemble = function()
772 invokesync("pc-assemble");
775 jpcrr.change_authors = function()
776 invokesync("change-authors");
779 jpcrr.ram_dump = function(name, binary)
780 local _name, _fname;
781 _name, _fname = toresourcename(name);
782 if binary then
783 invokesync("ram-dump-binary", {_name});
784 else
785 invokesync("ram-dump-text", {_name});
787 return _name;
790 jpcrr.hud.left_gap = function(f, g)
791 invoke("hud-left-gap", {toString(f), toString(g)});
794 jpcrr.hud.right_gap = function(f, g)
795 invoke("hud-right-gap", {toString(f), toString(g)});
798 jpcrr.hud.top_gap = function(f, g)
799 invoke("hud-top-gap", {toString(f), toString(g)});
802 jpcrr.hud.bottom_gap = function(f, g)
803 invoke("hud-bottom-gap", {toString(f), toString(g)});
806 jpcrr.hud.white_solid_box = function(f, x, y, w, h)
807 invoke("hud-white-solid-box", {toString(f), toString(x), toString(y), toString(w), toString(h)});
810 jpcrr.hud.box = function(f, x, y, w, h, t, lr, lg, lb, la, fr, fg, fb, fa)
811 invoke("hud-box", {toString(f), toString(x), toString(y), toString(w), toString(h),
812 toString(t), toString(lr), toString(lg), toString(lb), toString(la), toString(fr),
813 toString(fg), tostring(fb), toString(fa)});
816 jpcrr.hud.bitmap = function(f, x, y, bmap, lr, lg, lb, la, fr, fg, fb, fa)
817 invoke("hud-bitmap", {toString(f), toString(x), toString(y), bmap, toString(lr),
818 toString(lg), toString(lb), toString(la), toString(fr), toString(fg), tostring(fb),
819 toString(fa)});
822 jpcrr.set_pccontrol_pos = function(x, y)
823 invokesync("pccontrol-setwinpos", {toString(x), toString(y)});
826 jpcrr.set_luaplugin_pos = function(x, y)
827 invokesync("luaplugin-setwinpos", {toString(x), toString(y)});
830 jpcrr.set_pcmonitor_pos = function(x, y)
831 invokesync("pcmonitor-setwinpos", {toString(x), toString(y)});
834 jpcrr.set_pcstartstoptest_pos = function(x, y)
835 invokesync("pcstartstoptest-setwinpos", {toString(x), toString(y)});
838 jpcrr.set_virtualkeyboard_pos = function(x, y)
839 invokesync("virtualkeyboard-setwinpos", {toString(x), toString(y)});
842 jpcrr.exit = function()
843 invokesync("luaplugin-terminate");
846 jpcrr.pc_start = function()
847 invoke("pc-start");
850 jpcrr.pc_stop = function()
851 invokesync("pc-stop");
854 jpcrr.vretrace_start_trap = function(is_on)
855 if is_on then
856 invokesync("trap-vretrace-start-on");
857 else
858 invokesync("trap-vretrace-start-off");
862 jpcrr.vretrace_end_trap = function(is_on)
863 if is_on then
864 invokesync("trap-vretrace-end-on");
865 else
866 invokesync("trap-vretrace-end-off");
870 jpcrr.timed_trap = function(nsecs)
871 if nsecs then
872 invokesync("trap-timed", {toString(nsecs)});
873 else
874 invokesync("trap-timed-disable");
878 jpcrr.write_byte = function(addr, value)
879 invokesync("memory-write", {toString(addr), toString(value), "1"});
882 jpcrr.write_word = function(addr, value)
883 invokesync("memory-write", {toString(addr), toString(value), "2"});
886 jpcrr.write_dword = function(addr, value)
887 invokesync("memory-write", {toString(addr), toString(value), "4"});
890 jpcrr.read_byte = function(addr)
891 local t = {toString(addr), "1"};
892 t = invokecall("memory-read", t);
893 return (t or {})[1];
896 jpcrr.read_word = function(addr)
897 local t = {toString(addr), "2"};
898 t = invokecall("memory-read", t);
899 return (t or {})[1];
902 jpcrr.read_dword = function(addr)
903 local t = {toString(addr), "4"};
904 t = invokecall("memory-read", t);
905 return (t or {})[1];
908 jpcrr.invoke = nil;
909 jpcrr.invoke_synchronous = nil;
910 jpcrr.call = null
912 -- Dofile.
913 dofile = function(_script)
914 local chunk, err, indication
915 chunk, err = loadfile(_script);
916 if not chunk then
917 error("Kernel: Can't load subscript " .. _script .. ": " .. err);
919 return chunk();
922 local args2 = args;
923 args = null;
924 args = {};
925 for k, v in pairs(args2) do
926 if (#k > 2 and string.byte(k, 1) == 120 and string.byte(k, 2) == 45) then
927 args[string.sub(k, 3)] = v;
930 jpcrr_raw = null;
933 chunk, err = loadfile(script);
934 if not chunk then
935 print("Kernel: Can't load script " .. script .. ": " .. err);
936 invoke("luaplugin-terminate");
937 while true do end
940 script = null;
941 indication, err = pcall(chunk);
942 if not indication then
943 print("Kernel: Unprotected error in script: " .. err);
944 invoke("luaplugin-terminate");
945 while true do end