Add space hack to font converter
[jpcrr.git] / luakernel.lua
blob166b7b8003d2e67961a83d2c63efbeeba4e63297
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_vga()
59 -- Waits for VGA to enter frame hold mode. Frame hold happens once per frame.
60 -- - jpcrr.release_vga()
61 -- Allow VGA to exit frame hold mode. Wait for frame hold first.
62 -- - jpcrr.vga_resolution()
63 -- Return VGA x and y resolutions. -1x-1 or 0x0 is returned if no valid resolution.
64 -- Should only be called during frame hold.
65 -- - jpcrr.hud.left_gap(number flags, number gap)
66 -- Set left gap for HUD. If flags has bit 0 (1) set, draw on screen, if bit
67 -- 1 (2) is set, dump to video dump.
68 -- - jpcrr.hud.right_gap(number flags, number gap)
69 -- Set right gap for HUD. If flags has bit 0 (1) set, draw on screen, if bit
70 -- 1 (2) is set, dump to video dump.
71 -- - jpcrr.hud.top_gap(number flags, number gap)
72 -- Set top gap for HUD. If flags has bit 0 (1) set, draw on screen, if bit
73 -- 1 (2) is set, dump to video dump.
74 -- - jpcrr.hud.bottom_gap(number flags, number gap)
75 -- Set bottom gap for HUD. If flags has bit 0 (1) set, draw on screen, if bit
76 -- 1 (2) is set, dump to video dump.
77 -- - jpcrr.hud.white_solid_box(number flags, number x, number y, number w, number h)
78 -- Draw with solid opaque box.
79 -- - jpcrr.hud.box(number flags, number x, number y, number w, number h, number linethick,
80 -- number lineRed, number lineGreen, number lineBlue, number lineAlpha,
81 -- number fillRed, number fillGreen, number fillBlue, number fillAlpha)
82 -- Draw box with specified size, border line thickness, line color and fill color.
83 -- - jpcrr.hud.bitmap(number flags, number x, number y, string bmap,
84 -- number fgRed, number fgGreen, number fgBlue, number fgAlpha,
85 -- number bgRed, number bgGreen, number bgBlue, number bgAlpha)
86 -- Draw bitmal with specified foreground color and background color.
87 -- - jpcrr.component_encode(table components)
88 -- Return component encoding for specified components.
89 -- - jpcrr.component_decode(string line)
90 -- Return component decoding for specified line, nil/nil if it doesn't encode
91 -- anything, nil/string if parse error occurs (the error is the second return).
92 -- - jpcrr.save_state(string name)
93 -- Savestate into specified file. Returns name used.
94 -- - jpcrr.save_movie(string name)
95 -- Save movie into specified file. Returns name used.
96 -- - jpcrr.load_state_normal(string name)
97 -- Load specified savestate. Returns name used.
98 -- - jpcrr.load_state_preserve_events(string name)
99 -- Load specified savestate, preserving events. Returns name used.
100 -- - jpcrr.load_state_movie(string name)
101 -- Load specified savestate as movie. Returns name used.
102 -- - jpcrr.assemble()
103 -- Open system settings dialog.
104 -- - jpcrr.change_authors()
105 -- Open change authors dialog.
106 -- - jpcrr.exit = function()
107 -- Exit the Lua VM.
108 -- - jpcrr.ram_dump(string name, boolean binary)
109 -- Dump PC memory to specified file. If binary is true, dump is binary, otherwise
110 -- textual hexadecimal dump.
111 -- - jpcrr.write_byte(number addr, number value)
112 -- Write byte to specified physical address.
113 -- - jpcrr.write_word(number addr, number value)
114 -- Write word to specified physical address (little endian).
115 -- - jpcrr.write_dword(number addr, number value)
116 -- Write dword to specified physical address (little endian).
117 -- - jpcrr.read_byte(number addr)
118 -- Return byte from specified physical address.
119 -- - jpcrr.read_word(number addr)
120 -- Return word from specified physical address (little endian).
121 -- - jpcrr.read_dword(number addr)
122 -- Return dword from specified physical address (little endian).
123 -- - jpcrr.timed_trap(number nsecs)
124 -- Set trap after specified number of nanoseconds. Use nil as nsecs to disable.
125 -- - jpcrr.vretrace_start_trap(boolean is_on)
126 -- Set trap on vretrace start on/off.
127 -- - jpcrr.vretrace_end_trap(boolean is_on)
128 -- Set trap on vretrace end on/off.
129 -- - jpcrr.pc_start()
130 -- Start PC execution.
131 -- - jpcrr.pc_stop()
132 -- Stop PC execution.
133 -- - jpcrr.set_pccontrol_pos(number x, number y)
134 -- Set position of PCControl window.
135 -- - jpcrr.set_luaplugin_pos(number x, number y)
136 -- Set position of LuaPlugin window.
137 -- - jpcrr.set_pcmonitor_pos(number x, number y)
138 -- Set position of PCMonitor window.
139 -- - jpcrr.set_pcstartstoptest_pos(number x, number y)
140 -- Set position of PCStartStopTest window.
141 -- - jpcrr.set_virtualkeyboard_pos(number x, number y)
142 -- Set position of VirtualKeyboard window.
144 -- I/O functions have the following conventions. If function returns any real data, the first
145 -- return value returns this data or is nil. Otherwise first return value is true or false.
146 -- If first return value is nil or false, then the second return value gives textual error
147 -- message for failed operation, or is nil if EOF occured before anything was read.
149 -- Unlink, rename and mkdir don't follow this pattern. They just return true/false to signal
150 -- success or failure.
152 -- Specifying nil as name of file results random filename being used (it even works with unlink,
153 -- mkdir, rename and read-only access, but doesn't make any sense there).
155 -- Class: BinaryFile:
156 -- Binary file for RO or RW access. Methods are as follows:
157 -- - name()
158 -- Return name of file.
159 -- - length()
160 -- Return length of file.
161 -- - set_length(number length)
162 -- Truncate file to specified length
163 -- - read(number offset, number length)
164 -- Read up to length bytes from offset.
165 -- - write(number offset, string content)
166 -- Write content to specified offset.
167 -- - close()
168 -- Close the file.
169 -- Class: BinaryInput:
170 -- Binary file for sequential input. Methods are as follows:
171 -- - name()
172 -- Return name of file.
173 -- - four_to_five()
174 -- Return BinaryInput that is four to five decoding of this stream.
175 -- - text()
176 -- Return stream as TextInput.
177 -- - inflate()
178 -- Return BinaryInput that is inflate of this stream.
179 -- - read(number bytes)
180 -- Read up to bytes bytes from file.
181 -- - read()
182 -- Read the entiere file at once.
183 -- - close()
184 -- Close the file.
185 -- Character set for binary files is Latin-1.
187 -- Class: BinaryOutput:
188 -- Binary file for sequential output. Methods are as follows:
189 -- - name()
190 -- Return name of file.
191 -- - four_to_five()
192 -- Return BinaryOutput that writes four to five encoded output to this stream.
193 -- - text()
194 -- Return stream as TextOutput.
195 -- - deflate()
196 -- Return BinaryOutput that writes deflate output to this stream.
197 -- - write(string content)
198 -- Write string to file.
199 -- - close()
200 -- Close the file.
201 -- Character set for binary files is Latin-1.
203 -- Class: TextInput:
204 -- - name()
205 -- Return name of file.
206 -- - read()
207 -- Read line from file.
208 -- - read_component()
209 -- Read next componented line into array.
210 -- - lines()
211 -- Line iterator function.
212 -- - close()
213 -- Close the file.
214 -- Character set for text files is UTF-8.
216 -- Class: TextOutput:
217 -- - name()
218 -- Return name of file.
219 -- - write(string line)
220 -- Write line line to file.
221 -- - write_component(table components)
222 -- Write componented line.
223 -- - close()
224 -- Close the file.
225 -- Character set for text files is UTF-8.
227 -- Class ArchiveIn:
228 -- - member(string name)
229 -- Open substream for member name. The methods are the same as for io.opentextin.
230 -- - member_binary(string name)
231 -- Open binary (four to five) substream for member name. The methods are the same as
232 -- for io.openbinaryin.
233 -- - close()
234 -- Close the file. Any opened substreams are invalidated.
236 -- Class ArchiveOut:
237 -- - member(string name)
238 -- Open substream for member name. The methods are the same as for io.opentextout. Note that
239 -- previous member must be closed before next can open.
240 -- - member_binary(string name)
241 -- Open binary (four to five) substream for member name. The methods are the same as
242 -- for io.openbinaryout. Note that previous substream must be closed before next can open.
243 -- - commit()
244 -- Commit the file. No substream may be open. Closes the file.
245 -- - rollback()
246 -- Rollback the file. No substream may be open. Closes the file.
248 -- - io.open(string name, string mode) -> BinaryFile
249 -- Open file named @name in specified mode. The mode can be 'r' (read only) or 'rw' (read and
250 -- write).
251 -- - io.open_read(string name) -> BinaryInput
252 -- Open file named @name as binary input stream.
253 -- - io.open_write(string name) -> BinaryOutput
254 -- Open file named @name as binary input stream.
255 -- - io.open_arch_read(string name) -> ArchiveIn
256 -- Open file named @name as input archive.
257 -- - io.open_arch_write(string name) -> ArchiveOut
258 -- Open file named @name as output archive.
259 -- - io.mkdir(string name)
260 -- Create directory name. Returns name created on success, nil on failure.
261 -- - io.unlink(string name)
262 -- Delete file/directory name. Returns name deleted on success, nil on failure.
263 -- - io.rename(string old, string new)
264 -- Rename file old -> new. Returns old, new on success, nil on failure.
273 local handle, err, chunk, indication, k, v;
275 local loadmod = loadmodule;
276 loadmodule = nil;
278 local export_module_in = function(tab, modname, prefix)
279 local fun = loadmod(modname);
280 for k, v in pairs(fun) do
281 tab[(prefix or "") .. k] = v;
285 jpcrr = {};
286 jpcrr.hud = {};
287 bit = {};
288 io = {};
290 export_module_in(jpcrr, "org.jpc.luaextensions.Base");
291 export_module_in(jpcrr, "org.jpc.luaextensions.ComponentCoding", "component_");
292 export_module_in(bit, "org.jpc.luaextensions.Bitops");
294 -- Few misc functions.
295 assert = function(val, err)
296 if (not val) and err then
297 error(err);
299 return val;
302 modulus_split = function(number, ...)
303 local dividers = {...};
304 local results = {};
305 local rem;
307 for k, v in ipairs(dividers) do
308 rem = number % v;
309 table.insert(results, (number - rem) / v);
310 number = rem;
313 table.insert(results, number);
314 return unpack(results);
317 local getmtable = getmetatable;
318 local toString = tostring;
319 local inject_binary_file;
320 local inject_binary_input;
321 local inject_binary_output;
322 local inject_text_input;
323 local inject_text_output;
324 local inject_archive_input;
325 local inject_archive_output;
327 -- Class member injectors.
328 inject_binary_file = function(obj, name)
329 local _name = name;
330 getmtable(obj).name = function(obj)
331 return _name;
333 getmtable(obj).__index = function(tab, name)
334 local x = getmtable(obj)[name];
335 if x then
336 return x;
338 error("Invalid method " .. name .. " for BinaryFile");
340 return obj;
343 inject_binary_input = function(obj, name)
344 local _name = name;
345 local old_four_to_five = getmtable(obj).four_to_five;
346 local old_inflate = getmtable(obj).inflate;
347 local old_text = getmtable(obj).text;
348 local old_read = getmtable(obj).read;
350 getmtable(obj).name = function(obj)
351 return _name;
353 getmtable(obj).four_to_five = function(obj)
354 local res, err;
355 res, err = old_four_to_five(obj);
356 if not res then
357 return res, err;
359 return inject_binary_input(res, "four-to-five<" .. _name .. ">");
361 getmtable(obj).inflate = function(obj)
362 local res, err;
363 res, err = old_inflate(obj);
364 if not res then
365 return res, err;
367 return inject_binary_input(res, "inflate<" .. _name .. ">");
369 getmtable(obj).text = function(obj)
370 local res, err;
371 res, err = old_text(obj);
372 if not res then
373 return res, err;
375 return inject_text_input(res, "text<" .. _name .. ">");
377 getmtable(obj).read = function(obj, toread)
378 if toread then
379 return old_read(obj, toread);
380 else
381 local res = "";
382 local ret, err;
383 while true do
384 ret, err = old_read(obj, 16384);
385 if not ret then
386 if not err then
387 return res;
389 return nil, err;
391 res = res .. ret;
395 getmtable(obj).__index = function(tab, name)
396 local x = getmtable(obj)[name];
397 if x then
398 return x;
400 error("Invalid method " .. name .. " for BinaryInput");
402 return obj;
405 inject_binary_output = function(obj, name)
406 local _name = name;
407 local old_four_to_five = getmtable(obj).four_to_five;
408 local old_deflate = getmtable(obj).deflate;
409 local old_text = getmtable(obj).text;
411 getmtable(obj).name = function(obj)
412 return _name;
414 getmtable(obj).four_to_five = function(obj)
415 local res, err;
416 res, err = old_four_to_five(obj);
417 if not res then
418 return res, err;
420 return inject_binary_output(res, "four-to-five<" .. _name .. ">");
422 getmtable(obj).deflate = function(obj)
423 local res, err;
424 res, err = old_deflate(obj);
425 if not res then
426 return res, err;
428 return inject_binary_output(res, "deflate<" .. _name .. ">");
430 getmtable(obj).text = function(obj)
431 local res, err;
432 res, err = old_text(obj);
433 if not res then
434 return res, err;
436 return inject_text_output(res, "text<" .. _name .. ">");
438 getmtable(obj).__index = function(tab, name)
439 local x = getmtable(obj)[name];
440 if x then
441 return x;
443 error("Invalid method " .. name .. " for BinaryOutput");
445 return obj;
448 inject_text_input = function(obj, name)
449 local _name = name;
450 getmtable(obj).lines = function(obj)
451 return function(state, prevline)
452 return state:read();
453 end, obj, nil;
455 getmtable(obj).name = function(obj)
456 return _name;
458 getmtable(obj).__index = function(tab, name)
459 local x = getmtable(obj)[name];
460 if x then
461 return x;
463 error("Invalid method " .. name .. " for TextInput");
465 return obj;
468 inject_text_output = function(obj, name)
469 local _name = name;
470 getmtable(obj).name = function(obj)
471 return _name;
473 getmtable(obj).__index = function(tab, name)
474 local x = getmtable(obj)[name];
475 if x then
476 return x;
478 error("Invalid method " .. name .. " for TextOutput");
480 return obj;
483 inject_archive_input = function(obj, name)
484 local _name = name;
485 local old_member = getmtable(obj).member;
486 getmtable(obj).member = function(obj, member)
487 local res, err;
488 res, err = old_member(obj, member);
489 if not res then
490 return res, err;
492 return inject_binary_input(res, _name .. "[" .. member .. "]");
494 getmtable(obj).name = function(obj)
495 return _name;
497 getmtable(obj).__index = function(tab, name)
498 local x = getmtable(obj)[name];
499 if x then
500 return x;
502 error("Invalid method " .. name .. " for ArchiveInput");
504 return obj;
507 inject_archive_output = function(obj, name)
508 local _name = name;
509 local old_member = getmtable(obj).member;
510 getmtable(obj).member = function(obj, member)
511 local res, err;
512 res, err = old_member(obj, member);
513 if not res then
514 return res, err;
516 return inject_binary_output(res, _name .. "[" .. member .. "]");
518 getmtable(obj).name = function(obj)
519 return _name;
521 getmtable(obj).__index = function(tab, name)
522 local x = getmtable(obj)[name];
523 if x then
524 return x;
526 error("Invalid method " .. name .. " for ArchiveOutput");
528 return obj;
532 -- Redefined print.
534 local rprint = print_console_msg;
535 print_console_msg = nil;
536 print = function(...)
537 local x = "";
538 local y = {...};
539 local i;
540 for i = 1,#y do
541 if i > 1 then
542 x = x .. "\t" .. toString(y[i]);
543 else
544 x = toString(y[i]);
547 rprint(x);
549 print_console_msg = nil;
552 -- I/O routines.
553 local stringfind = string.find;
554 local randname = loadmod("org.jpc.luaextensions.DelayedDelete").random_temp_name;
555 local path = args["luapath"] or ".";
556 local toresourcename = function(resname)
557 if not resname then
558 return randname(path .. "/", "luatemp-");
561 if not stringfind(resname, "[%d%l%u_%-]") then
562 error("Bad resource name (case 1): " .. resname);
564 if stringfind(resname, "^/") then
565 error("Bad resource name (case 2): " .. resname);
567 if stringfind(resname, "%.%.") then
568 error("Bad resource name (case 3): " .. resname);
570 if stringfind(resname, "\\") then
571 error("Bad resource name (case 4): " .. resname);
574 return resname, path .. "/" .. resname;
579 local openbinin = loadmod("org.jpc.luaextensions.BinaryInFile").open;
580 local openbinout = loadmod("org.jpc.luaextensions.BinaryOutFile").open;
581 local openarchin = loadmod("org.jpc.luaextensions.ArchiveIn").open;
582 local openarchout = loadmod("org.jpc.luaextensions.ArchiveOut").open;
583 local openbinary = loadmod("org.jpc.luaextensions.BinaryFile").open;
585 local baseFS = loadmod("org.jpc.luaextensions.BaseFSOps");
586 local mkdir = baseFS.mkdir;
587 local unlink = baseFS.unlink;
588 local rename = baseFS.rename;
590 local getmtable = getmetatable;
592 loadfile = function(_script)
593 local file, file2, err, content;
594 local x, y;
595 x, y = toresourcename(_script);
596 file, err = openbinin(y, "r");
597 if not file then
598 return nil, "Can't open " .. _script .. ": " .. err;
600 file2, err = file:text();
601 if not file2 then
602 return nil, "Can't transform " .. _script .. ": " .. err;
604 content = "";
605 line = file2:read();
606 while line do
607 content = content .. line .. "\n";
608 line = file2:read();
610 file2:close();
611 file:close();
612 return loadstring(content, _script);
615 io.open = function(name, mode)
616 local _name;
617 local res, err;
618 local y;
619 _name, y = toresourcename(name);
620 res, err = openbinary(y, mode);
621 if not res then
622 return res, err;
624 return inject_binary_file(res, _name);
627 io.open_arch_read = function(name)
628 local _name = name;
629 local res, err;
630 local y;
631 _name, y = toresourcename(name);
632 res, err = openarchin(y);
633 if not res then
634 return res, err;
636 return inject_archive_input(res, _name);
639 io.open_arch_write = function(name)
640 local _name = name;
641 local res, err;
642 local y;
643 _name, y = toresourcename(name);
644 res, err = openarchout(y);
645 if not res then
646 return res, err;
648 return inject_archive_output(res, _name);
651 io.open_read = function(name)
652 local _name = name;
653 local res, err;
654 local y;
655 _name, y = toresourcename(name);
656 res, err = openbinin(y);
657 if not res then
658 return res, err;
660 return inject_binary_input(res, _name);
663 io.open_write = function(name)
664 local _name = name;
665 local res, err;
666 local y;
667 _name, y = toresourcename(name);
668 res, err = openbinout(y);
669 if not res then
670 return res, err;
672 return inject_binary_output(res, _name);
675 io.mkdir = function(name)
676 local _name, y;
677 _name, y = toresourcename(name);
678 if mkdir(y) then
679 return _name;
680 else
681 return nil;
685 io.unlink = function(name)
686 local _name, y;
687 _name, y = toresourcename(name);
688 if unlink(y) then
689 return _name;
690 else
691 return nil;
695 io.rename = function(name1, name2)
696 local _name, y;
697 local _name2, y2;
698 _name, y = toresourcename(name1);
699 _name2, y2 = toresourcename(name2);
700 if rename(y, y2) then
701 return _name, _name2;
702 else
703 return nil;
708 -- Various stuff built on top of ECI.
709 local invoke = jpcrr.invoke;
710 local invokecall = jpcrr.call;
711 local invokesync = jpcrr.invoke_synchronous;
713 jpcrr.save_state = function(name)
714 local _name, _fname;
715 _name, _fname = toresourcename(name);
716 invokesync("state-save", {_fname});
717 return _name;
720 jpcrr.save_movie = function(name)
721 local _name, _fname;
722 _name, _fname = toresourcename(name);
723 invokesync("movie-save", {_name});
724 return _name;
727 jpcrr.load_state_normal = function(name)
728 local _name, _fname;
729 _name, _fname = toresourcename(name);
730 invokesync("state-load", {_name});
731 return _name;
734 jpcrr.load_state_preserve_events = function(name)
735 local _name, _fname;
736 _name, _fname = toresourcename(name);
737 invokesync("state-load-noevents", {_name});
738 return _name;
741 jpcrr.load_state_movie = function(name)
742 local _name, _fname;
743 _name, _fname = toresourcename(name);
744 invokesync("state-load-movie", {_name});
745 return _name;
748 jpcrr.assemble = function()
749 invokesync("pc-assemble");
752 jpcrr.change_authors = function()
753 invokesync("change-authors");
756 jpcrr.ram_dump = function(name, binary)
757 local _name, _fname;
758 _name, _fname = toresourcename(name);
759 if binary then
760 invokesync("ram-dump-binary", {_name});
761 else
762 invokesync("ram-dump-text", {_name});
764 return _name;
767 jpcrr.hud.left_gap = function(f, g)
768 invoke("hud-left-gap", {toString(f), toString(g)});
771 jpcrr.hud.right_gap = function(f, g)
772 invoke("hud-right-gap", {toString(f), toString(g)});
775 jpcrr.hud.top_gap = function(f, g)
776 invoke("hud-top-gap", {toString(f), toString(g)});
779 jpcrr.hud.bottom_gap = function(f, g)
780 invoke("hud-bottom-gap", {toString(f), toString(g)});
783 jpcrr.hud.white_solid_box = function(f, x, y, w, h)
784 invoke("hud-white-solid-box", {toString(f), toString(x), toString(y), toString(w), toString(h)});
787 jpcrr.hud.box = function(f, x, y, w, h, t, lr, lg, lb, la, fr, fg, fb, fa)
788 invoke("hud-box", {toString(f), toString(x), toString(y), toString(w), toString(h),
789 toString(t), toString(lr), toString(lg), toString(lb), toString(la), toString(fr),
790 toString(fg), tostring(fb), toString(fa)});
793 jpcrr.hud.bitmap = function(f, x, y, bmap, lr, lg, lb, la, fr, fg, fb, fa)
794 invoke("hud-bitmap", {toString(f), toString(x), toString(y), bmap, toString(lr),
795 toString(lg), toString(lb), toString(la), toString(fr), toString(fg), tostring(fb),
796 toString(fa)});
799 jpcrr.set_pccontrol_pos = function(x, y)
800 invokesync("pccontrol-setwinpos", {toString(x), toString(y)});
803 jpcrr.set_luaplugin_pos = function(x, y)
804 invokesync("luaplugin-setwinpos", {toString(x), toString(y)});
807 jpcrr.set_pcmonitor_pos = function(x, y)
808 invokesync("pcmonitor-setwinpos", {toString(x), toString(y)});
811 jpcrr.set_pcstartstoptest_pos = function(x, y)
812 invokesync("pcstartstoptest-setwinpos", {toString(x), toString(y)});
815 jpcrr.set_virtualkeyboard_pos = function(x, y)
816 invokesync("virtualkeyboard-setwinpos", {toString(x), toString(y)});
819 jpcrr.exit = function()
820 invokesync("luaplugin-terminate");
823 jpcrr.pc_start = function()
824 invoke("pc-start");
827 jpcrr.pc_stop = function()
828 invokesync("pc-stop");
831 jpcrr.vretrace_start_trap = function(is_on)
832 if is_on then
833 invokesync("trap-vretrace-start-on");
834 else
835 invokesync("trap-vretrace-start-off");
839 jpcrr.vretrace_end_trap = function(is_on)
840 if is_on then
841 invokesync("trap-vretrace-end-on");
842 else
843 invokesync("trap-vretrace-end-off");
847 jpcrr.timed_trap = function(nsecs)
848 if nsecs then
849 invokesync("trap-timed", {toString(nsecs)});
850 else
851 invokesync("trap-timed-disable");
855 jpcrr.write_byte = function(addr, value)
856 invokesync("memory-write", {toString(addr), toString(value), "1"});
859 jpcrr.write_word = function(addr, value)
860 invokesync("memory-write", {toString(addr), toString(value), "2"});
863 jpcrr.write_dword = function(addr, value)
864 invokesync("memory-write", {toString(addr), toString(value), "4"});
867 jpcrr.read_byte = function(addr)
868 local t = {toString(addr), "1"};
869 t = invokecall("memory-read", t);
870 return (t or {})[1];
873 jpcrr.read_word = function(addr)
874 local t = {toString(addr), "2"};
875 t = invokecall("memory-read", t);
876 return (t or {})[1];
879 jpcrr.read_dword = function(addr)
880 local t = {toString(addr), "4"};
881 t = invokecall("memory-read", t);
882 return (t or {})[1];
885 jpcrr.invoke = nil;
886 jpcrr.invoke_synchronous = nil;
887 jpcrr.call = null
889 -- Dofile.
890 dofile = function(_script)
891 local chunk, err, indication
892 chunk, err = loadfile(_script);
893 if not chunk then
894 error("Kernel: Can't load subscript " .. _script .. ": " .. err);
896 return chunk();
899 local args2 = args;
900 args = null;
901 args = {};
902 for k, v in pairs(args2) do
903 if (#k > 2 and string.byte(k, 1) == 120 and string.byte(k, 2) == 45) then
904 args[string.sub(k, 3)] = v;
907 jpcrr_raw = null;
910 chunk, err = loadfile(script);
911 if not chunk then
912 print("Kernel: Can't load script " .. script .. ": " .. err);
913 invoke("luaplugin-terminate");
914 while true do end
917 script = null;
918 indication, err = pcall(chunk);
919 if not indication then
920 print("Kernel: Unprotected error in script: " .. err);
921 invoke("luaplugin-terminate");
922 while true do end