Update manual
[jpcrr.git] / luakernel.lua
blobd4ff710d1c810221c32d159d2f3197a5fefa6347
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.wait_message()
53 -- Waits for message (string) to come from message queue. Reutrns nil if interrupted.
54 -- - jpcrr.poll_message()
55 -- Checks if there is message from message queue. Reutrns message if there is one,
56 -- nil if none.
57 -- - jpcrr.wait_pc_stop()
58 -- Waits for PC execution to stop (but does not attempt to actually stop it).
59 -- If script is in frame hold, the frame hold is released.
60 -- Returns true if execution got stopped, false if interrupted.
61 -- - jpcrr.pc_running()
62 -- Returns true if PC is running.
63 -- - jpcrr.clock_time()
64 -- Returns current time or nil if no PC.
65 -- - jpcrr.pc_connected()
66 -- Returns true if PC is connected.
67 -- - jpcrr.wait_pc_attach()
68 -- Wait for PC to attach.
69 -- - jpcrr.next_frame()
70 -- Wait for next frame output hold.
71 -- - jpcrr.in_frame_hold()
72 -- Returns true if in frame hold, false otherwise.
73 -- - jpcrr.keypressed(number key)
74 -- Return true if key is pressed, else false.
75 -- - jpcrr.wait_vga()
76 -- Waits for VGA to enter frame hold mode. Frame hold happens once per frame.
77 -- - jpcrr.release_vga()
78 -- Allow VGA to exit frame hold mode. Wait for frame hold first.
79 -- - jpcrr.vga_resolution()
80 -- Return VGA x and y resolutions. -1x-1 or 0x0 is returned if no valid resolution.
81 -- Should only be called during frame hold.
82 -- - jpcrr.hud.left_gap(number flags, number gap)
83 -- Set left 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.right_gap(number flags, number gap)
86 -- Set right gap for HUD. If flags has bit 0 (1) set, draw on screen, if bit
87 -- 1 (2) is set, dump to video dump.
88 -- - jpcrr.hud.top_gap(number flags, number gap)
89 -- Set top gap for HUD. If flags has bit 0 (1) set, draw on screen, if bit
90 -- 1 (2) is set, dump to video dump.
91 -- - jpcrr.hud.bottom_gap(number flags, number gap)
92 -- Set bottom gap for HUD. If flags has bit 0 (1) set, draw on screen, if bit
93 -- 1 (2) is set, dump to video dump.
94 -- - jpcrr.hud.white_solid_box(number flags, number x, number y, number w, number h)
95 -- Draw with solid opaque box.
96 -- - jpcrr.hud.box(number flags, number x, number y, number w, number h, number linethick,
97 -- number lineRed, number lineGreen, number lineBlue, number lineAlpha,
98 -- number fillRed, number fillGreen, number fillBlue, number fillAlpha)
99 -- Draw box with specified size, border line thickness, line color and fill color.
100 -- - jpcrr.hud.circle(number flags, number x, number y, number r, number linethick,
101 -- number lineRed, number lineGreen, number lineBlue, number lineAlpha,
102 -- number fillRed, number fillGreen, number fillBlue, number fillAlpha)
103 -- Draw circle with specified size, border line thickness, line color and fill color.
104 -- - jpcrr.hud.bitmap(number flags, number x, number y, string bmap,
105 -- number fgRed, number fgGreen, number fgBlue, number fgAlpha,
106 -- number bgRed, number bgGreen, number bgBlue, number bgAlpha)
107 -- Draw bitmap with specified foreground color and background color.
108 -- - jpcrr.hud.bitmap_binary(number flags, number x, number y, string bmap,
109 -- number fgRed, number fgGreen, number fgBlue, number fgAlpha,
110 -- number bgRed, number bgGreen, number bgBlue, number bgAlpha)
111 -- Draw binary bitmap with specified foreground color and background color.
112 -- - jpcrr.joystick_state()
113 -- Returns nil if no joystick. Otherwise returns hold times for all four axis (numeric)
114 -- followed by button states (boolean).
115 -- - jpcrr.component_encode(table components)
116 -- Return component encoding for specified components.
117 -- - jpcrr.component_decode(string line)
118 -- Return component decoding for specified line, nil/nil if it doesn't encode
119 -- anything, nil/string if parse error occurs (the error is the second return).
120 -- - jpcrr.save_state(string name)
121 -- Savestate into specified file. Returns name used.
122 -- - jpcrr.save_movie(string name)
123 -- Save movie into specified file. Returns name used.
124 -- - jpcrr.load_state_normal(string name)
125 -- Load specified savestate. Returns name used.
126 -- - jpcrr.load_state_preserve_events(string name)
127 -- Load specified savestate, preserving events. Returns name used.
128 -- - jpcrr.load_state_movie(string name)
129 -- Load specified savestate as movie. Returns name used.
130 -- - jpcrr.assemble()
131 -- Open system settings dialog.
132 -- - jpcrr.change_authors()
133 -- Open change authors dialog.
134 -- - jpcrr.exit = function()
135 -- Exit the Lua VM.
136 -- - jpcrr.ram_dump(string name, boolean binary)
137 -- Dump PC memory to specified file. If binary is true, dump is binary, otherwise
138 -- textual hexadecimal dump.
139 -- - jpcrr.write_byte(number addr, number value)
140 -- Write byte to specified physical address.
141 -- - jpcrr.write_word(number addr, number value)
142 -- Write word to specified physical address (little endian).
143 -- - jpcrr.write_dword(number addr, number value)
144 -- Write dword to specified physical address (little endian).
145 -- - jpcrr.read_byte(number addr)
146 -- Return byte from specified physical address.
147 -- - jpcrr.read_word(number addr)
148 -- Return word from specified physical address (little endian).
149 -- - jpcrr.read_dword(number addr)
150 -- Return dword from specified physical address (little endian).
151 -- - jpcrr.timed_trap(number nsecs)
152 -- Set trap after specified number of nanoseconds. Use nil as nsecs to disable.
153 -- - jpcrr.vretrace_start_trap(boolean is_on)
154 -- Set trap on vretrace start on/off.
155 -- - jpcrr.vretrace_end_trap(boolean is_on)
156 -- Set trap on vretrace end on/off.
157 -- - jpcrr.pc_start()
158 -- Start PC execution.
159 -- - jpcrr.pc_stop()
160 -- Stop PC execution.
161 -- - jpcrr.set_pccontrol_pos(number x, number y)
162 -- Set position of PCControl window.
163 -- - jpcrr.set_luaplugin_pos(number x, number y)
164 -- Set position of LuaPlugin window.
165 -- - jpcrr.set_pcmonitor_pos(number x, number y)
166 -- Set position of PCMonitor window.
167 -- - jpcrr.set_pcstartstoptest_pos(number x, number y)
168 -- Set position of PCStartStopTest window.
169 -- - jpcrr.set_virtualkeyboard_pos(number x, number y)
170 -- Set position of VirtualKeyboard window.
171 -- - jpcrr.stringlessthan(String x, String y)
172 -- Return true if x is before y in codepoint lexical order, otherwise false.
173 -- - jpcrr.screenshot(boolean include_hud)
174 -- Take screen shot (Requires monitor). If include_hud is true, include HUD
175 -- (as shown on screen). Note that this should only be called during frame
176 -- hold or results are pretty much undefined.
178 -- I/O functions have the following conventions. If function returns any real data, the first
179 -- return value returns this data or is nil. Otherwise first return value is true or false.
180 -- If first return value is nil or false, then the second return value gives textual error
181 -- message for failed operation, or is nil if EOF occured before anything was read.
183 -- Unlink, rename and mkdir don't follow this pattern. They just return true/false to signal
184 -- success or failure.
186 -- Specifying nil as name of file results random filename being used (it even works with unlink,
187 -- mkdir, rename and read-only access, but doesn't make any sense there).
189 -- Class: BinaryFile:
190 -- Binary file for RO or RW access. Methods are as follows:
191 -- - name()
192 -- Return name of file.
193 -- - length()
194 -- Return length of file.
195 -- - set_length(number length)
196 -- Truncate file to specified length
197 -- - read(number offset, number length)
198 -- Read up to length bytes from offset.
199 -- - write(number offset, string content)
200 -- Write content to specified offset.
201 -- - close()
202 -- Close the file.
203 -- Class: BinaryInput:
204 -- Binary file for sequential input. Methods are as follows:
205 -- - name()
206 -- Return name of file.
207 -- - four_to_five()
208 -- Return BinaryInput that is four to five decoding of this stream.
209 -- - text()
210 -- Return stream as TextInput.
211 -- - inflate()
212 -- Return BinaryInput that is inflate of this stream.
213 -- - read(number bytes)
214 -- Read up to bytes bytes from file.
215 -- - read()
216 -- Read the entiere file at once.
217 -- - close()
218 -- Close the file.
219 -- Character set for binary files is Latin-1.
221 -- Class: BinaryOutput:
222 -- Binary file for sequential output. Methods are as follows:
223 -- - name()
224 -- Return name of file.
225 -- - four_to_five()
226 -- Return BinaryOutput that writes four to five encoded output to this stream.
227 -- - text()
228 -- Return stream as TextOutput.
229 -- - deflate()
230 -- Return BinaryOutput that writes deflate output to this stream.
231 -- - write(string content)
232 -- Write string to file.
233 -- - close()
234 -- Close the file.
235 -- Character set for binary files is Latin-1.
237 -- Class: TextInput:
238 -- - name()
239 -- Return name of file.
240 -- - read()
241 -- Read line from file.
242 -- - read_component()
243 -- Read next componented line into array.
244 -- - lines()
245 -- Line iterator function.
246 -- - close()
247 -- Close the file.
248 -- Character set for text files is UTF-8.
250 -- Class: TextOutput:
251 -- - name()
252 -- Return name of file.
253 -- - write(string line)
254 -- Write line line to file.
255 -- - write_component(table components)
256 -- Write componented line.
257 -- - close()
258 -- Close the file.
259 -- Character set for text files is UTF-8.
261 -- Class ArchiveIn:
262 -- - member(string name)
263 -- Open substream for member name. The methods are the same as for io.opentextin.
264 -- - member_binary(string name)
265 -- Open binary (four to five) substream for member name. The methods are the same as
266 -- for io.openbinaryin.
267 -- - close()
268 -- Close the file. Any opened substreams are invalidated.
269 -- - member_list()
270 -- Return table listing all members of archive (sorted by name).
271 -- Class ArchiveOut:
272 -- - member(string name)
273 -- Open substream for member name. The methods are the same as for io.opentextout. Note that
274 -- previous member must be closed before next can open.
275 -- - member_binary(string name)
276 -- Open binary (four to five) substream for member name. The methods are the same as
277 -- for io.openbinaryout. Note that previous substream must be closed before next can open.
278 -- - commit()
279 -- Commit the file. No substream may be open. Closes the file.
280 -- - rollback()
281 -- Rollback the file. No substream may be open. Closes the file.
283 -- - io.open(string name, string mode) -> BinaryFile
284 -- Open file named @name in specified mode. The mode can be 'r' (read only) or 'rw' (read and
285 -- write).
286 -- - io.open_read(string name) -> BinaryInput
287 -- Open file named @name as binary input stream.
288 -- - io.open_write(string name) -> BinaryOutput
289 -- Open file named @name as binary input stream.
290 -- - io.open_arch_read(string name) -> ArchiveIn
291 -- Open file named @name as input archive.
292 -- - io.open_arch_write(string name) -> ArchiveOut
293 -- Open file named @name as output archive.
294 -- - io.mkdir(string name)
295 -- Create directory name. Returns name created on success, nil on failure.
296 -- - io.unlink(string name)
297 -- Delete file/directory name. Returns name deleted on success, nil on failure.
298 -- - io.rename(string old, string new)
299 -- Rename file old -> new. Returns old, new on success, nil on failure.
300 -- - io.transform.text()
301 -- Returns function that calls text() method of its parameter.
302 -- - io.transform.four_to_five()
303 -- Returns function that calls four_to_five() method of its parameter.
304 -- - io.transform.deflate()
305 -- Returns function that calls deflate() method of its parameter.
306 -- - io.transform.inflate()
307 -- Returns function that calls inflate() method of its parameter.
308 -- - io.dotransform(object obj, function...)
309 -- Call specified functions on specified object. If any function fails (first argument nil
310 -- or false), call close method on preceeding object. Otherwise call specified functions
311 -- chained left to right and return the result.
312 -- - io.dotransform2(object obj, string err, function...)
313 -- Similar to dotransform except if obj is nil or false, returns obj, err.
319 local handle, err, chunk, indication, k, v;
321 local loadmod = loadmodule;
322 loadmodule = nil;
324 local export_module_in = function(tab, modname, prefix)
325 local fun = loadmod(modname);
326 for k, v in pairs(fun) do
327 tab[(prefix or "") .. k] = v;
331 jpcrr = {};
332 jpcrr.hud = {};
333 bit = {};
334 io = {};
336 export_module_in(jpcrr, "org.jpc.luaextensions.Base");
337 export_module_in(jpcrr, "org.jpc.luaextensions.InputDevices");
338 export_module_in(jpcrr, "org.jpc.luaextensions.ComponentCoding", "component_");
339 export_module_in(bit, "org.jpc.luaextensions.Bitops");
341 -- Few misc functions.
342 assert = function(val, err)
343 if (not val) and err then
344 error(err);
346 return val;
349 modulus_split = function(number, ...)
350 local dividers = {...};
351 local results = {};
352 local rem;
354 for k, v in ipairs(dividers) do
355 rem = number % v;
356 table.insert(results, (number - rem) / v);
357 number = rem;
360 table.insert(results, number);
361 return unpack(results);
364 local getmtable = getmetatable;
365 local toString = tostring;
366 local inject_binary_file;
367 local inject_binary_input;
368 local inject_binary_output;
369 local inject_text_input;
370 local inject_text_output;
371 local inject_archive_input;
372 local inject_archive_output;
374 -- Class member injectors.
375 inject_binary_file = function(obj, name)
376 local _name = name;
377 getmtable(obj).name = function(obj)
378 return _name;
380 getmtable(obj).__index = function(tab, name)
381 local x = getmtable(obj)[name];
382 if x then
383 return x;
385 error("Invalid method " .. name .. " for BinaryFile");
387 return obj;
390 inject_binary_input = function(obj, underlying, name)
391 local _name = name;
392 local old_four_to_five = getmtable(obj).four_to_five;
393 local old_inflate = getmtable(obj).inflate;
394 local old_text = getmtable(obj).text;
395 local old_read = getmtable(obj).read;
396 local old_close = getmtable(obj).close;
397 local underlying_object = underlying;
399 getmtable(obj).name = function(obj)
400 return _name;
402 getmtable(obj).four_to_five = function(obj)
403 local res, err;
404 res, err = old_four_to_five(obj);
405 if not res then
406 return res, err;
408 return inject_binary_input(res, obj, "four-to-five<" .. _name .. ">");
410 getmtable(obj).inflate = function(obj)
411 local res, err;
412 res, err = old_inflate(obj);
413 if not res then
414 return res, err;
416 return inject_binary_input(res, obj, "inflate<" .. _name .. ">");
418 getmtable(obj).text = function(obj)
419 local res, err;
420 res, err = old_text(obj);
421 if not res then
422 return res, err;
424 return inject_text_input(res, obj, "text<" .. _name .. ">");
426 getmtable(obj).read = function(obj, toread)
427 if toread then
428 return old_read(obj, toread);
429 else
430 local res = "";
431 local ret, err;
432 while true do
433 ret, err = old_read(obj, 16384);
434 if not ret then
435 if not err then
436 return res;
438 return nil, err;
440 res = res .. ret;
444 getmtable(obj).close = function(obj)
445 local ret, err, ret2, err2;
446 ret, err = old_close(obj);
447 if underlying_object then ret2, err2 = underlying_object:close(); end
448 if ret and not ret2 then
449 err = err2;
450 ret = ret2;
452 return ret, err;
454 getmtable(obj).__index = function(tab, name)
455 local x = getmtable(obj)[name];
456 if x then
457 return x;
459 error("Invalid method " .. name .. " for BinaryInput");
461 return obj;
464 inject_binary_output = function(obj, underlying, name)
465 local _name = name;
466 local old_four_to_five = getmtable(obj).four_to_five;
467 local old_deflate = getmtable(obj).deflate;
468 local old_text = getmtable(obj).text;
469 local old_close = getmtable(obj).close;
470 local underlying_object = underlying;
472 getmtable(obj).name = function(obj)
473 return _name;
475 getmtable(obj).four_to_five = function(obj)
476 local res, err;
477 res, err = old_four_to_five(obj);
478 if not res then
479 return res, err;
481 return inject_binary_output(res, obj, "four-to-five<" .. _name .. ">");
483 getmtable(obj).deflate = function(obj)
484 local res, err;
485 res, err = old_deflate(obj);
486 if not res then
487 return res, err;
489 return inject_binary_output(res, obj, "deflate<" .. _name .. ">");
491 getmtable(obj).text = function(obj)
492 local res, err;
493 res, err = old_text(obj);
494 if not res then
495 return res, err;
497 return inject_text_output(res, obj, "text<" .. _name .. ">");
499 getmtable(obj).close = function(obj)
500 local ret, err, ret2, err2;
501 ret, err = old_close(obj);
502 if underlying_object then ret2, err2 = underlying_object:close(); end
503 if ret and not ret2 then
504 err = err2;
505 ret = ret2;
507 return ret, err;
509 getmtable(obj).__index = function(tab, name)
510 local x = getmtable(obj)[name];
511 if x then
512 return x;
514 error("Invalid method " .. name .. " for BinaryOutput");
516 return obj;
519 inject_text_input = function(obj, underlying, name)
520 local _name = name;
521 local old_close = getmtable(obj).close;
522 local underlying_object = underlying;
524 getmtable(obj).lines = function(obj)
525 return function(state, prevline)
526 return state:read();
527 end, obj, nil;
529 getmtable(obj).name = function(obj)
530 return _name;
532 getmtable(obj).close = function(obj)
533 local ret, err, ret2, err2;
534 ret, err = old_close(obj);
535 if underlying_object then ret2, err2 = underlying_object:close(); end
536 if ret and not ret2 then
537 err = err2;
538 ret = ret2;
540 return ret, err;
542 getmtable(obj).__index = function(tab, name)
543 local x = getmtable(obj)[name];
544 if x then
545 return x;
547 error("Invalid method " .. name .. " for TextInput");
549 return obj;
552 inject_text_output = function(obj, underlying, name)
553 local _name = name;
554 local old_close = getmtable(obj).close;
555 local underlying_object = underlying;
557 getmtable(obj).name = function(obj)
558 return _name;
560 getmtable(obj).close = function(obj)
561 local ret, err, ret2, err2;
562 ret, err = old_close(obj);
563 if underlying_object then ret2, err2 = underlying_object:close(); end
564 if ret and underlying_object then
565 err = err2;
566 ret = ret2;
568 return ret, err;
570 getmtable(obj).__index = function(tab, name)
571 local x = getmtable(obj)[name];
572 if x then
573 return x;
575 error("Invalid method " .. name .. " for TextOutput");
577 return obj;
580 inject_archive_input = function(obj, name)
581 local _name = name;
582 local old_member = getmtable(obj).member;
583 local old_member_list = getmtable(obj).member_list;
584 getmtable(obj).member = function(obj, member)
585 local res, err;
586 res, err = old_member(obj, member);
587 if not res then
588 return res, err;
590 return inject_binary_input(res, nil, _name .. "[" .. member .. "]");
592 getmtable(obj).name = function(obj)
593 return _name;
595 getmtable(obj).member_list = function(obj)
596 local tab = old_member_list(obj);
597 if tab then table.sort(tab, jpcrr.stringlessthan); end
598 return tab;
600 getmtable(obj).__index = function(tab, name)
601 local x = getmtable(obj)[name];
602 if x then
603 return x;
605 error("Invalid method " .. name .. " for ArchiveInput");
607 return obj;
610 inject_archive_output = function(obj, name)
611 local _name = name;
612 local old_member = getmtable(obj).member;
613 getmtable(obj).member = function(obj, member)
614 local res, err;
615 res, err = old_member(obj, member);
616 if not res then
617 return res, err;
619 return inject_binary_output(res, nil, _name .. "[" .. member .. "]");
621 getmtable(obj).name = function(obj)
622 return _name;
624 getmtable(obj).__index = function(tab, name)
625 local x = getmtable(obj)[name];
626 if x then
627 return x;
629 error("Invalid method " .. name .. " for ArchiveOutput");
631 return obj;
635 -- Redefined print.
637 local rprint = print_console_msg;
638 print_console_msg = nil;
639 print = function(...)
640 local x = "";
641 local y = {...};
642 local i;
643 for i = 1,#y do
644 if i > 1 then
645 x = x .. "\t" .. toString(y[i]);
646 else
647 x = toString(y[i]);
650 rprint(x);
652 print_console_msg = nil;
655 -- I/O routines.
656 local stringfind = string.find;
657 local randname = loadmod("org.jpc.luaextensions.DelayedDelete").random_temp_name;
658 local path = args["luapath"] or ".";
659 local toresourcename = function(resname)
660 if not resname then
661 return randname(path .. "/", "luatemp-");
664 if not stringfind(resname, "[%d%l%u_%-]") then
665 error("Bad resource name (case 1): " .. resname);
667 if stringfind(resname, "^/") then
668 error("Bad resource name (case 2): " .. resname);
670 if stringfind(resname, "%.%.") then
671 error("Bad resource name (case 3): " .. resname);
673 if stringfind(resname, "\\") then
674 error("Bad resource name (case 4): " .. resname);
677 return resname, path .. "/" .. resname;
682 local openbinin = loadmod("org.jpc.luaextensions.BinaryInFile").open;
683 local openbinout = loadmod("org.jpc.luaextensions.BinaryOutFile").open;
684 local openarchin = loadmod("org.jpc.luaextensions.ArchiveIn").open;
685 local openarchout = loadmod("org.jpc.luaextensions.ArchiveOut").open;
686 local openbinary = loadmod("org.jpc.luaextensions.BinaryFile").open;
688 local baseFS = loadmod("org.jpc.luaextensions.BaseFSOps");
689 local mkdir = baseFS.mkdir;
690 local unlink = baseFS.unlink;
691 local rename = baseFS.rename;
693 local getmtable = getmetatable;
695 loadfile = function(_script)
696 local file, file2, err, content;
697 local x, y;
698 x, y = toresourcename(_script);
699 file, err = openbinin(y, "r");
700 if not file then
701 return nil, "Can't open " .. _script .. ": " .. err;
703 file2, err = file:text();
704 if not file2 then
705 return nil, "Can't transform " .. _script .. ": " .. err;
707 content = "";
708 line = file2:read();
709 while line do
710 content = content .. line .. "\n";
711 line = file2:read();
713 file2:close();
714 file:close();
715 return loadstring(content, _script);
718 io.open = function(name, mode)
719 local _name;
720 local res, err;
721 local y;
722 _name, y = toresourcename(name);
723 res, err = openbinary(y, mode);
724 if not res then
725 return res, err;
727 return inject_binary_file(res, _name);
730 io.open_arch_read = function(name)
731 local _name = name;
732 local res, err;
733 local y;
734 _name, y = toresourcename(name);
735 res, err = openarchin(y);
736 if not res then
737 return res, err;
739 return inject_archive_input(res, _name);
742 io.open_arch_write = function(name)
743 local _name = name;
744 local res, err;
745 local y;
746 _name, y = toresourcename(name);
747 res, err = openarchout(y);
748 if not res then
749 return res, err;
751 return inject_archive_output(res, _name);
754 io.open_read = function(name)
755 local _name = name;
756 local res, err;
757 local y;
758 _name, y = toresourcename(name);
759 res, err = openbinin(y);
760 if not res then
761 return res, err;
763 return inject_binary_input(res, nil, _name);
766 io.open_write = function(name)
767 local _name = name;
768 local res, err;
769 local y;
770 _name, y = toresourcename(name);
771 res, err = openbinout(y);
772 if not res then
773 return res, err;
775 return inject_binary_output(res, nil, _name);
778 io.mkdir = function(name)
779 local _name, y;
780 _name, y = toresourcename(name);
781 if mkdir(y) then
782 return _name;
783 else
784 return nil;
788 io.unlink = function(name)
789 local _name, y;
790 _name, y = toresourcename(name);
791 if unlink(y) then
792 return _name;
793 else
794 return nil;
798 io.rename = function(name1, name2)
799 local _name, y;
800 local _name2, y2;
801 _name, y = toresourcename(name1);
802 _name2, y2 = toresourcename(name2);
803 if rename(y, y2) then
804 return _name, _name2;
805 else
806 return nil;
810 io.transform = {};
812 io.transform.text = function()
813 return function(obj)
814 return obj:text();
818 io.transform.four_to_five = function()
819 return function(obj)
820 return obj:four_to_five();
824 io.transform.inflate = function()
825 return function(obj)
826 return obj:inflate();
830 io.transform.deflate = function()
831 return function(obj)
832 return obj:deflate();
836 io.dotransform = function(obj, ...)
837 local todo = {...};
838 local k, v;
839 local obj2, err;
840 for k, v in ipairs(todo) do
841 obj2, err = v(obj);
842 if not obj2 then
843 obj:close();
844 return nil, err;
846 obj = obj2;
848 return obj;
851 io.dotransform2 = function(obj, err, ...)
852 if not obj then
853 return obj, err;
855 return io.dotransform(obj, err, ...);
860 jpcrr.next_frame = function(name)
861 while true do
862 if not jpcrr.pc_connected() then
863 jpcrr.wait_pc_attach();
865 if jpcrr.in_frame_hold() then
866 jpcrr.release_vga();
868 if jpcrr.wait_vga() then
869 return;
875 -- Various stuff built on top of ECI.
876 local invoke = jpcrr.invoke;
877 local invokecall = jpcrr.call;
878 local invokesync = jpcrr.invoke_synchronous;
880 jpcrr.save_state = function(name)
881 local _name, _fname;
882 _name, _fname = toresourcename(name);
883 invokesync("state-save", {_fname});
884 return _name;
887 jpcrr.save_movie = function(name)
888 local _name, _fname;
889 _name, _fname = toresourcename(name);
890 invokesync("movie-save", {_name});
891 return _name;
894 jpcrr.load_state_normal = function(name)
895 local _name, _fname;
896 _name, _fname = toresourcename(name);
897 invokesync("state-load", {_name});
898 return _name;
901 jpcrr.load_state_preserve_events = function(name)
902 local _name, _fname;
903 _name, _fname = toresourcename(name);
904 invokesync("state-load-noevents", {_name});
905 return _name;
908 jpcrr.load_state_movie = function(name)
909 local _name, _fname;
910 _name, _fname = toresourcename(name);
911 invokesync("state-load-movie", {_name});
912 return _name;
915 jpcrr.assemble = function()
916 invokesync("pc-assemble");
919 jpcrr.change_authors = function()
920 invokesync("change-authors");
923 jpcrr.ram_dump = function(name, binary)
924 local _name, _fname;
925 _name, _fname = toresourcename(name);
926 if binary then
927 invokesync("ram-dump-binary", {_name});
928 else
929 invokesync("ram-dump-text", {_name});
931 return _name;
934 jpcrr.hud.left_gap = function(f, g)
935 invoke("hud-left-gap", {toString(f), toString(g)});
938 jpcrr.hud.right_gap = function(f, g)
939 invoke("hud-right-gap", {toString(f), toString(g)});
942 jpcrr.hud.top_gap = function(f, g)
943 invoke("hud-top-gap", {toString(f), toString(g)});
946 jpcrr.hud.bottom_gap = function(f, g)
947 invoke("hud-bottom-gap", {toString(f), toString(g)});
950 jpcrr.hud.white_solid_box = function(f, x, y, w, h)
951 invoke("hud-white-solid-box", {toString(f), toString(x), toString(y), toString(w), toString(h)});
954 jpcrr.hud.box = function(f, x, y, w, h, t, lr, lg, lb, la, fr, fg, fb, fa)
955 invoke("hud-box", {toString(f), toString(x), toString(y), toString(w), toString(h),
956 toString(t), toString(lr), toString(lg), toString(lb), toString(la), toString(fr),
957 toString(fg), tostring(fb), toString(fa)});
960 jpcrr.hud.circle = function(f, x, y, r, t, lr, lg, lb, la, fr, fg, fb, fa)
961 invoke("hud-circle", {toString(f), toString(x), toString(y), toString(r),
962 toString(t), toString(lr), toString(lg), toString(lb), toString(la), toString(fr),
963 toString(fg), tostring(fb), toString(fa)});
966 jpcrr.hud.bitmap = function(f, x, y, bmap, lr, lg, lb, la, fr, fg, fb, fa)
967 invoke("hud-bitmap", {toString(f), toString(x), toString(y), bmap, toString(lr),
968 toString(lg), toString(lb), toString(la), toString(fr), toString(fg), tostring(fb),
969 toString(fa)});
972 jpcrr.hud.bitmap_binary = function(f, x, y, bmap, lr, lg, lb, la, fr, fg, fb, fa)
973 invoke("hud-bitmap-binary", {toString(f), toString(x), toString(y), bmap, toString(lr),
974 toString(lg), toString(lb), toString(la), toString(fr), toString(fg), tostring(fb),
975 toString(fa)});
978 jpcrr.set_pccontrol_pos = function(x, y)
979 invokesync("pccontrol-setwinpos", {toString(x), toString(y)});
982 jpcrr.set_luaplugin_pos = function(x, y)
983 invokesync("luaplugin-setwinpos", {toString(x), toString(y)});
986 jpcrr.set_pcmonitor_pos = function(x, y)
987 invokesync("pcmonitor-setwinpos", {toString(x), toString(y)});
990 jpcrr.set_pcstartstoptest_pos = function(x, y)
991 invokesync("pcstartstoptest-setwinpos", {toString(x), toString(y)});
994 jpcrr.set_virtualkeyboard_pos = function(x, y)
995 invokesync("virtualkeyboard-setwinpos", {toString(x), toString(y)});
998 jpcrr.exit = function()
999 invokesync("luaplugin-terminate");
1002 jpcrr.pc_start = function()
1003 invoke("pc-start");
1006 jpcrr.pc_stop = function()
1007 invokesync("pc-stop");
1010 jpcrr.screenshot = function(include_hud)
1011 if include_hud then
1012 invoke("screenshot-renderbuffer");
1013 else
1014 invoke("screenshot-vgabuffer");
1019 jpcrr.vretrace_start_trap = function(is_on)
1020 if is_on then
1021 invokesync("trap-vretrace-start-on");
1022 else
1023 invokesync("trap-vretrace-start-off");
1027 jpcrr.vretrace_end_trap = function(is_on)
1028 if is_on then
1029 invokesync("trap-vretrace-end-on");
1030 else
1031 invokesync("trap-vretrace-end-off");
1035 jpcrr.timed_trap = function(nsecs)
1036 if nsecs then
1037 invokesync("trap-timed", {toString(nsecs)});
1038 else
1039 invokesync("trap-timed-disable");
1043 jpcrr.write_byte = function(addr, value)
1044 invokesync("memory-write", {toString(addr), toString(value), "1"});
1047 jpcrr.write_word = function(addr, value)
1048 invokesync("memory-write", {toString(addr), toString(value), "2"});
1051 jpcrr.write_dword = function(addr, value)
1052 invokesync("memory-write", {toString(addr), toString(value), "4"});
1055 jpcrr.read_byte = function(addr)
1056 local t = {toString(addr), "1"};
1057 t = invokecall("memory-read", t);
1058 return (t or {})[1];
1061 jpcrr.read_word = function(addr)
1062 local t = {toString(addr), "2"};
1063 t = invokecall("memory-read", t);
1064 return (t or {})[1];
1067 jpcrr.read_dword = function(addr)
1068 local t = {toString(addr), "4"};
1069 t = invokecall("memory-read", t);
1070 return (t or {})[1];
1073 jpcrr.invoke = nil;
1074 jpcrr.invoke_synchronous = nil;
1075 jpcrr.call = null
1077 -- Dofile.
1078 dofile = function(_script)
1079 local chunk, err, indication
1080 chunk, err = loadfile(_script);
1081 if not chunk then
1082 error("Kernel: Can't load subscript " .. _script .. ": " .. err);
1084 return chunk();
1087 local args2 = args;
1088 args = null;
1089 args = {};
1090 for k, v in pairs(args2) do
1091 if (#k > 2 and string.byte(k, 1) == 120 and string.byte(k, 2) == 45) then
1092 args[string.sub(k, 3)] = v;
1095 jpcrr_raw = null;
1098 chunk = null;
1099 loaded, err = pcall(function()
1100 chunk, err = loadfile(script);
1101 if not chunk then
1102 error(err);
1104 end);
1105 if not loaded then
1106 print("Kernel: Can't load script " .. script .. ": " .. err);
1107 invoke("luaplugin-terminate");
1108 while true do end
1111 script = null;
1112 indication, err = pcall(chunk);
1113 if not indication then
1114 print("Kernel: Unprotected error in script: " .. err);
1115 invoke("luaplugin-terminate");
1116 while true do end