Remove debug print from memory search script
[jpcrr.git] / datafiles / luakernel
blobfccf808af9e9c84e2f7ed403f2c09f70222f2239
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.
260 --      - jpcrr.hostmemory.read()
261 --              Returns contents of host memory.
262 --      - jpcrr.hostmemory.write(string contents)
263 --              Overwrites host memory with specified string.
264 --      - jpcrr.project_id()
265 --              Get the project ID (nil if no movie).
267 --      I/O functions have the following conventions. If function returns any real data, the first
268 --      return value returns this data or is nil. Otherwise first return value is true or false.
269 --      If first return value is nil or false, then the second return value gives textual error
270 --      message for failed operation, or is nil if EOF occured before anything was read.
272 --      Unlink, rename and mkdir don't follow this pattern. They just return true/false to signal
273 --      success or failure.
275 --      Specifying nil as name of file results random filename being used (it even works with unlink,
276 --      mkdir, rename and read-only access, but doesn't make any sense there).
278 --      Specifying empty filename prompts for file (doesn't work with mkdir, rename nor unlink). Use
279 --      '/<title>' to specify title for prompt dialog.
281 --      Class: BinaryFile:
282 --              Binary file for RO or RW access. Methods are as follows:
283 --              - name()
284 --                      Return name of file.
285 --              - length()
286 --                      Return length of file.
287 --              - set_length(number length)
288 --                      Truncate file to specified length
289 --              - read(number offset, number length)
290 --                      Read up to length bytes from offset.
291 --              - write(number offset, string content)
292 --                      Write content to specified offset.
293 --              - close()
294 --                      Close the file.
295 --      Class: BinaryInput:
296 --              Binary file for sequential input. Methods are as follows:
297 --              - name()
298 --                      Return name of file.
299 --              - four_to_five()
300 --                      Return BinaryInput that is four to five decoding of this stream.
301 --              - text()
302 --                      Return stream as TextInput.
303 --              - inflate()
304 --                      Return BinaryInput that is inflate of this stream.
305 --              - read(number bytes)
306 --                      Read up to bytes bytes from file.
307 --              - read()
308 --                      Read the entiere file at once.
309 --              - close()
310 --                      Close the file.
311 --              Character set for binary files is Latin-1.
313 --      Class: BinaryOutput:
314 --              Binary file for sequential output. Methods are as follows:
315 --              - name()
316 --                      Return name of file.
317 --              - four_to_five()
318 --                      Return BinaryOutput that writes four to five encoded output to this stream.
319 --              - text()
320 --                      Return stream as TextOutput.
321 --              - deflate()
322 --                      Return BinaryOutput that writes deflate output to this stream.
323 --              - write(string content)
324 --                      Write string to file.
325 --              - close()
326 --                      Close the file.
327 --              Character set for binary files is Latin-1.
329 --      Class: TextInput:
330 --              - name()
331 --                      Return name of file.
332 --              - read()
333 --                      Read line from file.
334 --              - read_component()
335 --                      Read next componented line into array.
336 --              - lines()
337 --                      Line iterator function.
338 --              - close()
339 --                      Close the file.
340 --      Character set for text files is UTF-8.
342 --      Class: TextOutput:
343 --              - name()
344 --                      Return name of file.
345 --              - write(string line)
346 --                      Write line line to file.
347 --              - write_component(table components)
348 --                      Write componented line.
349 --              - close()
350 --                      Close the file.
351 --              Character set for text files is UTF-8.
353 --      Class ArchiveIn:
354 --              - member(string name)
355 --                      Open substream for member name. The methods are the same as for io.opentextin.
356 --              - member_binary(string name)
357 --                      Open binary (four to five) substream for member name. The methods are the same as
358 --                      for io.openbinaryin.
359 --              - close()
360 --                      Close the file. Any opened substreams are invalidated.
361 --              - member_list()
362 --                      Return table listing all members of archive (sorted by name).
363 --      Class ArchiveOut:
364 --              - member(string name)
365 --                      Open substream for member name. The methods are the same as for io.opentextout. Note that
366 --                      previous member must be closed before next can open.
367 --              - member_binary(string name)
368 --                      Open binary (four to five) substream for member name. The methods are the same as
369 --                      for io.openbinaryout. Note that previous substream must be closed before next can open.
370 --              - commit()
371 --                      Commit the file. No substream may be open. Closes the file.
372 --              - rollback()
373 --                      Rollback the file. No substream may be open. Closes the file.
375 --      - io.open(string name, string mode) -> BinaryFile
376 --              Open file named @name in specified mode. The mode can be 'r' (read only) or 'rw' (read and
377 --              write).
378 --      - io.open_read(string name) -> BinaryInput
379 --              Open file named @name as binary input stream.
380 --      - io.open_write(string name) -> BinaryOutput
381 --              Open file named @name as binary input stream.
382 --      - io.open_arch_read(string name) -> ArchiveIn
383 --              Open file named @name as input archive.
384 --      - io.open_arch_write(string name) -> ArchiveOut
385 --              Open file named @name as output archive.
386 --      - io.mkdir(string name)
387 --              Create directory name. Returns name created on success, nil on failure.
388 --      - io.unlink(string name)
389 --              Delete file/directory name. Returns name deleted on success, nil on failure.
390 --      - io.rename(string old, string new)
391 --              Rename file old -> new. Returns old, new on success, nil on failure.
392 --      - io.transform.text()
393 --              Returns function that calls text() method of its parameter.
394 --      - io.transform.four_to_five()
395 --              Returns function that calls four_to_five() method of its parameter.
396 --      - io.transform.deflate()
397 --              Returns function that calls deflate() method of its parameter.
398 --      - io.transform.inflate()
399 --              Returns function that calls inflate() method of its parameter.
400 --      - io.dotransform(object obj, function...)
401 --              Call specified functions on specified object. If any function fails (first argument nil
402 --              or false), call close method on preceeding object. Otherwise call specified functions
403 --              chained left to right and return the result.
404 --      - io.dotransform2(object obj, string err, function...)
405 --              Similar to dotransform except if obj is nil or false, returns obj, err.
408 local stopping = false;
409 local mesage_function = nil;
410 local lock_function = nil;
411 local uiaction_function = nil;
412 local stop_function = nil;
413 local attach_function = nil;
414 local _print_console_msg = print_console_msg;
416 local handle, err, chunk, indication, k, v;
418 local loadmod = loadmodule;
419 loadmodule = nil;
421 local export_module_in = function(tab, modname, prefix)
422         local fun = loadmod(modname);
423         if not fun then
424                 _print_console_msg("Extension library " .. modname .. " not found");
425                 return nil;
426         end
427         for k, v in pairs(fun) do
428                 tab[(prefix or "") .. k] = v;
429         end
432 jpcrr = {};
433 jpcrr.hud = {};
434 jpcrr.events = {};
435 jpcrr.window = {};
436 jpcrr.memorysearch = {};
437 jpcrr.hostmemory = {};
438 bit = {};
439 io = {};
440 local HUD = {};
442 export_module_in(jpcrr, "org.jpc.luaextensions.Base");
443 export_module_in(jpcrr, "org.jpc.luaextensions.InputDevices");
444 export_module_in(jpcrr, "org.jpc.luaextensions.ComponentCoding", "component_");
445 export_module_in(jpcrr.events, "org.jpc.luaextensions.Events");
446 export_module_in(jpcrr.window, "org.jpc.luaextensions.Window");
447 export_module_in(bit, "org.jpc.luaextensions.Bitops");
448 export_module_in(jpcrr.memorysearch, "org.jpc.luaextensions.MemorySearch");
449 export_module_in(HUD, "org.jpc.luaextensions.HUD");
450 export_module_in(jpcrr.hostmemory, "org.jpc.luaextensions.HostMemory");
452 -- HUD bindings.
453 local HUD = HUD.HUD;
454 jpcrr.HUD = HUD;
456 -- Few misc functions.
457 assert = function(val, err)
458         if (not val) and err then
459                 error(err);
460         end
461         return val;
464 modulus_split = function(number, ...)
465         local dividers = {...};
466         local results = {};
467         local rem;
469         for k, v in ipairs(dividers) do
470                 rem = number % v;
471                 table.insert(results, (number - rem) / v);
472                 number = rem;
473         end
475         table.insert(results, number);
476         return unpack(results);
479 jpcrr.register_redraw_function = function(f)
480         if f and type(f) ~= "function" then
481                 error("Incorrect type of argument to register_redraw_function");
482         end
483         lock_function = f;
486 jpcrr.register_message_function = function(f)
487         if f and type(f) ~= "function" then
488                 error("Incorrect type of argument to register_message_function");
489         end
490         message_function = f;
493 jpcrr.register_stop_function = function(f)
494         if f and type(f) ~= "function" then
495                 error("Incorrect type of argument to register_stop_function");
496         end
497         stop_function = f;
500 jpcrr.register_attach_function = function(f)
501         if f and type(f) ~= "function" then
502                 error("Incorrect type of argument to register_attach_function");
503         end
504         attach_function = f;
507 jpcrr.register_uiaction_function = function(f)
508         if f and type(f) ~= "function" then
509                 error("Incorrect type of argument to register_uiaction_function");
510         end
511         uiaction_function = f;
516 local getmtable = getmetatable;
517 local toString = tostring;
518 local inject_binary_file;
519 local inject_binary_input;
520 local inject_binary_output;
521 local inject_text_input;
522 local inject_text_output;
523 local inject_archive_input;
524 local inject_archive_output;
526 -- Class member injectors.
527 inject_binary_file = function(obj, name)
528         local _name = name;
529         getmtable(obj).name = function(obj)
530                 return _name;
531         end
532         getmtable(obj).__index = function(tab, name)
533                 local x = getmtable(obj)[name];
534                 if x then
535                         return x;
536                 end
537                 error("Invalid method " .. name .. " for BinaryFile");
538         end
539         return obj;
542 inject_binary_input = function(obj, underlying, name)
543         local _name = name;
544         local old_four_to_five = getmtable(obj).four_to_five;
545         local old_inflate = getmtable(obj).inflate;
546         local old_text = getmtable(obj).text;
547         local old_read = getmtable(obj).read;
548         local old_close = getmtable(obj).close;
549         local underlying_object = underlying;
551         getmtable(obj).name = function(obj)
552                 return _name;
553         end
554         getmtable(obj).four_to_five = function(obj)
555                 local res, err;
556                 res, err = old_four_to_five(obj);
557                 if not res then
558                         return res, err;
559                 end
560                 return inject_binary_input(res, obj, "four-to-five<" .. _name .. ">");
561         end
562         getmtable(obj).inflate = function(obj)
563                 local res, err;
564                 res, err = old_inflate(obj);
565                 if not res then
566                         return res, err;
567                 end
568                 return inject_binary_input(res, obj, "inflate<" .. _name .. ">");
569         end
570         getmtable(obj).text = function(obj)
571                 local res, err;
572                 res, err = old_text(obj);
573                 if not res then
574                         return res, err;
575                 end
576                 return inject_text_input(res, obj, "text<" .. _name .. ">");
577         end
578         getmtable(obj).read = function(obj, toread)
579                 if toread then
580                         return old_read(obj, toread);
581                 else
582                         local res = "";
583                         local ret, err;
584                         while true do
585                                 ret, err = old_read(obj, 16384);
586                                 if not ret then
587                                         if not err then
588                                                 return res;
589                                         end
590                                         return nil, err;
591                                 end
592                                 res = res .. ret;
593                         end
594                 end
595         end
596         getmtable(obj).close = function(obj)
597                 local ret, err, ret2, err2;
598                 ret, err = old_close(obj);
599                 if underlying_object then ret2, err2 = underlying_object:close(); end
600                 if ret and not ret2 then
601                         err = err2;
602                         ret = ret2;
603                 end
604                 return ret, err;
605         end
606         getmtable(obj).__index = function(tab, name)
607                 local x = getmtable(obj)[name];
608                 if x then
609                         return x;
610                 end
611                 error("Invalid method " .. name .. " for BinaryInput");
612         end
613         return obj;
616 inject_binary_output = function(obj, underlying, name)
617         local _name = name;
618         local old_four_to_five = getmtable(obj).four_to_five;
619         local old_deflate = getmtable(obj).deflate;
620         local old_text = getmtable(obj).text;
621         local old_close = getmtable(obj).close;
622         local underlying_object = underlying;
624         getmtable(obj).name = function(obj)
625                 return _name;
626         end
627         getmtable(obj).four_to_five = function(obj)
628                 local res, err;
629                 res, err = old_four_to_five(obj);
630                 if not res then
631                         return res, err;
632                 end
633                 return inject_binary_output(res, obj, "four-to-five<" .. _name .. ">");
634         end
635         getmtable(obj).deflate = function(obj)
636                 local res, err;
637                 res, err = old_deflate(obj);
638                 if not res then
639                         return res, err;
640                 end
641                 return inject_binary_output(res, obj, "deflate<" .. _name .. ">");
642         end
643         getmtable(obj).text = function(obj)
644                 local res, err;
645                 res, err = old_text(obj);
646                 if not res then
647                         return res, err;
648                 end
649                 return inject_text_output(res, obj, "text<" .. _name .. ">");
650         end
651         getmtable(obj).close = function(obj)
652                 local ret, err, ret2, err2;
653                 ret, err = old_close(obj);
654                 if underlying_object then ret2, err2 = underlying_object:close(); end
655                 if ret and not ret2 then
656                         err = err2;
657                         ret = ret2;
658                 end
659                 return ret, err;
660         end
661         getmtable(obj).__index = function(tab, name)
662                 local x = getmtable(obj)[name];
663                 if x then
664                         return x;
665                 end
666                 error("Invalid method " .. name .. " for BinaryOutput");
667         end
668         return obj;
671 inject_text_input = function(obj, underlying, name)
672         local _name = name;
673         local old_close = getmtable(obj).close;
674         local underlying_object = underlying;
676         getmtable(obj).lines = function(obj)
677                 return function(state, prevline)
678                         return state:read();
679                 end, obj, nil;
680         end
681         getmtable(obj).name = function(obj)
682                 return _name;
683         end
684         getmtable(obj).close = function(obj)
685                 local ret, err, ret2, err2;
686                 ret, err = old_close(obj);
687                 if underlying_object then ret2, err2 = underlying_object:close(); end
688                 if ret and not ret2 then
689                         err = err2;
690                         ret = ret2;
691                 end
692                 return ret, err;
693         end
694         getmtable(obj).__index = function(tab, name)
695                 local x = getmtable(obj)[name];
696                 if x then
697                         return x;
698                 end
699                 error("Invalid method " .. name .. " for TextInput");
700         end
701         return obj;
704 inject_text_output = function(obj, underlying, name)
705         local _name = name;
706         local old_close = getmtable(obj).close;
707         local underlying_object = underlying;
709         getmtable(obj).name = function(obj)
710                 return _name;
711         end
712         getmtable(obj).close = function(obj)
713                 local ret, err, ret2, err2;
714                 ret, err = old_close(obj);
715                 if underlying_object then ret2, err2 = underlying_object:close(); end
716                 if ret and underlying_object then
717                         err = err2;
718                         ret = ret2;
719                 end
720                 return ret, err;
721         end
722         getmtable(obj).__index = function(tab, name)
723                 local x = getmtable(obj)[name];
724                 if x then
725                         return x;
726                 end
727                 error("Invalid method " .. name .. " for TextOutput");
728         end
729         return obj;
732 inject_archive_input = function(obj, name)
733         local _name = name;
734         local old_member = getmtable(obj).member;
735         local old_member_list = getmtable(obj).member_list;
736         getmtable(obj).member = function(obj, member)
737                 local res, err;
738                 res, err = old_member(obj, member);
739                 if not res then
740                         return res, err;
741                 end
742                 return inject_binary_input(res, nil, _name .. "[" .. member .. "]");
743         end
744         getmtable(obj).name = function(obj)
745                 return _name;
746         end
747         getmtable(obj).member_list = function(obj)
748                 local tab = old_member_list(obj);
749                 if tab then table.sort(tab, jpcrr.stringlessthan); end
750                 return tab;
751         end
752         getmtable(obj).__index = function(tab, name)
753                 local x = getmtable(obj)[name];
754                 if x then
755                         return x;
756                 end
757                 error("Invalid method " .. name .. " for ArchiveInput");
758         end
759         return obj;
762 inject_archive_output = function(obj, name)
763         local _name = name;
764         local old_member = getmtable(obj).member;
765         getmtable(obj).member = function(obj, member)
766                 local res, err;
767                 res, err = old_member(obj, member);
768                 if not res then
769                         return res, err;
770                 end
771                 return inject_binary_output(res, nil, _name .. "[" .. member .. "]");
772         end
773         getmtable(obj).name = function(obj)
774                 return _name;
775         end
776         getmtable(obj).__index = function(tab, name)
777                 local x = getmtable(obj)[name];
778                 if x then
779                         return x;
780                 end
781                 error("Invalid method " .. name .. " for ArchiveOutput");
782         end
783         return obj;
787 -- Redefined routines.
789         local rprint = print_console_msg;
790         print_console_msg = nil;
791         print = function(...)
792                 local x = "";
793                 local y = {...};
794                 local i;
795                 for i = 1,#y do
796                         if i > 1 then
797                                 x = x .. "\t" .. toString(y[i]);
798                         else
799                                 x = toString(y[i]);
800                         end
801                 end
802                 rprint(x);
803         end
804         print_console_msg = nil;
809 -- I/O routines.
810 local stringfind = string.find;
811 local randname = loadmod("org.jpc.luaextensions.DelayedDelete").random_temp_name;
812 local selectname = loadmod("org.jpc.luaextensions.BaseFSOps").opensave_dialog;
813 local path = args["luapath"] or ".";
814 local toresourcename = function(resname, save, text)
815         if not resname then
816                 return randname(path .. "/", "luatemp-");
817         end
819         if resname == "" and text then
820                 local a, b;
821                 a, b = selectname(save, text);
822                 return a, (a or b);
823         end
825         if stringfind(resname, "^/") then
826                 if not text then
827                         error("Bad resource name (case 2): " .. resname);
828                 end
829                 local a, b;
830                 a, b = selectname(save, string.sub(resname, 2));
831                 return a, (a or b);
832         end
834         if not stringfind(resname, "[%d%l%u_%-]") then
835                 error("Bad resource name (case 1): " .. resname);
836         end
837         if stringfind(resname, "%.%.") then
838                 error("Bad resource name (case 3): " .. resname);
839         end
840         if stringfind(resname, "\\") then
841                 error("Bad resource name (case 4): " .. resname);
842         end
844         return resname, path .. "/" .. resname;
849         local openbinin = loadmod("org.jpc.luaextensions.BinaryInFile").open;
850         local openbinout = loadmod("org.jpc.luaextensions.BinaryOutFile").open;
851         local openarchin = loadmod("org.jpc.luaextensions.ArchiveIn").open;
852         local openarchout = loadmod("org.jpc.luaextensions.ArchiveOut").open;
853         local openbinary = loadmod("org.jpc.luaextensions.BinaryFile").open;
855         local baseFS = loadmod("org.jpc.luaextensions.BaseFSOps");
856         local mkdir = baseFS.mkdir;
857         local unlink = baseFS.unlink;
858         local rename = baseFS.rename;
860         local getmtable = getmetatable;
862         loadfile = function(_script)
863                 local file, file2, err, content;
864                 local x, y;
865                 x, y = toresourcename(_script, false, "Select script to load");
866                 if not x then return x, y; end
867                 file, err = openbinin(y, "r");
868                 if not file then
869                         return nil, "Can't open " .. _script .. ": " .. err;
870                 end
871                 file2, err = file:text();
872                 if not file2 then
873                         return nil, "Can't transform " .. _script .. ": " .. err;
874                 end
875                 content = "";
876                 line = file2:read();
877                 while line do
878                         content = content .. line .. "\n";
879                         line = file2:read();
880                 end
881                 file2:close();
882                 file:close();
883                 return loadstring(content, _script);
884         end
886         io.open = function(name, mode)
887                 local _name;
888                 local res, err;
889                 local y;
890                 if mode == "r" then
891                         _name, y = toresourcename(name, false, "Select file to read");
892                 else
893                         _name, y = toresourcename(name, true, "Select file to write");
894                 end
895                 if not _name then return _name, y; end
896                 res, err = openbinary(y, mode);
897                 if not res then
898                         return res, err;
899                 end
900                 return inject_binary_file(res, _name);
901         end
903         io.open_arch_read = function(name)
904                 local _name = name;
905                 local res, err;
906                 local y;
907                 _name, y = toresourcename(name, false, "Select archive to read");
908                 if not _name then return _name, y; end
909                 res, err = openarchin(y);
910                 if not res then
911                         return res, err;
912                 end
913                 return inject_archive_input(res, _name);
914         end
916         io.open_arch_write = function(name)
917                 local _name = name;
918                 local res, err;
919                 local y;
920                 _name, y = toresourcename(name, true, "Select archive to write");
921                 if not _name then return _name, y; end
922                 res, err = openarchout(y);
923                 if not res then
924                         return res, err;
925                 end
926                 return inject_archive_output(res, _name);
927         end
929         io.open_read = function(name)
930                 local _name = name;
931                 local res, err;
932                 local y;
933                 _name, y = toresourcename(name, false, "Select file to read");
934                 if not _name then return _name, y; end
935                 res, err = openbinin(y);
936                 if not res then
937                         return res, err;
938                 end
939                 return inject_binary_input(res, nil, _name);
940         end
942         io.open_write = function(name)
943                 local _name = name;
944                 local res, err;
945                 local y;
946                 _name, y = toresourcename(name, true, "Select file to write");
947                 if not _name then return _name, y; end
948                 res, err = openbinout(y);
949                 if not res then
950                         return res, err;
951                 end
952                 return inject_binary_output(res, nil, _name);
953         end
955         io.mkdir = function(name)
956                 local _name, y;
957                 _name, y = toresourcename(name);
958                 if mkdir(y) then
959                         return _name;
960                 else
961                         return nil;
962                 end
963         end
965         io.unlink = function(name)
966                 local _name, y;
967                 _name, y = toresourcename(name);
968                 if unlink(y) then
969                         return _name;
970                 else
971                         return nil;
972                 end
973         end
975         io.rename = function(name1, name2)
976                 local _name, y;
977                 local _name2, y2;
978                 _name, y = toresourcename(name1);
979                 _name2, y2 = toresourcename(name2);
980                 if rename(y, y2) then
981                         return _name, _name2;
982                 else
983                         return nil;
984                 end
985         end
987         io.transform = {};
989         io.transform.text = function()
990                 return function(obj)
991                         return obj:text();
992                 end
993         end
995         io.transform.four_to_five = function()
996                 return function(obj)
997                         return obj:four_to_five();
998                 end
999         end
1001         io.transform.inflate = function()
1002                 return function(obj)
1003                         return obj:inflate();
1004                 end
1005         end
1007         io.transform.deflate = function()
1008                 return function(obj)
1009                         return obj:deflate();
1010                 end
1011         end
1013         io.dotransform = function(obj, ...)
1014                 local todo = {...};
1015                 local k, v;
1016                 local obj2, err;
1017                 for k, v in ipairs(todo) do
1018                         obj2, err = v(obj);
1019                         if not obj2 then
1020                                 obj:close();
1021                                 return nil, err;
1022                         end
1023                         obj = obj2;
1024                 end
1025                 return obj;
1026         end
1028         io.dotransform2 = function(obj, err, ...)
1029                 if not obj then
1030                         return obj, err;
1031                 end
1032                 return io.dotransform(obj, err, ...);
1033         end
1037 -- Various stuff built on top of ECI.
1038 local invoke = jpcrr.invoke;
1039 local invokecall = jpcrr.call;
1040 local invokesync = jpcrr.invoke_synchronous;
1042 jpcrr.sendevent = function(...)
1043         local arguments = {...};
1044         local k, v;
1045         for k, v in ipairs(arguments) do
1046                 arguments[k] = toString(v);
1047         end
1048         invokesync("sendevent", arguments);
1051 jpcrr.sendevent_lowbound = function(...)
1052         local arguments = {...};
1053         local k, v;
1054         for k, v in ipairs(arguments) do
1055                 arguments[k] = toString(v);
1056         end
1057         invokesync("sendevent-lowbound", arguments);
1060 jpcrr.save_state = function(name)
1061         local _name, _fname;
1062         _name, _fname = toresourcename(name, true, "File to savestate to");
1063         invokesync("state-save", {_fname});
1064         return _name;
1067 jpcrr.save_movie = function(name)
1068         local _name, _fname;
1069         _name, _fname = toresourcename(name, true, "File to save movie to");
1070         invokesync("movie-save", {_fname});
1071         return _name;
1074 jpcrr.load_state_normal = function(name)
1075         local _name, _fname;
1076         _name, _fname = toresourcename(name, false, "File to loadstate from");
1077         invokesync("state-load", {_fname});
1078         return _name;
1081 jpcrr.load_state_preserve_events = function(name)
1082         local _name, _fname;
1083         _name, _fname = toresourcename(name, false, "File to loadstate (preserve events) from");
1084         invokesync("state-load-noevents", {_fname});
1085         return _name;
1088 jpcrr.load_state_movie = function(name)
1089         local _name, _fname;
1090         _name, _fname = toresourcename(name, false, "File to load movie from");
1091         invokesync("movie-load", {_fname});
1092         return _name;
1095 jpcrr.assemble = function()
1096         invokesync("pc-assemble");
1099 jpcrr.change_authors = function()
1100         invokesync("change-authors");
1103 jpcrr.ram_dump = function(name, binary)
1104         local _name, _fname;
1105         _name, _fname = toresourcename(name, true, "Select file to ramdump to");
1106         if binary then
1107                 invokesync("ram-dump-binary", {_fname});
1108         else
1109                 invokesync("ram-dump-text", {_fname});
1110         end
1111         return _name;
1114 local poll_event = jpcrr.poll_event;
1115 local _print = print;
1116 local _unlock = jpcrr.release_vga;
1117 jpcrr.poll_event = function()
1118         local a, b;
1119         local failed = false;
1120         while not failed do
1121                 a, b = poll_event();
1122                 if not a then
1123                         failed = true;
1124                 end
1125                 if a and a == "message" and message_function then
1126                         a, b = pcall(message_function, b);
1127                         if not a then
1128                                 _print("Error running message callback: " .. b);
1129                         end
1130                         a = nil;
1131                 end
1132                 if a and a == "uiaction" and uiaction_function then
1133                         a, b = pcall(uiaction_function, b);
1134                         if not a then
1135                                 _print("Error running uiaction callback: " .. b);
1136                         end
1137                         a = nil;
1138                 end
1139                 if a and a == "stop" and stop_function then
1140                         a, b = pcall(stop_function);
1141                         if not a then
1142                                 _print("Error running stop callback: " .. b);
1143                         end
1144                         a = nil;
1145                 end
1146                 if a and a == "attach" and attach_function then
1147                         a, b = pcall(attach_function);
1148                         if not a then
1149                                 _print("Error running attach callback: " .. b);
1150                         end
1151                         a = nil;
1152                 end
1153                 if a and a == "lock" and lock_function then
1154                         a, b = pcall(lock_function);
1155                         _unlock();
1156                         if not a then
1157                                 _print("Error running redraw callback: " .. b);
1158                         end
1159                         if stoppping then
1160                                 return "lock";
1161                         end
1162                         a = nil;
1163                 end
1164                 if a and a == "lock" and stopping then
1165                         _unlock();
1166                         return "lock";
1167                 end
1168         end
1169         return a, b;
1173 local wait_event = jpcrr.wait_event;
1174 local _print = print;
1175 local _unlock = jpcrr.release_vga;
1176 jpcrr.wait_event = function()
1177         local a, b;
1178         while not a do
1179                 a, b = wait_event();
1180                 if a and a == "message" and message_function then
1181                         a, b = pcall(message_function, b);
1182                         if not a then
1183                                 _print("Error running message callback: " .. b);
1184                         end
1185                         a = nil;
1186                 end
1187                 if a and a == "uiaction" and uiaction_function then
1188                         a, b = pcall(uiaction_function, b);
1189                         if not a then
1190                                 _print("Error running uiaction callback: " .. b);
1191                         end
1192                         a = nil;
1193                 end
1194                 if a and a == "stop" and stop_function then
1195                         a, b = pcall(stop_function);
1196                         if not a then
1197                                 _print("Error running stop callback: " .. b);
1198                         end
1199                         a = nil;
1200                 end
1201                 if a and a == "attach" and attach_function then
1202                         a, b = pcall(attach_function);
1203                         if not a then
1204                                 _print("Error running attach callback: " .. b);
1205                         end
1206                         a = nil;
1207                 end
1208                 if a and a == "lock" and lock_function then
1209                         a, b = pcall(lock_function);
1210                         _unlock();
1211                         if not a then
1212                                 _print("Error running redraw callback: " .. b);
1213                         end
1214                         if stopping then
1215                                 return a, b;
1216                         end
1217                         a = nil;
1218                 end
1219         end
1220         return a, b;
1224 jpcrr.hud.left_gap = function(f, g)
1225         HUD("left_gap", f, g);
1228 jpcrr.hud.right_gap = function(f, g)
1229         HUD("right_gap", f, g);
1232 jpcrr.hud.top_gap = function(f, g)
1233         HUD("top_gap", f, g);
1236 jpcrr.hud.bottom_gap = function(f, g)
1237         HUD("bottom_gap", f, g);
1240 jpcrr.hud.white_solid_box = function(f, x, y, w, h)
1241         HUD("hud_white_solid_box", f, x, y, w, h);
1244 jpcrr.hud.box = function(f, x, y, w, h, t, lr, lg, lb, la, fr, fg, fb, fa)
1245         la = la or 255;
1246         fr = fr or 0;
1247         fg = fg or 0;
1248         fb = fb or 0;
1249         fa = fa or 0;
1250         HUD("box", f, x, y, w, h, t, lr, lg, lb, la, fr, fg, fb, fa);
1253 jpcrr.hud.circle = function(f, x, y, r, t, lr, lg, lb, la, fr, fg, fb, fa)
1254         la = la or 255;
1255         fr = fr or 0;
1256         fg = fg or 0;
1257         fb = fb or 0;
1258         fa = fa or 0;
1259         HUD("circle", f, x, y, r, t, lr, lg, lb, la, fr, fg, fb, fa)
1262 jpcrr.hud.bitmap = function(f, x, y, bmap, lr, lg, lb, la, fr, fg, fb, fa)
1263         la = la or 255;
1264         fr = fr or 0;
1265         fg = fg or 0;
1266         fb = fb or 0;
1267         fa = fa or 0;
1268         HUD("bitmap", f, x, y, bmap, lr, lg, lb, la, fr, fg, fb, fa)
1271 jpcrr.hud.bitmap_binary = function(f, x, y, bmap, lr, lg, lb, la, fr, fg, fb, fa)
1272         la = la or 255;
1273         fr = fr or 0;
1274         fg = fg or 0;
1275         fb = fb or 0;
1276         fa = fa or 0;
1277         HUD("bitmap_binary", f, x, y, bmap, lr, lg, lb, la, fr, fg, fb, fa)
1280 jpcrr.hud.chargen = function(f, x, y, text, multiline, lr, lg, lb, la, fr, fg, fb, fa)
1281         la = la or 255;
1282         fr = fr or 0;
1283         fg = fg or 0;
1284         fb = fb or 0;
1285         fa = fa or 0;
1286         HUD("vga_chargen", f, x, y, text, lr, lg, lb, la, fr, fg, fb, fa, multiline)
1289 jpcrr.shutdown_emulator = function()
1290         invokesync("shutdown-emulator", {});
1293 jpcrr.set_pccontrol_pos = function(x, y)
1294         invokesync("pccontrol-setwinpos", {toString(x), toString(y)});
1297 jpcrr.set_luaplugin_pos = function(x, y)
1298         invokesync("luaplugin-setwinpos", {toString(x), toString(y)});
1301 jpcrr.set_pcmonitor_pos = function(x, y)
1302         invokesync("pcmonitor-setwinpos", {toString(x), toString(y)});
1305 jpcrr.set_pcstartstoptest_pos = function(x, y)
1306         invokesync("pcstartstoptest-setwinpos", {toString(x), toString(y)});
1309 jpcrr.set_virtualkeyboard_pos = function(x, y)
1310         invokesync("virtualkeyboard-setwinpos", {toString(x), toString(y)});
1313 jpcrr.exit = function()
1314         invokesync("luaplugin-terminate");
1317 jpcrr.pc_start = function()
1318         invoke("pc-start");
1321 jpcrr.pc_stop = function()
1322         invokesync("pc-stop");
1325 jpcrr.screenshot = function(include_hud)
1326         if include_hud then
1327                 invoke("screenshot-renderbuffer");
1328         else
1329                 invoke("screenshot-vgabuffer");
1330         end
1333 jpcrr.bios_kbd_trap = function(is_on)
1334         if is_on then
1335                 invokesync("trap-bios-kbd-on");
1336         else
1337                 invokesync("trap-bios-kbd-off");
1338         end
1341 jpcrr.vretrace_start_trap = function(is_on)
1342         if is_on then
1343                 invokesync("trap-vretrace-start-on");
1344         else
1345                 invokesync("trap-vretrace-start-off");
1346         end
1349 jpcrr.vretrace_end_trap = function(is_on)
1350         if is_on then
1351                 invokesync("trap-vretrace-end-on");
1352         else
1353                 invokesync("trap-vretrace-end-off");
1354         end
1357 jpcrr.timed_trap = function(nsecs)
1358         if nsecs then
1359                 invokesync("trap-timed", {toString(nsecs)});
1360         else
1361                 invokesync("trap-timed-disable");
1362         end
1365 jpcrr.write_byte = function(addr, value)
1366         invokesync("memory-write", {toString(addr), toString(value), "1"});
1369 jpcrr.write_word = function(addr, value)
1370         invokesync("memory-write", {toString(addr), toString(value), "2"});
1373 jpcrr.write_dword = function(addr, value)
1374         invokesync("memory-write", {toString(addr), toString(value), "4"});
1377 jpcrr.read_byte = function(addr)
1378         local t = {toString(addr), "1"};
1379         t = invokecall("memory-read", t);
1380         return (t or {})[1];
1383 jpcrr.read_word = function(addr)
1384         local t = {toString(addr), "2"};
1385         t = invokecall("memory-read", t);
1386         return (t or {})[1];
1389 jpcrr.read_dword = function(addr)
1390         local t = {toString(addr), "4"};
1391         t = invokecall("memory-read", t);
1392         return (t or {})[1];
1395 jpcrr.read_byte_signed = function(addr)
1396         local t = {toString(addr), "1"};
1397         t = invokecall("memory-read", t);
1398         return bit.tosigned((t or {})[1], 7);
1401 jpcrr.read_word_signed = function(addr)
1402         local t = {toString(addr), "2"};
1403         t = invokecall("memory-read", t);
1404         return bit.tosigned((t or {})[1], 15);
1407 jpcrr.read_dword_signed = function(addr)
1408         local t = {toString(addr), "4"};
1409         t = invokecall("memory-read", t);
1410         return bit.tosigned((t or {})[1], 31);
1413 local e_wait_event = jpcrr.wait_event;
1414 local running = jpcrr.pc_running;
1415 local stop_and_execute_in_progress = false;
1416 jpcrr.stop_and_execute = function(f)
1417         local a, b;
1418         _unlock();
1419         if stop_and_execute_in_progress then
1420                 return false;
1421         end
1422         if not running() then
1423                 a, b = pcall(f);
1424                 if not a then
1425                         error("Error in after stop callback: " .. b);
1426                 end
1427                 return true;
1428         end
1429         jpcrr.pc_stop();
1430         while true do
1431                 stop_and_execute_in_progress = true;
1432                 a, b = e_wait_event();
1433                 stop_and_execute_in_progress = false;
1434                 if a and a == "lock" then
1435                         _unlock();
1436                         if stopping then
1437                                 break;
1438                         end
1439                 elseif a and (a == "stop" or a == "attach") then
1440                         stopping = true;
1441                 end
1442         end
1443         stopping = false;
1444         a, b = pcall(f);
1445         if not a then
1446                 error("Error in after stop callback: " .. b);
1447         end
1448         return true;
1452 jpcrr.invoke = nil;
1453 jpcrr.invoke_synchronous = nil;
1454 jpcrr.call = null
1456 -- Dofile.
1457 dofile = function(_script)
1458         local chunk, err, indication
1459         chunk, err = loadfile(_script);
1460         if not chunk then
1461                 error("Kernel: Can't load subscript " .. _script .. ": " .. err);
1462         end
1463         return chunk();
1466 local args2 = args;
1467 args = null;
1468 args = {};
1469 for k, v in pairs(args2) do
1470         if (#k > 2 and string.byte(k, 1) == 120 and string.byte(k, 2) == 45) then
1471                 args[string.sub(k, 3)] = v;
1472         end
1474 jpcrr_raw = null;
1477         chunk = null;
1478         loaded, err = pcall(function()
1479                 chunk, err = loadfile(script);
1480                 if not chunk then
1481                         error(err);
1482                 end
1483         end);
1484         if not loaded then
1485                 print("Kernel: Can't load script " .. script .. ": " .. err);
1486                 invoke("luaplugin-terminate");
1487                 while true do end
1488         end
1490         script = null;
1491         indication, err = pcall(chunk);
1492         if not indication then
1493                 print("Kernel: Unprotected error in script: " .. err);
1494                 invoke("luaplugin-terminate");
1495                 while true do end
1496         end