Add ability to edit game name from UI
[jpcrr.git] / datafiles / luakernel
bloba308d0002345f64b07da937b6bfcb6e45c23a4f4
1 --
2 -- Copyright 2009-2010 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.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
80 --              is no event).
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.vga_edge_count()
86 --              Returns how many times VGA vretrace signal has been seen rising.
87 --      - jpcrr.vga_scroll_count()
88 --              Returns how many times VGA has scrolled.
89 --      - jpcrr.pc_connected()
90 --              Returns true if PC is connected.
91 --      - jpcrr.in_frame_hold()
92 --              Returns true if in frame hold, false otherwise.
93 --      - jpcrr.keypressed(number key)
94 --              Return true if key is pressed, else false.
95 --      - jpcrr.keypressed_edge(number key)
96 --              Return true if key is pressed at input edge, else false.
97 --      - jpcrr.release_vga()
98 --              Allow VGA to exit frame hold mode. Wait for frame hold first.
99 --      - jpcrr.vga_resolution()
100 --              Return VGA x and y resolutions. -1x-1 or 0x0 is returned if no valid resolution.
101 --              Should only be called during frame hold.
102 --      - jpcrr.frame_number()
103 --              Return current VGA frame number or nil if no PC present.
104 --      - jpcrr.shutdown_emulator()
105 --              Shutdown the entiere emulator immediately (graceful shutdown, PCRunner only).
106 --      - jpcrr.hud.left_gap(number flags, number gap)
107 --              Set left gap for HUD. If flags has bit 0 (1) set, draw on screen, if bit
108 --              1 (2) is set, dump to video dump.
109 --      - jpcrr.hud.right_gap(number flags, number gap)
110 --              Set right gap for HUD. If flags has bit 0 (1) set, draw on screen, if bit
111 --              1 (2) is set, dump to video dump.
112 --      - jpcrr.hud.top_gap(number flags, number gap)
113 --              Set top gap for HUD. If flags has bit 0 (1) set, draw on screen, if bit
114 --              1 (2) is set, dump to video dump.
115 --      - jpcrr.hud.bottom_gap(number flags, number gap)
116 --              Set bottom gap for HUD. If flags has bit 0 (1) set, draw on screen, if bit
117 --              1 (2) is set, dump to video dump.
118 --      - jpcrr.hud.white_solid_box(number flags, number x, number y, number w, number h)
119 --              Draw with solid opaque box.
120 --      - jpcrr.hud.box(number flags, number x, number y, number w, number h, number linethick,
121 --                      number lineRed, number lineGreen, number lineBlue, number lineAlpha,
122 --                      number fillRed, number fillGreen, number fillBlue, number fillAlpha)
123 --              Draw box with specified size, border line thickness, line color and fill color.
124 --      - jpcrr.hud.circle(number flags, number x, number y, number r, number linethick,
125 --                      number lineRed, number lineGreen, number lineBlue, number lineAlpha,
126 --                      number fillRed, number fillGreen, number fillBlue, number fillAlpha)
127 --              Draw circle with specified size, border line thickness, line color and fill color.
128 --      - jpcrr.hud.bitmap(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 bitmap with specified foreground color and background color.
132 --      - jpcrr.hud.bitmap_binary(number flags, number x, number y, string bmap,
133 --                      number fgRed, number fgGreen, number fgBlue, number fgAlpha,
134 --                      number bgRed, number bgGreen, number bgBlue, number bgAlpha)
135 --              Draw binary bitmap with specified foreground color and background color.
136 --      - jpcrr.hud.changen(number flags, number x, number y, string text,
137 --                      number fgRed, number fgGreen, number fgBlue, number fgAlpha,
138 --                      number bgRed, number bgGreen, number bgBlue, number bgAlpha,
139 --                      boolean multiline)
140 --              Output string using chargen.
141 --      - jpcrr.events.count()
142 --              Return current event count. Nil if no PC.
143 --      - jpcrr.events.current_sequence()
144 --              Return sequence number of next event (event sequence numbers are 0-based). Nil if
145 --              no PC, -1 if at end of movie.
146 --      - jpcrr.events.by_sequence(number seq)
147 --              Return array for specified event. Nil if no PC, empty array if not valid sequence
148 --              number. Otherwise, first element of array is timestamp (numeric), the second is
149 --              event class and rest are the arguments.
150 --      - jpcrr.joystick_state()
151 --              Returns nil if no joystick. Otherwise returns hold times for all four axis (numeric)
152 --              followed by button states (boolean).
153 --      - jpcrr.keyboard_leds()
154 --              Returns nil if no keyboard, false if LED status is unknown. Otherwise returns three
155 --              booleans, first being state of num lock, second being state of caps lock and third
156 --              being state of scroll lock.
157 --      - jpcrr.mouse_state()
158 --              Returns nil if no mouse. Otherwise returns X, Y and Z axis pending motions (numeric)
159 --              followed by button states (5 booleans).
160 --      - jpcrr.component_encode(table components)
161 --              Return component encoding for specified components.
162 --      - jpcrr.component_decode(string line)
163 --              Return component decoding for specified line, nil/nil if it doesn't encode
164 --              anything, nil/string if parse error occurs (the error is the second return).
165 --      - jpcrr.save_state(string name)
166 --              Savestate into specified file. Returns name used.
167 --      - jpcrr.save_movie(string name)
168 --              Save movie into specified file. Returns name used.
169 --      - jpcrr.load_state_normal(string name)
170 --              Load specified savestate. Returns name used.
171 --      - jpcrr.load_state_preserve_events(string name)
172 --              Load specified savestate, preserving events. Returns name used.
173 --      - jpcrr.load_state_movie(string name)
174 --              Load specified savestate as movie. Returns name used.
175 --      - jpcrr.assemble()
176 --              Open system settings dialog.
177 --      - jpcrr.change_authors()
178 --              Open change authors dialog.
179 --      - jpcrr.exit = function()
180 --              Exit the Lua VM.
181 --      - jpcrr.ram_dump(string name, boolean binary)
182 --              Dump PC memory to specified file. If binary is true, dump is binary, otherwise
183 --              textual hexadecimal dump.
184 --      - jpcrr.write_byte(number addr, number value)
185 --              Write byte to specified physical address.
186 --      - jpcrr.write_word(number addr, number value)
187 --              Write word to specified physical address (little endian).
188 --      - jpcrr.write_dword(number addr, number value)
189 --              Write dword to specified physical address (little endian).
190 --      - jpcrr.read_byte(number addr)
191 --              Return byte from specified physical address.
192 --      - jpcrr.read_word(number addr)
193 --              Return word from specified physical address (little endian).
194 --      - jpcrr.read_dword(number addr)
195 --              Return dword from specified physical address (little endian).
196 --      - jpcrr.read_byte_signed(number addr)
197 --              Return signed byte from specified physical address.
198 --      - jpcrr.read_word_signed(number addr)
199 --              Return signed word from specified physical address (little endian).
200 --      - jpcrr.read_dword_signed(number addr)
201 --              Return signed dword from specified physical address (little endian).
202 --      - jpcrr.timed_trap(number nsecs)
203 --              Set trap after specified number of nanoseconds. Use nil as nsecs to disable.
204 --      - jpcrr.vretrace_start_trap(boolean is_on)
205 --              Set trap on vretrace start on/off.
206 --      - jpcrr.vretrace_end_trap(boolean is_on)
207 --              Set trap on vretrace end on/off.
208 --      - jpcrr.bios_kbd_trap(boolean is_on)
209 --              Set trap on BIOS kbd on/off.
210 --      - jpcrr.pc_start()
211 --              Start PC execution.
212 --      - jpcrr.pc_stop()
213 --              Stop PC execution.
214 --      - jpcrr.set_pccontrol_pos(number x, number y)
215 --              Set position of PCControl window.
216 --      - jpcrr.set_luaplugin_pos(number x, number y)
217 --              Set position of LuaPlugin window.
218 --      - jpcrr.set_pcmonitor_pos(number x, number y)
219 --              Set position of PCMonitor window.
220 --      - jpcrr.set_pcstartstoptest_pos(number x, number y)
221 --              Set position of PCStartStopTest window.
222 --      - jpcrr.set_virtualkeyboard_pos(number x, number y)
223 --              Set position of VirtualKeyboard window.
224 --      - jpcrr.stringlessthan(String x, String y)
225 --              Return true if x is before y in codepoint lexical order, otherwise false.
226 --      - jpcrr.screenshot(boolean include_hud)
227 --              Take screen shot (Requires monitor). If include_hud is true, include HUD
228 --              (as shown on screen). Note that this should only be called during frame
229 --              hold or results are pretty much undefined.
230 --      - jpcrr.sendevent(string class, string/number...)
231 --              Sends specified event.
232 --      - jpcrr.sendevent_lowbound(number lowbound, string class, string/number...)
233 --              Sends specified event with specified time low bound.
234 --      - jpcrr.movie_rerecords()
235 --              Return number of rerecords (nil if no movie loaded).
236 --      - jpcrr.movie_length()
237 --              Return length of movie in ns (nil if no movie loaded).
238 --      - jpcrr.movie_headers()
239 --              Return headers of movie as array of arrays (nil if no movie loaded).
240 --      - jpcrr.register_redraw_function(function)
241 --              This function is called every time screen is redrawn. It is called with
242 --              VGA lock held and that lock is automatically released after call. If this
243 --              function has been registered, no lock events will be generated.
244 --      - jpcrr.register_message_function(function)
245 --              This function is called with message as parameter every time message is
246 --              received. Suppresses message events.
247 --      - jpcrr.register_attach_function(function)
248 --              This function is called every time attach is
249 --              received. Suppresses attach events.
250 --      - jpcrr.register_stop_function(function)
251 --              This function is called every time stop is
252 --              received. Suppresses stop events.
253 --      - jpcrr.register_uiaction_function(function)
254 --              This function is called with widget name as parameter every time
255 --              UI action event is received. Suppresses ui action events.
256 --      - jpcrr.stop_and_execute(function)
257 --              Stop PC execution and call specified function after PC has stopped
258 --              fully. Note that only handler functions receive events until this
259 --              returns.
261 --      I/O functions have the following conventions. If function returns any real data, the first
262 --      return value returns this data or is nil. Otherwise first return value is true or false.
263 --      If first return value is nil or false, then the second return value gives textual error
264 --      message for failed operation, or is nil if EOF occured before anything was read.
266 --      Unlink, rename and mkdir don't follow this pattern. They just return true/false to signal
267 --      success or failure.
269 --      Specifying nil as name of file results random filename being used (it even works with unlink,
270 --      mkdir, rename and read-only access, but doesn't make any sense there).
272 --      Specifying empty filename prompts for file (doesn't work with mkdir, rename nor unlink). Use
273 --      '/<title>' to specify title for prompt dialog.
275 --      Class: BinaryFile:
276 --              Binary file for RO or RW access. Methods are as follows:
277 --              - name()
278 --                      Return name of file.
279 --              - length()
280 --                      Return length of file.
281 --              - set_length(number length)
282 --                      Truncate file to specified length
283 --              - read(number offset, number length)
284 --                      Read up to length bytes from offset.
285 --              - write(number offset, string content)
286 --                      Write content to specified offset.
287 --              - close()
288 --                      Close the file.
289 --      Class: BinaryInput:
290 --              Binary file for sequential input. Methods are as follows:
291 --              - name()
292 --                      Return name of file.
293 --              - four_to_five()
294 --                      Return BinaryInput that is four to five decoding of this stream.
295 --              - text()
296 --                      Return stream as TextInput.
297 --              - inflate()
298 --                      Return BinaryInput that is inflate of this stream.
299 --              - read(number bytes)
300 --                      Read up to bytes bytes from file.
301 --              - read()
302 --                      Read the entiere file at once.
303 --              - close()
304 --                      Close the file.
305 --              Character set for binary files is Latin-1.
307 --      Class: BinaryOutput:
308 --              Binary file for sequential output. Methods are as follows:
309 --              - name()
310 --                      Return name of file.
311 --              - four_to_five()
312 --                      Return BinaryOutput that writes four to five encoded output to this stream.
313 --              - text()
314 --                      Return stream as TextOutput.
315 --              - deflate()
316 --                      Return BinaryOutput that writes deflate output to this stream.
317 --              - write(string content)
318 --                      Write string to file.
319 --              - close()
320 --                      Close the file.
321 --              Character set for binary files is Latin-1.
323 --      Class: TextInput:
324 --              - name()
325 --                      Return name of file.
326 --              - read()
327 --                      Read line from file.
328 --              - read_component()
329 --                      Read next componented line into array.
330 --              - lines()
331 --                      Line iterator function.
332 --              - close()
333 --                      Close the file.
334 --      Character set for text files is UTF-8.
336 --      Class: TextOutput:
337 --              - name()
338 --                      Return name of file.
339 --              - write(string line)
340 --                      Write line line to file.
341 --              - write_component(table components)
342 --                      Write componented line.
343 --              - close()
344 --                      Close the file.
345 --              Character set for text files is UTF-8.
347 --      Class ArchiveIn:
348 --              - member(string name)
349 --                      Open substream for member name. The methods are the same as for io.opentextin.
350 --              - member_binary(string name)
351 --                      Open binary (four to five) substream for member name. The methods are the same as
352 --                      for io.openbinaryin.
353 --              - close()
354 --                      Close the file. Any opened substreams are invalidated.
355 --              - member_list()
356 --                      Return table listing all members of archive (sorted by name).
357 --      Class ArchiveOut:
358 --              - member(string name)
359 --                      Open substream for member name. The methods are the same as for io.opentextout. Note that
360 --                      previous member must be closed before next can open.
361 --              - member_binary(string name)
362 --                      Open binary (four to five) substream for member name. The methods are the same as
363 --                      for io.openbinaryout. Note that previous substream must be closed before next can open.
364 --              - commit()
365 --                      Commit the file. No substream may be open. Closes the file.
366 --              - rollback()
367 --                      Rollback the file. No substream may be open. Closes the file.
369 --      - io.open(string name, string mode) -> BinaryFile
370 --              Open file named @name in specified mode. The mode can be 'r' (read only) or 'rw' (read and
371 --              write).
372 --      - io.open_read(string name) -> BinaryInput
373 --              Open file named @name as binary input stream.
374 --      - io.open_write(string name) -> BinaryOutput
375 --              Open file named @name as binary input stream.
376 --      - io.open_arch_read(string name) -> ArchiveIn
377 --              Open file named @name as input archive.
378 --      - io.open_arch_write(string name) -> ArchiveOut
379 --              Open file named @name as output archive.
380 --      - io.mkdir(string name)
381 --              Create directory name. Returns name created on success, nil on failure.
382 --      - io.unlink(string name)
383 --              Delete file/directory name. Returns name deleted on success, nil on failure.
384 --      - io.rename(string old, string new)
385 --              Rename file old -> new. Returns old, new on success, nil on failure.
386 --      - io.transform.text()
387 --              Returns function that calls text() method of its parameter.
388 --      - io.transform.four_to_five()
389 --              Returns function that calls four_to_five() method of its parameter.
390 --      - io.transform.deflate()
391 --              Returns function that calls deflate() method of its parameter.
392 --      - io.transform.inflate()
393 --              Returns function that calls inflate() method of its parameter.
394 --      - io.dotransform(object obj, function...)
395 --              Call specified functions on specified object. If any function fails (first argument nil
396 --              or false), call close method on preceeding object. Otherwise call specified functions
397 --              chained left to right and return the result.
398 --      - io.dotransform2(object obj, string err, function...)
399 --              Similar to dotransform except if obj is nil or false, returns obj, err.
402 local stopping = false;
403 local mesage_function = nil;
404 local lock_function = nil;
405 local uiaction_function = nil;
406 local stop_function = nil;
407 local attach_function = nil;
409 local handle, err, chunk, indication, k, v;
411 local loadmod = loadmodule;
412 loadmodule = nil;
414 local export_module_in = function(tab, modname, prefix)
415         local fun = loadmod(modname);
416         for k, v in pairs(fun) do
417                 tab[(prefix or "") .. k] = v;
418         end
421 jpcrr = {};
422 jpcrr.hud = {};
423 jpcrr.events = {};
424 jpcrr.window = {};
425 jpcrr.memorysearch = {};
426 bit = {};
427 io = {};
428 local HUD = {};
430 export_module_in(jpcrr, "org.jpc.luaextensions.Base");
431 export_module_in(jpcrr, "org.jpc.luaextensions.InputDevices");
432 export_module_in(jpcrr, "org.jpc.luaextensions.ComponentCoding", "component_");
433 export_module_in(jpcrr.events, "org.jpc.luaextensions.Events");
434 export_module_in(jpcrr.window, "org.jpc.luaextensions.Window");
435 export_module_in(bit, "org.jpc.luaextensions.Bitops");
436 export_module_in(jpcrr.memorysearch, "org.jpc.luaextensions.MemorySearch");
437 export_module_in(HUD, "org.jpc.luaextensions.HUD");
439 -- HUD bindings.
440 local HUD = HUD.HUD;
441 jpcrr.HUD = HUD;
443 -- Few misc functions.
444 assert = function(val, err)
445         if (not val) and err then
446                 error(err);
447         end
448         return val;
451 modulus_split = function(number, ...)
452         local dividers = {...};
453         local results = {};
454         local rem;
456         for k, v in ipairs(dividers) do
457                 rem = number % v;
458                 table.insert(results, (number - rem) / v);
459                 number = rem;
460         end
462         table.insert(results, number);
463         return unpack(results);
466 jpcrr.register_redraw_function = function(f)
467         if f and type(f) ~= "function" then
468                 error("Incorrect type of argument to register_redraw_function");
469         end
470         lock_function = f;
473 jpcrr.register_message_function = function(f)
474         if f and type(f) ~= "function" then
475                 error("Incorrect type of argument to register_message_function");
476         end
477         message_function = f;
480 jpcrr.register_stop_function = function(f)
481         if f and type(f) ~= "function" then
482                 error("Incorrect type of argument to register_stop_function");
483         end
484         stop_function = f;
487 jpcrr.register_attach_function = function(f)
488         if f and type(f) ~= "function" then
489                 error("Incorrect type of argument to register_attach_function");
490         end
491         attach_function = f;
494 jpcrr.register_uiaction_function = function(f)
495         if f and type(f) ~= "function" then
496                 error("Incorrect type of argument to register_uiaction_function");
497         end
498         uiaction_function = f;
503 local getmtable = getmetatable;
504 local toString = tostring;
505 local inject_binary_file;
506 local inject_binary_input;
507 local inject_binary_output;
508 local inject_text_input;
509 local inject_text_output;
510 local inject_archive_input;
511 local inject_archive_output;
513 -- Class member injectors.
514 inject_binary_file = function(obj, name)
515         local _name = name;
516         getmtable(obj).name = function(obj)
517                 return _name;
518         end
519         getmtable(obj).__index = function(tab, name)
520                 local x = getmtable(obj)[name];
521                 if x then
522                         return x;
523                 end
524                 error("Invalid method " .. name .. " for BinaryFile");
525         end
526         return obj;
529 inject_binary_input = function(obj, underlying, name)
530         local _name = name;
531         local old_four_to_five = getmtable(obj).four_to_five;
532         local old_inflate = getmtable(obj).inflate;
533         local old_text = getmtable(obj).text;
534         local old_read = getmtable(obj).read;
535         local old_close = getmtable(obj).close;
536         local underlying_object = underlying;
538         getmtable(obj).name = function(obj)
539                 return _name;
540         end
541         getmtable(obj).four_to_five = function(obj)
542                 local res, err;
543                 res, err = old_four_to_five(obj);
544                 if not res then
545                         return res, err;
546                 end
547                 return inject_binary_input(res, obj, "four-to-five<" .. _name .. ">");
548         end
549         getmtable(obj).inflate = function(obj)
550                 local res, err;
551                 res, err = old_inflate(obj);
552                 if not res then
553                         return res, err;
554                 end
555                 return inject_binary_input(res, obj, "inflate<" .. _name .. ">");
556         end
557         getmtable(obj).text = function(obj)
558                 local res, err;
559                 res, err = old_text(obj);
560                 if not res then
561                         return res, err;
562                 end
563                 return inject_text_input(res, obj, "text<" .. _name .. ">");
564         end
565         getmtable(obj).read = function(obj, toread)
566                 if toread then
567                         return old_read(obj, toread);
568                 else
569                         local res = "";
570                         local ret, err;
571                         while true do
572                                 ret, err = old_read(obj, 16384);
573                                 if not ret then
574                                         if not err then
575                                                 return res;
576                                         end
577                                         return nil, err;
578                                 end
579                                 res = res .. ret;
580                         end
581                 end
582         end
583         getmtable(obj).close = function(obj)
584                 local ret, err, ret2, err2;
585                 ret, err = old_close(obj);
586                 if underlying_object then ret2, err2 = underlying_object:close(); end
587                 if ret and not ret2 then
588                         err = err2;
589                         ret = ret2;
590                 end
591                 return ret, err;
592         end
593         getmtable(obj).__index = function(tab, name)
594                 local x = getmtable(obj)[name];
595                 if x then
596                         return x;
597                 end
598                 error("Invalid method " .. name .. " for BinaryInput");
599         end
600         return obj;
603 inject_binary_output = function(obj, underlying, name)
604         local _name = name;
605         local old_four_to_five = getmtable(obj).four_to_five;
606         local old_deflate = getmtable(obj).deflate;
607         local old_text = getmtable(obj).text;
608         local old_close = getmtable(obj).close;
609         local underlying_object = underlying;
611         getmtable(obj).name = function(obj)
612                 return _name;
613         end
614         getmtable(obj).four_to_five = function(obj)
615                 local res, err;
616                 res, err = old_four_to_five(obj);
617                 if not res then
618                         return res, err;
619                 end
620                 return inject_binary_output(res, obj, "four-to-five<" .. _name .. ">");
621         end
622         getmtable(obj).deflate = function(obj)
623                 local res, err;
624                 res, err = old_deflate(obj);
625                 if not res then
626                         return res, err;
627                 end
628                 return inject_binary_output(res, obj, "deflate<" .. _name .. ">");
629         end
630         getmtable(obj).text = function(obj)
631                 local res, err;
632                 res, err = old_text(obj);
633                 if not res then
634                         return res, err;
635                 end
636                 return inject_text_output(res, obj, "text<" .. _name .. ">");
637         end
638         getmtable(obj).close = function(obj)
639                 local ret, err, ret2, err2;
640                 ret, err = old_close(obj);
641                 if underlying_object then ret2, err2 = underlying_object:close(); end
642                 if ret and not ret2 then
643                         err = err2;
644                         ret = ret2;
645                 end
646                 return ret, err;
647         end
648         getmtable(obj).__index = function(tab, name)
649                 local x = getmtable(obj)[name];
650                 if x then
651                         return x;
652                 end
653                 error("Invalid method " .. name .. " for BinaryOutput");
654         end
655         return obj;
658 inject_text_input = function(obj, underlying, name)
659         local _name = name;
660         local old_close = getmtable(obj).close;
661         local underlying_object = underlying;
663         getmtable(obj).lines = function(obj)
664                 return function(state, prevline)
665                         return state:read();
666                 end, obj, nil;
667         end
668         getmtable(obj).name = function(obj)
669                 return _name;
670         end
671         getmtable(obj).close = function(obj)
672                 local ret, err, ret2, err2;
673                 ret, err = old_close(obj);
674                 if underlying_object then ret2, err2 = underlying_object:close(); end
675                 if ret and not ret2 then
676                         err = err2;
677                         ret = ret2;
678                 end
679                 return ret, err;
680         end
681         getmtable(obj).__index = function(tab, name)
682                 local x = getmtable(obj)[name];
683                 if x then
684                         return x;
685                 end
686                 error("Invalid method " .. name .. " for TextInput");
687         end
688         return obj;
691 inject_text_output = function(obj, underlying, name)
692         local _name = name;
693         local old_close = getmtable(obj).close;
694         local underlying_object = underlying;
696         getmtable(obj).name = function(obj)
697                 return _name;
698         end
699         getmtable(obj).close = function(obj)
700                 local ret, err, ret2, err2;
701                 ret, err = old_close(obj);
702                 if underlying_object then ret2, err2 = underlying_object:close(); end
703                 if ret and underlying_object then
704                         err = err2;
705                         ret = ret2;
706                 end
707                 return ret, err;
708         end
709         getmtable(obj).__index = function(tab, name)
710                 local x = getmtable(obj)[name];
711                 if x then
712                         return x;
713                 end
714                 error("Invalid method " .. name .. " for TextOutput");
715         end
716         return obj;
719 inject_archive_input = function(obj, name)
720         local _name = name;
721         local old_member = getmtable(obj).member;
722         local old_member_list = getmtable(obj).member_list;
723         getmtable(obj).member = function(obj, member)
724                 local res, err;
725                 res, err = old_member(obj, member);
726                 if not res then
727                         return res, err;
728                 end
729                 return inject_binary_input(res, nil, _name .. "[" .. member .. "]");
730         end
731         getmtable(obj).name = function(obj)
732                 return _name;
733         end
734         getmtable(obj).member_list = function(obj)
735                 local tab = old_member_list(obj);
736                 if tab then table.sort(tab, jpcrr.stringlessthan); end
737                 return tab;
738         end
739         getmtable(obj).__index = function(tab, name)
740                 local x = getmtable(obj)[name];
741                 if x then
742                         return x;
743                 end
744                 error("Invalid method " .. name .. " for ArchiveInput");
745         end
746         return obj;
749 inject_archive_output = function(obj, name)
750         local _name = name;
751         local old_member = getmtable(obj).member;
752         getmtable(obj).member = function(obj, member)
753                 local res, err;
754                 res, err = old_member(obj, member);
755                 if not res then
756                         return res, err;
757                 end
758                 return inject_binary_output(res, nil, _name .. "[" .. member .. "]");
759         end
760         getmtable(obj).name = function(obj)
761                 return _name;
762         end
763         getmtable(obj).__index = function(tab, name)
764                 local x = getmtable(obj)[name];
765                 if x then
766                         return x;
767                 end
768                 error("Invalid method " .. name .. " for ArchiveOutput");
769         end
770         return obj;
774 -- Redefined routines.
776         local rprint = print_console_msg;
777         print_console_msg = nil;
778         print = function(...)
779                 local x = "";
780                 local y = {...};
781                 local i;
782                 for i = 1,#y do
783                         if i > 1 then
784                                 x = x .. "\t" .. toString(y[i]);
785                         else
786                                 x = toString(y[i]);
787                         end
788                 end
789                 rprint(x);
790         end
791         print_console_msg = nil;
796 -- I/O routines.
797 local stringfind = string.find;
798 local randname = loadmod("org.jpc.luaextensions.DelayedDelete").random_temp_name;
799 local selectname = loadmod("org.jpc.luaextensions.BaseFSOps").opensave_dialog;
800 local path = args["luapath"] or ".";
801 local toresourcename = function(resname, save, text)
802         if not resname then
803                 return randname(path .. "/", "luatemp-");
804         end
806         if resname == "" and text then
807                 local a, b;
808                 a, b = selectname(save, text);
809                 return a, (a or b);
810         end
812         if stringfind(resname, "^/") then
813                 if not text then
814                         error("Bad resource name (case 2): " .. resname);
815                 end
816                 local a, b;
817                 a, b = selectname(save, string.sub(resname, 2));
818                 return a, (a or b);
819         end
821         if not stringfind(resname, "[%d%l%u_%-]") then
822                 error("Bad resource name (case 1): " .. resname);
823         end
824         if stringfind(resname, "%.%.") then
825                 error("Bad resource name (case 3): " .. resname);
826         end
827         if stringfind(resname, "\\") then
828                 error("Bad resource name (case 4): " .. resname);
829         end
831         return resname, path .. "/" .. resname;
836         local openbinin = loadmod("org.jpc.luaextensions.BinaryInFile").open;
837         local openbinout = loadmod("org.jpc.luaextensions.BinaryOutFile").open;
838         local openarchin = loadmod("org.jpc.luaextensions.ArchiveIn").open;
839         local openarchout = loadmod("org.jpc.luaextensions.ArchiveOut").open;
840         local openbinary = loadmod("org.jpc.luaextensions.BinaryFile").open;
842         local baseFS = loadmod("org.jpc.luaextensions.BaseFSOps");
843         local mkdir = baseFS.mkdir;
844         local unlink = baseFS.unlink;
845         local rename = baseFS.rename;
847         local getmtable = getmetatable;
849         loadfile = function(_script)
850                 local file, file2, err, content;
851                 local x, y;
852                 x, y = toresourcename(_script, false, "Select script to load");
853                 if not x then return x, y; end
854                 file, err = openbinin(y, "r");
855                 if not file then
856                         return nil, "Can't open " .. _script .. ": " .. err;
857                 end
858                 file2, err = file:text();
859                 if not file2 then
860                         return nil, "Can't transform " .. _script .. ": " .. err;
861                 end
862                 content = "";
863                 line = file2:read();
864                 while line do
865                         content = content .. line .. "\n";
866                         line = file2:read();
867                 end
868                 file2:close();
869                 file:close();
870                 return loadstring(content, _script);
871         end
873         io.open = function(name, mode)
874                 local _name;
875                 local res, err;
876                 local y;
877                 if mode == "r" then
878                         _name, y = toresourcename(name, false, "Select file to read");
879                 else
880                         _name, y = toresourcename(name, true, "Select file to write");
881                 end
882                 if not _name then return _name, y; end
883                 res, err = openbinary(y, mode);
884                 if not res then
885                         return res, err;
886                 end
887                 return inject_binary_file(res, _name);
888         end
890         io.open_arch_read = function(name)
891                 local _name = name;
892                 local res, err;
893                 local y;
894                 _name, y = toresourcename(name, false, "Select archive to read");
895                 if not _name then return _name, y; end
896                 res, err = openarchin(y);
897                 if not res then
898                         return res, err;
899                 end
900                 return inject_archive_input(res, _name);
901         end
903         io.open_arch_write = function(name)
904                 local _name = name;
905                 local res, err;
906                 local y;
907                 _name, y = toresourcename(name, true, "Select archive to write");
908                 if not _name then return _name, y; end
909                 res, err = openarchout(y);
910                 if not res then
911                         return res, err;
912                 end
913                 return inject_archive_output(res, _name);
914         end
916         io.open_read = function(name)
917                 local _name = name;
918                 local res, err;
919                 local y;
920                 _name, y = toresourcename(name, false, "Select file to read");
921                 if not _name then return _name, y; end
922                 res, err = openbinin(y);
923                 if not res then
924                         return res, err;
925                 end
926                 return inject_binary_input(res, nil, _name);
927         end
929         io.open_write = function(name)
930                 local _name = name;
931                 local res, err;
932                 local y;
933                 _name, y = toresourcename(name, true, "Select file to write");
934                 if not _name then return _name, y; end
935                 res, err = openbinout(y);
936                 if not res then
937                         return res, err;
938                 end
939                 return inject_binary_output(res, nil, _name);
940         end
942         io.mkdir = function(name)
943                 local _name, y;
944                 _name, y = toresourcename(name);
945                 if mkdir(y) then
946                         return _name;
947                 else
948                         return nil;
949                 end
950         end
952         io.unlink = function(name)
953                 local _name, y;
954                 _name, y = toresourcename(name);
955                 if unlink(y) then
956                         return _name;
957                 else
958                         return nil;
959                 end
960         end
962         io.rename = function(name1, name2)
963                 local _name, y;
964                 local _name2, y2;
965                 _name, y = toresourcename(name1);
966                 _name2, y2 = toresourcename(name2);
967                 if rename(y, y2) then
968                         return _name, _name2;
969                 else
970                         return nil;
971                 end
972         end
974         io.transform = {};
976         io.transform.text = function()
977                 return function(obj)
978                         return obj:text();
979                 end
980         end
982         io.transform.four_to_five = function()
983                 return function(obj)
984                         return obj:four_to_five();
985                 end
986         end
988         io.transform.inflate = function()
989                 return function(obj)
990                         return obj:inflate();
991                 end
992         end
994         io.transform.deflate = function()
995                 return function(obj)
996                         return obj:deflate();
997                 end
998         end
1000         io.dotransform = function(obj, ...)
1001                 local todo = {...};
1002                 local k, v;
1003                 local obj2, err;
1004                 for k, v in ipairs(todo) do
1005                         obj2, err = v(obj);
1006                         if not obj2 then
1007                                 obj:close();
1008                                 return nil, err;
1009                         end
1010                         obj = obj2;
1011                 end
1012                 return obj;
1013         end
1015         io.dotransform2 = function(obj, err, ...)
1016                 if not obj then
1017                         return obj, err;
1018                 end
1019                 return io.dotransform(obj, err, ...);
1020         end
1024 -- Various stuff built on top of ECI.
1025 local invoke = jpcrr.invoke;
1026 local invokecall = jpcrr.call;
1027 local invokesync = jpcrr.invoke_synchronous;
1029 jpcrr.sendevent = function(...)
1030         local arguments = {...};
1031         local k, v;
1032         for k, v in ipairs(arguments) do
1033                 arguments[k] = toString(v);
1034         end
1035         invokesync("sendevent", arguments);
1038 jpcrr.sendevent_lowbound = function(...)
1039         local arguments = {...};
1040         local k, v;
1041         for k, v in ipairs(arguments) do
1042                 arguments[k] = toString(v);
1043         end
1044         invokesync("sendevent-lowbound", arguments);
1047 jpcrr.save_state = function(name)
1048         local _name, _fname;
1049         _name, _fname = toresourcename(name, true, "File to savestate to");
1050         invokesync("state-save", {_fname});
1051         return _name;
1054 jpcrr.save_movie = function(name)
1055         local _name, _fname;
1056         _name, _fname = toresourcename(name, true, "File to save movie to");
1057         invokesync("movie-save", {_fname});
1058         return _name;
1061 jpcrr.load_state_normal = function(name)
1062         local _name, _fname;
1063         _name, _fname = toresourcename(name, false, "File to loadstate from");
1064         invokesync("state-load", {_fname});
1065         return _name;
1068 jpcrr.load_state_preserve_events = function(name)
1069         local _name, _fname;
1070         _name, _fname = toresourcename(name, false, "File to loadstate (preserve events) from");
1071         invokesync("state-load-noevents", {_fname});
1072         return _name;
1075 jpcrr.load_state_movie = function(name)
1076         local _name, _fname;
1077         _name, _fname = toresourcename(name, false, "File to load movie from");
1078         invokesync("movie-load", {_fname});
1079         return _name;
1082 jpcrr.assemble = function()
1083         invokesync("pc-assemble");
1086 jpcrr.change_authors = function()
1087         invokesync("change-authors");
1090 jpcrr.ram_dump = function(name, binary)
1091         local _name, _fname;
1092         _name, _fname = toresourcename(name, true, "Select file to ramdump to");
1093         if binary then
1094                 invokesync("ram-dump-binary", {_fname});
1095         else
1096                 invokesync("ram-dump-text", {_fname});
1097         end
1098         return _name;
1101 local poll_event = jpcrr.poll_event;
1102 local _print = print;
1103 local _unlock = jpcrr.release_vga;
1104 jpcrr.poll_event = function()
1105         local a, b;
1106         local failed = false;
1107         while not failed do
1108                 a, b = poll_event();
1109                 if not a then
1110                         failed = true;
1111                 end
1112                 if a and a == "message" and message_function then
1113                         a, b = pcall(message_function, b);
1114                         if not a then
1115                                 _print("Error running message callback: " .. b);
1116                         end
1117                         a = nil;
1118                 end
1119                 if a and a == "uiaction" and uiaction_function then
1120                         a, b = pcall(uiaction_function, b);
1121                         if not a then
1122                                 _print("Error running uiaction callback: " .. b);
1123                         end
1124                         a = nil;
1125                 end
1126                 if a and a == "stop" and stop_function then
1127                         a, b = pcall(stop_function);
1128                         if not a then
1129                                 _print("Error running stop callback: " .. b);
1130                         end
1131                         a = nil;
1132                 end
1133                 if a and a == "attach" and attach_function then
1134                         a, b = pcall(attach_function);
1135                         if not a then
1136                                 _print("Error running attach callback: " .. b);
1137                         end
1138                         a = nil;
1139                 end
1140                 if a and a == "lock" and lock_function then
1141                         a, b = pcall(lock_function);
1142                         _unlock();
1143                         if not a then
1144                                 _print("Error running redraw callback: " .. b);
1145                         end
1146                         if stoppping then
1147                                 return "lock";
1148                         end
1149                         a = nil;
1150                 end
1151                 if a and a == "lock" and stopping then
1152                         _unlock();
1153                         return "lock";
1154                 end
1155         end
1156         return a, b;
1160 local wait_event = jpcrr.wait_event;
1161 local _print = print;
1162 local _unlock = jpcrr.release_vga;
1163 jpcrr.wait_event = function()
1164         local a, b;
1165         while not a do
1166                 a, b = wait_event();
1167                 if a and a == "message" and message_function then
1168                         a, b = pcall(message_function, b);
1169                         if not a then
1170                                 _print("Error running message callback: " .. b);
1171                         end
1172                         a = nil;
1173                 end
1174                 if a and a == "uiaction" and uiaction_function then
1175                         a, b = pcall(uiaction_function, b);
1176                         if not a then
1177                                 _print("Error running uiaction callback: " .. b);
1178                         end
1179                         a = nil;
1180                 end
1181                 if a and a == "stop" and stop_function then
1182                         a, b = pcall(stop_function);
1183                         if not a then
1184                                 _print("Error running stop callback: " .. b);
1185                         end
1186                         a = nil;
1187                 end
1188                 if a and a == "attach" and attach_function then
1189                         a, b = pcall(attach_function);
1190                         if not a then
1191                                 _print("Error running attach callback: " .. b);
1192                         end
1193                         a = nil;
1194                 end
1195                 if a and a == "lock" and lock_function then
1196                         a, b = pcall(lock_function);
1197                         _unlock();
1198                         if not a then
1199                                 _print("Error running redraw callback: " .. b);
1200                         end
1201                         if stopping then
1202                                 return a, b;
1203                         end
1204                         a = nil;
1205                 end
1206         end
1207         return a, b;
1211 jpcrr.hud.left_gap = function(f, g)
1212         HUD("left_gap", f, g);
1215 jpcrr.hud.right_gap = function(f, g)
1216         HUD("right_gap", f, g);
1219 jpcrr.hud.top_gap = function(f, g)
1220         HUD("top_gap", f, g);
1223 jpcrr.hud.bottom_gap = function(f, g)
1224         HUD("bottom_gap", f, g);
1227 jpcrr.hud.white_solid_box = function(f, x, y, w, h)
1228         HUD("hud_white_solid_box", f, x, y, w, h);
1231 jpcrr.hud.box = function(f, x, y, w, h, t, lr, lg, lb, la, fr, fg, fb, fa)
1232         la = la or 255;
1233         fr = fr or 0;
1234         fg = fg or 0;
1235         fb = fb or 0;
1236         fa = fa or 0;
1237         HUD("box", f, x, y, w, h, t, lr, lg, lb, la, fr, fg, fb, fa);
1240 jpcrr.hud.circle = function(f, x, y, r, t, lr, lg, lb, la, fr, fg, fb, fa)
1241         la = la or 255;
1242         fr = fr or 0;
1243         fg = fg or 0;
1244         fb = fb or 0;
1245         fa = fa or 0;
1246         HUD("circle", f, x, y, r, t, lr, lg, lb, la, fr, fg, fb, fa)
1249 jpcrr.hud.bitmap = function(f, x, y, bmap, lr, lg, lb, la, fr, fg, fb, fa)
1250         la = la or 255;
1251         fr = fr or 0;
1252         fg = fg or 0;
1253         fb = fb or 0;
1254         fa = fa or 0;
1255         HUD("bitmap", f, x, y, bmap, lr, lg, lb, la, fr, fg, fb, fa)
1258 jpcrr.hud.bitmap_binary = function(f, x, y, bmap, lr, lg, lb, la, fr, fg, fb, fa)
1259         la = la or 255;
1260         fr = fr or 0;
1261         fg = fg or 0;
1262         fb = fb or 0;
1263         fa = fa or 0;
1264         HUD("bitmap_binary", f, x, y, bmap, lr, lg, lb, la, fr, fg, fb, fa)
1267 jpcrr.hud.chargen = function(f, x, y, text, multiline, lr, lg, lb, la, fr, fg, fb, fa)
1268         la = la or 255;
1269         fr = fr or 0;
1270         fg = fg or 0;
1271         fb = fb or 0;
1272         fa = fa or 0;
1273         HUD("vga_chargen", f, x, y, text, lr, lg, lb, la, fr, fg, fb, fa, multiline)
1276 jpcrr.shutdown_emulator = function()
1277         invokesync("shutdown-emulator", {});
1280 jpcrr.set_pccontrol_pos = function(x, y)
1281         invokesync("pccontrol-setwinpos", {toString(x), toString(y)});
1284 jpcrr.set_luaplugin_pos = function(x, y)
1285         invokesync("luaplugin-setwinpos", {toString(x), toString(y)});
1288 jpcrr.set_pcmonitor_pos = function(x, y)
1289         invokesync("pcmonitor-setwinpos", {toString(x), toString(y)});
1292 jpcrr.set_pcstartstoptest_pos = function(x, y)
1293         invokesync("pcstartstoptest-setwinpos", {toString(x), toString(y)});
1296 jpcrr.set_virtualkeyboard_pos = function(x, y)
1297         invokesync("virtualkeyboard-setwinpos", {toString(x), toString(y)});
1300 jpcrr.exit = function()
1301         invokesync("luaplugin-terminate");
1304 jpcrr.pc_start = function()
1305         invoke("pc-start");
1308 jpcrr.pc_stop = function()
1309         invokesync("pc-stop");
1312 jpcrr.screenshot = function(include_hud)
1313         if include_hud then
1314                 invoke("screenshot-renderbuffer");
1315         else
1316                 invoke("screenshot-vgabuffer");
1317         end
1320 jpcrr.bios_kbd_trap = function(is_on)
1321         if is_on then
1322                 invokesync("trap-bios-kbd-on");
1323         else
1324                 invokesync("trap-bios-kbd-off");
1325         end
1328 jpcrr.vretrace_start_trap = function(is_on)
1329         if is_on then
1330                 invokesync("trap-vretrace-start-on");
1331         else
1332                 invokesync("trap-vretrace-start-off");
1333         end
1336 jpcrr.vretrace_end_trap = function(is_on)
1337         if is_on then
1338                 invokesync("trap-vretrace-end-on");
1339         else
1340                 invokesync("trap-vretrace-end-off");
1341         end
1344 jpcrr.timed_trap = function(nsecs)
1345         if nsecs then
1346                 invokesync("trap-timed", {toString(nsecs)});
1347         else
1348                 invokesync("trap-timed-disable");
1349         end
1352 jpcrr.write_byte = function(addr, value)
1353         invokesync("memory-write", {toString(addr), toString(value), "1"});
1356 jpcrr.write_word = function(addr, value)
1357         invokesync("memory-write", {toString(addr), toString(value), "2"});
1360 jpcrr.write_dword = function(addr, value)
1361         invokesync("memory-write", {toString(addr), toString(value), "4"});
1364 jpcrr.read_byte = function(addr)
1365         local t = {toString(addr), "1"};
1366         t = invokecall("memory-read", t);
1367         return (t or {})[1];
1370 jpcrr.read_word = function(addr)
1371         local t = {toString(addr), "2"};
1372         t = invokecall("memory-read", t);
1373         return (t or {})[1];
1376 jpcrr.read_dword = function(addr)
1377         local t = {toString(addr), "4"};
1378         t = invokecall("memory-read", t);
1379         return (t or {})[1];
1382 jpcrr.read_byte_signed = function(addr)
1383         local t = {toString(addr), "1"};
1384         t = invokecall("memory-read", t);
1385         return bit.tosigned((t or {})[1], 7);
1388 jpcrr.read_word_signed = function(addr)
1389         local t = {toString(addr), "2"};
1390         t = invokecall("memory-read", t);
1391         return bit.tosigned((t or {})[1], 15);
1394 jpcrr.read_dword_signed = function(addr)
1395         local t = {toString(addr), "4"};
1396         t = invokecall("memory-read", t);
1397         return bit.tosigned((t or {})[1], 31);
1400 local e_wait_event = jpcrr.wait_event;
1401 local running = jpcrr.pc_running;
1402 local stop_and_execute_in_progress = false;
1403 jpcrr.stop_and_execute = function(f)
1404         local a, b;
1405         _unlock();
1406         if stop_and_execute_in_progress then
1407                 return false;
1408         end
1409         if not running() then
1410                 a, b = pcall(f);
1411                 if not a then
1412                         error("Error in after stop callback: " .. b);
1413                 end
1414                 return true;
1415         end
1416         jpcrr.pc_stop();
1417         while true do
1418                 stop_and_execute_in_progress = true;
1419                 a, b = e_wait_event();
1420                 stop_and_execute_in_progress = false;
1421                 if a and a == "lock" then
1422                         _unlock();
1423                         if stopping then
1424                                 break;
1425                         end
1426                 elseif a and (a == "stop" or a == "attach") then
1427                         stopping = true;
1428                 end
1429         end
1430         stopping = false;
1431         a, b = pcall(f);
1432         if not a then
1433                 error("Error in after stop callback: " .. b);
1434         end
1435         return true;
1439 jpcrr.invoke = nil;
1440 jpcrr.invoke_synchronous = nil;
1441 jpcrr.call = null
1443 -- Dofile.
1444 dofile = function(_script)
1445         local chunk, err, indication
1446         chunk, err = loadfile(_script);
1447         if not chunk then
1448                 error("Kernel: Can't load subscript " .. _script .. ": " .. err);
1449         end
1450         return chunk();
1453 local args2 = args;
1454 args = null;
1455 args = {};
1456 for k, v in pairs(args2) do
1457         if (#k > 2 and string.byte(k, 1) == 120 and string.byte(k, 2) == 45) then
1458                 args[string.sub(k, 3)] = v;
1459         end
1461 jpcrr_raw = null;
1464         chunk = null;
1465         loaded, err = pcall(function()
1466                 chunk, err = loadfile(script);
1467                 if not chunk then
1468                         error(err);
1469                 end
1470         end);
1471         if not loaded then
1472                 print("Kernel: Can't load script " .. script .. ": " .. err);
1473                 invoke("luaplugin-terminate");
1474                 while true do end
1475         end
1477         script = null;
1478         indication, err = pcall(chunk);
1479         if not indication then
1480                 print("Kernel: Unprotected error in script: " .. err);
1481                 invoke("luaplugin-terminate");
1482                 while true do end
1483         end