2 -- Copyright 2009-2010 Ilari Liusvaara
4 -- Licenced under GNU GPL v2.
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
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
24 -- - bit.any(number...)
25 -- Returns 48-bit number that has those bits set that are set in any of its
27 -- - bit.parity(number...)
28 -- Returns 48-bit number that has those bits set that are set in even number
30 -- - bit.any(number...)
31 -- Returns 48-bit number that has those bits set that are set in all of its
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
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,
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.
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.shutdown_emulator()
83 -- Shutdown the entiere emulator immediately (graceful shutdown, PCRunner only).
84 -- - jpcrr.hud.left_gap(number flags, number gap)
85 -- Set left gap for HUD. If flags has bit 0 (1) set, draw on screen, if bit
86 -- 1 (2) is set, dump to video dump.
87 -- - jpcrr.hud.right_gap(number flags, number gap)
88 -- Set right gap for HUD. If flags has bit 0 (1) set, draw on screen, if bit
89 -- 1 (2) is set, dump to video dump.
90 -- - jpcrr.hud.top_gap(number flags, number gap)
91 -- Set top gap for HUD. If flags has bit 0 (1) set, draw on screen, if bit
92 -- 1 (2) is set, dump to video dump.
93 -- - jpcrr.hud.bottom_gap(number flags, number gap)
94 -- Set bottom gap for HUD. If flags has bit 0 (1) set, draw on screen, if bit
95 -- 1 (2) is set, dump to video dump.
96 -- - jpcrr.hud.white_solid_box(number flags, number x, number y, number w, number h)
97 -- Draw with solid opaque box.
98 -- - jpcrr.hud.box(number flags, number x, number y, number w, number h, number linethick,
99 -- number lineRed, number lineGreen, number lineBlue, number lineAlpha,
100 -- number fillRed, number fillGreen, number fillBlue, number fillAlpha)
101 -- Draw box with specified size, border line thickness, line color and fill color.
102 -- - jpcrr.hud.circle(number flags, number x, number y, number r, number linethick,
103 -- number lineRed, number lineGreen, number lineBlue, number lineAlpha,
104 -- number fillRed, number fillGreen, number fillBlue, number fillAlpha)
105 -- Draw circle with specified size, border line thickness, line color and fill color.
106 -- - jpcrr.hud.bitmap(number flags, number x, number y, string bmap,
107 -- number fgRed, number fgGreen, number fgBlue, number fgAlpha,
108 -- number bgRed, number bgGreen, number bgBlue, number bgAlpha)
109 -- Draw bitmap with specified foreground color and background color.
110 -- - jpcrr.hud.bitmap_binary(number flags, number x, number y, string bmap,
111 -- number fgRed, number fgGreen, number fgBlue, number fgAlpha,
112 -- number bgRed, number bgGreen, number bgBlue, number bgAlpha)
113 -- Draw binary bitmap with specified foreground color and background color.
114 -- - jpcrr.joystick_state()
115 -- Returns nil if no joystick. Otherwise returns hold times for all four axis (numeric)
116 -- followed by button states (boolean).
117 -- - jpcrr.keyboard_leds()
118 -- Returns nil if no keyboard, false if LED status is unknown. Otherwise returns three
119 -- booleans, first being state of num lock, second being state of caps lock and third
120 -- being state of scroll lock.
121 -- - jpcrr.mouse_state()
122 -- Returns nil if no mouse. Otherwise returns X, Y and Z axis pending motions (numeric)
123 -- followed by button states (5 booleans).
124 -- - jpcrr.component_encode(table components)
125 -- Return component encoding for specified components.
126 -- - jpcrr.component_decode(string line)
127 -- Return component decoding for specified line, nil/nil if it doesn't encode
128 -- anything, nil/string if parse error occurs (the error is the second return).
129 -- - jpcrr.save_state(string name)
130 -- Savestate into specified file. Returns name used.
131 -- - jpcrr.save_movie(string name)
132 -- Save movie into specified file. Returns name used.
133 -- - jpcrr.load_state_normal(string name)
134 -- Load specified savestate. Returns name used.
135 -- - jpcrr.load_state_preserve_events(string name)
136 -- Load specified savestate, preserving events. Returns name used.
137 -- - jpcrr.load_state_movie(string name)
138 -- Load specified savestate as movie. Returns name used.
139 -- - jpcrr.assemble()
140 -- Open system settings dialog.
141 -- - jpcrr.change_authors()
142 -- Open change authors dialog.
143 -- - jpcrr.exit = function()
145 -- - jpcrr.ram_dump(string name, boolean binary)
146 -- Dump PC memory to specified file. If binary is true, dump is binary, otherwise
147 -- textual hexadecimal dump.
148 -- - jpcrr.write_byte(number addr, number value)
149 -- Write byte to specified physical address.
150 -- - jpcrr.write_word(number addr, number value)
151 -- Write word to specified physical address (little endian).
152 -- - jpcrr.write_dword(number addr, number value)
153 -- Write dword to specified physical address (little endian).
154 -- - jpcrr.read_byte(number addr)
155 -- Return byte from specified physical address.
156 -- - jpcrr.read_word(number addr)
157 -- Return word from specified physical address (little endian).
158 -- - jpcrr.read_dword(number addr)
159 -- Return dword from specified physical address (little endian).
160 -- - jpcrr.timed_trap(number nsecs)
161 -- Set trap after specified number of nanoseconds. Use nil as nsecs to disable.
162 -- - jpcrr.vretrace_start_trap(boolean is_on)
163 -- Set trap on vretrace start on/off.
164 -- - jpcrr.vretrace_end_trap(boolean is_on)
165 -- Set trap on vretrace end on/off.
166 -- - jpcrr.pc_start()
167 -- Start PC execution.
169 -- Stop PC execution.
170 -- - jpcrr.set_pccontrol_pos(number x, number y)
171 -- Set position of PCControl window.
172 -- - jpcrr.set_luaplugin_pos(number x, number y)
173 -- Set position of LuaPlugin window.
174 -- - jpcrr.set_pcmonitor_pos(number x, number y)
175 -- Set position of PCMonitor window.
176 -- - jpcrr.set_pcstartstoptest_pos(number x, number y)
177 -- Set position of PCStartStopTest window.
178 -- - jpcrr.set_virtualkeyboard_pos(number x, number y)
179 -- Set position of VirtualKeyboard window.
180 -- - jpcrr.stringlessthan(String x, String y)
181 -- Return true if x is before y in codepoint lexical order, otherwise false.
182 -- - jpcrr.screenshot(boolean include_hud)
183 -- Take screen shot (Requires monitor). If include_hud is true, include HUD
184 -- (as shown on screen). Note that this should only be called during frame
185 -- hold or results are pretty much undefined.
186 -- - jpcrr.sendevent(string/number...)
187 -- Sends specified event.
188 -- - jpcrr.movie_rerecords()
189 -- Return number of rerecords (nil if no movie loaded).
190 -- - jpcrr.movie_length()
191 -- Return length of movie in ns (nil if no movie loaded).
192 -- - jpcrr.movie_headers()
193 -- Return headers of movie as array of arrays (nil if no movie loaded).
195 -- I/O functions have the following conventions. If function returns any real data, the first
196 -- return value returns this data or is nil. Otherwise first return value is true or false.
197 -- If first return value is nil or false, then the second return value gives textual error
198 -- message for failed operation, or is nil if EOF occured before anything was read.
200 -- Unlink, rename and mkdir don't follow this pattern. They just return true/false to signal
201 -- success or failure.
203 -- Specifying nil as name of file results random filename being used (it even works with unlink,
204 -- mkdir, rename and read-only access, but doesn't make any sense there).
206 -- Specifying empty filename prompts for file (doesn't work with mkdir, rename nor unlink). Use
207 -- '/<title>' to specify title for prompt dialog.
209 -- Class: BinaryFile:
210 -- Binary file for RO or RW access. Methods are as follows:
212 -- Return name of file.
214 -- Return length of file.
215 -- - set_length(number length)
216 -- Truncate file to specified length
217 -- - read(number offset, number length)
218 -- Read up to length bytes from offset.
219 -- - write(number offset, string content)
220 -- Write content to specified offset.
223 -- Class: BinaryInput:
224 -- Binary file for sequential input. Methods are as follows:
226 -- Return name of file.
228 -- Return BinaryInput that is four to five decoding of this stream.
230 -- Return stream as TextInput.
232 -- Return BinaryInput that is inflate of this stream.
233 -- - read(number bytes)
234 -- Read up to bytes bytes from file.
236 -- Read the entiere file at once.
239 -- Character set for binary files is Latin-1.
241 -- Class: BinaryOutput:
242 -- Binary file for sequential output. Methods are as follows:
244 -- Return name of file.
246 -- Return BinaryOutput that writes four to five encoded output to this stream.
248 -- Return stream as TextOutput.
250 -- Return BinaryOutput that writes deflate output to this stream.
251 -- - write(string content)
252 -- Write string to file.
255 -- Character set for binary files is Latin-1.
259 -- Return name of file.
261 -- Read line from file.
262 -- - read_component()
263 -- Read next componented line into array.
265 -- Line iterator function.
268 -- Character set for text files is UTF-8.
270 -- Class: TextOutput:
272 -- Return name of file.
273 -- - write(string line)
274 -- Write line line to file.
275 -- - write_component(table components)
276 -- Write componented line.
279 -- Character set for text files is UTF-8.
282 -- - member(string name)
283 -- Open substream for member name. The methods are the same as for io.opentextin.
284 -- - member_binary(string name)
285 -- Open binary (four to five) substream for member name. The methods are the same as
286 -- for io.openbinaryin.
288 -- Close the file. Any opened substreams are invalidated.
290 -- Return table listing all members of archive (sorted by name).
292 -- - member(string name)
293 -- Open substream for member name. The methods are the same as for io.opentextout. Note that
294 -- previous member must be closed before next can open.
295 -- - member_binary(string name)
296 -- Open binary (four to five) substream for member name. The methods are the same as
297 -- for io.openbinaryout. Note that previous substream must be closed before next can open.
299 -- Commit the file. No substream may be open. Closes the file.
301 -- Rollback the file. No substream may be open. Closes the file.
303 -- - io.open(string name, string mode) -> BinaryFile
304 -- Open file named @name in specified mode. The mode can be 'r' (read only) or 'rw' (read and
306 -- - io.open_read(string name) -> BinaryInput
307 -- Open file named @name as binary input stream.
308 -- - io.open_write(string name) -> BinaryOutput
309 -- Open file named @name as binary input stream.
310 -- - io.open_arch_read(string name) -> ArchiveIn
311 -- Open file named @name as input archive.
312 -- - io.open_arch_write(string name) -> ArchiveOut
313 -- Open file named @name as output archive.
314 -- - io.mkdir(string name)
315 -- Create directory name. Returns name created on success, nil on failure.
316 -- - io.unlink(string name)
317 -- Delete file/directory name. Returns name deleted on success, nil on failure.
318 -- - io.rename(string old, string new)
319 -- Rename file old -> new. Returns old, new on success, nil on failure.
320 -- - io.transform.text()
321 -- Returns function that calls text() method of its parameter.
322 -- - io.transform.four_to_five()
323 -- Returns function that calls four_to_five() method of its parameter.
324 -- - io.transform.deflate()
325 -- Returns function that calls deflate() method of its parameter.
326 -- - io.transform.inflate()
327 -- Returns function that calls inflate() method of its parameter.
328 -- - io.dotransform(object obj, function...)
329 -- Call specified functions on specified object. If any function fails (first argument nil
330 -- or false), call close method on preceeding object. Otherwise call specified functions
331 -- chained left to right and return the result.
332 -- - io.dotransform2(object obj, string err, function...)
333 -- Similar to dotransform except if obj is nil or false, returns obj, err.
339 local handle, err, chunk, indication, k, v;
341 local loadmod = loadmodule;
344 local export_module_in = function(tab, modname, prefix)
345 local fun = loadmod(modname);
346 for k, v in pairs(fun) do
347 tab[(prefix or "") .. k] = v;
356 export_module_in(jpcrr, "org.jpc.luaextensions.Base");
357 export_module_in(jpcrr, "org.jpc.luaextensions.InputDevices");
358 export_module_in(jpcrr, "org.jpc.luaextensions.ComponentCoding", "component_");
359 export_module_in(bit, "org.jpc.luaextensions.Bitops");
361 -- Few misc functions.
362 assert = function(val, err)
363 if (not val) and err then
369 modulus_split = function(number, ...)
370 local dividers = {...};
374 for k, v in ipairs(dividers) do
376 table.insert(results, (number - rem) / v);
380 table.insert(results, number);
381 return unpack(results);
384 local getmtable = getmetatable;
385 local toString = tostring;
386 local inject_binary_file;
387 local inject_binary_input;
388 local inject_binary_output;
389 local inject_text_input;
390 local inject_text_output;
391 local inject_archive_input;
392 local inject_archive_output;
394 -- Class member injectors.
395 inject_binary_file = function(obj, name)
397 getmtable(obj).name = function(obj)
400 getmtable(obj).__index = function(tab, name)
401 local x = getmtable(obj)[name];
405 error("Invalid method " .. name .. " for BinaryFile");
410 inject_binary_input = function(obj, underlying, name)
412 local old_four_to_five = getmtable(obj).four_to_five;
413 local old_inflate = getmtable(obj).inflate;
414 local old_text = getmtable(obj).text;
415 local old_read = getmtable(obj).read;
416 local old_close = getmtable(obj).close;
417 local underlying_object = underlying;
419 getmtable(obj).name = function(obj)
422 getmtable(obj).four_to_five = function(obj)
424 res, err = old_four_to_five(obj);
428 return inject_binary_input(res, obj, "four-to-five<" .. _name .. ">");
430 getmtable(obj).inflate = function(obj)
432 res, err = old_inflate(obj);
436 return inject_binary_input(res, obj, "inflate<" .. _name .. ">");
438 getmtable(obj).text = function(obj)
440 res, err = old_text(obj);
444 return inject_text_input(res, obj, "text<" .. _name .. ">");
446 getmtable(obj).read = function(obj, toread)
448 return old_read(obj, toread);
453 ret, err = old_read(obj, 16384);
464 getmtable(obj).close = function(obj)
465 local ret, err, ret2, err2;
466 ret, err = old_close(obj);
467 if underlying_object then ret2, err2 = underlying_object:close(); end
468 if ret and not ret2 then
474 getmtable(obj).__index = function(tab, name)
475 local x = getmtable(obj)[name];
479 error("Invalid method " .. name .. " for BinaryInput");
484 inject_binary_output = function(obj, underlying, name)
486 local old_four_to_five = getmtable(obj).four_to_five;
487 local old_deflate = getmtable(obj).deflate;
488 local old_text = getmtable(obj).text;
489 local old_close = getmtable(obj).close;
490 local underlying_object = underlying;
492 getmtable(obj).name = function(obj)
495 getmtable(obj).four_to_five = function(obj)
497 res, err = old_four_to_five(obj);
501 return inject_binary_output(res, obj, "four-to-five<" .. _name .. ">");
503 getmtable(obj).deflate = function(obj)
505 res, err = old_deflate(obj);
509 return inject_binary_output(res, obj, "deflate<" .. _name .. ">");
511 getmtable(obj).text = function(obj)
513 res, err = old_text(obj);
517 return inject_text_output(res, obj, "text<" .. _name .. ">");
519 getmtable(obj).close = function(obj)
520 local ret, err, ret2, err2;
521 ret, err = old_close(obj);
522 if underlying_object then ret2, err2 = underlying_object:close(); end
523 if ret and not ret2 then
529 getmtable(obj).__index = function(tab, name)
530 local x = getmtable(obj)[name];
534 error("Invalid method " .. name .. " for BinaryOutput");
539 inject_text_input = function(obj, underlying, name)
541 local old_close = getmtable(obj).close;
542 local underlying_object = underlying;
544 getmtable(obj).lines = function(obj)
545 return function(state, prevline)
549 getmtable(obj).name = function(obj)
552 getmtable(obj).close = function(obj)
553 local ret, err, ret2, err2;
554 ret, err = old_close(obj);
555 if underlying_object then ret2, err2 = underlying_object:close(); end
556 if ret and not ret2 then
562 getmtable(obj).__index = function(tab, name)
563 local x = getmtable(obj)[name];
567 error("Invalid method " .. name .. " for TextInput");
572 inject_text_output = function(obj, underlying, name)
574 local old_close = getmtable(obj).close;
575 local underlying_object = underlying;
577 getmtable(obj).name = function(obj)
580 getmtable(obj).close = function(obj)
581 local ret, err, ret2, err2;
582 ret, err = old_close(obj);
583 if underlying_object then ret2, err2 = underlying_object:close(); end
584 if ret and underlying_object then
590 getmtable(obj).__index = function(tab, name)
591 local x = getmtable(obj)[name];
595 error("Invalid method " .. name .. " for TextOutput");
600 inject_archive_input = function(obj, name)
602 local old_member = getmtable(obj).member;
603 local old_member_list = getmtable(obj).member_list;
604 getmtable(obj).member = function(obj, member)
606 res, err = old_member(obj, member);
610 return inject_binary_input(res, nil, _name .. "[" .. member .. "]");
612 getmtable(obj).name = function(obj)
615 getmtable(obj).member_list = function(obj)
616 local tab = old_member_list(obj);
617 if tab then table.sort(tab, jpcrr.stringlessthan); end
620 getmtable(obj).__index = function(tab, name)
621 local x = getmtable(obj)[name];
625 error("Invalid method " .. name .. " for ArchiveInput");
630 inject_archive_output = function(obj, name)
632 local old_member = getmtable(obj).member;
633 getmtable(obj).member = function(obj, member)
635 res, err = old_member(obj, member);
639 return inject_binary_output(res, nil, _name .. "[" .. member .. "]");
641 getmtable(obj).name = function(obj)
644 getmtable(obj).__index = function(tab, name)
645 local x = getmtable(obj)[name];
649 error("Invalid method " .. name .. " for ArchiveOutput");
657 local rprint = print_console_msg;
658 print_console_msg = nil;
659 print = function(...)
665 x = x .. "\t" .. toString(y[i]);
672 print_console_msg = nil;
676 local stringfind = string.find;
677 local randname = loadmod("org.jpc.luaextensions.DelayedDelete").random_temp_name;
678 local selectname = loadmod("org.jpc.luaextensions.BaseFSOps").opensave_dialog;
679 local path = args["luapath"] or ".";
680 local toresourcename = function(resname, save, text)
682 return randname(path .. "/", "luatemp-");
685 if resname == "" and text then
687 a, b = selectname(save, text);
691 if stringfind(resname, "^/") then
693 error("Bad resource name (case 2): " .. resname);
696 a, b = selectname(save, string.sub(resname, 2));
700 if not stringfind(resname, "[%d%l%u_%-]") then
701 error("Bad resource name (case 1): " .. resname);
703 if stringfind(resname, "%.%.") then
704 error("Bad resource name (case 3): " .. resname);
706 if stringfind(resname, "\\") then
707 error("Bad resource name (case 4): " .. resname);
710 return resname, path .. "/" .. resname;
715 local openbinin = loadmod("org.jpc.luaextensions.BinaryInFile").open;
716 local openbinout = loadmod("org.jpc.luaextensions.BinaryOutFile").open;
717 local openarchin = loadmod("org.jpc.luaextensions.ArchiveIn").open;
718 local openarchout = loadmod("org.jpc.luaextensions.ArchiveOut").open;
719 local openbinary = loadmod("org.jpc.luaextensions.BinaryFile").open;
721 local baseFS = loadmod("org.jpc.luaextensions.BaseFSOps");
722 local mkdir = baseFS.mkdir;
723 local unlink = baseFS.unlink;
724 local rename = baseFS.rename;
726 local getmtable = getmetatable;
728 loadfile = function(_script)
729 local file, file2, err, content;
731 x, y = toresourcename(_script, false, "Select script to load");
732 if not x then return x, y; end
733 file, err = openbinin(y, "r");
735 return nil, "Can't open " .. _script .. ": " .. err;
737 file2, err = file:text();
739 return nil, "Can't transform " .. _script .. ": " .. err;
744 content = content .. line .. "\n";
749 return loadstring(content, _script);
752 io.open = function(name, mode)
757 _name, y = toresourcename(name, false, "Select file to read");
759 _name, y = toresourcename(name, true, "Select file to write");
761 if not _name then return _name, y; end
762 res, err = openbinary(y, mode);
766 return inject_binary_file(res, _name);
769 io.open_arch_read = function(name)
773 _name, y = toresourcename(name, false, "Select archive to read");
774 if not _name then return _name, y; end
775 res, err = openarchin(y);
779 return inject_archive_input(res, _name);
782 io.open_arch_write = function(name)
786 _name, y = toresourcename(name, true, "Select archive to write");
787 if not _name then return _name, y; end
788 res, err = openarchout(y);
792 return inject_archive_output(res, _name);
795 io.open_read = function(name)
799 _name, y = toresourcename(name, false, "Select file to read");
800 if not _name then return _name, y; end
801 res, err = openbinin(y);
805 return inject_binary_input(res, nil, _name);
808 io.open_write = function(name)
812 _name, y = toresourcename(name, true, "Select file to write");
813 if not _name then return _name, y; end
814 res, err = openbinout(y);
818 return inject_binary_output(res, nil, _name);
821 io.mkdir = function(name)
823 _name, y = toresourcename(name);
831 io.unlink = function(name)
833 _name, y = toresourcename(name);
841 io.rename = function(name1, name2)
844 _name, y = toresourcename(name1);
845 _name2, y2 = toresourcename(name2);
846 if rename(y, y2) then
847 return _name, _name2;
855 io.transform.text = function()
861 io.transform.four_to_five = function()
863 return obj:four_to_five();
867 io.transform.inflate = function()
869 return obj:inflate();
873 io.transform.deflate = function()
875 return obj:deflate();
879 io.dotransform = function(obj, ...)
883 for k, v in ipairs(todo) do
894 io.dotransform2 = function(obj, err, ...)
898 return io.dotransform(obj, err, ...);
903 jpcrr.next_frame = function(name)
905 if not jpcrr.pc_connected() then
906 jpcrr.wait_pc_attach();
908 if jpcrr.in_frame_hold() then
911 if jpcrr.wait_vga() then
918 -- Various stuff built on top of ECI.
919 local invoke = jpcrr.invoke;
920 local invokecall = jpcrr.call;
921 local invokesync = jpcrr.invoke_synchronous;
923 jpcrr.sendevent = function(...)
924 local arguments = {...};
926 for k, v in ipairs(arguments) do
927 arguments[k] = toString(v);
929 invokesync("sendevent", arguments);
932 jpcrr.save_state = function(name)
934 _name, _fname = toresourcename(name);
935 invokesync("state-save", {_fname});
939 jpcrr.save_movie = function(name)
941 _name, _fname = toresourcename(name);
942 invokesync("movie-save", {_name});
946 jpcrr.load_state_normal = function(name)
948 _name, _fname = toresourcename(name);
949 invokesync("state-load", {_name});
953 jpcrr.load_state_preserve_events = function(name)
955 _name, _fname = toresourcename(name);
956 invokesync("state-load-noevents", {_name});
960 jpcrr.load_state_movie = function(name)
962 _name, _fname = toresourcename(name);
963 invokesync("state-load-movie", {_name});
967 jpcrr.assemble = function()
968 invokesync("pc-assemble");
971 jpcrr.change_authors = function()
972 invokesync("change-authors");
975 jpcrr.ram_dump = function(name, binary)
977 _name, _fname = toresourcename(name);
979 invokesync("ram-dump-binary", {_name});
981 invokesync("ram-dump-text", {_name});
986 jpcrr.hud.left_gap = function(f, g)
987 invoke("hud-left-gap", {toString(f), toString(g)});
990 jpcrr.hud.right_gap = function(f, g)
991 invoke("hud-right-gap", {toString(f), toString(g)});
994 jpcrr.hud.top_gap = function(f, g)
995 invoke("hud-top-gap", {toString(f), toString(g)});
998 jpcrr.hud.bottom_gap = function(f, g)
999 invoke("hud-bottom-gap", {toString(f), toString(g)});
1002 jpcrr.hud.white_solid_box = function(f, x, y, w, h)
1003 invoke("hud-white-solid-box", {toString(f), toString(x), toString(y), toString(w), toString(h)});
1006 jpcrr.hud.box = function(f, x, y, w, h, t, lr, lg, lb, la, fr, fg, fb, fa)
1007 invoke("hud-box", {toString(f), toString(x), toString(y), toString(w), toString(h),
1008 toString(t), toString(lr), toString(lg), toString(lb), toString(la), toString(fr),
1009 toString(fg), tostring(fb), toString(fa)});
1012 jpcrr.hud.circle = function(f, x, y, r, t, lr, lg, lb, la, fr, fg, fb, fa)
1013 invoke("hud-circle", {toString(f), toString(x), toString(y), toString(r),
1014 toString(t), toString(lr), toString(lg), toString(lb), toString(la), toString(fr),
1015 toString(fg), tostring(fb), toString(fa)});
1018 jpcrr.hud.bitmap = function(f, x, y, bmap, lr, lg, lb, la, fr, fg, fb, fa)
1019 invoke("hud-bitmap", {toString(f), toString(x), toString(y), bmap, toString(lr),
1020 toString(lg), toString(lb), toString(la), toString(fr), toString(fg), tostring(fb),
1024 jpcrr.hud.bitmap_binary = function(f, x, y, bmap, lr, lg, lb, la, fr, fg, fb, fa)
1025 invoke("hud-bitmap-binary", {toString(f), toString(x), toString(y), bmap, toString(lr),
1026 toString(lg), toString(lb), toString(la), toString(fr), toString(fg), tostring(fb),
1030 jpcrr.shutdown_emulator = function()
1031 invokesync("shutdown-emulator", {});
1034 jpcrr.set_pccontrol_pos = function(x, y)
1035 invokesync("pccontrol-setwinpos", {toString(x), toString(y)});
1038 jpcrr.set_luaplugin_pos = function(x, y)
1039 invokesync("luaplugin-setwinpos", {toString(x), toString(y)});
1042 jpcrr.set_pcmonitor_pos = function(x, y)
1043 invokesync("pcmonitor-setwinpos", {toString(x), toString(y)});
1046 jpcrr.set_pcstartstoptest_pos = function(x, y)
1047 invokesync("pcstartstoptest-setwinpos", {toString(x), toString(y)});
1050 jpcrr.set_virtualkeyboard_pos = function(x, y)
1051 invokesync("virtualkeyboard-setwinpos", {toString(x), toString(y)});
1054 jpcrr.exit = function()
1055 invokesync("luaplugin-terminate");
1058 jpcrr.pc_start = function()
1062 jpcrr.pc_stop = function()
1063 invokesync("pc-stop");
1066 jpcrr.screenshot = function(include_hud)
1068 invoke("screenshot-renderbuffer");
1070 invoke("screenshot-vgabuffer");
1075 jpcrr.vretrace_start_trap = function(is_on)
1077 invokesync("trap-vretrace-start-on");
1079 invokesync("trap-vretrace-start-off");
1083 jpcrr.vretrace_end_trap = function(is_on)
1085 invokesync("trap-vretrace-end-on");
1087 invokesync("trap-vretrace-end-off");
1091 jpcrr.timed_trap = function(nsecs)
1093 invokesync("trap-timed", {toString(nsecs)});
1095 invokesync("trap-timed-disable");
1099 jpcrr.write_byte = function(addr, value)
1100 invokesync("memory-write", {toString(addr), toString(value), "1"});
1103 jpcrr.write_word = function(addr, value)
1104 invokesync("memory-write", {toString(addr), toString(value), "2"});
1107 jpcrr.write_dword = function(addr, value)
1108 invokesync("memory-write", {toString(addr), toString(value), "4"});
1111 jpcrr.read_byte = function(addr)
1112 local t = {toString(addr), "1"};
1113 t = invokecall("memory-read", t);
1114 return (t or {})[1];
1117 jpcrr.read_word = function(addr)
1118 local t = {toString(addr), "2"};
1119 t = invokecall("memory-read", t);
1120 return (t or {})[1];
1123 jpcrr.read_dword = function(addr)
1124 local t = {toString(addr), "4"};
1125 t = invokecall("memory-read", t);
1126 return (t or {})[1];
1130 jpcrr.invoke_synchronous = nil;
1134 dofile = function(_script)
1135 local chunk, err, indication
1136 chunk, err = loadfile(_script);
1138 error("Kernel: Can't load subscript " .. _script .. ": " .. err);
1146 for k, v in pairs(args2) do
1147 if (#k > 2 and string.byte(k, 1) == 120 and string.byte(k, 2) == 45) then
1148 args[string.sub(k, 3)] = v;
1155 loaded, err = pcall(function()
1156 chunk, err = loadfile(script);
1162 print("Kernel: Can't load script " .. script .. ": " .. err);
1163 invoke("luaplugin-terminate");
1168 indication, err = pcall(chunk);
1169 if not indication then
1170 print("Kernel: Unprotected error in script: " .. err);
1171 invoke("luaplugin-terminate");