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.rol(number num, number shift)
51 -- Returns 48 rightmost bits of num rotated by shift places left. Going outside
52 -- shift range 0-47 produces unpredicatable results.
53 -- - bit.ror(number num, number shift)
54 -- Returns 48 rightmost bits of num rotated by shift places right. Going outside
55 -- shift range 0-47 produces unpredicatable results.
56 -- - bit.bswap2(number num)
57 -- Returns 16 rightmost bits of num byte-swapped.
58 -- - bit.bswap3(number num)
59 -- Returns 24 rightmost bits of num byte-swapped.
60 -- - bit.bswap4(number num)
61 -- Returns 32 rightmost bits of num byte-swapped.
62 -- - bit.bswap5(number num)
63 -- Returns 40 rightmost bits of num byte-swapped.
64 -- - bit.bswap6(number num)
65 -- Returns 48 rightmost bits of num byte-swapped.
66 -- - bit.signextend(number num, number bitnum)
67 -- Copy bitnum'th bit of num to all higher bits of num and return result. Going
68 -- outside bitnum range of 0-47 produces unpredictable results.
69 -- - bit.tosigned(number num, number bitnum)
70 -- Mask off bitnum'th bit and all higher bits. If bitnum'th bit of num was set,
71 -- perform 2s complement on number and negate the result.
72 -- - bit.tohex(number num)
73 -- Returns hexadecimal string representation of number.
74 -- - jpcrr.wait_event()
75 -- Waits for event. Returns event type and extra message (if present). Event
76 -- Types are "lock", "stop", "attach" and "message". Note that if you get event
77 -- of type "lock", you are now in frame hold.
78 -- - jpcrr.poll_event()
79 -- Same as wait_event(), but does not wait for event to occur (returns nil if there
81 -- - jpcrr.pc_running()
82 -- Returns true if PC is running.
83 -- - jpcrr.clock_time()
84 -- Returns current time or nil if no PC.
85 -- - jpcrr.pc_connected()
86 -- Returns true if PC is connected.
87 -- - jpcrr.in_frame_hold()
88 -- Returns true if in frame hold, false otherwise.
89 -- - jpcrr.keypressed(number key)
90 -- Return true if key is pressed, else false.
91 -- - jpcrr.keypressed_edge(number key)
92 -- Return true if key is pressed at input edge, else false.
93 -- - jpcrr.release_vga()
94 -- Allow VGA to exit frame hold mode. Wait for frame hold first.
95 -- - jpcrr.vga_resolution()
96 -- Return VGA x and y resolutions. -1x-1 or 0x0 is returned if no valid resolution.
97 -- Should only be called during frame hold.
98 -- - jpcrr.frame_number()
99 -- Return current VGA frame number or nil if no PC present.
100 -- - jpcrr.shutdown_emulator()
101 -- Shutdown the entiere emulator immediately (graceful shutdown, PCRunner only).
102 -- - jpcrr.hud.left_gap(number flags, number gap)
103 -- Set left gap for HUD. If flags has bit 0 (1) set, draw on screen, if bit
104 -- 1 (2) is set, dump to video dump.
105 -- - jpcrr.hud.right_gap(number flags, number gap)
106 -- Set right gap for HUD. If flags has bit 0 (1) set, draw on screen, if bit
107 -- 1 (2) is set, dump to video dump.
108 -- - jpcrr.hud.top_gap(number flags, number gap)
109 -- Set top gap for HUD. If flags has bit 0 (1) set, draw on screen, if bit
110 -- 1 (2) is set, dump to video dump.
111 -- - jpcrr.hud.bottom_gap(number flags, number gap)
112 -- Set bottom gap for HUD. If flags has bit 0 (1) set, draw on screen, if bit
113 -- 1 (2) is set, dump to video dump.
114 -- - jpcrr.hud.white_solid_box(number flags, number x, number y, number w, number h)
115 -- Draw with solid opaque box.
116 -- - jpcrr.hud.box(number flags, number x, number y, number w, number h, number linethick,
117 -- number lineRed, number lineGreen, number lineBlue, number lineAlpha,
118 -- number fillRed, number fillGreen, number fillBlue, number fillAlpha)
119 -- Draw box with specified size, border line thickness, line color and fill color.
120 -- - jpcrr.hud.circle(number flags, number x, number y, number r, number linethick,
121 -- number lineRed, number lineGreen, number lineBlue, number lineAlpha,
122 -- number fillRed, number fillGreen, number fillBlue, number fillAlpha)
123 -- Draw circle with specified size, border line thickness, line color and fill color.
124 -- - jpcrr.hud.bitmap(number flags, number x, number y, string bmap,
125 -- number fgRed, number fgGreen, number fgBlue, number fgAlpha,
126 -- number bgRed, number bgGreen, number bgBlue, number bgAlpha)
127 -- Draw bitmap with specified foreground color and background color.
128 -- - jpcrr.hud.bitmap_binary(number flags, number x, number y, string bmap,
129 -- number fgRed, number fgGreen, number fgBlue, number fgAlpha,
130 -- number bgRed, number bgGreen, number bgBlue, number bgAlpha)
131 -- Draw binary bitmap with specified foreground color and background color.
132 -- - jpcrr.events.count()
133 -- Return current event count. Nil if no PC.
134 -- - jpcrr.events.current_sequence()
135 -- Return sequence number of next event (event sequence numbers are 0-based). Nil if
136 -- no PC, -1 if at end of movie.
137 -- - jpcrr.events.by_sequence(number seq)
138 -- Return array for specified event. Nil if no PC, empty array if not valid sequence
139 -- number. Otherwise, first element of array is timestamp (numeric), the second is
140 -- event class and rest are the arguments.
141 -- - jpcrr.joystick_state()
142 -- Returns nil if no joystick. Otherwise returns hold times for all four axis (numeric)
143 -- followed by button states (boolean).
144 -- - jpcrr.keyboard_leds()
145 -- Returns nil if no keyboard, false if LED status is unknown. Otherwise returns three
146 -- booleans, first being state of num lock, second being state of caps lock and third
147 -- being state of scroll lock.
148 -- - jpcrr.mouse_state()
149 -- Returns nil if no mouse. Otherwise returns X, Y and Z axis pending motions (numeric)
150 -- followed by button states (5 booleans).
151 -- - jpcrr.component_encode(table components)
152 -- Return component encoding for specified components.
153 -- - jpcrr.component_decode(string line)
154 -- Return component decoding for specified line, nil/nil if it doesn't encode
155 -- anything, nil/string if parse error occurs (the error is the second return).
156 -- - jpcrr.save_state(string name)
157 -- Savestate into specified file. Returns name used.
158 -- - jpcrr.save_movie(string name)
159 -- Save movie into specified file. Returns name used.
160 -- - jpcrr.load_state_normal(string name)
161 -- Load specified savestate. Returns name used.
162 -- - jpcrr.load_state_preserve_events(string name)
163 -- Load specified savestate, preserving events. Returns name used.
164 -- - jpcrr.load_state_movie(string name)
165 -- Load specified savestate as movie. Returns name used.
166 -- - jpcrr.assemble()
167 -- Open system settings dialog.
168 -- - jpcrr.change_authors()
169 -- Open change authors dialog.
170 -- - jpcrr.exit = function()
172 -- - jpcrr.ram_dump(string name, boolean binary)
173 -- Dump PC memory to specified file. If binary is true, dump is binary, otherwise
174 -- textual hexadecimal dump.
175 -- - jpcrr.write_byte(number addr, number value)
176 -- Write byte to specified physical address.
177 -- - jpcrr.write_word(number addr, number value)
178 -- Write word to specified physical address (little endian).
179 -- - jpcrr.write_dword(number addr, number value)
180 -- Write dword to specified physical address (little endian).
181 -- - jpcrr.read_byte(number addr)
182 -- Return byte from specified physical address.
183 -- - jpcrr.read_word(number addr)
184 -- Return word from specified physical address (little endian).
185 -- - jpcrr.read_dword(number addr)
186 -- Return dword from specified physical address (little endian).
187 -- - jpcrr.read_byte_signed(number addr)
188 -- Return signed byte from specified physical address.
189 -- - jpcrr.read_word_signed(number addr)
190 -- Return signed word from specified physical address (little endian).
191 -- - jpcrr.read_dword_signed(number addr)
192 -- Return signed dword from specified physical address (little endian).
193 -- - jpcrr.timed_trap(number nsecs)
194 -- Set trap after specified number of nanoseconds. Use nil as nsecs to disable.
195 -- - jpcrr.vretrace_start_trap(boolean is_on)
196 -- Set trap on vretrace start on/off.
197 -- - jpcrr.vretrace_end_trap(boolean is_on)
198 -- Set trap on vretrace end on/off.
199 -- - jpcrr.pc_start()
200 -- Start PC execution.
202 -- Stop PC execution.
203 -- - jpcrr.set_pccontrol_pos(number x, number y)
204 -- Set position of PCControl window.
205 -- - jpcrr.set_luaplugin_pos(number x, number y)
206 -- Set position of LuaPlugin window.
207 -- - jpcrr.set_pcmonitor_pos(number x, number y)
208 -- Set position of PCMonitor window.
209 -- - jpcrr.set_pcstartstoptest_pos(number x, number y)
210 -- Set position of PCStartStopTest window.
211 -- - jpcrr.set_virtualkeyboard_pos(number x, number y)
212 -- Set position of VirtualKeyboard window.
213 -- - jpcrr.stringlessthan(String x, String y)
214 -- Return true if x is before y in codepoint lexical order, otherwise false.
215 -- - jpcrr.screenshot(boolean include_hud)
216 -- Take screen shot (Requires monitor). If include_hud is true, include HUD
217 -- (as shown on screen). Note that this should only be called during frame
218 -- hold or results are pretty much undefined.
219 -- - jpcrr.sendevent(string class, string/number...)
220 -- Sends specified event.
221 -- - jpcrr.sendevent_lowbound(number lowbound, string class, string/number...)
222 -- Sends specified event with specified time low bound.
223 -- - jpcrr.movie_rerecords()
224 -- Return number of rerecords (nil if no movie loaded).
225 -- - jpcrr.movie_length()
226 -- Return length of movie in ns (nil if no movie loaded).
227 -- - jpcrr.movie_headers()
228 -- Return headers of movie as array of arrays (nil if no movie loaded).
230 -- I/O functions have the following conventions. If function returns any real data, the first
231 -- return value returns this data or is nil. Otherwise first return value is true or false.
232 -- If first return value is nil or false, then the second return value gives textual error
233 -- message for failed operation, or is nil if EOF occured before anything was read.
235 -- Unlink, rename and mkdir don't follow this pattern. They just return true/false to signal
236 -- success or failure.
238 -- Specifying nil as name of file results random filename being used (it even works with unlink,
239 -- mkdir, rename and read-only access, but doesn't make any sense there).
241 -- Specifying empty filename prompts for file (doesn't work with mkdir, rename nor unlink). Use
242 -- '/<title>' to specify title for prompt dialog.
244 -- Class: BinaryFile:
245 -- Binary file for RO or RW access. Methods are as follows:
247 -- Return name of file.
249 -- Return length of file.
250 -- - set_length(number length)
251 -- Truncate file to specified length
252 -- - read(number offset, number length)
253 -- Read up to length bytes from offset.
254 -- - write(number offset, string content)
255 -- Write content to specified offset.
258 -- Class: BinaryInput:
259 -- Binary file for sequential input. Methods are as follows:
261 -- Return name of file.
263 -- Return BinaryInput that is four to five decoding of this stream.
265 -- Return stream as TextInput.
267 -- Return BinaryInput that is inflate of this stream.
268 -- - read(number bytes)
269 -- Read up to bytes bytes from file.
271 -- Read the entiere file at once.
274 -- Character set for binary files is Latin-1.
276 -- Class: BinaryOutput:
277 -- Binary file for sequential output. Methods are as follows:
279 -- Return name of file.
281 -- Return BinaryOutput that writes four to five encoded output to this stream.
283 -- Return stream as TextOutput.
285 -- Return BinaryOutput that writes deflate output to this stream.
286 -- - write(string content)
287 -- Write string to file.
290 -- Character set for binary files is Latin-1.
294 -- Return name of file.
296 -- Read line from file.
297 -- - read_component()
298 -- Read next componented line into array.
300 -- Line iterator function.
303 -- Character set for text files is UTF-8.
305 -- Class: TextOutput:
307 -- Return name of file.
308 -- - write(string line)
309 -- Write line line to file.
310 -- - write_component(table components)
311 -- Write componented line.
314 -- Character set for text files is UTF-8.
317 -- - member(string name)
318 -- Open substream for member name. The methods are the same as for io.opentextin.
319 -- - member_binary(string name)
320 -- Open binary (four to five) substream for member name. The methods are the same as
321 -- for io.openbinaryin.
323 -- Close the file. Any opened substreams are invalidated.
325 -- Return table listing all members of archive (sorted by name).
327 -- - member(string name)
328 -- Open substream for member name. The methods are the same as for io.opentextout. Note that
329 -- previous member must be closed before next can open.
330 -- - member_binary(string name)
331 -- Open binary (four to five) substream for member name. The methods are the same as
332 -- for io.openbinaryout. Note that previous substream must be closed before next can open.
334 -- Commit the file. No substream may be open. Closes the file.
336 -- Rollback the file. No substream may be open. Closes the file.
338 -- - io.open(string name, string mode) -> BinaryFile
339 -- Open file named @name in specified mode. The mode can be 'r' (read only) or 'rw' (read and
341 -- - io.open_read(string name) -> BinaryInput
342 -- Open file named @name as binary input stream.
343 -- - io.open_write(string name) -> BinaryOutput
344 -- Open file named @name as binary input stream.
345 -- - io.open_arch_read(string name) -> ArchiveIn
346 -- Open file named @name as input archive.
347 -- - io.open_arch_write(string name) -> ArchiveOut
348 -- Open file named @name as output archive.
349 -- - io.mkdir(string name)
350 -- Create directory name. Returns name created on success, nil on failure.
351 -- - io.unlink(string name)
352 -- Delete file/directory name. Returns name deleted on success, nil on failure.
353 -- - io.rename(string old, string new)
354 -- Rename file old -> new. Returns old, new on success, nil on failure.
355 -- - io.transform.text()
356 -- Returns function that calls text() method of its parameter.
357 -- - io.transform.four_to_five()
358 -- Returns function that calls four_to_five() method of its parameter.
359 -- - io.transform.deflate()
360 -- Returns function that calls deflate() method of its parameter.
361 -- - io.transform.inflate()
362 -- Returns function that calls inflate() method of its parameter.
363 -- - io.dotransform(object obj, function...)
364 -- Call specified functions on specified object. If any function fails (first argument nil
365 -- or false), call close method on preceeding object. Otherwise call specified functions
366 -- chained left to right and return the result.
367 -- - io.dotransform2(object obj, string err, function...)
368 -- Similar to dotransform except if obj is nil or false, returns obj, err.
374 local handle, err, chunk, indication, k, v;
376 local loadmod = loadmodule;
379 local export_module_in = function(tab, modname, prefix)
380 local fun = loadmod(modname);
381 for k, v in pairs(fun) do
382 tab[(prefix or "") .. k] = v;
392 export_module_in(jpcrr, "org.jpc.luaextensions.Base");
393 export_module_in(jpcrr, "org.jpc.luaextensions.InputDevices");
394 export_module_in(jpcrr, "org.jpc.luaextensions.ComponentCoding", "component_");
395 export_module_in(jpcrr.events, "org.jpc.luaextensions.Events");
396 export_module_in(bit, "org.jpc.luaextensions.Bitops");
398 -- Few misc functions.
399 assert = function(val, err)
400 if (not val) and err then
406 modulus_split = function(number, ...)
407 local dividers = {...};
411 for k, v in ipairs(dividers) do
413 table.insert(results, (number - rem) / v);
417 table.insert(results, number);
418 return unpack(results);
421 local getmtable = getmetatable;
422 local toString = tostring;
423 local inject_binary_file;
424 local inject_binary_input;
425 local inject_binary_output;
426 local inject_text_input;
427 local inject_text_output;
428 local inject_archive_input;
429 local inject_archive_output;
431 -- Class member injectors.
432 inject_binary_file = function(obj, name)
434 getmtable(obj).name = function(obj)
437 getmtable(obj).__index = function(tab, name)
438 local x = getmtable(obj)[name];
442 error("Invalid method " .. name .. " for BinaryFile");
447 inject_binary_input = function(obj, underlying, name)
449 local old_four_to_five = getmtable(obj).four_to_five;
450 local old_inflate = getmtable(obj).inflate;
451 local old_text = getmtable(obj).text;
452 local old_read = getmtable(obj).read;
453 local old_close = getmtable(obj).close;
454 local underlying_object = underlying;
456 getmtable(obj).name = function(obj)
459 getmtable(obj).four_to_five = function(obj)
461 res, err = old_four_to_five(obj);
465 return inject_binary_input(res, obj, "four-to-five<" .. _name .. ">");
467 getmtable(obj).inflate = function(obj)
469 res, err = old_inflate(obj);
473 return inject_binary_input(res, obj, "inflate<" .. _name .. ">");
475 getmtable(obj).text = function(obj)
477 res, err = old_text(obj);
481 return inject_text_input(res, obj, "text<" .. _name .. ">");
483 getmtable(obj).read = function(obj, toread)
485 return old_read(obj, toread);
490 ret, err = old_read(obj, 16384);
501 getmtable(obj).close = function(obj)
502 local ret, err, ret2, err2;
503 ret, err = old_close(obj);
504 if underlying_object then ret2, err2 = underlying_object:close(); end
505 if ret and not ret2 then
511 getmtable(obj).__index = function(tab, name)
512 local x = getmtable(obj)[name];
516 error("Invalid method " .. name .. " for BinaryInput");
521 inject_binary_output = function(obj, underlying, name)
523 local old_four_to_five = getmtable(obj).four_to_five;
524 local old_deflate = getmtable(obj).deflate;
525 local old_text = getmtable(obj).text;
526 local old_close = getmtable(obj).close;
527 local underlying_object = underlying;
529 getmtable(obj).name = function(obj)
532 getmtable(obj).four_to_five = function(obj)
534 res, err = old_four_to_five(obj);
538 return inject_binary_output(res, obj, "four-to-five<" .. _name .. ">");
540 getmtable(obj).deflate = function(obj)
542 res, err = old_deflate(obj);
546 return inject_binary_output(res, obj, "deflate<" .. _name .. ">");
548 getmtable(obj).text = function(obj)
550 res, err = old_text(obj);
554 return inject_text_output(res, obj, "text<" .. _name .. ">");
556 getmtable(obj).close = function(obj)
557 local ret, err, ret2, err2;
558 ret, err = old_close(obj);
559 if underlying_object then ret2, err2 = underlying_object:close(); end
560 if ret and not ret2 then
566 getmtable(obj).__index = function(tab, name)
567 local x = getmtable(obj)[name];
571 error("Invalid method " .. name .. " for BinaryOutput");
576 inject_text_input = function(obj, underlying, name)
578 local old_close = getmtable(obj).close;
579 local underlying_object = underlying;
581 getmtable(obj).lines = function(obj)
582 return function(state, prevline)
586 getmtable(obj).name = function(obj)
589 getmtable(obj).close = function(obj)
590 local ret, err, ret2, err2;
591 ret, err = old_close(obj);
592 if underlying_object then ret2, err2 = underlying_object:close(); end
593 if ret and not ret2 then
599 getmtable(obj).__index = function(tab, name)
600 local x = getmtable(obj)[name];
604 error("Invalid method " .. name .. " for TextInput");
609 inject_text_output = function(obj, underlying, name)
611 local old_close = getmtable(obj).close;
612 local underlying_object = underlying;
614 getmtable(obj).name = function(obj)
617 getmtable(obj).close = function(obj)
618 local ret, err, ret2, err2;
619 ret, err = old_close(obj);
620 if underlying_object then ret2, err2 = underlying_object:close(); end
621 if ret and underlying_object then
627 getmtable(obj).__index = function(tab, name)
628 local x = getmtable(obj)[name];
632 error("Invalid method " .. name .. " for TextOutput");
637 inject_archive_input = function(obj, name)
639 local old_member = getmtable(obj).member;
640 local old_member_list = getmtable(obj).member_list;
641 getmtable(obj).member = function(obj, member)
643 res, err = old_member(obj, member);
647 return inject_binary_input(res, nil, _name .. "[" .. member .. "]");
649 getmtable(obj).name = function(obj)
652 getmtable(obj).member_list = function(obj)
653 local tab = old_member_list(obj);
654 if tab then table.sort(tab, jpcrr.stringlessthan); end
657 getmtable(obj).__index = function(tab, name)
658 local x = getmtable(obj)[name];
662 error("Invalid method " .. name .. " for ArchiveInput");
667 inject_archive_output = function(obj, name)
669 local old_member = getmtable(obj).member;
670 getmtable(obj).member = function(obj, member)
672 res, err = old_member(obj, member);
676 return inject_binary_output(res, nil, _name .. "[" .. member .. "]");
678 getmtable(obj).name = function(obj)
681 getmtable(obj).__index = function(tab, name)
682 local x = getmtable(obj)[name];
686 error("Invalid method " .. name .. " for ArchiveOutput");
692 -- Redefined routines.
694 local rprint = print_console_msg;
695 print_console_msg = nil;
696 print = function(...)
702 x = x .. "\t" .. toString(y[i]);
709 print_console_msg = nil;
715 local stringfind = string.find;
716 local randname = loadmod("org.jpc.luaextensions.DelayedDelete").random_temp_name;
717 local selectname = loadmod("org.jpc.luaextensions.BaseFSOps").opensave_dialog;
718 local path = args["luapath"] or ".";
719 local toresourcename = function(resname, save, text)
721 return randname(path .. "/", "luatemp-");
724 if resname == "" and text then
726 a, b = selectname(save, text);
730 if stringfind(resname, "^/") then
732 error("Bad resource name (case 2): " .. resname);
735 a, b = selectname(save, string.sub(resname, 2));
739 if not stringfind(resname, "[%d%l%u_%-]") then
740 error("Bad resource name (case 1): " .. resname);
742 if stringfind(resname, "%.%.") then
743 error("Bad resource name (case 3): " .. resname);
745 if stringfind(resname, "\\") then
746 error("Bad resource name (case 4): " .. resname);
749 return resname, path .. "/" .. resname;
754 local openbinin = loadmod("org.jpc.luaextensions.BinaryInFile").open;
755 local openbinout = loadmod("org.jpc.luaextensions.BinaryOutFile").open;
756 local openarchin = loadmod("org.jpc.luaextensions.ArchiveIn").open;
757 local openarchout = loadmod("org.jpc.luaextensions.ArchiveOut").open;
758 local openbinary = loadmod("org.jpc.luaextensions.BinaryFile").open;
760 local baseFS = loadmod("org.jpc.luaextensions.BaseFSOps");
761 local mkdir = baseFS.mkdir;
762 local unlink = baseFS.unlink;
763 local rename = baseFS.rename;
765 local getmtable = getmetatable;
767 loadfile = function(_script)
768 local file, file2, err, content;
770 x, y = toresourcename(_script, false, "Select script to load");
771 if not x then return x, y; end
772 file, err = openbinin(y, "r");
774 return nil, "Can't open " .. _script .. ": " .. err;
776 file2, err = file:text();
778 return nil, "Can't transform " .. _script .. ": " .. err;
783 content = content .. line .. "\n";
788 return loadstring(content, _script);
791 io.open = function(name, mode)
796 _name, y = toresourcename(name, false, "Select file to read");
798 _name, y = toresourcename(name, true, "Select file to write");
800 if not _name then return _name, y; end
801 res, err = openbinary(y, mode);
805 return inject_binary_file(res, _name);
808 io.open_arch_read = function(name)
812 _name, y = toresourcename(name, false, "Select archive to read");
813 if not _name then return _name, y; end
814 res, err = openarchin(y);
818 return inject_archive_input(res, _name);
821 io.open_arch_write = function(name)
825 _name, y = toresourcename(name, true, "Select archive to write");
826 if not _name then return _name, y; end
827 res, err = openarchout(y);
831 return inject_archive_output(res, _name);
834 io.open_read = function(name)
838 _name, y = toresourcename(name, false, "Select file to read");
839 if not _name then return _name, y; end
840 res, err = openbinin(y);
844 return inject_binary_input(res, nil, _name);
847 io.open_write = function(name)
851 _name, y = toresourcename(name, true, "Select file to write");
852 if not _name then return _name, y; end
853 res, err = openbinout(y);
857 return inject_binary_output(res, nil, _name);
860 io.mkdir = function(name)
862 _name, y = toresourcename(name);
870 io.unlink = function(name)
872 _name, y = toresourcename(name);
880 io.rename = function(name1, name2)
883 _name, y = toresourcename(name1);
884 _name2, y2 = toresourcename(name2);
885 if rename(y, y2) then
886 return _name, _name2;
894 io.transform.text = function()
900 io.transform.four_to_five = function()
902 return obj:four_to_five();
906 io.transform.inflate = function()
908 return obj:inflate();
912 io.transform.deflate = function()
914 return obj:deflate();
918 io.dotransform = function(obj, ...)
922 for k, v in ipairs(todo) do
933 io.dotransform2 = function(obj, err, ...)
937 return io.dotransform(obj, err, ...);
942 -- Various stuff built on top of ECI.
943 local invoke = jpcrr.invoke;
944 local invokecall = jpcrr.call;
945 local invokesync = jpcrr.invoke_synchronous;
947 jpcrr.sendevent = function(...)
948 local arguments = {...};
950 for k, v in ipairs(arguments) do
951 arguments[k] = toString(v);
953 invokesync("sendevent", arguments);
956 jpcrr.sendevent_lowbound = function(...)
957 local arguments = {...};
959 for k, v in ipairs(arguments) do
960 arguments[k] = toString(v);
962 invokesync("sendevent-lowbound", arguments);
965 jpcrr.save_state = function(name)
967 _name, _fname = toresourcename(name);
968 invokesync("state-save", {_fname});
972 jpcrr.save_movie = function(name)
974 _name, _fname = toresourcename(name);
975 invokesync("movie-save", {_fname});
979 jpcrr.load_state_normal = function(name)
981 _name, _fname = toresourcename(name);
982 invokesync("state-load", {_fname});
986 jpcrr.load_state_preserve_events = function(name)
988 _name, _fname = toresourcename(name);
989 invokesync("state-load-noevents", {_fname});
993 jpcrr.load_state_movie = function(name)
995 _name, _fname = toresourcename(name);
996 invokesync("state-load-movie", {_fname});
1000 jpcrr.assemble = function()
1001 invokesync("pc-assemble");
1004 jpcrr.change_authors = function()
1005 invokesync("change-authors");
1008 jpcrr.ram_dump = function(name, binary)
1009 local _name, _fname;
1010 _name, _fname = toresourcename(name);
1012 invokesync("ram-dump-binary", {_fname});
1014 invokesync("ram-dump-text", {_fname});
1019 local wait_event = jpcrr.wait_event;
1020 jpcrr.wait_event = function()
1023 a, b = wait_event();
1029 jpcrr.hud.left_gap = function(f, g)
1030 invoke("hud-left-gap", {toString(f), toString(g)});
1033 jpcrr.hud.right_gap = function(f, g)
1034 invoke("hud-right-gap", {toString(f), toString(g)});
1037 jpcrr.hud.top_gap = function(f, g)
1038 invoke("hud-top-gap", {toString(f), toString(g)});
1041 jpcrr.hud.bottom_gap = function(f, g)
1042 invoke("hud-bottom-gap", {toString(f), toString(g)});
1045 jpcrr.hud.white_solid_box = function(f, x, y, w, h)
1046 invoke("hud-white-solid-box", {toString(f), toString(x), toString(y), toString(w), toString(h)});
1049 jpcrr.hud.box = function(f, x, y, w, h, t, lr, lg, lb, la, fr, fg, fb, fa)
1050 invoke("hud-box", {toString(f), toString(x), toString(y), toString(w), toString(h),
1051 toString(t), toString(lr), toString(lg), toString(lb), toString(la), toString(fr),
1052 toString(fg), tostring(fb), toString(fa)});
1055 jpcrr.hud.circle = function(f, x, y, r, t, lr, lg, lb, la, fr, fg, fb, fa)
1056 invoke("hud-circle", {toString(f), toString(x), toString(y), toString(r),
1057 toString(t), toString(lr), toString(lg), toString(lb), toString(la), toString(fr),
1058 toString(fg), tostring(fb), toString(fa)});
1061 jpcrr.hud.bitmap = function(f, x, y, bmap, lr, lg, lb, la, fr, fg, fb, fa)
1062 invoke("hud-bitmap", {toString(f), toString(x), toString(y), bmap, toString(lr),
1063 toString(lg), toString(lb), toString(la), toString(fr), toString(fg), tostring(fb),
1067 jpcrr.hud.bitmap_binary = function(f, x, y, bmap, lr, lg, lb, la, fr, fg, fb, fa)
1068 invoke("hud-bitmap-binary", {toString(f), toString(x), toString(y), bmap, toString(lr),
1069 toString(lg), toString(lb), toString(la), toString(fr), toString(fg), tostring(fb),
1073 jpcrr.shutdown_emulator = function()
1074 invokesync("shutdown-emulator", {});
1077 jpcrr.set_pccontrol_pos = function(x, y)
1078 invokesync("pccontrol-setwinpos", {toString(x), toString(y)});
1081 jpcrr.set_luaplugin_pos = function(x, y)
1082 invokesync("luaplugin-setwinpos", {toString(x), toString(y)});
1085 jpcrr.set_pcmonitor_pos = function(x, y)
1086 invokesync("pcmonitor-setwinpos", {toString(x), toString(y)});
1089 jpcrr.set_pcstartstoptest_pos = function(x, y)
1090 invokesync("pcstartstoptest-setwinpos", {toString(x), toString(y)});
1093 jpcrr.set_virtualkeyboard_pos = function(x, y)
1094 invokesync("virtualkeyboard-setwinpos", {toString(x), toString(y)});
1097 jpcrr.exit = function()
1098 invokesync("luaplugin-terminate");
1101 jpcrr.pc_start = function()
1105 jpcrr.pc_stop = function()
1106 invokesync("pc-stop");
1109 jpcrr.screenshot = function(include_hud)
1111 invoke("screenshot-renderbuffer");
1113 invoke("screenshot-vgabuffer");
1118 jpcrr.vretrace_start_trap = function(is_on)
1120 invokesync("trap-vretrace-start-on");
1122 invokesync("trap-vretrace-start-off");
1126 jpcrr.vretrace_end_trap = function(is_on)
1128 invokesync("trap-vretrace-end-on");
1130 invokesync("trap-vretrace-end-off");
1134 jpcrr.timed_trap = function(nsecs)
1136 invokesync("trap-timed", {toString(nsecs)});
1138 invokesync("trap-timed-disable");
1142 jpcrr.write_byte = function(addr, value)
1143 invokesync("memory-write", {toString(addr), toString(value), "1"});
1146 jpcrr.write_word = function(addr, value)
1147 invokesync("memory-write", {toString(addr), toString(value), "2"});
1150 jpcrr.write_dword = function(addr, value)
1151 invokesync("memory-write", {toString(addr), toString(value), "4"});
1154 jpcrr.read_byte = function(addr)
1155 local t = {toString(addr), "1"};
1156 t = invokecall("memory-read", t);
1157 return (t or {})[1];
1160 jpcrr.read_word = function(addr)
1161 local t = {toString(addr), "2"};
1162 t = invokecall("memory-read", t);
1163 return (t or {})[1];
1166 jpcrr.read_dword = function(addr)
1167 local t = {toString(addr), "4"};
1168 t = invokecall("memory-read", t);
1169 return (t or {})[1];
1172 jpcrr.read_byte_signed = function(addr)
1173 local t = {toString(addr), "1"};
1174 t = invokecall("memory-read", t);
1175 return bit.tosigned((t or {})[1], 7);
1178 jpcrr.read_word_signed = function(addr)
1179 local t = {toString(addr), "2"};
1180 t = invokecall("memory-read", t);
1181 return bit.tosigned((t or {})[1], 15);
1184 jpcrr.read_dword_signed = function(addr)
1185 local t = {toString(addr), "4"};
1186 t = invokecall("memory-read", t);
1187 return bit.tosigned((t or {})[1], 31);
1191 jpcrr.invoke_synchronous = nil;
1195 dofile = function(_script)
1196 local chunk, err, indication
1197 chunk, err = loadfile(_script);
1199 error("Kernel: Can't load subscript " .. _script .. ": " .. err);
1207 for k, v in pairs(args2) do
1208 if (#k > 2 and string.byte(k, 1) == 120 and string.byte(k, 2) == 45) then
1209 args[string.sub(k, 3)] = v;
1216 loaded, err = pcall(function()
1217 chunk, err = loadfile(script);
1223 print("Kernel: Can't load script " .. script .. ": " .. err);
1224 invoke("luaplugin-terminate");
1229 indication, err = pcall(chunk);
1230 if not indication then
1231 print("Kernel: Unprotected error in script: " .. err);
1232 invoke("luaplugin-terminate");