first public release
This commit is contained in:
commit
8180d49f24
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
images/*
|
||||
|
26
LICENSE
Normal file
26
LICENSE
Normal file
|
@ -0,0 +1,26 @@
|
|||
Copyright (c) 2012, Fabian Hemmer
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
The views and conclusions contained in the software and documentation are those
|
||||
of the authors and should not be interpreted as representing official policies,
|
||||
either expressed or implied, of the FreeBSD Project.
|
72
Makefile
Normal file
72
Makefile
Normal file
|
@ -0,0 +1,72 @@
|
|||
CLOSURE=~/closure/closure-compiler/build/compiler.jar
|
||||
CPP=cpp
|
||||
|
||||
|
||||
all: v86_all.js
|
||||
browser: v86_all.js
|
||||
node: v86_node.js
|
||||
|
||||
src/cpu.js: src/*.macro.js
|
||||
# build cpu.macro.js using cpp
|
||||
$(CPP) -P -undef -Wundef -std=c99 -nostdinc -Wtrigraphs -fdollars-in-identifiers -C src/cpu.macro.js src/cpu.js
|
||||
|
||||
|
||||
|
||||
# Used for nodejs builds and in order to profile code.
|
||||
# `debug` gives identifiers a readable name, make sure it doesn't have any side effects.
|
||||
CLOSURE_READABLE=--formatting PRETTY_PRINT --debug
|
||||
|
||||
CLOSURE_SOURCE_MAP=\
|
||||
--source_map_format V3\
|
||||
--create_source_map
|
||||
|
||||
CLOSURE_FLAGS=\
|
||||
--compilation_level ADVANCED_OPTIMIZATIONS\
|
||||
--externs externs.js\
|
||||
--warning_level VERBOSE\
|
||||
--jscomp_off uselessCode\
|
||||
--use_types_for_optimization\
|
||||
--summary_detail_level 3\
|
||||
--language_in ECMASCRIPT5_STRICT
|
||||
|
||||
|
||||
CORE_FILES=const.js io.js cpu.js main.js disk.js pci.js floppy.js memory.js dma.js pit.js vga.js ps2.js pic.js rtc.js uart.js
|
||||
BROWSER_FILES=browser/main.js browser/screen.js browser/keyboard.js browser/mouse.js
|
||||
NODE_FILES=node/main.js node/keyboard.js node/screen.js
|
||||
|
||||
v86_all.js: src/*.js src/browser/*.js src/cpu.js
|
||||
-ls -lh v86_all.js
|
||||
cd src &&\
|
||||
java -jar $(CLOSURE) \
|
||||
--js_output_file "../v86_all.js"\
|
||||
--define=DEBUG=false\
|
||||
$(CLOSURE_SOURCE_MAP) v86_all.js.map\
|
||||
$(CLOSURE_FLAGS)\
|
||||
--js $(CORE_FILES)\
|
||||
--js $(BROWSER_FILES)
|
||||
|
||||
echo "//# sourceMappingURL=src/v86_all.js.map" >> v86_all.js
|
||||
ls -lh v86_all.js
|
||||
|
||||
|
||||
v86_node.js: src/*.js src/node/*.js
|
||||
cd src &&\
|
||||
java -jar $(CLOSURE) \
|
||||
--js_output_file "../v86_node.js"\
|
||||
--define=DEBUG=false\
|
||||
$(CLOSURE_FLAGS)\
|
||||
--js $(CORE_FILES) $(NODE_FILES)
|
||||
|
||||
|
||||
pack:
|
||||
rm -f v86-latest.tar.gz
|
||||
# Not sure if legally necessary
|
||||
#--exclude "qemu"
|
||||
tar -zcvf ../v86-latest.tar.gz ../v86/ \
|
||||
--exclude "images" \
|
||||
--exclude ".git"
|
||||
|
||||
|
||||
|
||||
clean:
|
||||
rm -f v86-latest.tar.gz v86_all.js src/v86_all.js.map src/cpu.js
|
87
Readme.md
Normal file
87
Readme.md
Normal file
|
@ -0,0 +1,87 @@
|
|||
How does it work?
|
||||
-
|
||||
|
||||
v86 emulates an x86-compatible CPU and hardware. Here's a list of emulated hardware:
|
||||
|
||||
- An x86 compatible CPU. The instruction set is around Pentium 1 level. Some
|
||||
features are missing, more specifically:
|
||||
- Task gates, far calls in protected mode
|
||||
- 16 bit protected mode features and Virtual 8086 mode
|
||||
- Single stepping
|
||||
- MMX, SSE
|
||||
- A bunch of FPU instructions, FPU exceptions
|
||||
- Some other exceptions
|
||||
- A floating point unit (FPU). Calculations are done with JavaScript's double
|
||||
precision numbers (64 bit), so they are not as precise as calculations on a
|
||||
real FPU (80 bit).
|
||||
- An ISA bus.
|
||||
- A floppy disk controller (8272A).
|
||||
- A DMA (direct memory access) controller, currently only used by the FDC.
|
||||
- An 8042 Keyboard Controller, PS2. With mouse support.
|
||||
- An 8254 Programmable Interval Timer (PIT).
|
||||
- An 8259 Programmable Interrupt Controller (PIC).
|
||||
- A CMOS Real Time Clock (RTC).
|
||||
- A VGA controller with SVGA support and Bochs VBE Extensions. This includes
|
||||
support for large resolutions.
|
||||
- A PCI bus. This one is mostly incomplete and not used by every device.
|
||||
- An AT disk controller with some ATAPI and some SCSI commands. This is quite
|
||||
incomplete and possibly buggy, too.
|
||||
|
||||
|
||||
How to build, run and embed?
|
||||
-
|
||||
|
||||
- In order to build the `cpu.js` file, you need `make` and `cpp` (the C preprocessor).
|
||||
Run: `make src/cpu.js`.
|
||||
- If you want a compressed and fast (ie, with debug code removed) version, you
|
||||
need Closure Compiler.
|
||||
Set the path to `compiler.jar` in the Makefile and run `make v86_all.js`.
|
||||
- For more details on how to customize the behaviour and interface, see [docs/adapters.md](docs/adapters.md).
|
||||
|
||||
|
||||
Why?
|
||||
-
|
||||
|
||||
Similiar projects have been done before, but I decided to work on this as a fun
|
||||
project and learn something about the x86 architecture. It has grown pretty
|
||||
advanced and I just got Linux and KolibriOS working recently and
|
||||
there might be some actual uses.
|
||||
|
||||
If you build something interesting, let me know. However, keep in mind that the project
|
||||
is not very stable at the moment.
|
||||
|
||||
|
||||
How can I contribute?
|
||||
-
|
||||
|
||||
- Someone who could work on hardware devices, such as a modem or the AT
|
||||
controller. I'll write an overview for that at a later point, if people are
|
||||
interested.
|
||||
- Donate. Since Bitcoin is the new cool thing, here's my address:
|
||||
`14KBXSoewGzbQY8VoznJ5MZXGxoia8RxC9`
|
||||
|
||||
License
|
||||
-
|
||||
|
||||
Simplified BSD License, see [LICENSE](LICENSE), unless otherwise noted.
|
||||
|
||||
|
||||
Credits
|
||||
-
|
||||
|
||||
- Test cases via QEMU, http://wiki.qemu.org/Main_Page
|
||||
- https://github.com/creationix/node-sdl
|
||||
- ascii.ttf (used in node) from http://www.apollosoft.de/ASCII/indexen.htm
|
||||
|
||||
|
||||
More questions?
|
||||
-
|
||||
|
||||
Shoot me an email to `copy@copy.sh`. Please don't tell about bugs via mail,
|
||||
create a bug report on github instead.
|
||||
|
||||
|
||||
Author
|
||||
-
|
||||
|
||||
Fabian Hemmer (http://copy.sh/, `copy@copy.sh`)
|
165
bios/COPYING.LESSER
Normal file
165
bios/COPYING.LESSER
Normal file
|
@ -0,0 +1,165 @@
|
|||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
94
bios/seabios-config
Normal file
94
bios/seabios-config
Normal file
|
@ -0,0 +1,94 @@
|
|||
#
|
||||
# Automatically generated make config: don't edit
|
||||
# SeaBIOS Configuration
|
||||
# Sun Nov 18 21:22:50 2012
|
||||
#
|
||||
|
||||
#
|
||||
# General Features
|
||||
#
|
||||
# CONFIG_COREBOOT is not set
|
||||
CONFIG_XEN=y
|
||||
CONFIG_THREADS=y
|
||||
# CONFIG_THREAD_OPTIONROMS is not set
|
||||
CONFIG_RELOCATE_INIT=y
|
||||
# CONFIG_BOOTMENU is not set
|
||||
# CONFIG_BOOTORDER is not set
|
||||
|
||||
#
|
||||
# Hardware support
|
||||
#
|
||||
CONFIG_ATA=y
|
||||
# CONFIG_ATA_DMA is not set
|
||||
# CONFIG_ATA_PIO32 is not set
|
||||
CONFIG_AHCI=y
|
||||
CONFIG_VIRTIO_BLK=y
|
||||
CONFIG_VIRTIO_SCSI=y
|
||||
CONFIG_ESP_SCSI=y
|
||||
CONFIG_LSI_SCSI=y
|
||||
CONFIG_FLOPPY=y
|
||||
CONFIG_PS2PORT=y
|
||||
CONFIG_USB=y
|
||||
CONFIG_USB_UHCI=y
|
||||
CONFIG_USB_OHCI=y
|
||||
CONFIG_USB_EHCI=y
|
||||
CONFIG_USB_MSC=y
|
||||
CONFIG_USB_UAS=y
|
||||
CONFIG_USB_HUB=y
|
||||
CONFIG_USB_KEYBOARD=y
|
||||
CONFIG_USB_MOUSE=y
|
||||
CONFIG_SERIAL=y
|
||||
CONFIG_LPT=y
|
||||
CONFIG_USE_SMM=y
|
||||
CONFIG_MTRR_INIT=y
|
||||
|
||||
#
|
||||
# BIOS interfaces
|
||||
#
|
||||
CONFIG_DRIVES=y
|
||||
CONFIG_CDROM_BOOT=y
|
||||
CONFIG_CDROM_EMU=y
|
||||
CONFIG_PCIBIOS=n
|
||||
CONFIG_APMBIOS=n
|
||||
CONFIG_PNPBIOS=n
|
||||
CONFIG_OPTIONROMS=y
|
||||
CONFIG_OPTIONROMS_DEPLOYED=y
|
||||
CONFIG_PMM=y
|
||||
CONFIG_BOOT=y
|
||||
CONFIG_KEYBOARD=y
|
||||
CONFIG_KBD_CALL_INT15_4F=y
|
||||
CONFIG_MOUSE=y
|
||||
CONFIG_S3_RESUME=y
|
||||
CONFIG_VGAHOOKS=y
|
||||
# CONFIG_DISABLE_A20 is not set
|
||||
|
||||
#
|
||||
# BIOS Tables
|
||||
#
|
||||
CONFIG_PIRTABLE=n
|
||||
CONFIG_MPTABLE=n
|
||||
CONFIG_SMBIOS=n
|
||||
CONFIG_ACPI=n
|
||||
|
||||
#
|
||||
# VGA ROM
|
||||
#
|
||||
# CONFIG_NO_VGABIOS is not set
|
||||
CONFIG_VGA_STANDARD_VGA=y
|
||||
# CONFIG_VGA_CIRRUS is not set
|
||||
# CONFIG_VGA_BOCHS is not set
|
||||
# CONFIG_VGA_GEODEGX2 is not set
|
||||
# CONFIG_VGA_GEODELX is not set
|
||||
CONFIG_BUILD_VGABIOS=y
|
||||
CONFIG_VGA_VBE=y
|
||||
CONFIG_VGA_PCI=y
|
||||
# CONFIG_OVERRIDE_PCI_ID is not set
|
||||
CONFIG_VGA_VID=0x0000
|
||||
CONFIG_VGA_DID=0x0000
|
||||
|
||||
#
|
||||
# Debugging
|
||||
#
|
||||
CONFIG_DEBUG_LEVEL=2
|
||||
# CONFIG_DEBUG_SERIAL is not set
|
||||
CONFIG_DEBUG_IO=y
|
BIN
bios/seabios.bin
Normal file
BIN
bios/seabios.bin
Normal file
Binary file not shown.
BIN
bios/vgabios.bin
Normal file
BIN
bios/vgabios.bin
Normal file
Binary file not shown.
71
debug.html
Normal file
71
debug.html
Normal file
|
@ -0,0 +1,71 @@
|
|||
<!doctype html>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
|
||||
<title>Virtual x86</title>
|
||||
|
||||
<script src="loader.js"></script>
|
||||
<link rel="stylesheet" href="v86.css">
|
||||
|
||||
<textarea readonly id="log"></textarea>
|
||||
|
||||
<div>
|
||||
|
||||
<a href="/v86/">To fast version</a>
|
||||
|
||||
<div id="boot_options">
|
||||
CD image: <input type="file" id="cd_image"><br>
|
||||
<small>(Bootable El Torito)</small><br><br>
|
||||
Floppy disk image: <input type="file" id="floppy_image"><br>
|
||||
<small>(1.44 or 2.88)</small><br><br>
|
||||
Hard drive disk image: <input type="file" id="hd_image"><br>
|
||||
<small></small><br><br>
|
||||
<hr>
|
||||
or <input type="button" value="Start FreeDOS" id="start_freedos">
|
||||
<br>
|
||||
<br>
|
||||
<input type="button" value="Start Linux" id="start_linux">
|
||||
<input type="button" value="Start KolibriOS" id="start_koli">
|
||||
<input type="button" value="Start Windows" id="start_win101">
|
||||
<input type="button" value="Start OpenBSD" id="start_bsd">
|
||||
<input type="button" value="Start Test" id="start_test">
|
||||
</div>
|
||||
<div id="runtime_options" style="display: none">
|
||||
<input type="button" value="Step" id="step">
|
||||
<input type="button" value="Run until" id="run_until">
|
||||
<input type="button" value="Debugger" id="debugger">
|
||||
<br>
|
||||
<div id="log_levels"></div>
|
||||
|
||||
<input type="button" value="Pause" id="run">
|
||||
<input type="button" value="Reset" id="reset">
|
||||
<input type="button" value="Send Ctrl-Alt-Del" id="ctrlaltdel">
|
||||
<input type="button" value="Get floppy image" id="get_floppy">
|
||||
<input type="button" value="Lock mouse" id="lock_mouse">
|
||||
<input type="button" value="Go fullscreen" id="fullscreen">
|
||||
|
||||
Scale:
|
||||
<input type="number" min="0.25" step="0.25" value="1.0" id="scale" style="width: 50px">
|
||||
|
||||
<div id="info">
|
||||
<div>running <span id="running_time"></span>s</div>
|
||||
<div>speed <span id="speed"></span>kIPS</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<pre style="display: none" id="loading"></pre>
|
||||
|
||||
<a href="readme.html">readme</a>
|
||||
<br>
|
||||
<br>
|
||||
</div>
|
||||
|
||||
<div id="screen_container">
|
||||
<div id="screen"></div>
|
||||
<canvas id="vga"></canvas>
|
||||
</div>
|
||||
|
||||
<br style="clear:both">
|
||||
|
||||
<input class="phone_keyboard">
|
||||
|
15
docs/Makefile
Normal file
15
docs/Makefile
Normal file
|
@ -0,0 +1,15 @@
|
|||
|
||||
DOCS=adapters embedding
|
||||
HTML=$(addsuffix .html, $(DOCS))
|
||||
MD=$(addsuffix .md, $(DOCS))
|
||||
|
||||
|
||||
all: $(HTML)
|
||||
|
||||
|
||||
%.html: %.md
|
||||
markdown $< > $@
|
||||
|
||||
|
||||
clean:
|
||||
rm -f *.html
|
49
docs/adapters.md
Normal file
49
docs/adapters.md
Normal file
|
@ -0,0 +1,49 @@
|
|||
|
||||
|
||||
Adapters are used to communicate between virtual hardware and the browser (or
|
||||
nodejs, or anything else). Currently, there are 3 adapters: Keyboard, Mouse and
|
||||
Screen. Adapters are passed through `settings.keyboard_adapter`,
|
||||
`settings.mouse_adapter` and `settings.screen_adapter` respectively, but they
|
||||
can also be undefined.
|
||||
|
||||
Here is a list of functions that must be implemented by adapters:
|
||||
|
||||
**ScreenAdapter:**
|
||||
|
||||
- `put_pixel(x, y, color)`
|
||||
- `put_pixel_linear(offset, color_part)`
|
||||
- `put_char(row, col, chr, bg_color, fg_color)`
|
||||
- `update_cursor(row, col)`
|
||||
- `update_cursor_scanline(start, end)`
|
||||
- `clear_screen()`
|
||||
- `timer_graphical()`
|
||||
- `timer_text()`
|
||||
- `set_mode(is_graphical)`
|
||||
- `set_size_graphical(width, height)`
|
||||
- `set_size_text(rows, cols)`
|
||||
- `destroy()`
|
||||
|
||||
**KeyboardAdapter:**
|
||||
|
||||
- `init(send_code_fn)`
|
||||
- `destroy()`
|
||||
- `enabled`
|
||||
|
||||
**MouseAdapter:**
|
||||
|
||||
- `init(click_fn, move_fn, wheel_fn)`
|
||||
- `destroy()`
|
||||
- `enabled`
|
||||
|
||||
**More**
|
||||
|
||||
In addition to adapters, the following functions must be provided in global
|
||||
scope (TODO: Improve that).
|
||||
|
||||
- `next_tick()`
|
||||
- `set_tick(fn)`
|
||||
- `log(str)` - only in debug modes
|
||||
|
||||
|
||||
<br>
|
||||
Everything on this page may be subject to change.
|
62
index.html
Normal file
62
index.html
Normal file
|
@ -0,0 +1,62 @@
|
|||
<!doctype html>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
|
||||
<title>Virtual x86</title>
|
||||
|
||||
<script src="v86_all.js"></script>
|
||||
<link rel="stylesheet" href="v86.css">
|
||||
|
||||
<textarea readonly id="log"></textarea>
|
||||
|
||||
<div>
|
||||
<div id="boot_options">
|
||||
CD image: <input type="file" id="cd_image"><br>
|
||||
<br>
|
||||
Floppy disk image: <input type="file" id="floppy_image"><br>
|
||||
<br>
|
||||
Hard drive disk image: <input type="file" id="hd_image"><br>
|
||||
<br>
|
||||
- OR -
|
||||
<br>
|
||||
<br>
|
||||
<input type="button" value="KolibriOS (1.4 MB)" id="start_koli"> - Graphical OS, takes about 60 seconds to boot<br>
|
||||
<input type="button" value="Linux 2.6 (4.9 MB)" id="start_linux"> - With busybox and lua interpreter, takes about 20 seconds to boot<br>
|
||||
<input type="button" value="Windows 1.01 (1.4 MB)" id="start_win101"> - Takes 1 second to boot<br>
|
||||
<input type="button" value="FreeDOS (0.7 MB)" id="start_freedos"> - With nasm, vim, debug.com, some games and demos, takes 1 second to boot<br>
|
||||
<input type="button" value="OpenBSD (1.4 MB)" id="start_bsd"> - Random boot floppy, takes very long to boot<br>
|
||||
</div>
|
||||
<div id="runtime_options" style="display: none">
|
||||
<input type="button" value="Pause" id="run">
|
||||
<input type="button" value="Reset" id="reset">
|
||||
<input type="button" value="Send Ctrl-Alt-Del" id="ctrlaltdel">
|
||||
<input type="button" value="Get modified floppy image" id="get_floppy">
|
||||
<input type="button" value="Lock mouse" id="lock_mouse">
|
||||
<input type="button" value="Go fullscreen" id="fullscreen">
|
||||
|
||||
Scale:
|
||||
<input type="number" min="0.25" step="0.25" value="1.0" id="scale" style="width: 50px">
|
||||
|
||||
<div id="info">
|
||||
<div>running <span id="running_time"></span>s</div>
|
||||
<div>speed <span id="speed"></span>kIPS</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<pre style="display: none" id="loading"></pre>
|
||||
<br>
|
||||
<br>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="screen_container">
|
||||
<div id="screen"></div>
|
||||
<canvas id="vga"></canvas>
|
||||
</div>
|
||||
|
||||
<br style="clear: both">
|
||||
<input type="text" class="phone_keyboard" style="display: none">
|
||||
<br>
|
||||
|
||||
<b>News:</b> Source Code now available: <a href="https://github.com/copy/iwbtc">Github</a>, <a href="v86-latest.tar.gz">tarball</a>.</li>
|
||||
|
||||
|
28
loader.js
Normal file
28
loader.js
Normal file
|
@ -0,0 +1,28 @@
|
|||
// load all files to run v86 in browser, uncompiled
|
||||
|
||||
(function()
|
||||
{
|
||||
var PATH = "src/",
|
||||
CORE_FILES="const.js io.js cpu.js main.js disk.js pci.js floppy.js memory.js dma.js pit.js vga.js ps2.js pic.js rtc.js uart.js"
|
||||
BROWSER_FILES="browser/main.js browser/screen.js browser/keyboard.js browser/mouse.js"
|
||||
|
||||
window.onload = function()
|
||||
{
|
||||
load_scripts(CORE_FILES);
|
||||
load_scripts(BROWSER_FILES);
|
||||
|
||||
function load_scripts(resp)
|
||||
{
|
||||
var files = resp.split(" "),
|
||||
script;
|
||||
|
||||
for(var i = 0; i < files.length; i++)
|
||||
{
|
||||
script = document.createElement("script");
|
||||
script.src = PATH + files[i] + "?" + Math.random();
|
||||
document.body.appendChild(script);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
})();
|
1646
src/arith.macro.js
Normal file
1646
src/arith.macro.js
Normal file
File diff suppressed because it is too large
Load diff
236
src/browser/keyboard.js
Normal file
236
src/browser/keyboard.js
Normal file
|
@ -0,0 +1,236 @@
|
|||
"use strict";
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
function KeyboardAdapter()
|
||||
{
|
||||
var
|
||||
/**
|
||||
* @type {!Object.<boolean>}
|
||||
*/
|
||||
keys_pressed = {},
|
||||
|
||||
keyboard = this,
|
||||
|
||||
// callback to call on a keypress
|
||||
send_code;
|
||||
|
||||
this.enabled = true;
|
||||
|
||||
/**
|
||||
* Format:
|
||||
* Javascript event.keyCode -> make code
|
||||
* @const
|
||||
*/
|
||||
var charmap = new Uint16Array([
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
// 0x08: backspace, tab, enter
|
||||
0x0E, 0x0F, 0, 0, 0, 0x1C, 0, 0,
|
||||
|
||||
// 0x10: shift, ctrl, alt, pause, caps lock
|
||||
0x2A, 0x1D, 0x38, 0, 0x3A, 0, 0, 0,
|
||||
|
||||
// 0x18: escape
|
||||
0, 0, 0, 0x01, 0, 0, 0, 0,
|
||||
|
||||
// 0x20: spacebar, page down/up, end, home, arrow keys, ins, del
|
||||
0x39, 0xE049, 0xE051, 0x4F, 0x47, 0x4B, 0x48, 0x4D,
|
||||
0x50, 0, 0, 0, 0, 0x52, 0x53, 0,
|
||||
|
||||
// 0x30: numbers
|
||||
0x0B, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
|
||||
0x09, 0x0A,
|
||||
|
||||
// 0x3B: ;= (firefox only)
|
||||
0, 0x27, 0, 0x0D, 0, 0, 0,
|
||||
|
||||
// 0x65: letters
|
||||
0x1E, 0x30, 0x2E, 0x20, 0x12, 0x21, 0x22, 0x23, 0x17, 0x24, 0x25, 0x26, 0x32,
|
||||
0x31, 0x18, 0x19, 0x10, 0x13, 0x1F, 0x14, 0x16, 0x2F, 0x11, 0x2D, 0x15, 0x2C,
|
||||
|
||||
0, 0, 0, 0, 0,
|
||||
|
||||
// 0x60: keypad
|
||||
0x52, 0x4F, 0x50, 0x51, 0x4B, 0x4C, 0x4D, 0x47,
|
||||
0x48, 0x49, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
// 0x70: F1 to F12
|
||||
0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x57, 0x58,
|
||||
|
||||
0, 0, 0, 0,
|
||||
|
||||
// 0x80
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
// 0x90
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
// 0xA0: - (firefox only)
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0x0C, 0, 0,
|
||||
|
||||
// 0xB0
|
||||
// ,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0x27, 0x0D, 0x33, 0x0C, 0x34, 0x35,
|
||||
|
||||
// 0xC0
|
||||
// `
|
||||
0x29, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
// 0xD0
|
||||
// [']\
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0x1A, 0x2B, 0x1B, 0x28, 0
|
||||
]);
|
||||
|
||||
this.init = function(code_fn)
|
||||
{
|
||||
this.destroy();
|
||||
|
||||
send_code = code_fn;
|
||||
|
||||
window.addEventListener("keyup", keyup_handler, false);
|
||||
window.addEventListener("keydown", keydown_handler, false);
|
||||
window.addEventListener("blur", blur_handler, false);
|
||||
};
|
||||
|
||||
this.destroy = function()
|
||||
{
|
||||
window.removeEventListener("keyup", keyup_handler, false);
|
||||
window.removeEventListener("keydown", keydown_handler, false);
|
||||
window.removeEventListener("blur", blur_handler, false);
|
||||
};
|
||||
|
||||
|
||||
function may_handle(e)
|
||||
{
|
||||
if(
|
||||
(e.shiftKey && e.ctrlKey && e.keyCode === 74) ||
|
||||
e.keyCode === 116
|
||||
) {
|
||||
// don't prevent opening chromium dev tools or F5
|
||||
// maybe add other important combinations here, too
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!keyboard.enabled)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(e.target)
|
||||
{
|
||||
return e.target.className === "phone_keyboard" ||
|
||||
(e.target.nodeName !== "INPUT" && e.target.nodeName !== "TEXTAREA");
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
function keyup_handler(e)
|
||||
{
|
||||
if(!may_handle(e))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var code = e.keyCode;
|
||||
|
||||
if(!keys_pressed[code])
|
||||
{
|
||||
// stray keyup
|
||||
return false;
|
||||
}
|
||||
|
||||
keys_pressed[code] = false;
|
||||
|
||||
if(!handler(code, false))
|
||||
{
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
function keydown_handler(e)
|
||||
{
|
||||
if(!may_handle(e))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var code = e.keyCode;
|
||||
|
||||
if(keys_pressed[code])
|
||||
{
|
||||
handler(code, false);
|
||||
}
|
||||
|
||||
keys_pressed[code] = true;
|
||||
|
||||
|
||||
if(!handler(code, true))
|
||||
{
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
function blur_handler(e)
|
||||
{
|
||||
// trigger keyup for all pressed keys
|
||||
var keys = Object.keys(keys_pressed),
|
||||
key;
|
||||
|
||||
for(var i = 0; i < keys.length; i++)
|
||||
{
|
||||
key = +keys[i];
|
||||
|
||||
if(keys_pressed[key])
|
||||
{
|
||||
handler(key, false);
|
||||
}
|
||||
}
|
||||
|
||||
keys_pressed = {};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} chr
|
||||
* @param {boolean} keydown
|
||||
*/
|
||||
function handler(chr, keydown)
|
||||
{
|
||||
if(chr >= charmap.length || charmap[chr] === 0)
|
||||
{
|
||||
dbg_log("missing char: " + h(chr), LOG_PS2);
|
||||
return true;
|
||||
}
|
||||
|
||||
var code = charmap[chr];
|
||||
|
||||
if(!keydown)
|
||||
{
|
||||
code |= 0x80;
|
||||
}
|
||||
dbg_log("Key: " + h(code) + " from " + h(chr) + " down=" + keydown, LOG_PS2);
|
||||
|
||||
if(code > 0xFF)
|
||||
{
|
||||
// prefix
|
||||
send_code(code >> 8);
|
||||
send_code(code & 0xFF);
|
||||
}
|
||||
else
|
||||
{
|
||||
send_code(code);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
589
src/browser/main.js
Normal file
589
src/browser/main.js
Normal file
|
@ -0,0 +1,589 @@
|
|||
"use strict";
|
||||
|
||||
|
||||
// setImmediate for the browser
|
||||
var next_tick, set_tick;
|
||||
|
||||
(function()
|
||||
{
|
||||
var fn,
|
||||
host = location.protocol + "//" + location.hostname;
|
||||
|
||||
set_tick = function(f)
|
||||
{
|
||||
fn = f;
|
||||
|
||||
window.removeEventListener("message", tick_handler, false);
|
||||
window.addEventListener("message", tick_handler, false);
|
||||
};
|
||||
|
||||
next_tick = function()
|
||||
{
|
||||
window.postMessage(null, host);
|
||||
};
|
||||
|
||||
function tick_handler(e)
|
||||
{
|
||||
if(e.origin === host)
|
||||
{
|
||||
fn();
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
function log(data)
|
||||
{
|
||||
var log_element = document.getElementById("log");
|
||||
|
||||
log_element.textContent += data + "\n";
|
||||
log_element.scrollTop = 1e9;
|
||||
}
|
||||
|
||||
function dump_text(text)
|
||||
{
|
||||
var box = document.createElement("textarea");
|
||||
|
||||
box.appendChild(document.createTextNode(text));
|
||||
document.body.appendChild(box);
|
||||
}
|
||||
|
||||
function dump_file(ab, name)
|
||||
{
|
||||
var blob = new Blob([ab]),
|
||||
a;
|
||||
|
||||
a = document.createElement("a");
|
||||
a["download"] = name;
|
||||
a.href = window.URL.createObjectURL(blob),
|
||||
a.textContent = "Download " + name;
|
||||
a.onclick = function() { a.parentNode.removeChild(a); };
|
||||
|
||||
a.dataset["downloadurl"] = ["application/octet-stream", a["download"], a.href].join(":");
|
||||
|
||||
document.body.appendChild(a);
|
||||
}
|
||||
|
||||
(function()
|
||||
{
|
||||
|
||||
/** @param {?=} progress */
|
||||
function load_file(filename, done, progress)
|
||||
{
|
||||
var http = new XMLHttpRequest();
|
||||
|
||||
http.open("get", filename, true);
|
||||
http.responseType = "arraybuffer";
|
||||
|
||||
http.onload = function(e)
|
||||
{
|
||||
//if(http.readyState === 4 && http.status === 200)
|
||||
if(http.response)
|
||||
{
|
||||
done(http.response);
|
||||
}
|
||||
};
|
||||
|
||||
if(progress)
|
||||
{
|
||||
http.onprogress = function(e)
|
||||
{
|
||||
progress(e);
|
||||
};
|
||||
}
|
||||
|
||||
http.send(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asynchronous access to ArrayBuffer, loading blocks lazily as needed.
|
||||
* This is just a prototype and partly incomplete.
|
||||
*
|
||||
* @constructor
|
||||
* @param {string} filename Name of the file to download parts
|
||||
* from. Replaces %d with the block number (padded)
|
||||
*/
|
||||
function AsyncXHRBuffer(filename, block_size, size)
|
||||
{
|
||||
var block_count = size / block_size,
|
||||
loaded_blocks,
|
||||
padding_width;
|
||||
|
||||
dbg_assert(block_count === (block_count | 0));
|
||||
loaded_blocks = Array(block_count);
|
||||
|
||||
padding_width = ("" + (block_count - 1)).length;
|
||||
|
||||
this.byteLength = size;
|
||||
|
||||
// warning: fn may be called synchronously or asynchronously
|
||||
this.get = function(start, len, fn)
|
||||
{
|
||||
// TODO: Unaligned read
|
||||
dbg_assert(start % block_size === 0);
|
||||
dbg_assert(len % block_size === 0);
|
||||
dbg_assert(len);
|
||||
|
||||
var blocks_to_load = len / block_size,
|
||||
data,
|
||||
loaded_count = 0,
|
||||
start_block = start / block_size;
|
||||
|
||||
if(blocks_to_load > 1)
|
||||
{
|
||||
// copy blocks in this buffer if there is more than one
|
||||
data = new Uint8Array(len);
|
||||
}
|
||||
|
||||
for(var i = start_block; i < start_block + blocks_to_load; i++)
|
||||
{
|
||||
this.load_block(i, block_loaded);
|
||||
}
|
||||
|
||||
function block_loaded(buffer, i)
|
||||
{
|
||||
var block = new Uint8Array(buffer);
|
||||
loaded_count++;
|
||||
|
||||
if(blocks_to_load === 1)
|
||||
{
|
||||
data = block;
|
||||
}
|
||||
else
|
||||
{
|
||||
data.set(block, (i - start_block) * block_size);
|
||||
}
|
||||
|
||||
if(loaded_count === blocks_to_load)
|
||||
{
|
||||
fn(data);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.load_block = function(i, fn)
|
||||
{
|
||||
var cached_block = loaded_blocks[i];
|
||||
|
||||
if(cached_block === undefined)
|
||||
{
|
||||
var file = filename.replace("%d", String.pad0(i, padding_width));
|
||||
|
||||
load_file(file, function(buffer)
|
||||
{
|
||||
loaded_blocks[i] = buffer;
|
||||
fn(buffer, i);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
fn(cached_block, i);
|
||||
}
|
||||
};
|
||||
|
||||
this.get_buffer = function(fn)
|
||||
{
|
||||
// We must download all parts, unlikely a good idea for big files
|
||||
if(size > 32 * 1024 * 1024)
|
||||
{
|
||||
dbg_log("Warning: Downloading all parts of a huge file. Will probably " +
|
||||
"crash or never finish");
|
||||
}
|
||||
|
||||
this.get(0, size, function(data)
|
||||
{
|
||||
return data.buffer;
|
||||
});
|
||||
};
|
||||
|
||||
this.set = function(start, slice, fn)
|
||||
{
|
||||
// Discard (we can't write to the server)
|
||||
// TODO: Put data into cache
|
||||
};
|
||||
}
|
||||
|
||||
function lock_mouse(elem)
|
||||
{
|
||||
var fn = elem["requestPointerLock"] ||
|
||||
elem["mozRequestPointerLock"] ||
|
||||
elem["webkitRequestPointerLock"];
|
||||
|
||||
if(fn)
|
||||
{
|
||||
fn.call(elem);
|
||||
}
|
||||
}
|
||||
|
||||
function show_progress(e)
|
||||
{
|
||||
var el = $("loading");
|
||||
el.style.display = "block";
|
||||
|
||||
if(e.lengthComputable)
|
||||
{
|
||||
var per50 = e.loaded / e.total * 50 | 0;
|
||||
|
||||
el.textContent = "Loading: " + 2 * per50 + "% [" +
|
||||
String.chr_repeat("#", per50) +
|
||||
String.chr_repeat(" ", 50 - per50) + "]";
|
||||
}
|
||||
else
|
||||
{
|
||||
el.textContent = "Loading ...";
|
||||
}
|
||||
}
|
||||
|
||||
function $(id)
|
||||
{
|
||||
return document.getElementById(id);
|
||||
}
|
||||
|
||||
window.onload = function()
|
||||
{
|
||||
if(!("responseType" in new XMLHttpRequest))
|
||||
{
|
||||
log("Your browser is not supported because it doesn't have XMLHttpRequest.responseType");
|
||||
return;
|
||||
}
|
||||
|
||||
var settings = {
|
||||
load_devices: true
|
||||
};
|
||||
|
||||
|
||||
$("lock_mouse").onclick = function()
|
||||
{
|
||||
lock_mouse(document.body);
|
||||
$("lock_mouse").blur();
|
||||
};
|
||||
|
||||
load_file("bios/seabios.bin", function(img)
|
||||
{
|
||||
settings.bios = img;
|
||||
});
|
||||
|
||||
load_file("bios/vgabios.bin", function(img)
|
||||
{
|
||||
settings.vga_bios = img;
|
||||
});
|
||||
|
||||
function load_local(me, type)
|
||||
{
|
||||
if(me.files.length)
|
||||
{
|
||||
var reader = new FileReader();
|
||||
|
||||
reader.onload = function(e)
|
||||
{
|
||||
var buffer = new SyncBuffer(e.target.result);
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case "floppy":
|
||||
settings.floppy_disk = buffer;
|
||||
break;
|
||||
case "hd":
|
||||
settings.hda_disk = buffer;
|
||||
break;
|
||||
case "cdrom":
|
||||
settings.cdrom_disk = buffer;
|
||||
break;
|
||||
}
|
||||
|
||||
init(settings);
|
||||
};
|
||||
|
||||
//reader.readAsBinaryString($("file").files[0]);
|
||||
reader.readAsArrayBuffer(me.files[0]);
|
||||
}
|
||||
};
|
||||
|
||||
$("floppy_image").onchange = function()
|
||||
{
|
||||
load_local(this, "floppy");
|
||||
};
|
||||
|
||||
$("cd_image").onchange = function()
|
||||
{
|
||||
load_local(this, "cdrom");
|
||||
};
|
||||
|
||||
$("hd_image").onchange = function()
|
||||
{
|
||||
load_local(this, "hd");
|
||||
};
|
||||
|
||||
$("start_freedos").onclick = function()
|
||||
{
|
||||
load_file("images/freedos722.img", function(buffer)
|
||||
{
|
||||
settings.floppy_disk = new SyncBuffer(buffer);
|
||||
init(settings);
|
||||
}, show_progress);
|
||||
|
||||
$("start_freedos").blur();
|
||||
};
|
||||
|
||||
$("start_win101").onclick = function()
|
||||
{
|
||||
load_file("images/windows101.img", function(buffer)
|
||||
{
|
||||
settings.floppy_disk = new SyncBuffer(buffer);
|
||||
init(settings);
|
||||
}, show_progress);
|
||||
|
||||
$("start_win101").blur();
|
||||
};
|
||||
|
||||
|
||||
$("start_linux").onclick = function()
|
||||
{
|
||||
load_file("images/linux.iso", function(buffer)
|
||||
{
|
||||
settings.cdrom_disk = new SyncBuffer(buffer);
|
||||
init(settings);
|
||||
}, show_progress);
|
||||
|
||||
$("start_linux").blur();
|
||||
};
|
||||
|
||||
$("start_koli").onclick = function()
|
||||
{
|
||||
load_file("images/kolibri.img", function(buffer)
|
||||
{
|
||||
settings.floppy_disk = new SyncBuffer(buffer);
|
||||
init(settings);
|
||||
}, show_progress);
|
||||
|
||||
$("start_koli").blur();
|
||||
};
|
||||
|
||||
$("start_bsd").onclick = function()
|
||||
{
|
||||
load_file("images/openbsd.img", function(buffer)
|
||||
{
|
||||
settings.floppy_disk = new SyncBuffer(buffer);
|
||||
init(settings);
|
||||
}, show_progress);
|
||||
|
||||
$("start_bsd").blur();
|
||||
};
|
||||
|
||||
if(DEBUG)
|
||||
{
|
||||
$("start_test").onclick = function()
|
||||
{
|
||||
settings.floppy_disk = new AsyncXHRBuffer("images/fd/freedos.part%d.img", 512, 720 * 1024);
|
||||
init(settings);
|
||||
|
||||
//settings.bios = settings.vga_bios = undefined;
|
||||
//settings.linux = {};
|
||||
////settings.linux.cmdline = "console=ttyS0 root=/dev/hda ro init=/sbin/init notsc=1 hdb=none"
|
||||
//settings.linux.cmdline = "root=/dev/ram0 rw init=/sbin/init notsc=1";
|
||||
|
||||
//load_file("images/linux/vmlinux.bin", function(buffer)
|
||||
//{
|
||||
// settings.linux.vmlinux = buffer;
|
||||
// load_file("images/linux/linuxstart.bin", function(buffer)
|
||||
// {
|
||||
// settings.linux.linuxstart = buffer;
|
||||
// load_file("images/linux/root.bin", function(buffer)
|
||||
// {
|
||||
// settings.linux.root = buffer;
|
||||
// init(settings);
|
||||
// });
|
||||
// });
|
||||
//});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// works in firefox and chromium
|
||||
if(document.readyState === "complete")
|
||||
{
|
||||
window.onload();
|
||||
}
|
||||
|
||||
|
||||
// load_external("https://dl.dropbox.com/example/freedos.img.js");
|
||||
function load_external(url)
|
||||
{
|
||||
window["loaded"] = function(bin_image)
|
||||
{
|
||||
var buffer = new ArrayBuffer(bin_image.length),
|
||||
buffer_array = new Uint8Array(buffer);
|
||||
|
||||
for(var i = 0; i < bin_image.length; i++)
|
||||
{
|
||||
buffer_array[i] = bin_image.charCodeAt(i);
|
||||
}
|
||||
|
||||
window["loaded"] = function() {
|
||||
dbg_log("load_external: result loaded twice ?");
|
||||
};
|
||||
};
|
||||
|
||||
var script = document.createElement("script");
|
||||
script.src = url;
|
||||
|
||||
document.body.appendChild(script);
|
||||
}
|
||||
|
||||
|
||||
function init(settings)
|
||||
{
|
||||
var cpu = new v86(),
|
||||
screen_adapter = new ScreenAdapter();
|
||||
|
||||
$("boot_options").parentNode.removeChild($("boot_options"));
|
||||
$("loading").style.display = "none";
|
||||
$("runtime_options").style.display = "block";
|
||||
document.getElementsByClassName("phone_keyboard")[0].style.display = "block";
|
||||
|
||||
if(DEBUG)
|
||||
{
|
||||
$("step").onclick = function()
|
||||
{
|
||||
debug.step();
|
||||
}
|
||||
|
||||
$("run_until").onclick = function()
|
||||
{
|
||||
debug.run_until();
|
||||
};
|
||||
|
||||
$("debugger").onclick = function()
|
||||
{
|
||||
debug.debugger();
|
||||
};
|
||||
}
|
||||
|
||||
var running = true;
|
||||
|
||||
$("run").onclick = function()
|
||||
{
|
||||
if(running)
|
||||
{
|
||||
running_time += Date.now() - last_tick;
|
||||
$("run").value = "Run";
|
||||
cpu.stop();
|
||||
}
|
||||
else
|
||||
{
|
||||
$("run").value = "Pause";
|
||||
cpu.run();
|
||||
last_tick = Date.now();
|
||||
}
|
||||
|
||||
running = !running;
|
||||
$("run").blur();
|
||||
};
|
||||
|
||||
var time = document.getElementById("running_time"),
|
||||
ips = document.getElementById("speed"),
|
||||
last_tick = Date.now(),
|
||||
running_time = 0,
|
||||
last_instr_counter = 0;
|
||||
|
||||
function update_info()
|
||||
{
|
||||
if(running)
|
||||
{
|
||||
var now = Date.now();
|
||||
|
||||
running_time += now - last_tick;
|
||||
last_tick = now;
|
||||
|
||||
ips.textContent = (cpu.instr_counter - last_instr_counter) / 1000 | 0;
|
||||
time.textContent = (running_time / 1000 | 0);
|
||||
|
||||
last_instr_counter = cpu.instr_counter;
|
||||
}
|
||||
}
|
||||
|
||||
setInterval(update_info, 1000);
|
||||
|
||||
$("reset").onclick = function()
|
||||
{
|
||||
cpu.restart();
|
||||
$("reset").blur();
|
||||
};
|
||||
|
||||
$("get_floppy").onclick = function()
|
||||
{
|
||||
var buffer = cpu.dev.fdc.buffer;
|
||||
|
||||
if(!buffer)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
buffer.get_buffer(function(b)
|
||||
{
|
||||
dump_file(b, "floppy.img");
|
||||
});
|
||||
|
||||
$("get_floppy").blur();
|
||||
};
|
||||
|
||||
$("ctrlaltdel").onclick = function()
|
||||
{
|
||||
var ps2 = cpu.dev.ps2;
|
||||
|
||||
ps2.kbd_send_code(0x1D); // ctrl
|
||||
ps2.kbd_send_code(0x38); // alt
|
||||
ps2.kbd_send_code(0x53); // delete
|
||||
|
||||
// break codes
|
||||
ps2.kbd_send_code(0x1D | 0x80);
|
||||
ps2.kbd_send_code(0x38 | 0x80);
|
||||
ps2.kbd_send_code(0x53 | 0x80);
|
||||
|
||||
$("ctrlaltdel").blur();
|
||||
};
|
||||
|
||||
$("scale").onchange = function()
|
||||
{
|
||||
var n = parseFloat(this.value);
|
||||
|
||||
if(n || n > 0)
|
||||
{
|
||||
screen_adapter.set_scale(n, n);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.value = "1";
|
||||
}
|
||||
};
|
||||
|
||||
$("fullscreen").onclick = function()
|
||||
{
|
||||
var elem = document.getElementById("screen_container"),
|
||||
|
||||
// bracket notation because otherwise they get renamed by closure compiler
|
||||
fn = elem["requestFullScreen"] ||
|
||||
elem["webkitRequestFullscreen"] ||
|
||||
elem["mozRequestFullScreen"] ||
|
||||
elem["msRequestFullScreen"];
|
||||
|
||||
if(fn)
|
||||
{
|
||||
fn.call(elem);
|
||||
|
||||
// This is necessary, because otherwise chromium keyboard doesn't work anymore.
|
||||
// Might (but doesn't seem to) break something else
|
||||
document.getElementsByClassName("phone_keyboard")[0].focus();
|
||||
}
|
||||
|
||||
lock_mouse(elem);
|
||||
};
|
||||
|
||||
settings.screen_adapter = screen_adapter;
|
||||
settings.keyboard_adapter = new KeyboardAdapter();
|
||||
settings.mouse_adapter = new MouseAdapter();
|
||||
|
||||
cpu.init(settings);
|
||||
cpu.run();
|
||||
}
|
||||
|
||||
})();
|
132
src/browser/mouse.js
Normal file
132
src/browser/mouse.js
Normal file
|
@ -0,0 +1,132 @@
|
|||
|
||||
/** @constructor */
|
||||
function MouseAdapter()
|
||||
{
|
||||
/** @const */
|
||||
var SPEED_FACTOR = .5;
|
||||
|
||||
var left_down = false,
|
||||
right_down = false,
|
||||
middle_down = false,
|
||||
|
||||
last_x = 0,
|
||||
last_y = 0,
|
||||
|
||||
// callback to call on a mouse click
|
||||
send_click,
|
||||
|
||||
// callback to call on a mouse move
|
||||
send_delta,
|
||||
|
||||
mouse = this;
|
||||
|
||||
this.enabled = false;
|
||||
|
||||
function may_handle(e)
|
||||
{
|
||||
return mouse.enabled &&
|
||||
(!e.target || e.type === "mousemove" || (e.target.nodeName !== "INPUT" && e.target.nodeName !== "TEXTAREA"));
|
||||
}
|
||||
|
||||
this.destroy = function()
|
||||
{
|
||||
window.removeEventListener("mousemove", mousemove_handler, false);
|
||||
document.removeEventListener("contextmenu", contextmenu_handler, false);
|
||||
window.removeEventListener("mousedown", mousedown_handler, false);
|
||||
window.removeEventListener("mouseup", mouseup_handler, false);
|
||||
};
|
||||
|
||||
this.init = function(click_fn, delta_fn, wheel_fn)
|
||||
{
|
||||
this.destroy();
|
||||
|
||||
send_click = click_fn;
|
||||
send_delta = delta_fn;
|
||||
|
||||
// TODO: wheel_fn
|
||||
|
||||
window.addEventListener("mousemove", mousemove_handler, false);
|
||||
document.addEventListener("contextmenu", contextmenu_handler, false);
|
||||
window.addEventListener("mousedown", mousedown_handler, false);
|
||||
window.addEventListener("mouseup", mouseup_handler, false);
|
||||
};
|
||||
|
||||
function mousemove_handler(e)
|
||||
{
|
||||
if(!may_handle(e))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var delta_x, delta_y;
|
||||
|
||||
if(true)
|
||||
{
|
||||
delta_x = e["webkitMovementX"] || e["mozMovementX"] || 0;
|
||||
delta_y = e["webkitMovementY"] || e["mozMovementY"] || 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fallback for other browsers?
|
||||
delta_x = e.clientX - last_x;
|
||||
delta_y = e.clientY - last_y;
|
||||
|
||||
last_x = e.clientX;
|
||||
last_y = e.clientY;
|
||||
}
|
||||
|
||||
|
||||
delta_x = Math.roundInfinity(delta_x * SPEED_FACTOR);
|
||||
delta_y = Math.roundInfinity(delta_y * SPEED_FACTOR);
|
||||
|
||||
send_delta(delta_x, -delta_y);
|
||||
|
||||
}
|
||||
|
||||
function contextmenu_handler(e)
|
||||
{
|
||||
if(may_handle(e))
|
||||
{
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
function mousedown_handler(e)
|
||||
{
|
||||
if(may_handle(e))
|
||||
{
|
||||
click_event(e, true);
|
||||
}
|
||||
}
|
||||
|
||||
function mouseup_handler(e)
|
||||
{
|
||||
if(may_handle(e))
|
||||
{
|
||||
click_event(e, false);
|
||||
}
|
||||
}
|
||||
|
||||
function click_event(e, down)
|
||||
{
|
||||
if(e.which === 1)
|
||||
{
|
||||
left_down = down;
|
||||
}
|
||||
else if(e.which === 2)
|
||||
{
|
||||
middle_down = down;
|
||||
}
|
||||
else if(e.which === 3)
|
||||
{
|
||||
right_down = down;
|
||||
}
|
||||
else
|
||||
{
|
||||
dbg_log("Unknown event.which: " + e.which, LOG_MOUSE);
|
||||
}
|
||||
send_click(left_down, middle_down, right_down);
|
||||
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
354
src/browser/screen.js
Normal file
354
src/browser/screen.js
Normal file
|
@ -0,0 +1,354 @@
|
|||
"use strict";
|
||||
|
||||
if(!window.requestAnimationFrame)
|
||||
{
|
||||
window.requestAnimationFrame =
|
||||
window.mozRequestAnimationFrame ||
|
||||
window.webkitRequestAnimationFrame;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adapter to use visual screen in browsers (in constrast to node)
|
||||
* @constructor
|
||||
*/
|
||||
function ScreenAdapter()
|
||||
{
|
||||
var
|
||||
dom_target = document.body,
|
||||
text_screen = document.getElementById("screen"),
|
||||
graphic_screen = document.getElementById("vga"),
|
||||
graphic_context = graphic_screen.getContext("2d"),
|
||||
cursor_element = document.createElement("div"),
|
||||
|
||||
|
||||
graphic_image_data,
|
||||
graphic_buffer,
|
||||
|
||||
/** @type {number} */
|
||||
cursor_row,
|
||||
|
||||
/** @type {number} */
|
||||
cursor_col,
|
||||
|
||||
/** @type {number} */
|
||||
scale_x = 1,
|
||||
|
||||
/** @type {number} */
|
||||
scale_y = 1,
|
||||
|
||||
graphical_mode_width,
|
||||
|
||||
screen = this,
|
||||
|
||||
changed_rows,
|
||||
|
||||
did_redraw = true,
|
||||
|
||||
// Index 0: ASCII code
|
||||
// Index 1: Background color
|
||||
// Index 2: Foreground color
|
||||
text_mode_data,
|
||||
|
||||
// number of columns
|
||||
text_mode_width,
|
||||
|
||||
// number of rows
|
||||
text_mode_height;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Charmaps that containt unicode sequences for the default dospage
|
||||
* @const
|
||||
*/
|
||||
var charmap_high = new Uint16Array([
|
||||
0xC7, 0xFC, 0xE9, 0xE2, 0xE4, 0xE0, 0xE5, 0xE7,
|
||||
0xEA, 0xEB, 0xE8, 0xEF, 0xEE, 0xEC, 0xC4, 0xC5,
|
||||
0xC9, 0xE6, 0xC6, 0xF4, 0xF6, 0xF2, 0xFB, 0xF9,
|
||||
0xFF, 0xD6, 0xDC, 0xA2, 0xA3, 0xA5, 0x20A7, 0x192,
|
||||
0xE1, 0xED, 0xF3, 0xFA, 0xF1, 0xD1, 0xAA, 0xBA,
|
||||
0xBF, 0x2310, 0xAC, 0xBD, 0xBC, 0xA1, 0xAB, 0xBB,
|
||||
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
|
||||
0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
|
||||
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F,
|
||||
0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
|
||||
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B,
|
||||
0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
|
||||
0x3B1, 0xDF, 0x393, 0x3C0, 0x3A3, 0x3C3, 0xB5, 0x3C4,
|
||||
0x3A6, 0x398, 0x3A9, 0x3B4, 0x221E, 0x3C6, 0x3B5, 0x2229,
|
||||
0x2261, 0xB1, 0x2265, 0x2264, 0x2320, 0x2321, 0xF7,
|
||||
0x2248, 0xB0, 0x2219, 0xB7, 0x221A, 0x207F, 0xB2, 0x25A0, 0xA0
|
||||
]);
|
||||
|
||||
/** @const */
|
||||
var charmap_low = new Uint16Array([
|
||||
0x20, 0x263A, 0x263B, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022,
|
||||
0x25D8, 0x25CB, 0x25D9, 0x2642, 0x2640, 0x266A, 0x266B, 0x263C,
|
||||
0x25BA, 0x25C4, 0x2195, 0x203C, 0xB6, 0xA7, 0x25AC, 0x21A8,
|
||||
0x2191, 0x2193, 0x2192, 0x2190, 0x221F, 0x2194, 0x25B2, 0x25BC
|
||||
]);
|
||||
|
||||
graphic_context["imageSmoothingEnabled"] = false;
|
||||
graphic_context["mozImageSmoothingEnabled"] = false;
|
||||
graphic_context["webkitImageSmoothingEnabled"] = false;
|
||||
|
||||
cursor_element.id = "cursor";
|
||||
text_screen.style.display = "block";
|
||||
|
||||
graphic_screen.style.display = "none";
|
||||
|
||||
this.put_char = function(row, col, chr, bg_color, fg_color)
|
||||
{
|
||||
changed_rows[row] = 1;
|
||||
|
||||
var p = 3 * (row * text_mode_width + col);
|
||||
text_mode_data[p] = chr;
|
||||
text_mode_data[p + 1] = bg_color;
|
||||
text_mode_data[p + 2] = fg_color;
|
||||
};
|
||||
|
||||
this.timer_text = function()
|
||||
{
|
||||
if(!did_redraw)
|
||||
{
|
||||
return;
|
||||
}
|
||||
did_redraw = false;
|
||||
|
||||
requestAnimationFrame(update_text);
|
||||
};
|
||||
|
||||
function update_text()
|
||||
{
|
||||
did_redraw = true;
|
||||
|
||||
for(var i = 0; i < text_mode_height; i++)
|
||||
{
|
||||
if(changed_rows[i])
|
||||
{
|
||||
screen.text_update_row(i);
|
||||
changed_rows[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.put_pixel = function(x, y, color)
|
||||
{
|
||||
var offset = y * graphical_mode_width + x << 2;
|
||||
|
||||
graphic_buffer[offset] = color >> 16 & 0xFF;
|
||||
graphic_buffer[offset + 1] = color >> 8 & 0xFF;
|
||||
graphic_buffer[offset + 2] = color & 0xFF;
|
||||
};
|
||||
|
||||
this.put_pixel_linear = function(index, color)
|
||||
{
|
||||
// (addr ^ 3) - 1: Change BGR (svga) order to RGB (canvas)
|
||||
graphic_buffer[(index ^ 3) - 1] = color;
|
||||
};
|
||||
|
||||
this.timer_graphical = function()
|
||||
{
|
||||
if(!did_redraw)
|
||||
{
|
||||
return;
|
||||
}
|
||||
did_redraw = false;
|
||||
|
||||
requestAnimationFrame(function()
|
||||
{
|
||||
did_redraw = true;
|
||||
graphic_context.putImageData(graphic_image_data, 0, 0);
|
||||
});
|
||||
};
|
||||
|
||||
this.destroy = function()
|
||||
{
|
||||
//dom_target.removeChild(text_screen);
|
||||
//dom_target.removeChild(graphic_screen);
|
||||
};
|
||||
|
||||
this.set_mode = function(graphical)
|
||||
{
|
||||
if(graphical)
|
||||
{
|
||||
text_screen.style.display = "none";
|
||||
graphic_screen.style.display = "block";
|
||||
}
|
||||
else
|
||||
{
|
||||
text_screen.style.display = "block";
|
||||
graphic_screen.style.display = "none";
|
||||
}
|
||||
};
|
||||
|
||||
this.clear_screen = function()
|
||||
{
|
||||
graphic_context.fillStyle = "#000";
|
||||
graphic_context.fillRect(0, 0, graphic_screen.width, graphic_screen.height);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {number} cols
|
||||
* @param {number} rows
|
||||
*/
|
||||
this.set_size_text = function(cols, rows)
|
||||
{
|
||||
changed_rows = new Int8Array(rows);
|
||||
text_mode_data = new Int32Array(cols * rows * 3);
|
||||
|
||||
text_mode_width = cols;
|
||||
text_mode_height = rows;
|
||||
|
||||
while(text_screen.firstChild)
|
||||
{
|
||||
text_screen.removeChild(text_screen.firstChild);
|
||||
}
|
||||
|
||||
for(var i = 0; i < rows; i++)
|
||||
{
|
||||
text_screen.appendChild(document.createElement("div"));
|
||||
}
|
||||
};
|
||||
|
||||
this.set_size_graphical = function(width, height)
|
||||
{
|
||||
graphic_screen.style.display = "block";
|
||||
|
||||
graphic_screen.width = width;
|
||||
graphic_screen.height = height;
|
||||
|
||||
//graphic_screen.style.width = width * scale_x + "px";
|
||||
//graphic_screen.style.height = height * scale_y + "px";
|
||||
|
||||
// Make sure to call this here, because pixels are transparent otherwise
|
||||
screen.clear_screen();
|
||||
|
||||
graphic_image_data = graphic_context.getImageData(0, 0, width, height);
|
||||
graphic_buffer = graphic_image_data.data;
|
||||
|
||||
graphical_mode_width = width;
|
||||
};
|
||||
|
||||
this.set_scale = function(s_x, s_y)
|
||||
{
|
||||
scale_x = s_x;
|
||||
scale_y = s_y;
|
||||
|
||||
elem_set_scale(graphic_screen, scale_x, scale_y);
|
||||
elem_set_scale(text_screen, scale_x, scale_y);
|
||||
};
|
||||
this.set_scale(scale_x, scale_y);
|
||||
|
||||
function elem_set_scale(elem, scale_x, scale_y)
|
||||
{
|
||||
var scale_str = "";
|
||||
|
||||
scale_str += scale_x === 1 ? "" : " scaleX(" + scale_x + ")";
|
||||
scale_str += scale_y === 1 ? "" : " scaleY(" + scale_y + ")";
|
||||
|
||||
elem.style.webkitTransform = elem.style.MozTransform = scale_str;
|
||||
}
|
||||
|
||||
this.update_cursor_scanline = function(start, end)
|
||||
{
|
||||
if(start & 0x20)
|
||||
{
|
||||
cursor_element.style.display = "none";
|
||||
}
|
||||
else
|
||||
{
|
||||
cursor_element.style.display = "inline";
|
||||
|
||||
cursor_element.style.height = (end - start) + "px";
|
||||
cursor_element.style.marginTop = start + "px";
|
||||
}
|
||||
};
|
||||
|
||||
this.update_cursor = function(row, col)
|
||||
{
|
||||
if(row !== cursor_row || col !== cursor_col)
|
||||
{
|
||||
changed_rows[row] = 1;
|
||||
changed_rows[cursor_row] = 1;
|
||||
|
||||
cursor_row = row;
|
||||
cursor_col = col;
|
||||
}
|
||||
};
|
||||
|
||||
this.text_update_row = function(row)
|
||||
{
|
||||
var offset = 3 * row * text_mode_width,
|
||||
row_element,
|
||||
color_element,
|
||||
bg_color,
|
||||
fg_color,
|
||||
text;
|
||||
|
||||
row_element = document.createElement("div");
|
||||
|
||||
for(var i = 0; i < text_mode_width; )
|
||||
{
|
||||
color_element = document.createElement("span");
|
||||
|
||||
bg_color = text_mode_data[offset + 1];
|
||||
fg_color = text_mode_data[offset + 2];
|
||||
|
||||
color_element.style.backgroundColor = "#" + h(bg_color, 6);
|
||||
color_element.style.color = "#" + h(fg_color, 6);
|
||||
|
||||
text = "";
|
||||
|
||||
// put characters of the same color in one element
|
||||
while(i < text_mode_width
|
||||
&& text_mode_data[offset + 1] === bg_color
|
||||
&& text_mode_data[offset + 2] === fg_color)
|
||||
{
|
||||
var ascii = text_mode_data[offset],
|
||||
chr;
|
||||
|
||||
// use of utf-8
|
||||
if(ascii > 127)
|
||||
{
|
||||
chr = String.fromCharCode(charmap_high[ascii - 0x80]);
|
||||
}
|
||||
else if(ascii < 32)
|
||||
{
|
||||
chr = String.fromCharCode(charmap_low[ascii]);
|
||||
}
|
||||
else
|
||||
{
|
||||
chr = String.fromCharCode(ascii);
|
||||
}
|
||||
|
||||
text += chr;
|
||||
|
||||
i++;
|
||||
offset += 3;
|
||||
|
||||
if(row === cursor_row)
|
||||
{
|
||||
if(i === cursor_col)
|
||||
{
|
||||
// next row will be cursor
|
||||
// create new element
|
||||
break;
|
||||
}
|
||||
else if(i === cursor_col + 1)
|
||||
{
|
||||
// found the cursor
|
||||
row_element.appendChild(cursor_element);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
color_element.textContent = text;
|
||||
row_element.appendChild(color_element);
|
||||
}
|
||||
|
||||
text_screen.replaceChild(row_element, text_screen.childNodes[row]);
|
||||
};
|
||||
}
|
155
src/const.js
Normal file
155
src/const.js
Normal file
|
@ -0,0 +1,155 @@
|
|||
|
||||
/** @define {boolean} */
|
||||
var DEBUG = true;
|
||||
|
||||
|
||||
var
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
memory_size = 1024 * 1024 * 64;
|
||||
|
||||
var
|
||||
|
||||
/** @const */ LOG_ALL = -1,
|
||||
/** @const */ LOG_NONE = 0,
|
||||
|
||||
/** @const */ LOG_OTHER = 0x00001,
|
||||
/** @const */ LOG_CPU = 0x00002,
|
||||
/** @const */ LOG_FPU = 0x00004,
|
||||
/** @const */ LOG_MEM = 0x00008,
|
||||
/** @const */ LOG_DMA = 0x00010,
|
||||
/** @const */ LOG_IO = 0x00020,
|
||||
/** @const */ LOG_PS2 = 0x00040,
|
||||
/** @const */ LOG_PIC = 0x00080,
|
||||
/** @const */ LOG_VGA = 0x00100,
|
||||
/** @const */ LOG_PIT = 0x00200,
|
||||
/** @const */ LOG_MOUSE = 0x00400,
|
||||
/** @const */ LOG_PCI = 0x00800,
|
||||
/** @const */ LOG_BIOS = 0x01000,
|
||||
/** @const */ LOG_CD = 0x02000,
|
||||
/** @const */ LOG_SERIAL = 0x04000,
|
||||
/** @const */ LOG_DISK = 0x08000,
|
||||
/** @const */ LOG_RTC = 0x10000,
|
||||
|
||||
|
||||
|
||||
///** @const */ LOG_LEVEL = LOG_OTHER | LOG_PS2 | LOG_BIOS;
|
||||
///** @const */ LOG_LEVEL = LOG_PS2 | LOG_OTHER | LOG_IO;
|
||||
///** @const */ LOG_LEVEL = LOG_PS2;
|
||||
///** @const */ LOG_LEVEL = LOG_OTHER | LOG_CPU | LOG_BIOS;
|
||||
///** @const */ LOG_LEVEL = LOG_VGA | LOG_IO | LOG_BIOS | LOG_OTHER;
|
||||
///** @const */ LOG_LEVEL = LOG_FPU | LOG_OTHER;
|
||||
///** @const */ LOG_LEVEL = LOG_DMA | LOG_DISK | LOG_IO | LOG_PCI;
|
||||
///** @const */ LOG_LEVEL = LOG_DMA | LOG_DISK | LOG_PCI | LOG_CD | LOG_BIOS;
|
||||
/** @const */ LOG_LEVEL = LOG_ALL & ~LOG_DISK & ~LOG_DMA & ~LOG_VGA & ~LOG_PS2 & ~LOG_FPU;
|
||||
///** @const */ LOG_LEVEL = LOG_SERIAL | LOG_IO;
|
||||
///** @const */ LOG_LEVEL = LOG_PIT | LOG_RTC;
|
||||
///** @const */ LOG_LEVEL = 0;
|
||||
|
||||
|
||||
var
|
||||
/** @const */ TLB_SYSTEM_READ = 1,
|
||||
/** @const */ TLB_SYSTEM_WRITE = 2,
|
||||
/** @const */ TLB_USER_READ = 4,
|
||||
/** @const */ TLB_USER_WRITE = 8;
|
||||
|
||||
|
||||
var
|
||||
|
||||
|
||||
// flags register bitflags
|
||||
/** @const */ flag_carry = 1,
|
||||
/** @const */ flag_parity = 4,
|
||||
/** @const */ flag_adjust = 16,
|
||||
/** @const */ flag_zero = 64,
|
||||
/** @const */ flag_sign = 128,
|
||||
/** @const */ flag_trap = 256,
|
||||
/** @const */ flag_interrupt = 512,
|
||||
/** @const */ flag_direction = 1024,
|
||||
/** @const */ flag_overflow = 2048,
|
||||
/** @const */ flag_iopl = 1 << 12 | 1 << 13,
|
||||
/** @const */ flag_nt = 1 << 14,
|
||||
/** @const */ flag_vm = 1 << 17,
|
||||
|
||||
/**
|
||||
* default values of unused flags bits
|
||||
* @const
|
||||
*/
|
||||
flags_default = 1 << 1,
|
||||
|
||||
/**
|
||||
* bitmask to select used flags bits
|
||||
* @const
|
||||
*/
|
||||
flags_mask = 1 << 0 | 1 << 2 | 1 << 4 | 1 << 6 | 1 << 7 | 1 << 8 | 1 << 9
|
||||
| 1 << 10 | 1 << 11 | 1 << 12 | 1 << 13 | 1 << 14 |
|
||||
1 << 16 | 1 << 17 | 1 << 18 | 1 << 19 | 1 << 20 | 1 << 21,
|
||||
|
||||
/**
|
||||
* all arithmetic flags
|
||||
* @const
|
||||
*/
|
||||
flags_all = flag_carry | flag_parity | flag_adjust | flag_zero | flag_sign | flag_overflow,
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* opsizes used by get flag functions
|
||||
*
|
||||
* @const
|
||||
*/
|
||||
OPSIZE_8 = 8,
|
||||
/** @const */
|
||||
OPSIZE_16 = 16,
|
||||
/** @const */
|
||||
OPSIZE_32 = 32,
|
||||
|
||||
/** @const */
|
||||
PSE_ENABLED = 128,
|
||||
|
||||
/** @const */ reg_eax = 0,
|
||||
/** @const */ reg_ecx = 1,
|
||||
/** @const */ reg_edx = 2,
|
||||
/** @const */ reg_ebx = 3,
|
||||
/** @const */ reg_esp = 4,
|
||||
/** @const */ reg_ebp = 5,
|
||||
/** @const */ reg_esi = 6,
|
||||
/** @const */ reg_edi = 7,
|
||||
|
||||
/** @const */ reg_ax = 0,
|
||||
/** @const */ reg_cx = 2,
|
||||
/** @const */ reg_dx = 4,
|
||||
/** @const */ reg_bx = 6,
|
||||
/** @const */ reg_sp = 8,
|
||||
/** @const */ reg_bp = 10,
|
||||
/** @const */ reg_si = 12,
|
||||
/** @const */ reg_di = 14,
|
||||
|
||||
/** @const */ reg_al = 0,
|
||||
/** @const */ reg_cl = 4,
|
||||
/** @const */ reg_dl = 8,
|
||||
/** @const */ reg_bl = 12,
|
||||
/** @const */ reg_ah = 1,
|
||||
/** @const */ reg_ch = 5,
|
||||
/** @const */ reg_dh = 9,
|
||||
/** @const */ reg_bh = 13,
|
||||
|
||||
|
||||
/** @const */ reg_es = 0,
|
||||
/** @const */ reg_cs = 1,
|
||||
/** @const */ reg_ss = 2,
|
||||
/** @const */ reg_ds = 3,
|
||||
/** @const */ reg_fs = 4,
|
||||
/** @const */ reg_gs = 5,
|
||||
/** @const */ reg_noseg = 6,
|
||||
|
||||
|
||||
|
||||
/** @const */ LOOP_COUNTER = 20001,
|
||||
/** @const */ TIME_PER_FRAME = 33;
|
||||
|
||||
|
||||
|
6029
src/cpu.js
Normal file
6029
src/cpu.js
Normal file
File diff suppressed because one or more lines are too long
2384
src/cpu.macro.js
Normal file
2384
src/cpu.macro.js
Normal file
File diff suppressed because it is too large
Load diff
445
src/debug.macro.js
Normal file
445
src/debug.macro.js
Normal file
|
@ -0,0 +1,445 @@
|
|||
"use strict";
|
||||
|
||||
debug.dump_regs = dump_regs;
|
||||
debug.dump_regs_short = dump_regs_short;
|
||||
debug.dump_stack = dump_stack;
|
||||
|
||||
debug.dump_page_directory = dump_page_directory;
|
||||
debug.dump_gdt_ldt = dump_gdt_ldt;
|
||||
debug.dump_idt = dump_idt;
|
||||
|
||||
debug.step = step;
|
||||
debug.run_until = run_until;
|
||||
|
||||
debug.debugger = function()
|
||||
{
|
||||
debugger;
|
||||
}
|
||||
|
||||
function step()
|
||||
{
|
||||
step_mode = true;
|
||||
|
||||
if(!running)
|
||||
{
|
||||
cycle();
|
||||
}
|
||||
|
||||
dump_regs();
|
||||
var now = Date.now();
|
||||
|
||||
vga.timer(now);
|
||||
timer.timer(now);
|
||||
rtc.timer(now);
|
||||
|
||||
running = false;
|
||||
}
|
||||
|
||||
function run_until()
|
||||
{
|
||||
running = false;
|
||||
var a = parseInt(prompt("input hex", ""), 16);
|
||||
if(a) while(instruction_pointer != a) cycle()
|
||||
dump_regs();
|
||||
}
|
||||
|
||||
// http://ref.x86asm.net/x86reference.xml
|
||||
// for debuggin' purposes
|
||||
var opcode_map = [
|
||||
"ADD", "ADD", "ADD", "ADD", "ADD", "ADD", "PUSH", "POP",
|
||||
"OR", "OR", "OR", "OR", "OR", "OR", "PUSH", "0F:",
|
||||
"ADC", "ADC", "ADC", "ADC", "ADC", "ADC", "PUSH", "POP",
|
||||
"SBB", "SBB", "SBB", "SBB", "SBB", "SBB", "PUSH", "POP",
|
||||
"AND", "AND", "AND", "AND", "AND", "AND", "ES", "DAA",
|
||||
"SUB", "SUB", "SUB", "SUB", "SUB", "SUB", "CS", "DAS",
|
||||
"XOR", "XOR", "XOR", "XOR", "XOR", "XOR", "SS", "AAA",
|
||||
"CMP", "CMP", "CMP", "CMP", "CMP", "CMP", "DS", "AAS",
|
||||
"INC", "INC", "INC", "INC", "INC", "INC", "INC", "INC",
|
||||
"DEC", "DEC", "DEC", "DEC", "DEC", "DEC", "DEC", "DEC",
|
||||
"PUSH", "PUSH", "PUSH", "PUSH", "PUSH", "PUSH", "PUSH", "PUSH",
|
||||
"POP", "POP", "POP", "POP", "POP", "POP", "POP", "POP",
|
||||
"PUSHA", "POPA", "BOUND", "ARPL", "FS", "GS", "none", "none",
|
||||
"PUSH", "IMUL", "PUSH", "IMUL", "INS", "INS", "OUTS", "OUTS",
|
||||
"JO", "JNO", "JB", "JNB", "JZ", "JNZ", "JBE", "JNBE",
|
||||
"JS", "JNS", "JP", "JNP", "JL", "JNL", "JLE", "JNLE",
|
||||
"ADD", "ADD", "ADD", "ADD", "TEST", "TEST", "XCHG", "XCHG",
|
||||
"MOV", "MOV", "MOV", "MOV", "MOV", "LEA", "MOV", "POP",
|
||||
"NOP", "XCHG", "XCHG", "XCHG", "XCHG", "XCHG", "XCHG", "XCHG",
|
||||
"CBW", "CWD", "CALLF", "FWAIT", "PUSHF", "POPF", "SAHF", "LAHF",
|
||||
"MOV", "MOV", "MOV", "MOV", "MOVS", "MOVS", "CMPS", "CMPS",
|
||||
"TEST", "TEST", "STOS", "STOS", "LODS", "LODS", "SCAS", "SCAS",
|
||||
"MOV", "MOV", "MOV", "MOV", "MOV", "MOV", "MOV", "MOV",
|
||||
"MOV", "MOV", "MOV", "MOV", "MOV", "MOV", "MOV", "MOV",
|
||||
"ROL", "ROL", "RETN", "RETN", "LES", "LDS", "MOV", "MOV",
|
||||
"ENTER", "LEAVE", "RETF", "RETF", "INT", "INT", "INTO", "IRET",
|
||||
"ROL", "ROL", "ROL", "ROL", "AAM", "AAD", "none", "XLAT",
|
||||
"FADD", "FLD", "FIADD", "FILD", "FADD", "FLD", "FIADD", "FILD",
|
||||
"LOOPNZ", "LOOPZ", "LOOP", "JCXZ", "IN", "IN", "OUT", "OUT",
|
||||
"CALL", "JMP", "JMPF", "JMP", "IN", "IN", "OUT", "OUT",
|
||||
"LOCK", "none", "REPNZ", "REPZ", "HLT", "CMC", "TEST", "TEST",
|
||||
"CLC", "STC", "CLI", "STI", "CLD", "STD", "INC", "INC"
|
||||
];
|
||||
|
||||
function logop(_ip, op)
|
||||
{
|
||||
if(!DEBUG || !ops)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(!step_mode)
|
||||
{
|
||||
//return;
|
||||
}
|
||||
|
||||
|
||||
ops.add(_ip);
|
||||
ops.add(opcode_map[op] || "unkown");
|
||||
ops.add(op);
|
||||
}
|
||||
|
||||
function dump_stack(start, end)
|
||||
{
|
||||
var esp = reg32[reg_esp];
|
||||
dbg_log("========= STACK ==========");
|
||||
|
||||
if(end >= start || end === undefined)
|
||||
{
|
||||
start = 5;
|
||||
end = -5;
|
||||
}
|
||||
|
||||
for(var i = start; i > end; i--)
|
||||
{
|
||||
var line = " ";
|
||||
|
||||
if(!i) line = "=> ";
|
||||
|
||||
line += h(i, 2) + " | ";
|
||||
|
||||
dbg_log(line + h(esp + 4 * i, 8) + " | " + h(memory.read32s(esp + 4 * i) >>> 0));
|
||||
}
|
||||
}
|
||||
|
||||
function dump_regs_short()
|
||||
{
|
||||
var
|
||||
r32 = { "eax": reg_eax, "ecx": reg_ecx, "edx": reg_edx, "ebx": reg_ebx,
|
||||
"esp": reg_esp, "ebp": reg_ebp, "esi": reg_esi, "edi": reg_edi },
|
||||
r32_names = ["eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"],
|
||||
s = { "cs": reg_cs, "ds": reg_ds, "es": reg_es, "fs": reg_fs, "gs": reg_gs, "ss": reg_ss },
|
||||
line1 = "",
|
||||
line2 = "";
|
||||
|
||||
|
||||
|
||||
for(var i = 0; i < 4; i++)
|
||||
{
|
||||
line1 += r32_names[i] + "=" + h(reg32[r32[r32_names[i]]], 8) + " ";
|
||||
line2 += r32_names[i+4] + "=" + h(reg32[r32[r32_names[i+4]]], 8) + " ";
|
||||
}
|
||||
|
||||
line1 += " eip=" + h(get_real_ip(), 8);
|
||||
line2 += " flg=" + h(get_flags());
|
||||
|
||||
line1 += " ds=" + h(sreg[reg_ds], 4) + " es=" + h(sreg[reg_es], 4) + " fs=" + h(sreg[reg_fs], 4);
|
||||
line2 += " gs=" + h(sreg[reg_gs], 4) + " cs=" + h(sreg[reg_cs], 4) + " ss=" + h(sreg[reg_ss], 4);
|
||||
|
||||
dbg_log(line1);
|
||||
dbg_log(line2);
|
||||
}
|
||||
|
||||
function dump_regs()
|
||||
{
|
||||
var
|
||||
r32 = { "eax": reg_eax, "ecx": reg_ecx, "edx": reg_edx, "ebx": reg_ebx,
|
||||
"esp": reg_esp, "ebp": reg_ebp, "esi": reg_esi, "edi": reg_edi },
|
||||
|
||||
s = { "cs": reg_cs, "ds": reg_ds, "es": reg_es,
|
||||
"fs": reg_fs, "gs": reg_gs, "ss": reg_ss },
|
||||
|
||||
out = "";
|
||||
|
||||
|
||||
var opcodes = ops.toArray();
|
||||
for(var i = 0; i < opcodes.length; i += 3)
|
||||
{
|
||||
if(opcodes[i])
|
||||
{
|
||||
out += h(opcodes[i], 6) + ": " +
|
||||
String.pads(opcodes[i + 1], 20) + h(opcodes[i + 2], 2) + "\n";
|
||||
}
|
||||
}
|
||||
|
||||
log(out.substr(0, out.length - 1));
|
||||
ops.clear();
|
||||
|
||||
dbg_log("----- DUMP (ip = 0x" + h(instruction_pointer >>> 0) + ") ----------")
|
||||
dbg_log("protected mode: " + protected_mode);
|
||||
|
||||
for(i in r32)
|
||||
{
|
||||
dbg_log(i + " = 0x" + h(reg32[r32[i]], 8));
|
||||
}
|
||||
dbg_log("eip = 0x" + h(get_real_ip(), 8));
|
||||
|
||||
for(i in s)
|
||||
{
|
||||
dbg_log(i + " = 0x" + h(sreg[s[i]], 4));
|
||||
}
|
||||
|
||||
out = "";
|
||||
|
||||
var flg = { "cf": getcf, "pf": getpf, "zf": getzf, "sf": getsf,
|
||||
"of": getof, "df": flag_direction, "if": flag_interrupt };
|
||||
|
||||
for(var i in flg)
|
||||
{
|
||||
if(+flg[i])
|
||||
{
|
||||
out += i + "=" + Number(!!(flags & flg[i])) + " | ";
|
||||
}
|
||||
else
|
||||
{
|
||||
out += i + "=" + Number(!!flg[i]()) + " | ";
|
||||
}
|
||||
}
|
||||
out += "iopl=" + getiopl();
|
||||
dbg_log(out);
|
||||
|
||||
|
||||
//dbg_log("last operation: " + h(last_op1 | 0) + ", " + h(last_op2 | 0) + " = " +
|
||||
//h(last_result | 0) + " (" + last_op_size + " bit)")
|
||||
|
||||
}
|
||||
|
||||
function dump_gdt_ldt()
|
||||
{
|
||||
dbg_log("gdt: (len = " + h(gdtr_size) + ")");
|
||||
dump_table(translate_address_read(gdtr_offset), gdtr_size);
|
||||
|
||||
dbg_log("\nldt: (len = " + h(ldtr_size) + ")");
|
||||
dump_table(translate_address_read(ldtr_offset), ldtr_size);
|
||||
|
||||
function dump_table(addr, size)
|
||||
{
|
||||
for(var i = 0; i < size; i += 8, addr += 8)
|
||||
{
|
||||
var base = memory.read16(addr + 2) |
|
||||
memory.read8(addr + 4) << 16 |
|
||||
memory.read8(addr + 7) << 24,
|
||||
|
||||
limit = (memory.read16(addr) | memory.read8(addr + 6) & 0xF) + 1,
|
||||
access = memory.read8(addr + 5),
|
||||
flags = memory.read8(addr + 6) >> 4,
|
||||
flags_str = '',
|
||||
dpl = access >> 5 & 3;
|
||||
|
||||
if(!(access & 128))
|
||||
{
|
||||
// present bit not set
|
||||
//continue;
|
||||
flags_str += 'NP ';
|
||||
}
|
||||
else
|
||||
{
|
||||
flags_str += ' P ';
|
||||
}
|
||||
|
||||
if(access & 16)
|
||||
{
|
||||
if(flags & 4)
|
||||
{
|
||||
flags_str += '32b ';
|
||||
}
|
||||
else
|
||||
{
|
||||
flags_str += '16b ';
|
||||
}
|
||||
|
||||
if(access & 8)
|
||||
{
|
||||
// executable
|
||||
flags_str += 'X ';
|
||||
|
||||
if(access & 4)
|
||||
{
|
||||
flags_str += 'C ';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// data
|
||||
flags_str += 'R ';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// system
|
||||
flags_str += 'sys: ' + h(access & 15);
|
||||
}
|
||||
|
||||
if(flags & 8)
|
||||
{
|
||||
limit <<= 12;
|
||||
}
|
||||
|
||||
dbg_log(h(i & ~7, 4) + " " + h(base >>> 0, 8) + " (" + h(limit, 8) + " bytes) " +
|
||||
flags_str + "; dpl = " + dpl + ", a = " + access.toString(2) +
|
||||
", f = " + flags.toString(2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function dump_idt()
|
||||
{
|
||||
for(var i = 0; i < idtr_size; i += 8)
|
||||
{
|
||||
var addr = do_page_translation(idtr_offset + i, 0, 0),
|
||||
base = memory.read16(addr) | memory.read16(addr + 6) << 16,
|
||||
selector = memory.read16(addr + 2),
|
||||
type = memory.read8(addr + 5),
|
||||
line,
|
||||
dpl = type >> 5 & 3;
|
||||
|
||||
if((type & 31) === 5)
|
||||
{
|
||||
line = 'task gate ';
|
||||
}
|
||||
else if((type & 31) === 14)
|
||||
{
|
||||
line = 'intr gate ';
|
||||
}
|
||||
else if((type & 31) === 15)
|
||||
{
|
||||
line = 'trap gate ';
|
||||
}
|
||||
else
|
||||
{
|
||||
line = 'invalid ';
|
||||
}
|
||||
|
||||
|
||||
if(type & 128)
|
||||
{
|
||||
line += ' P';
|
||||
}
|
||||
else
|
||||
{
|
||||
// present bit not set
|
||||
//continue;
|
||||
line += 'NP';
|
||||
}
|
||||
|
||||
|
||||
dbg_log(h(i >> 3, 4) + " " + h(base >>> 0, 8) + ", " +
|
||||
h(selector, 4) + "; " + line + "; dpl = " + dpl + ", t = " + type.toString(2));
|
||||
}
|
||||
}
|
||||
|
||||
function load_page_entry(dword_entry, is_directory)
|
||||
{
|
||||
if(!(dword_entry & 1))
|
||||
{
|
||||
// present bit not set
|
||||
return false;
|
||||
}
|
||||
|
||||
var size = (dword_entry & 128) === 128,
|
||||
address;
|
||||
|
||||
if(size && !is_directory)
|
||||
{
|
||||
address = dword_entry & 0xFFC00000;
|
||||
}
|
||||
else
|
||||
{
|
||||
address = dword_entry & 0xFFFFF000;
|
||||
}
|
||||
|
||||
return {
|
||||
size: size,
|
||||
global: (dword_entry & 256) === 256,
|
||||
accessed: (dword_entry & 0x20) === 0x20,
|
||||
dirty: (dword_entry & 0x40) === 0x40,
|
||||
cache : (dword_entry & 16) === 16,
|
||||
user : (dword_entry & 4) === 4,
|
||||
read_write : (dword_entry & 2) === 2,
|
||||
address : address >>> 0
|
||||
};
|
||||
}
|
||||
|
||||
function dump_page_directory()
|
||||
{
|
||||
for(var i = 0; i < 1024; i++)
|
||||
{
|
||||
var dword = memory.read32s(cr3 + 4 * i),
|
||||
entry = load_page_entry(dword, true);
|
||||
|
||||
if(!entry)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var flags = '';
|
||||
|
||||
if(entry.size)
|
||||
flags += 'S ';
|
||||
|
||||
if(entry.cache)
|
||||
flags += 'D ';
|
||||
|
||||
if(entry.user)
|
||||
flags += 'U ';
|
||||
|
||||
if(entry.read_write)
|
||||
flags += 'R ';
|
||||
|
||||
if(entry.accessed)
|
||||
flags += 'A ';
|
||||
|
||||
dbg_log("=== " + h(entry.address >>> 0, 8) + " | " + flags);
|
||||
|
||||
if(entry.size)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for(var j = 0; j < 1024; j++)
|
||||
{
|
||||
dword = memory.read32s(entry.address + 4 * j);
|
||||
|
||||
var subentry = load_page_entry(dword, false);
|
||||
|
||||
if(subentry)
|
||||
{
|
||||
flags = '';
|
||||
|
||||
if(subentry.size)
|
||||
flags += 'S ';
|
||||
|
||||
if(subentry.cache)
|
||||
flags += 'D ';
|
||||
|
||||
if(subentry.user)
|
||||
flags += 'U ';
|
||||
|
||||
if(subentry.read_write)
|
||||
flags += 'R ';
|
||||
|
||||
if(subentry.global)
|
||||
flags += 'G ';
|
||||
|
||||
if(subentry.accessed)
|
||||
flags += 'A ';
|
||||
|
||||
if(subentry.dirty)
|
||||
flags += 'Di ';
|
||||
|
||||
dbg_log("# " + h((i << 22 | j << 12) >>> 0, 8) + " -> " +
|
||||
h(subentry.address, 8) + " | " + flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
545
src/disk.js
Normal file
545
src/disk.js
Normal file
|
@ -0,0 +1,545 @@
|
|||
"use strict";
|
||||
|
||||
|
||||
var
|
||||
/** @const */
|
||||
CDROM_SECTOR_SIZE = 2048,
|
||||
/** @const */
|
||||
HD_SECTOR_SIZE = 512;
|
||||
|
||||
|
||||
/** @constructor */
|
||||
function CDRom(dev, cd_buffer)
|
||||
{
|
||||
this.io = dev.io;
|
||||
this.memory = dev.memory;
|
||||
this.pic = dev.pic;
|
||||
this.pci = dev.pci;
|
||||
|
||||
this.vendor_id = 0x1002;
|
||||
this.class_revision = 0x106 << 16 | 0x01 << 8;
|
||||
this.irq = 14;
|
||||
this.iobase = 0xFFF10000;
|
||||
this.sector_size = CDROM_SECTOR_SIZE;
|
||||
this.buffer = cd_buffer;
|
||||
this.atapi = true;
|
||||
this.pci_id = 8;
|
||||
|
||||
this.init();
|
||||
}
|
||||
CDRom.prototype = new AHCIDevice();
|
||||
|
||||
/** @constructor */
|
||||
function HDD(dev, disk_buffer, nr)
|
||||
{
|
||||
var port = nr === 0 ? 0x1F0 : 0x170,
|
||||
irq = nr === 0 ? 14 : 15;
|
||||
|
||||
var pic = dev.pic;
|
||||
|
||||
this.io = dev.io;
|
||||
this.memory = dev.memory;
|
||||
this.pic = dev.pic;
|
||||
this.pci = dev.pci;
|
||||
|
||||
this.vendor_id = 0x1002;
|
||||
this.class_revision = 0x106 << 16 | 0x01 << 8;
|
||||
this.irq = irq;
|
||||
this.iobase = 0xFFF00000;
|
||||
this.sector_size = HD_SECTOR_SIZE;
|
||||
this.sector_count = disk_buffer.byteLength / this.sector_size;
|
||||
this.buffer = disk_buffer;
|
||||
this.atapi = false;
|
||||
this.pci_id = 0x10;
|
||||
|
||||
this.head_count = 16;
|
||||
this.sectors_per_track = 63;
|
||||
|
||||
this.cylinder_count = disk_buffer.byteLength /
|
||||
this.head_count / (this.sectors_per_track + 1) / this.sector_size;
|
||||
|
||||
dbg_assert(this.cylinder_count === (this.cylinder_count | 0));
|
||||
dbg_assert(this.cylinder_count <= 16383);
|
||||
|
||||
var me = this;
|
||||
|
||||
// status
|
||||
this.io.register_read(port | 7, read_status);
|
||||
|
||||
// alternate status, starting at 3f6/376
|
||||
this.io.register_read(port | 0x206, read_status);
|
||||
|
||||
function read_status()
|
||||
{
|
||||
dbg_log("ATA read status", LOG_DISK);
|
||||
|
||||
var status = 0x50;
|
||||
|
||||
if(data_pointer < pio_data.length)
|
||||
status |= 8;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
var last_drive = 0xFF,
|
||||
data_pointer = 0,
|
||||
pio_data = [],
|
||||
drq = false,
|
||||
is_lba = 0,
|
||||
slave = 0,
|
||||
bytecount = 0,
|
||||
sector = 0,
|
||||
cylinder = 0,
|
||||
head = 0;
|
||||
|
||||
|
||||
function push_irq()
|
||||
{
|
||||
pic.push_irq(me.irq);
|
||||
}
|
||||
|
||||
this.io.register_write(port | 6, function(data)
|
||||
{
|
||||
dbg_log("1F6 write " + h(data), LOG_DISK);
|
||||
|
||||
var slave = data & 0x10,
|
||||
mode = data & 0xE0,
|
||||
low = data & 0xF;
|
||||
|
||||
|
||||
if(slave)
|
||||
{
|
||||
//drq = false;
|
||||
return;
|
||||
}
|
||||
|
||||
is_lba = data >> 6 & 1;
|
||||
head = data & 0xF;
|
||||
last_drive = data;
|
||||
});
|
||||
|
||||
this.io.register_write(port | 2, function(data)
|
||||
{
|
||||
dbg_log("1F2 write: " + data, LOG_DISK);
|
||||
if(data)
|
||||
{
|
||||
bytecount = data << 9;
|
||||
}
|
||||
else
|
||||
{
|
||||
bytecount = 256 << 9;
|
||||
}
|
||||
//bytecount = 1 << 9;
|
||||
});
|
||||
this.io.register_write(port | 3, function(data)
|
||||
{
|
||||
sector = data;
|
||||
});
|
||||
this.io.register_write(port | 4, function(data)
|
||||
{
|
||||
cylinder = cylinder & 0xFF00 | data;
|
||||
});
|
||||
this.io.register_write(port | 5, function(data)
|
||||
{
|
||||
cylinder = cylinder & 0xFF | data << 8;
|
||||
});
|
||||
|
||||
this.io.register_write(port | 7, function(cmd)
|
||||
{
|
||||
if(cmd === 0xEC)
|
||||
{
|
||||
dbg_log("ATA identify device", LOG_DISK);
|
||||
// identify device
|
||||
// http://bochs.sourceforge.net/cgi-bin/lxr/source/iodev/harddrv.cc#L2821
|
||||
|
||||
data_pointer = 0;
|
||||
|
||||
pio_data = new Uint8Array([
|
||||
0x40, 0,
|
||||
// 1 cylinders
|
||||
me.cylinder_count, me.cylinder_count >> 8,
|
||||
0, 0,
|
||||
|
||||
// 3 heads
|
||||
me.head_count, me.head_count >> 8,
|
||||
0, 0,
|
||||
// 5
|
||||
0, 0,
|
||||
// sectors per track
|
||||
me.sectors_per_track, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
// 10-19 serial number
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
// 15
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
// 20
|
||||
3, 0, 0, 2, 4, 0,
|
||||
// 23-26 firmware revision
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
// 27 model number
|
||||
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
|
||||
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
|
||||
|
||||
// 47
|
||||
0, 0,
|
||||
1, 0,
|
||||
0, 3, // capabilities
|
||||
// 50
|
||||
0, 0,
|
||||
0, 2,
|
||||
0, 2,
|
||||
7, 0,
|
||||
|
||||
// 54 cylinders
|
||||
me.cylinder_count, me.cylinder_count >> 8,
|
||||
// 55 heads
|
||||
me.head_count, me.head_count >> 8,
|
||||
// 56 sectors per track
|
||||
me.sectors_per_track, 0,
|
||||
// capacity in sectors
|
||||
this.sector_count & 0xFF, this.sector_count >> 8 & 0xFF,
|
||||
this.sector_count >> 16 & 0xFF, this.sector_count >> 24 & 0xFF,
|
||||
|
||||
0, 0,
|
||||
// 60
|
||||
this.sector_count & 0xFF, this.sector_count >> 8 & 0xFF,
|
||||
this.sector_count >> 16 & 0xFF, this.sector_count >> 24 & 0xFF,
|
||||
|
||||
0, 0, 0, 0, 0, 0,
|
||||
// 65
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
// 70
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
// 75
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
// 80
|
||||
0x7E, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
// 85
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
// 90
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
// 95
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
// 100
|
||||
this.sector_count & 0xFF, this.sector_count >> 8 & 0xFF,
|
||||
this.sector_count >> 16 & 0xFF, this.sector_count >> 24 & 0xFF,
|
||||
|
||||
|
||||
]);
|
||||
|
||||
push_irq();
|
||||
}
|
||||
else if(cmd === 0x91)
|
||||
{
|
||||
dbg_log("ATA cmd 91", LOG_DISK);
|
||||
push_irq();
|
||||
}
|
||||
else if(cmd === 0x10)
|
||||
{
|
||||
// obsolete
|
||||
dbg_log("ATA cmd 10", LOG_DISK);
|
||||
push_irq();
|
||||
}
|
||||
else if(cmd = 0x27)
|
||||
{
|
||||
// READ NATIVE MAX ADDRESS EXT - read the actual size of the HD
|
||||
// https://en.wikipedia.org/wiki/Host_protected_area
|
||||
dbg_log("ATA cmd 27", LOG_DISK);
|
||||
push_irq();
|
||||
pio_data = [
|
||||
0, 0, // error
|
||||
0, 0, // count
|
||||
|
||||
// result
|
||||
disk_buffer.byteLength & 0xff,
|
||||
disk_buffer.byteLength >> 8 & 0xff,
|
||||
disk_buffer.byteLength >> 16 & 0xff,
|
||||
disk_buffer.byteLength >> 24 & 0xff,
|
||||
0, 0,
|
||||
|
||||
0, 0, //
|
||||
];
|
||||
}
|
||||
else if(cmd === 0x20)
|
||||
{
|
||||
if(DEBUG && is_lba)
|
||||
throw "unimplemented";
|
||||
|
||||
var lba = (cylinder * me.head_count + head) * me.sectors_per_track + sector - 1;
|
||||
dbg_log("ATA read: from=" + h(lba * me.sector_size) + " chs=" + cylinder + "/" + head + "/" + sector + " length=" + h(bytecount), LOG_DISK);
|
||||
|
||||
me.buffer.get(lba * me.sector_size, bytecount, function(data)
|
||||
{
|
||||
data_pointer = 0;
|
||||
pio_data = data;
|
||||
|
||||
push_irq();
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
dbg_log("New ATA cmd on 1F7: " + h(cmd), LOG_DISK);
|
||||
}
|
||||
});
|
||||
|
||||
this.io.register_read(port | 0, function()
|
||||
{
|
||||
if(data_pointer < pio_data.length)
|
||||
{
|
||||
dbg_log("Read 1F0: " + h(pio_data[data_pointer], 2), LOG_DISK);
|
||||
|
||||
if((data_pointer & 511) === 0)
|
||||
push_irq();
|
||||
|
||||
return pio_data[data_pointer++] & 0xFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
dbg_log("Read 1F0: empty", LOG_DISK);
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
this.io.register_read(port | 1, function()
|
||||
{
|
||||
dbg_log("Read 1F1", LOG_DISK);
|
||||
return 0xFF;
|
||||
});
|
||||
|
||||
this.io.register_read(port | 2, function()
|
||||
{
|
||||
dbg_log("Read 1F2", LOG_DISK);
|
||||
return 0xFF;
|
||||
});
|
||||
|
||||
|
||||
this.io.register_read(port | 3, function()
|
||||
{
|
||||
dbg_log("Read 1F3", LOG_DISK);
|
||||
return 0xFF;
|
||||
});
|
||||
|
||||
this.io.register_read(port | 6, function()
|
||||
{
|
||||
dbg_log("Read 1F6", LOG_DISK);
|
||||
return last_drive;
|
||||
});
|
||||
|
||||
this.init();
|
||||
}
|
||||
HDD.prototype = new AHCIDevice();
|
||||
|
||||
|
||||
/** @constructor */
|
||||
function AHCIDevice()
|
||||
{
|
||||
var me,
|
||||
memory;
|
||||
|
||||
this.init = function()
|
||||
{
|
||||
me = this;
|
||||
memory = this.memory;
|
||||
|
||||
this.pci.register_device(this, this.pci_id);
|
||||
|
||||
this.memory.mmap_register(this.iobase, 0x4000, true, mmio_read, mmio_write);
|
||||
|
||||
};
|
||||
|
||||
var host_ctl = 0,
|
||||
host_caps = 1,
|
||||
host_ports_impl = 1,
|
||||
host_intbits = 1,
|
||||
port_lst_addr,
|
||||
port_fis_addr;
|
||||
|
||||
function atapi_command_read(atapi, dest, byte_len)
|
||||
{
|
||||
var lba = Math.to_be32(memory.read32s(atapi + 2)),
|
||||
count = Math.to_be16(memory.read16(atapi + 7)),
|
||||
flags = memory.read8(atapi + 1),
|
||||
|
||||
//bytecount = Math.min(count * me.sector_size, byte_len + 1);
|
||||
bytecount = count * me.sector_size;
|
||||
|
||||
dbg_log("CD read lba=" + h(lba) +
|
||||
" lbacount=" + h(count) +
|
||||
" bytelen=" + h(byte_len) +
|
||||
" copycount=" + h(bytecount) +
|
||||
" flags=" + h(flags) +
|
||||
" buf=" + h(dest, 8), LOG_CD);
|
||||
|
||||
me.buffer.get(lba * me.sector_size, bytecount, function(data)
|
||||
{
|
||||
memory.write_blob(data, dest);
|
||||
});
|
||||
|
||||
//pic.push_irq(me.irq);
|
||||
}
|
||||
|
||||
function ata_command_rw(cmd_fis, dest, is_read)
|
||||
{
|
||||
var lba = memory.read32s(cmd_fis + 4) & 0xFFFFFF,
|
||||
count = memory.read16(cmd_fis + 12),
|
||||
bytecount = count * me.sector_size;
|
||||
|
||||
dbg_log("ahci " + (is_read ? "read" : "write") + ": lba=" + h(lba, 8) +
|
||||
" count=" + h(count, 4) +
|
||||
" dest=" + h(dest, 8));
|
||||
|
||||
if(is_read)
|
||||
{
|
||||
this.buffer.get(lba * me.sector_size, bytecount, function(data)
|
||||
{
|
||||
memory.write_blob(data, dest);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
this.buffer.set(lba * me.sector_size,
|
||||
new Uint8Array(memory.buffer, dest, bytecount),
|
||||
function()
|
||||
{
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function mmio_read(addr)
|
||||
{
|
||||
switch(addr)
|
||||
{
|
||||
case 0:
|
||||
return host_caps;
|
||||
|
||||
case 4:
|
||||
return host_ctl;
|
||||
|
||||
case 0xC:
|
||||
return host_ports_impl;
|
||||
|
||||
case 0x128:
|
||||
return 0x03;
|
||||
|
||||
case 0x110:
|
||||
return host_intbits;
|
||||
|
||||
default:
|
||||
dbg_log("New PCI mmio read from " + h(addr, 8), LOG_CD);
|
||||
}
|
||||
}
|
||||
|
||||
function mmio_write(addr, value)
|
||||
{
|
||||
switch(addr)
|
||||
{
|
||||
case 0x100:
|
||||
port_lst_addr = value;
|
||||
dbg_log("lst at " + h(value, 8), LOG_CD);
|
||||
break;
|
||||
case 0x108:
|
||||
port_fis_addr = value;
|
||||
dbg_log("fis at " + h(value, 8), LOG_CD);
|
||||
break;
|
||||
|
||||
case 0x118:
|
||||
dbg_log("port cmd: " + h(value, 8), LOG_CD);
|
||||
break;
|
||||
|
||||
case 0x138:
|
||||
var
|
||||
|
||||
ctba_addr = memory.read32s(port_lst_addr + 8),
|
||||
|
||||
first_prdt_start = ctba_addr + 0x80,
|
||||
flags = memory.read16(port_lst_addr),
|
||||
prdt_addr = memory.read32s(first_prdt_start) + 0x100000000 * memory.read32s(first_prdt_start + 4),
|
||||
prdt_len = memory.read32s(ctba_addr + 0x80 + 0xC) & 0xFFF,
|
||||
atapi_command = memory.read8(ctba_addr + 0x40),
|
||||
fis_command = memory.read8(ctba_addr + 2),
|
||||
|
||||
dma_fis_start = port_fis_addr + 0,
|
||||
pio_fis_start = port_fis_addr + 0x20,
|
||||
d2h_fis_start = port_fis_addr + 0x40,
|
||||
ufis_start = port_fis_addr + 0x60,
|
||||
|
||||
command_fis_start = ctba_addr + 0,
|
||||
atapi_command_start = ctba_addr + 0x40;
|
||||
|
||||
if((fis_command === 0xA0 || fis_command === 0xA1) &&
|
||||
!me.atapi)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// status success
|
||||
memory.write8(d2h_fis_start + 2, 0x40);
|
||||
|
||||
dbg_log("ctba at " + h(ctba_addr), LOG_CD);
|
||||
dbg_log("prdt at " + h(prdt_addr), LOG_CD);
|
||||
dbg_log("flags: " + h(flags, 2), LOG_CD);
|
||||
dbg_log("cmd fis command: " + h(fis_command, 2), LOG_CD);
|
||||
|
||||
dbg_log("fis LBA=" + h(memory.read32s(command_fis_start + 4) & 0xffffff), LOG_CD);
|
||||
|
||||
dbg_log("Prdts count: " + h(memory.read16(port_lst_addr + 2)), LOG_CD);
|
||||
dbg_log("PRD byte count: " + h(memory.read32s(port_lst_addr + 4)), LOG_CD);
|
||||
|
||||
dbg_log("First prdt byte count: " + h(memory.read32s(ctba_addr + 0x80 + 0xC)), LOG_CD);
|
||||
|
||||
if(fis_command === 0xC8 || fis_command === 0xCA)
|
||||
{
|
||||
ata_command_rw(command_fis_start, prdt_addr, fis_command === 0xC8);
|
||||
}
|
||||
else if(fis_command === 0xEC)
|
||||
{
|
||||
// ATA_CMD_IDENTIFY_DEVICE
|
||||
|
||||
// number of sectors
|
||||
memory.write32(prdt_addr + 120, me.buffer.byteLength / me.sector_size);
|
||||
}
|
||||
else if(fis_command === 0xA1)
|
||||
{
|
||||
// ATA_CMD_IDENTIFY_PACKET_DEVICE
|
||||
|
||||
// is CD
|
||||
memory.write32(prdt_addr, 0x0500);
|
||||
}
|
||||
else if(fis_command === 0xA0)
|
||||
{
|
||||
// ATA_CMD_PACKET
|
||||
if(atapi_command === 0x28)
|
||||
{
|
||||
atapi_command_read(ctba_addr + 0x40, prdt_addr, prdt_len);
|
||||
}
|
||||
else if(atapi_command === 0x2a)
|
||||
{
|
||||
// write
|
||||
dbg_log("atapi - unimplemented write", LOG_CD);
|
||||
}
|
||||
else if(atapi_command === 0x25)
|
||||
{
|
||||
// read capacity
|
||||
dbg_log("atapi - unimplemented read cap", LOG_CD);
|
||||
}
|
||||
else
|
||||
{
|
||||
dbg_log("atapi - unimplemented " + h(atapi_command, 2), LOG_CD);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dbg_log("unimplemented fis command: " + h(fis_command, 2));
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
dbg_log("PCI mmio write addr=" + h(addr, 8) + " value=" + h(value, 8), LOG_CD);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
149
src/dma.js
Normal file
149
src/dma.js
Normal file
|
@ -0,0 +1,149 @@
|
|||
"use strict";
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
function DMA(dev)
|
||||
{
|
||||
var io = dev.io,
|
||||
memory = dev.memory,
|
||||
|
||||
channels = [
|
||||
{ address: 0, count: 0 },
|
||||
{ address: 0, count: 0 },
|
||||
{ address: 0, count: 0 },
|
||||
{ address: 0, count: 0 }
|
||||
],
|
||||
|
||||
lsb_msb_flipflop = 0;
|
||||
|
||||
io.register_write(0x04, port_write.bind(0, 0x04));
|
||||
io.register_write(0x05, port_write.bind(0, 0x05));
|
||||
io.register_write(0x0A, portA_write);
|
||||
io.register_write(0x0B, portB_write);
|
||||
io.register_write(0x0C, portC_write);
|
||||
io.register_write(0x81, port81_write);
|
||||
|
||||
function port_write(port, data_byte)
|
||||
{
|
||||
dbg_log("port " + port + " write " + data_byte, LOG_DMA);
|
||||
|
||||
if(port < 8)
|
||||
{
|
||||
var channel = port >> 1;
|
||||
|
||||
if(port & 1)
|
||||
{
|
||||
channels[channel].count = flipflop_get(channels[channel].count, data_byte);
|
||||
}
|
||||
else
|
||||
{
|
||||
channels[channel].address = flipflop_get(channels[channel].address, data_byte);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function port_read(port)
|
||||
{
|
||||
if(port < 8)
|
||||
{
|
||||
var channel = port >> 1;
|
||||
|
||||
if(port & 1)
|
||||
{
|
||||
return channels[channel].count;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Bug?
|
||||
return channels[channel].address;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dbg_log("port " + h(port) + " read", LOG_DMA);
|
||||
}
|
||||
};
|
||||
|
||||
function portA_write(data_byte)
|
||||
{
|
||||
dbg_log("port A write: " + h(data_byte), LOG_DMA);
|
||||
};
|
||||
|
||||
function portB_write(data_byte)
|
||||
{
|
||||
dbg_log("port B write: " + h(data_byte), LOG_DMA);
|
||||
};
|
||||
|
||||
function portC_write(data_byte)
|
||||
{
|
||||
lsb_msb_flipflop = 0;
|
||||
}
|
||||
|
||||
function port81_write(data_byte)
|
||||
{
|
||||
channels[2].address = channels[2].address & 0xFFFF | data_byte << 16;
|
||||
}
|
||||
|
||||
// read data, write to memory
|
||||
this.do_read = function(buffer, start, len, channel, fn)
|
||||
{
|
||||
var read_count = channels[channel].count,
|
||||
addr = channels[channel].address;
|
||||
|
||||
dbg_log("DMA write channel " + channel, LOG_DMA);
|
||||
dbg_log("to " + h(addr) + " len " + h(read_count), LOG_DMA);
|
||||
|
||||
if(len < read_count)
|
||||
{
|
||||
dbg_log("DMA should read more than provided: " + h(len) + " " + h(read_count), LOG_DMA);
|
||||
}
|
||||
|
||||
channels[channel].address += len;
|
||||
|
||||
buffer.get(start, len, function(data)
|
||||
{
|
||||
memory.write_blob(data, addr);
|
||||
fn();
|
||||
});
|
||||
};
|
||||
|
||||
// write data, read memory
|
||||
this.do_write = function(buffer, start, len, channel, fn)
|
||||
{
|
||||
var read_count = channels[channel].count,
|
||||
addr = channels[channel].address;
|
||||
|
||||
dbg_log("DMA write channel " + channel, LOG_DMA);
|
||||
dbg_log("to " + h(addr) + " len " + h(read_count), LOG_DMA);
|
||||
dbg_log(channels[channel], LOG_DMA);
|
||||
|
||||
if(len < read_count)
|
||||
{
|
||||
dbg_log("DMA should read more than provided", LOG_DMA);
|
||||
}
|
||||
|
||||
buffer.set(start,
|
||||
new Uint8Array(memory.buffer, addr, read_count + 1),
|
||||
function() {
|
||||
fn();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function flipflop_get(old_dword, new_byte)
|
||||
{
|
||||
lsb_msb_flipflop ^= 1;
|
||||
|
||||
if(lsb_msb_flipflop)
|
||||
{
|
||||
// low byte
|
||||
return old_dword & ~0xFF | new_byte;
|
||||
}
|
||||
else
|
||||
{
|
||||
// high byte
|
||||
return old_dword & ~0xFF00 | new_byte << 8;
|
||||
}
|
||||
}
|
||||
}
|
1
src/externs.js
Normal file
1
src/externs.js
Normal file
|
@ -0,0 +1 @@
|
|||
var console = {};
|
396
src/floppy.js
Normal file
396
src/floppy.js
Normal file
|
@ -0,0 +1,396 @@
|
|||
"use strict";
|
||||
|
||||
/** @constructor */
|
||||
function FloppyController(dev, floppy_image)
|
||||
{
|
||||
var
|
||||
io = dev.io,
|
||||
pic = dev.pic,
|
||||
dma = dev.dma,
|
||||
|
||||
bytes_expecting = 0,
|
||||
receiving_command = new Uint8Array(10),
|
||||
receiving_index = 0,
|
||||
next_command,
|
||||
|
||||
response_data = new Uint8Array(10),
|
||||
response_index = 0,
|
||||
response_length = 0,
|
||||
|
||||
/** @const */
|
||||
byte_per_sector = 512,
|
||||
|
||||
/** @const */
|
||||
number_of_heads = 2;
|
||||
|
||||
this.buffer = floppy_image;
|
||||
|
||||
if(!floppy_image)
|
||||
{
|
||||
this.type = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
var number_of_cylinders,
|
||||
number_of_sectors,
|
||||
sectors_per_track;
|
||||
|
||||
if(floppy_image.byteLength === 1024 * 360)
|
||||
{
|
||||
this.type = 1;
|
||||
number_of_cylinders = 40;
|
||||
number_of_sectors = 2880;
|
||||
sectors_per_track = 9;
|
||||
}
|
||||
if(floppy_image.byteLength === 1024 * 1200)
|
||||
{
|
||||
this.type = 2;
|
||||
number_of_cylinders = 80;
|
||||
number_of_sectors = 2400;
|
||||
sectors_per_track = 15;
|
||||
}
|
||||
else if(floppy_image.byteLength === 1024 * 720)
|
||||
{
|
||||
this.type = 3;
|
||||
number_of_cylinders = 80;
|
||||
number_of_sectors = 2880;
|
||||
sectors_per_track = 9;
|
||||
}
|
||||
else if(floppy_image.byteLength === 1024 * 1440)
|
||||
{
|
||||
this.type = 4;
|
||||
number_of_cylinders = 80;
|
||||
number_of_sectors = 2880;
|
||||
sectors_per_track = 18;
|
||||
}
|
||||
else if(floppy_image.byteLength === 1024 * 2880)
|
||||
{
|
||||
this.type = 5;
|
||||
number_of_cylinders = 80;
|
||||
number_of_sectors = 5760;
|
||||
sectors_per_track = 36;
|
||||
}
|
||||
else if(floppy_image.byteLength === 1024 * 1722)
|
||||
{
|
||||
// type is wrong, but only this works for seabios
|
||||
this.type = 5;
|
||||
number_of_cylinders = 82;
|
||||
number_of_sectors = 3444;
|
||||
sectors_per_track = 21;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw unimpl("Unknown floppy size: " + h(floppy_image.byteLength));
|
||||
}
|
||||
|
||||
var status_reg0 = 0,
|
||||
status_reg1 = 0,
|
||||
status_reg2 = 0,
|
||||
drive = 0;
|
||||
|
||||
var last_cylinder = 0,
|
||||
last_head = 0,
|
||||
last_sector = 1;
|
||||
|
||||
io.register_read(0x3F0, port3F0_read);
|
||||
io.register_read(0x3F4, port3F4_read);
|
||||
io.register_read(0x3F5, port3F5_read);
|
||||
io.register_read(0x3F7, port3F7_read);
|
||||
|
||||
io.register_write(0x3F5, port3F5_write);
|
||||
|
||||
function port3F0_read()
|
||||
{
|
||||
dbg_log("3F0 read", LOG_DISK);
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
|
||||
function port3F4_read()
|
||||
{
|
||||
dbg_log("3F4 read", LOG_DISK);
|
||||
|
||||
var return_byte = 0x80;
|
||||
|
||||
if(response_index < response_length)
|
||||
{
|
||||
return_byte |= 0x40 | 0x10;
|
||||
}
|
||||
|
||||
if((dor & 8) === 0)
|
||||
{
|
||||
return_byte |= 0x20;
|
||||
}
|
||||
|
||||
return return_byte;
|
||||
};
|
||||
|
||||
function port3F7_read()
|
||||
{
|
||||
dbg_log("3F7 read", LOG_DISK);
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
function port3F5_read()
|
||||
{
|
||||
if(response_index < response_length)
|
||||
{
|
||||
dbg_log("3F5 read: " + response_data[response_index], LOG_DISK);
|
||||
return response_data[response_index++];
|
||||
}
|
||||
else
|
||||
{
|
||||
dbg_log("3F5 read, empty", LOG_DISK);
|
||||
return 0xFF;
|
||||
}
|
||||
};
|
||||
|
||||
function port3F5_write(reg_byte)
|
||||
{
|
||||
dbg_log("3F5 write " + h(reg_byte), LOG_DISK);
|
||||
|
||||
if(bytes_expecting > 0)
|
||||
{
|
||||
receiving_command[receiving_index++] = reg_byte;
|
||||
|
||||
bytes_expecting--;
|
||||
|
||||
if(bytes_expecting === 0)
|
||||
{
|
||||
if(DEBUG)
|
||||
{
|
||||
var log = "3F5 command received: ";
|
||||
for(var i = 0; i < receiving_index; i++)
|
||||
log += h(receiving_command[i]) + " ";
|
||||
dbg_log(log, LOG_DISK);
|
||||
}
|
||||
|
||||
next_command(receiving_command);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(reg_byte)
|
||||
{
|
||||
// TODO
|
||||
//case 2:
|
||||
//next_command = read_complete_track;
|
||||
//bytes_expecting = 8;
|
||||
//break;
|
||||
case 0x03:
|
||||
next_command = fix_drive_data;
|
||||
bytes_expecting = 2;
|
||||
break;
|
||||
case 0x04:
|
||||
next_command = check_drive_status;
|
||||
bytes_expecting = 1;
|
||||
break;
|
||||
case 0x05:
|
||||
case 0xC5:
|
||||
next_command = function(args) { do_sector(true, args); };
|
||||
bytes_expecting = 8;
|
||||
break;
|
||||
case 0xE6:
|
||||
next_command = function(args) { do_sector(false, args); };
|
||||
bytes_expecting = 8;
|
||||
break;
|
||||
case 0x07:
|
||||
next_command = calibrate;
|
||||
bytes_expecting = 1;
|
||||
break;
|
||||
case 0x08:
|
||||
check_interrupt_status();
|
||||
break;
|
||||
case 0x4A:
|
||||
next_command = read_sector_id;
|
||||
bytes_expecting = 1;
|
||||
break;
|
||||
case 0x0F:
|
||||
bytes_expecting = 2;
|
||||
next_command = seek;
|
||||
break;
|
||||
case 0x0E:
|
||||
// dump regs
|
||||
dbg_log("dump registers", LOG_DISK);
|
||||
response_data[0] = 0x80;
|
||||
response_index = 0;
|
||||
response_length = 1;
|
||||
|
||||
bytes_expecting = 0;
|
||||
break;
|
||||
default:
|
||||
if(DEBUG) throw "unimpl floppy command call " + h(reg_byte);
|
||||
}
|
||||
|
||||
receiving_index = 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// this should actually be write-only ... but people read it anyway
|
||||
var dor = 0;
|
||||
|
||||
function port3F2_read()
|
||||
{
|
||||
dbg_log("read 3F2: DOR", LOG_DISK);
|
||||
return dor;
|
||||
}
|
||||
io.register_read(0x3F2, port3F2_read);
|
||||
|
||||
function port3F2_write(value)
|
||||
{
|
||||
if((value & 4) === 4 && (dor & 4) === 0)
|
||||
{
|
||||
// reset
|
||||
pic.push_irq(6);
|
||||
}
|
||||
|
||||
dbg_log("start motors: " + h(value >> 4), LOG_DISK);
|
||||
dbg_log("enable dma: " + !!(value & 8), LOG_DISK);
|
||||
dbg_log("reset fdc: " + !!(value & 4), LOG_DISK);
|
||||
dbg_log("drive select: " + (value & 3), LOG_DISK);
|
||||
dbg_log("DOR = " + h(value), LOG_DISK);
|
||||
|
||||
dor = value;
|
||||
|
||||
}
|
||||
io.register_write(0x3F2, port3F2_write);
|
||||
|
||||
function check_drive_status(args)
|
||||
{
|
||||
dbg_log("check drive status", LOG_DISK);
|
||||
|
||||
response_index = 0;
|
||||
response_length = 1;
|
||||
response_data[0] = 1 << 5;
|
||||
}
|
||||
|
||||
function seek(args)
|
||||
{
|
||||
dbg_log("seek", LOG_DISK);
|
||||
|
||||
last_cylinder = args[1];
|
||||
last_head = args[0] >> 2 & 1;
|
||||
|
||||
if(dor & 8)
|
||||
{
|
||||
pic.push_irq(6);
|
||||
}
|
||||
}
|
||||
|
||||
function calibrate(args)
|
||||
{
|
||||
dbg_log("floppy calibrate", LOG_DISK);
|
||||
|
||||
if(dor & 8)
|
||||
{
|
||||
pic.push_irq(6);
|
||||
}
|
||||
}
|
||||
|
||||
function check_interrupt_status()
|
||||
{
|
||||
// do not trigger an interrupt here
|
||||
dbg_log("floppy check interrupt status", LOG_DISK);
|
||||
|
||||
response_index = 0;
|
||||
response_length = 2;
|
||||
|
||||
response_data[0] = 1 << 5;
|
||||
response_data[1] = last_cylinder;
|
||||
}
|
||||
|
||||
function do_sector(is_write, args)
|
||||
{
|
||||
var head = args[2],
|
||||
cylinder = args[1],
|
||||
sector = args[3],
|
||||
sector_size = 128 * (1 << args[4]),
|
||||
read_count = args[5] - args[3] + 1,
|
||||
|
||||
read_offset = ((head + number_of_heads * cylinder) * sectors_per_track + sector - 1) * sector_size;
|
||||
|
||||
dbg_log("Floppy Read", LOG_DISK);
|
||||
dbg_log("from " + h(read_offset) + " length " + h(read_count * sector_size), LOG_DISK);
|
||||
dbg_log(cylinder + " / " + head + " / " + sector, LOG_DISK);
|
||||
|
||||
if(!args[4])
|
||||
{
|
||||
dbg_log("FDC: sector count is zero, use data length instead", LOG_DISK);
|
||||
}
|
||||
|
||||
if(is_write)
|
||||
{
|
||||
dma.do_write(floppy_image, read_offset, read_count * sector_size, 2, done);
|
||||
}
|
||||
else
|
||||
{
|
||||
dma.do_read(floppy_image, read_offset, read_count * sector_size, 2, done);
|
||||
}
|
||||
|
||||
function done()
|
||||
{
|
||||
sector++;
|
||||
|
||||
if(sector > sectors_per_track)
|
||||
{
|
||||
sector = 1;
|
||||
head++;
|
||||
|
||||
if(head > 1)
|
||||
{
|
||||
head = 0;
|
||||
cylinder++;
|
||||
}
|
||||
}
|
||||
|
||||
last_cylinder = cylinder;
|
||||
last_head = head;
|
||||
last_sector = sector;
|
||||
|
||||
response_index = 0;
|
||||
response_length = 7;
|
||||
|
||||
response_data[0] = head << 2 | 0x20;
|
||||
response_data[1] = 0;
|
||||
response_data[2] = 0;
|
||||
response_data[3] = cylinder;
|
||||
response_data[4] = head;
|
||||
response_data[5] = sector;
|
||||
response_data[6] = args[4];
|
||||
|
||||
if(dor & 8)
|
||||
{
|
||||
pic.push_irq(6);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function fix_drive_data(args)
|
||||
{
|
||||
dbg_log("floppy fix drive data " + args, LOG_DISK);
|
||||
}
|
||||
|
||||
function read_sector_id(args)
|
||||
{
|
||||
dbg_log("floppy read sector id " + args, LOG_DISK);
|
||||
|
||||
response_index = 0;
|
||||
response_length = 7;
|
||||
|
||||
response_data[0] = 0;
|
||||
response_data[1] = 0;
|
||||
response_data[2] = 0;
|
||||
response_data[3] = 0;
|
||||
response_data[4] = 0;
|
||||
response_data[5] = 0;
|
||||
response_data[6] = 0;
|
||||
|
||||
if(dor & 8)
|
||||
{
|
||||
pic.push_irq(6);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
1656
src/fpu.macro.js
Normal file
1656
src/fpu.macro.js
Normal file
File diff suppressed because it is too large
Load diff
2263
src/instructions.macro.js
Normal file
2263
src/instructions.macro.js
Normal file
File diff suppressed because it is too large
Load diff
175
src/io.js
Normal file
175
src/io.js
Normal file
|
@ -0,0 +1,175 @@
|
|||
"use strict";
|
||||
|
||||
/**
|
||||
* The ISA IO bus
|
||||
* Devices register their ports here
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function IO()
|
||||
{
|
||||
var a20_byte = 0,
|
||||
me = this;
|
||||
|
||||
function get_port_description(addr)
|
||||
{
|
||||
// via seabios ioport.h
|
||||
var ports = {
|
||||
0x0004: "PORT_DMA_ADDR_2",
|
||||
0x0005: "PORT_DMA_CNT_2",
|
||||
0x000a: "PORT_DMA1_MASK_REG",
|
||||
0x000b: "PORT_DMA1_MODE_REG",
|
||||
0x000c: "PORT_DMA1_CLEAR_FF_REG",
|
||||
0x000d: "PORT_DMA1_MASTER_CLEAR",
|
||||
0x0020: "PORT_PIC1_CMD",
|
||||
0x0021: "PORT_PIC1_DATA",
|
||||
0x0040: "PORT_PIT_COUNTER0",
|
||||
0x0041: "PORT_PIT_COUNTER1",
|
||||
0x0042: "PORT_PIT_COUNTER2",
|
||||
0x0043: "PORT_PIT_MODE",
|
||||
0x0060: "PORT_PS2_DATA",
|
||||
0x0061: "PORT_PS2_CTRLB",
|
||||
0x0064: "PORT_PS2_STATUS",
|
||||
0x0070: "PORT_CMOS_INDEX",
|
||||
0x0071: "PORT_CMOS_DATA",
|
||||
0x0080: "PORT_DIAG",
|
||||
0x0081: "PORT_DMA_PAGE_2",
|
||||
0x0092: "PORT_A20",
|
||||
0x00a0: "PORT_PIC2_CMD",
|
||||
0x00a1: "PORT_PIC2_DATA",
|
||||
0x00b2: "PORT_SMI_CMD",
|
||||
0x00b3: "PORT_SMI_STATUS",
|
||||
0x00d4: "PORT_DMA2_MASK_REG",
|
||||
0x00d6: "PORT_DMA2_MODE_REG",
|
||||
0x00da: "PORT_DMA2_MASTER_CLEAR",
|
||||
0x00f0: "PORT_MATH_CLEAR",
|
||||
0x0170: "PORT_ATA2_CMD_BASE",
|
||||
0x01f0: "PORT_ATA1_CMD_BASE",
|
||||
0x0278: "PORT_LPT2",
|
||||
0x02e8: "PORT_SERIAL4",
|
||||
0x02f8: "PORT_SERIAL2",
|
||||
0x0374: "PORT_ATA2_CTRL_BASE",
|
||||
0x0378: "PORT_LPT1",
|
||||
0x03e8: "PORT_SERIAL3",
|
||||
//0x03f4: "PORT_ATA1_CTRL_BASE",
|
||||
0x03f0: "PORT_FD_BASE",
|
||||
0x03f2: "PORT_FD_DOR",
|
||||
0x03f4: "PORT_FD_STATUS",
|
||||
0x03f5: "PORT_FD_DATA",
|
||||
0x03f6: "PORT_HD_DATA",
|
||||
0x03f7: "PORT_FD_DIR",
|
||||
0x03f8: "PORT_SERIAL1",
|
||||
0x0cf8: "PORT_PCI_CMD",
|
||||
0x0cf9: "PORT_PCI_REBOOT",
|
||||
0x0cfc: "PORT_PCI_DATA",
|
||||
0x0402: "PORT_BIOS_DEBUG",
|
||||
0x0510: "PORT_QEMU_CFG_CTL",
|
||||
0x0511: "PORT_QEMU_CFG_DATA",
|
||||
0xb000: "PORT_ACPI_PM_BASE",
|
||||
0xb100: "PORT_SMB_BASE",
|
||||
0x8900: "PORT_BIOS_APM"
|
||||
};
|
||||
|
||||
if(ports[addr])
|
||||
{
|
||||
return " (" + ports[addr] + ")";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
function empty_port_read_debug(port_addr)
|
||||
{
|
||||
dbg_log(
|
||||
"read port #" + h(port_addr, 3) + get_port_description(port_addr),
|
||||
LOG_IO
|
||||
);
|
||||
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
function empty_port_write_debug(port_addr, out_byte)
|
||||
{
|
||||
dbg_log(
|
||||
"write port #" + h(port_addr, 3) + " <- " + h(out_byte, 2) + get_port_description(port_addr),
|
||||
LOG_IO
|
||||
);
|
||||
}
|
||||
|
||||
function empty_port_read()
|
||||
{
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
function empty_port_write(x)
|
||||
{
|
||||
}
|
||||
|
||||
var read_callbacks = [],
|
||||
write_callbacks = [];
|
||||
|
||||
for(var i = 0; i < 0x10000; i++)
|
||||
{
|
||||
// avoid sparse arrays
|
||||
|
||||
if(DEBUG)
|
||||
{
|
||||
read_callbacks[i] = empty_port_read_debug.bind(0, i);
|
||||
write_callbacks[i] = empty_port_write_debug.bind(0, i);
|
||||
}
|
||||
else
|
||||
{
|
||||
read_callbacks[i] = empty_port_read;
|
||||
write_callbacks[i] = empty_port_write;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} port_addr
|
||||
* @param {function():number} callback
|
||||
*/
|
||||
this.register_read = function(port_addr, callback)
|
||||
{
|
||||
read_callbacks[port_addr] = callback;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {number} port_addr
|
||||
* @param {function(number)} callback
|
||||
*/
|
||||
this.register_write = function(port_addr, callback)
|
||||
{
|
||||
write_callbacks[port_addr] = callback;
|
||||
};
|
||||
|
||||
|
||||
// should maybe be somewhere else?
|
||||
this.register_read(0x92, function()
|
||||
{
|
||||
return a20_byte;
|
||||
});
|
||||
|
||||
this.register_write(0x92, function(out_byte)
|
||||
{
|
||||
a20_byte = out_byte;
|
||||
});
|
||||
|
||||
// use by linux for timing
|
||||
this.register_write(0x80, function(out_byte)
|
||||
{
|
||||
});
|
||||
|
||||
this.port_write = function(port_addr, out_byte)
|
||||
{
|
||||
write_callbacks[port_addr](out_byte);
|
||||
};
|
||||
|
||||
// read byte from port
|
||||
this.port_read = function(port_addr)
|
||||
{
|
||||
return read_callbacks[port_addr]();
|
||||
};
|
||||
}
|
||||
|
339
src/main.js
Normal file
339
src/main.js
Normal file
|
@ -0,0 +1,339 @@
|
|||
"use strict";
|
||||
|
||||
Object.fromList = function(xs)
|
||||
{
|
||||
var result = {};
|
||||
|
||||
for(var i = 0; i < xs.length; i++)
|
||||
{
|
||||
result[xs[i][0]] = xs[i][1];
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
|
||||
|
||||
var dbg_names = Object.fromList([
|
||||
[1, ""],
|
||||
[LOG_CPU, "CPU"],
|
||||
[LOG_DISK, "DISK"],
|
||||
[LOG_FPU, "FPU"],
|
||||
[LOG_MEM, "MEM"],
|
||||
[LOG_DMA, "DMA"],
|
||||
[LOG_IO, "IO"],
|
||||
[LOG_PS2, "PS2"],
|
||||
[LOG_PIC, "PIC"],
|
||||
[LOG_VGA, "VGA"],
|
||||
[LOG_PIT, "PIT"],
|
||||
[LOG_MOUSE, "MOUS"],
|
||||
[LOG_PCI, "PCI"],
|
||||
[LOG_BIOS, "BIOS"],
|
||||
[LOG_CD, "CD"],
|
||||
[LOG_SERIAL, "SERI"],
|
||||
[LOG_RTC, "RTC"],
|
||||
]);
|
||||
|
||||
|
||||
/**
|
||||
* @param {number=} level
|
||||
*/
|
||||
function dbg_log(stuff, level)
|
||||
{
|
||||
if(!DEBUG) return;
|
||||
|
||||
level = level || 1;
|
||||
|
||||
if(level & LOG_LEVEL)
|
||||
{
|
||||
var level_name = dbg_names[level] || "";
|
||||
|
||||
console.log("[" + String.pads(level_name, 4) + "] " + stuff);
|
||||
}
|
||||
};
|
||||
|
||||
function dbg_trace()
|
||||
{
|
||||
if(!DEBUG) return;
|
||||
|
||||
dbg_log(Error().stack);
|
||||
}
|
||||
|
||||
/**
|
||||
* console.assert is fucking slow
|
||||
* @param {string=} msg
|
||||
*/
|
||||
function dbg_assert(cond, msg)
|
||||
{
|
||||
if(!DEBUG) return;
|
||||
|
||||
if(!cond)
|
||||
{
|
||||
//dump_regs();
|
||||
console.log(Error().stack);
|
||||
console.trace();
|
||||
if(msg)
|
||||
{
|
||||
throw "Assert failed: " + msg;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw "Assert failed";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Object.extend = function(target, src)
|
||||
{
|
||||
var keys = Object.keys(src);
|
||||
|
||||
for(var i = 0; i < keys.length; i++)
|
||||
{
|
||||
target[keys[i]] = src[keys[i]];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// pad string with spaces on the right
|
||||
String.pads = function(str, len)
|
||||
{
|
||||
str = str ? str + "" : "";
|
||||
|
||||
while(str.length < len)
|
||||
{
|
||||
str = str + " ";
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
// pad string with zeros on the left
|
||||
String.pad0 = function(str, len)
|
||||
{
|
||||
str = str ? str + "" : "";
|
||||
|
||||
while(str.length < len)
|
||||
{
|
||||
str = "0" + str;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
Array.range = function(n)
|
||||
{
|
||||
var a = [];
|
||||
|
||||
for(var i = 0; i < n; i++)
|
||||
{
|
||||
a[i] = i;
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
/**
|
||||
* number to hex
|
||||
* @param {number=} len
|
||||
*/
|
||||
function h(n, len)
|
||||
{
|
||||
//dbg_assert(typeof n === "number");
|
||||
|
||||
if(!n) return String.pad0("", len || 1);
|
||||
|
||||
if(len)
|
||||
{
|
||||
return String.pad0(n.toString(16).toUpperCase(), len);
|
||||
}
|
||||
else
|
||||
{
|
||||
return n.toString(16).toUpperCase();
|
||||
}
|
||||
}
|
||||
|
||||
Number.bits = function(n)
|
||||
{
|
||||
var result = [];
|
||||
|
||||
for(var bit = 31; bit > -1; bit--)
|
||||
{
|
||||
if(n & 1 << bit)
|
||||
{
|
||||
result.push(bit);
|
||||
}
|
||||
}
|
||||
|
||||
return result.join(', ');
|
||||
}
|
||||
|
||||
String.chr_repeat = function(chr, count)
|
||||
{
|
||||
var result = "";
|
||||
|
||||
while(count--)
|
||||
{
|
||||
result += chr;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Math.bcd_pack = function(n)
|
||||
{
|
||||
var i = 0,
|
||||
result = 0,
|
||||
digit;
|
||||
|
||||
while(n)
|
||||
{
|
||||
digit = n % 10;
|
||||
|
||||
result |= digit << (4 * i);
|
||||
i++;
|
||||
n = (n - digit) / 10;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string=} msg
|
||||
* */
|
||||
function unimpl(msg)
|
||||
{
|
||||
var s = "Unimplemented" + (msg ? ": " + msg : "");
|
||||
|
||||
log(s);
|
||||
|
||||
if(DEBUG)
|
||||
{
|
||||
console.trace();
|
||||
return s;
|
||||
}
|
||||
else
|
||||
{
|
||||
log("Execution stopped");
|
||||
return s;
|
||||
}
|
||||
//this.name = "Unimplemented";
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronous access to ArrayBuffer
|
||||
* @constructor
|
||||
*/
|
||||
function SyncBuffer(buffer)
|
||||
{
|
||||
this.byteLength = buffer.byteLength;
|
||||
|
||||
// warning: fn may be called synchronously or asynchronously
|
||||
this.get = function(start, len, fn)
|
||||
{
|
||||
fn(new Uint8Array(buffer, start, len));
|
||||
};
|
||||
|
||||
this.set = function(start, slice, fn)
|
||||
{
|
||||
new Uint8Array(buffer, start, slice.byteLength).set(slice);
|
||||
fn();
|
||||
};
|
||||
|
||||
this.get_buffer = function(fn)
|
||||
{
|
||||
fn(buffer);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple circular queue for logs
|
||||
*
|
||||
* @param {number} size
|
||||
* @param {?=} Proto
|
||||
* @constructor
|
||||
*/
|
||||
function CircularQueue(size, Proto)
|
||||
{
|
||||
var data,
|
||||
index;
|
||||
|
||||
this.add = function(item)
|
||||
{
|
||||
data[index] = item;
|
||||
|
||||
index = (index + 1) % size;
|
||||
};
|
||||
|
||||
this.toArray = function()
|
||||
{
|
||||
return [].slice.call(data, index).concat([].slice.call(data, 0, index));
|
||||
};
|
||||
|
||||
this.clear = function()
|
||||
{
|
||||
if(Proto)
|
||||
{
|
||||
data = new Proto(size);
|
||||
}
|
||||
else
|
||||
{
|
||||
data = [];
|
||||
}
|
||||
|
||||
index = 0;
|
||||
};
|
||||
|
||||
this.set = function(new_data)
|
||||
{
|
||||
data = new_data;
|
||||
index = 0;
|
||||
};
|
||||
|
||||
|
||||
this.clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// switch number to big endian
|
||||
Math.to_be32 = function(dword)
|
||||
{
|
||||
return dword >>> 24 |
|
||||
dword >> 8 & 0xff00 |
|
||||
dword << 8 & 0xff0000 |
|
||||
dword << 24;
|
||||
}
|
||||
|
||||
Math.to_be16 = function(word)
|
||||
{
|
||||
return word >>> 8 & 0xff | word << 8 & 0xff00;
|
||||
}
|
||||
|
||||
|
||||
// used in several places
|
||||
// the first entry is -1
|
||||
// http://jsperf.com/integer-log2/2
|
||||
var log2_table = (function()
|
||||
{
|
||||
var t = new Int8Array(256);
|
||||
|
||||
for(var i = 0, b = -2; i < 256; i++)
|
||||
{
|
||||
if(!(i & i - 1))
|
||||
b++;
|
||||
|
||||
t[i] = b;
|
||||
}
|
||||
|
||||
return t;
|
||||
})();
|
||||
|
||||
|
||||
// round away from zero, opposite of truncation
|
||||
Math.roundInfinity = function(x)
|
||||
{
|
||||
return x > 0 ? Math.ceil(x) : Math.floor(x);
|
||||
};
|
||||
|
486
src/memory.js
Normal file
486
src/memory.js
Normal file
|
@ -0,0 +1,486 @@
|
|||
"use strict";
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
function Memory(buffer, memory_size)
|
||||
{
|
||||
var int8array = new Uint8Array(buffer),
|
||||
int16array = new Uint16Array(buffer),
|
||||
int8sarray = new Int8Array(buffer),
|
||||
int32sarray = new Int32Array(buffer);
|
||||
|
||||
this.mem8 = int8array;
|
||||
this.mem8s = int8sarray;
|
||||
this.mem32s = int32sarray;
|
||||
|
||||
this.buffer = buffer;
|
||||
|
||||
// debug function called by all memory reads and writes
|
||||
|
||||
function debug_write(addr, size, value)
|
||||
{
|
||||
if(!DEBUG)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//dbg_assert(typeof value === "number" && !isNaN(value));
|
||||
debug_read(addr, size, true);
|
||||
}
|
||||
|
||||
/** @param {boolean=} is_write */
|
||||
function debug_read(addr, size, is_write)
|
||||
{
|
||||
if(!DEBUG)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
dbg_assert(typeof addr === "number");
|
||||
dbg_assert(!isNaN(addr));
|
||||
|
||||
if((addr >= memory_size || addr < 0) && !memory_map_registered[addr >>> MMAP_BLOCK_SIZE])
|
||||
{
|
||||
dbg_log("Read from unmapped memory space, addr=" + h(addr, 8) /*+ " at " + h(instruction_pointer, 8)*/, LOG_IO);
|
||||
}
|
||||
|
||||
//dbg_assert(memory_map_registered[addr >>> MMAP_BLOCK_SIZE]);
|
||||
};
|
||||
|
||||
this.dump_all = function(start, end)
|
||||
{
|
||||
start = start || 0;
|
||||
end = end || 0x100000;
|
||||
|
||||
|
||||
// textarea method: (slow)
|
||||
//var result_string = "";
|
||||
|
||||
//for(var i = start; i < start + end; i++)
|
||||
//{
|
||||
// result_string += String.fromCharCode(int8array[i]);
|
||||
//}
|
||||
|
||||
//dump_text(btoa(result_string));
|
||||
|
||||
// save as method:
|
||||
dump_file(buffer.slice(start, end), "memory.bin");
|
||||
|
||||
};
|
||||
|
||||
this.dump = function(addr, length)
|
||||
{
|
||||
length = length || 4 * 0x10;
|
||||
var line, byt;
|
||||
|
||||
for(var i = 0; i < length >> 4; i++)
|
||||
{
|
||||
line = h(addr + (i << 4), 5) + " ";
|
||||
|
||||
for(var j = 0; j < 0x10; j++)
|
||||
{
|
||||
byt = this.read8(addr + (i << 4) + j);
|
||||
line += h(byt, 2) + " ";
|
||||
}
|
||||
|
||||
line += " ";
|
||||
|
||||
for(j = 0; j < 0x10; j++)
|
||||
{
|
||||
byt = this.read8(addr + (i << 4) + j);
|
||||
line += (byt < 33 || byt > 126) ? "." : String.fromCharCode(byt);
|
||||
}
|
||||
|
||||
dbg_log(line);
|
||||
}
|
||||
};
|
||||
|
||||
this.print_memory_map = function()
|
||||
{
|
||||
var width = 0x80,
|
||||
height = 0x10,
|
||||
block_size = memory_size / width / height | 0,
|
||||
row;
|
||||
|
||||
for(var i = 0; i < height; i++)
|
||||
{
|
||||
row = "0x" + h(i * width * block_size, 8) + " | ";
|
||||
|
||||
for(var j = 0; j < width; j++)
|
||||
{
|
||||
var used = this.mem32s[(i * width + j) * block_size] > 0;
|
||||
|
||||
row += used ? "X" : " ";
|
||||
}
|
||||
|
||||
dbg_log(row);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
var
|
||||
/**
|
||||
* Arbritary value, the minimum number of bytes that can be mapped
|
||||
* by one device. This might be spec'd somewhere ...
|
||||
*
|
||||
* Written as a power of 2.
|
||||
*
|
||||
* @const
|
||||
*/
|
||||
MMAP_BLOCK_SIZE = 14,
|
||||
|
||||
/** @const */
|
||||
MMAP_BYTEWISE = 1,
|
||||
MMAP_DWORDWISE = 4,
|
||||
|
||||
|
||||
// this only supports a 32 bit address space
|
||||
memory_map_registered = new Int8Array(1 << 32 - MMAP_BLOCK_SIZE),
|
||||
|
||||
memory_map_read = [],
|
||||
memory_map_write = [];
|
||||
|
||||
for(var i = 0; i < (1 << 32 - MMAP_BLOCK_SIZE); i++)
|
||||
{
|
||||
// avoid sparse arrays
|
||||
memory_map_read[i] = memory_map_write[i] = undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param addr {number}
|
||||
* @param size {number}
|
||||
* @param is_dword {boolean} true if the memory is addressed in dwords, otherwise byte
|
||||
*
|
||||
*/
|
||||
this.mmap_register = function(addr, size, is_dword, read_func, write_func)
|
||||
{
|
||||
dbg_log("mmap_register32 " + h(addr, 8) + ": " + h(size, 8), LOG_IO);
|
||||
dbg_assert((addr & (1 << MMAP_BLOCK_SIZE) - 1) === 0);
|
||||
dbg_assert(size >= (1 << MMAP_BLOCK_SIZE) && (size & (1 << MMAP_BLOCK_SIZE) - 1) === 0);
|
||||
|
||||
var aligned_addr = addr >>> MMAP_BLOCK_SIZE,
|
||||
unit_size = is_dword ? MMAP_DWORDWISE : MMAP_BYTEWISE;
|
||||
|
||||
for(; size > 0; aligned_addr++)
|
||||
{
|
||||
memory_map_registered[aligned_addr] = unit_size;
|
||||
|
||||
memory_map_read[aligned_addr] = function(read_addr)
|
||||
{
|
||||
return read_func(read_addr - addr | 0);
|
||||
};
|
||||
memory_map_write[aligned_addr] = function(write_addr, value)
|
||||
{
|
||||
write_func(write_addr - addr | 0, value);
|
||||
}
|
||||
|
||||
size -= 1 << MMAP_BLOCK_SIZE;
|
||||
}
|
||||
};
|
||||
|
||||
function mmap_read8(addr)
|
||||
{
|
||||
var aligned_addr = addr >>> MMAP_BLOCK_SIZE,
|
||||
registered = memory_map_read[aligned_addr];
|
||||
|
||||
//dbg_log("mmap_read8 " + h(addr, 8), LOG_IO);
|
||||
|
||||
if(memory_map_registered[aligned_addr] === MMAP_BYTEWISE)
|
||||
{
|
||||
return registered(addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
return mmap_read32(addr & ~3) >> 8 * (addr & 3) & 0xFF;
|
||||
}
|
||||
};
|
||||
|
||||
function mmap_write8(addr, value)
|
||||
{
|
||||
var aligned_addr = addr >>> MMAP_BLOCK_SIZE,
|
||||
registered = memory_map_write[addr >>> MMAP_BLOCK_SIZE];
|
||||
|
||||
//dbg_log("mmap_write8 " + h(addr, 8) + ": " + h(value, 2), LOG_IO);
|
||||
|
||||
if(memory_map_registered[aligned_addr] === MMAP_BYTEWISE)
|
||||
{
|
||||
registered(addr, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
// impossible without reading. Maybe this should do nothing
|
||||
dbg_assert(false);
|
||||
}
|
||||
};
|
||||
|
||||
function mmap_read32(addr)
|
||||
{
|
||||
var registered = memory_map_read[addr >>> MMAP_BLOCK_SIZE];
|
||||
|
||||
//dbg_log("mmap_read32 " + h(addr, 8), LOG_IO);
|
||||
//dbg_assert((addr & 3) === 0);
|
||||
dbg_assert(registered);
|
||||
|
||||
if((addr & 3) === 0 &&
|
||||
memory_map_registered[addr >>> MMAP_BLOCK_SIZE] === MMAP_DWORDWISE)
|
||||
{
|
||||
return registered(addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
return mmap_read8(addr) | mmap_read8(addr + 1) << 8 |
|
||||
mmap_read8(addr + 2) << 16 | mmap_read8(addr + 3) << 24;
|
||||
}
|
||||
};
|
||||
|
||||
function mmap_write32(addr, value)
|
||||
{
|
||||
var registered = memory_map_write[addr >>> MMAP_BLOCK_SIZE];
|
||||
|
||||
//dbg_log("mmap_write32 " + h(addr, 8) + ": " + h(value, 8), LOG_IO);
|
||||
//dbg_assert((addr & 3) === 0);
|
||||
dbg_assert(registered);
|
||||
|
||||
if((addr & 3) === 0 &&
|
||||
memory_map_registered[addr >>> MMAP_BLOCK_SIZE] === MMAP_DWORDWISE)
|
||||
{
|
||||
registered(addr, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
mmap_write8(addr, value & 0xFF);
|
||||
mmap_write8(addr + 1, value >> 8 & 0xFF);
|
||||
mmap_write8(addr + 2, value >> 16 & 0xFF);
|
||||
mmap_write8(addr + 3, value >> 24 & 0xFF);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param addr {number}
|
||||
*/
|
||||
this.read8s = function(addr)
|
||||
{
|
||||
debug_read(addr, 1);
|
||||
|
||||
if(memory_map_registered[addr >>> MMAP_BLOCK_SIZE])
|
||||
{
|
||||
return mmap_read8(addr) << 24 >> 24;
|
||||
}
|
||||
else
|
||||
{
|
||||
return int8sarray[addr];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param addr {number}
|
||||
*/
|
||||
this.read8 = function(addr)
|
||||
{
|
||||
debug_read(addr, 1);
|
||||
|
||||
if(memory_map_registered[addr >>> MMAP_BLOCK_SIZE])
|
||||
{
|
||||
return mmap_read8(addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
return int8array[addr];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param addr {number}
|
||||
*/
|
||||
this.read16 = function(addr)
|
||||
{
|
||||
debug_read(addr, 2);
|
||||
|
||||
if(memory_map_registered[addr >>> MMAP_BLOCK_SIZE])
|
||||
{
|
||||
return mmap_read8(addr) | mmap_read8(addr + 1) << 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
return int8array[addr] | int8array[addr + 1] << 8;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param addr {number}
|
||||
*/
|
||||
this.read_aligned16 = function(addr)
|
||||
{
|
||||
debug_read(addr, 2);
|
||||
|
||||
if(memory_map_registered[addr >>> MMAP_BLOCK_SIZE])
|
||||
{
|
||||
return mmap_read8(addr) | mmap_read8(addr + 1) << 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
return int16array[addr >> 1];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param addr {number}
|
||||
*/
|
||||
this.read32s = function(addr)
|
||||
{
|
||||
debug_read(addr, 4);
|
||||
|
||||
if(memory_map_registered[addr >>> MMAP_BLOCK_SIZE])
|
||||
{
|
||||
return mmap_read32(addr) | 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return int8array[addr] | int8array[addr + 1] << 8 |
|
||||
int8array[addr + 2] << 16 | int8array[addr + 3] << 24;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param addr {number}
|
||||
*/
|
||||
this.read_aligned32 = function(addr)
|
||||
{
|
||||
debug_read(addr, 4);
|
||||
|
||||
if(memory_map_registered[addr >>> MMAP_BLOCK_SIZE])
|
||||
{
|
||||
return mmap_read32(addr) | 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return int32sarray[addr >> 2];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param addr {number}
|
||||
* @param value {number}
|
||||
*/
|
||||
this.write8 = function(addr, value)
|
||||
{
|
||||
debug_write(addr, 1, value);
|
||||
|
||||
if(memory_map_registered[addr >>> MMAP_BLOCK_SIZE])
|
||||
{
|
||||
mmap_write8(addr, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
int8array[addr] = value;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param addr {number}
|
||||
* @param value {number}
|
||||
*/
|
||||
this.write16 = function(addr, value)
|
||||
{
|
||||
debug_write(addr, 2, value);
|
||||
|
||||
if(memory_map_registered[addr >>> MMAP_BLOCK_SIZE])
|
||||
{
|
||||
mmap_write8(addr, value & 0xff);
|
||||
mmap_write8(addr + 1, value >> 8 & 0xff);
|
||||
}
|
||||
else
|
||||
{
|
||||
int8array[addr] = value;
|
||||
int8array[addr + 1] = value >> 8;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param addr {number}
|
||||
* @param value {number}
|
||||
*/
|
||||
this.write_aligned16 = function(addr, value)
|
||||
{
|
||||
debug_write(addr, 2, value);
|
||||
|
||||
if(memory_map_registered[addr >>> MMAP_BLOCK_SIZE])
|
||||
{
|
||||
mmap_write8(addr, value & 0xff);
|
||||
mmap_write8(addr + 1, value >> 8 & 0xff);
|
||||
}
|
||||
else
|
||||
{
|
||||
int16array[addr >> 1] = value;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param addr {number}
|
||||
* @param value {number}
|
||||
*/
|
||||
this.write32 = function(addr, value)
|
||||
{
|
||||
debug_write(addr, 4, value);
|
||||
|
||||
if(memory_map_registered[addr >>> MMAP_BLOCK_SIZE])
|
||||
{
|
||||
mmap_write32(addr, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
int8array[addr] = value;
|
||||
int8array[addr + 1] = value >> 8;
|
||||
int8array[addr + 2] = value >> 16;
|
||||
int8array[addr + 3] = value >> 24;
|
||||
}
|
||||
};
|
||||
|
||||
this.write_aligned32 = function(addr, value)
|
||||
{
|
||||
if(memory_map_registered[addr >>> MMAP_BLOCK_SIZE])
|
||||
{
|
||||
mmap_write32(addr, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
int32sarray[addr >> 2] = value;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param offset {number}
|
||||
* @param blob {Array.<number>}
|
||||
*/
|
||||
this.write_blob = function(blob, offset)
|
||||
{
|
||||
dbg_assert(blob && blob.length);
|
||||
int8array.set(blob, offset);
|
||||
};
|
||||
|
||||
/**
|
||||
* zero byte terminated string
|
||||
*/
|
||||
this.read_string = function(addr)
|
||||
{
|
||||
var str = "",
|
||||
data_byte;
|
||||
|
||||
while(data_byte = this.read8(addr))
|
||||
{
|
||||
str += String.fromCharCode(data_byte);
|
||||
addr++;
|
||||
}
|
||||
|
||||
return str;
|
||||
};
|
||||
|
||||
this.write_string = function(str, addr)
|
||||
{
|
||||
for(var i = 0; i < str.length; i++)
|
||||
{
|
||||
this.write8(addr + i, str.charCodeAt(i));
|
||||
}
|
||||
};
|
||||
}
|
458
src/misc_instr.macro.js
Normal file
458
src/misc_instr.macro.js
Normal file
|
@ -0,0 +1,458 @@
|
|||
/*
|
||||
* Some miscellaneous instructions:
|
||||
*
|
||||
* jmpcc16, jmpcc32, jmp16
|
||||
* loop, loope, loopne, jcxz
|
||||
* test_cc
|
||||
*
|
||||
* mov, push, pop
|
||||
* pusha, popa
|
||||
* xchg, lss
|
||||
* lea
|
||||
* enter
|
||||
* bswap
|
||||
*
|
||||
* Gets #included by cpu.macro.js
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
function jmp_rel16(rel16)
|
||||
{
|
||||
var current_cs = get_seg(reg_cs);
|
||||
|
||||
// limit ip to 16 bit
|
||||
// ugly
|
||||
instruction_pointer -= current_cs;
|
||||
instruction_pointer = (instruction_pointer + rel16) & 0xFFFF;
|
||||
instruction_pointer = instruction_pointer + current_cs | 0;
|
||||
}
|
||||
|
||||
function jmpcc16(condition)
|
||||
{
|
||||
if(condition)
|
||||
{
|
||||
jmp_rel16(read_imm16());
|
||||
}
|
||||
else
|
||||
{
|
||||
instruction_pointer += 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function jmpcc32(condition)
|
||||
{
|
||||
if(condition)
|
||||
{
|
||||
// don't write `instruction_pointer += read_imm32s()`
|
||||
var imm32s = read_imm32s();
|
||||
instruction_pointer = instruction_pointer + imm32s | 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
instruction_pointer = instruction_pointer + 4 | 0;
|
||||
}
|
||||
}
|
||||
|
||||
function loopne()
|
||||
{
|
||||
if(--regv[reg_vcx] && !getzf())
|
||||
{
|
||||
var imm8s = read_imm8s();
|
||||
instruction_pointer = instruction_pointer + imm8s | 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
instruction_pointer++;
|
||||
}
|
||||
}
|
||||
|
||||
function loope()
|
||||
{
|
||||
if(--regv[reg_vcx] && getzf())
|
||||
{
|
||||
var imm8s = read_imm8s();
|
||||
instruction_pointer = instruction_pointer + imm8s | 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
instruction_pointer++;
|
||||
}
|
||||
}
|
||||
|
||||
function loop()
|
||||
{
|
||||
if(--regv[reg_vcx])
|
||||
{
|
||||
var imm8s = read_imm8s();
|
||||
instruction_pointer = instruction_pointer + imm8s | 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
instruction_pointer++;
|
||||
}
|
||||
}
|
||||
|
||||
function jcxz()
|
||||
{
|
||||
var imm8s = read_imm8s();
|
||||
|
||||
if(regv[reg_vcx] === 0)
|
||||
{
|
||||
instruction_pointer = instruction_pointer + imm8s | 0;
|
||||
}
|
||||
}
|
||||
|
||||
var test_o = getof,
|
||||
test_b = getcf,
|
||||
test_z = getzf,
|
||||
test_s = getsf,
|
||||
test_p = getpf;
|
||||
|
||||
function test_be()
|
||||
{
|
||||
return getcf() || getzf();
|
||||
}
|
||||
|
||||
function test_l()
|
||||
{
|
||||
return !getsf() !== !getof();
|
||||
}
|
||||
|
||||
function test_le()
|
||||
{
|
||||
return getzf() || !getsf() !== !getof();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {number}
|
||||
* @const
|
||||
*/
|
||||
function getcf()
|
||||
{
|
||||
if(flags_changed & 1)
|
||||
{
|
||||
if(last_op_size === OPSIZE_32)
|
||||
{
|
||||
// cannot bit test above 2^32-1
|
||||
return last_result > 0xffffffff | last_result < 0;
|
||||
//return ((last_op1 ^ last_result) & (last_op2 ^ last_result)) >>> 31;
|
||||
}
|
||||
else
|
||||
{
|
||||
return last_result >> last_op_size & 1;
|
||||
}
|
||||
|
||||
//return last_result >= (1 << last_op_size) | last_result < 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return flags & 1;
|
||||
}
|
||||
}
|
||||
|
||||
/** @return {number} */
|
||||
function getpf()
|
||||
{
|
||||
if(flags_changed & flag_parity)
|
||||
{
|
||||
// inverted lookup table
|
||||
return 0x9669 << 2 >> ((last_result ^ last_result >> 4) & 0xF) & flag_parity;
|
||||
}
|
||||
else
|
||||
{
|
||||
return flags & flag_parity;
|
||||
}
|
||||
}
|
||||
|
||||
/** @return {number} */
|
||||
function getaf()
|
||||
{
|
||||
if(flags_changed & flag_adjust)
|
||||
{
|
||||
return (last_op1 ^ last_op2 ^ last_result ^ (last_op2 < 0) << 4) & flag_adjust;
|
||||
}
|
||||
else
|
||||
{
|
||||
return flags & flag_adjust;
|
||||
}
|
||||
}
|
||||
|
||||
/** @return {number} */
|
||||
function getzf()
|
||||
{
|
||||
if(flags_changed & flag_zero)
|
||||
{
|
||||
return (~last_result & last_result - 1) >> last_op_size - 7 & flag_zero;
|
||||
}
|
||||
else
|
||||
{
|
||||
return flags & flag_zero;
|
||||
}
|
||||
}
|
||||
|
||||
/** @return {number} */
|
||||
function getsf()
|
||||
{
|
||||
if(flags_changed & flag_sign)
|
||||
{
|
||||
return last_result >> last_op_size - 8 & flag_sign;
|
||||
}
|
||||
else
|
||||
{
|
||||
return flags & flag_sign;
|
||||
}
|
||||
}
|
||||
|
||||
/** @return {number} */
|
||||
function getof()
|
||||
{
|
||||
if(flags_changed & flag_overflow)
|
||||
{
|
||||
return (((last_op1 ^ last_result) & (last_op2 ^ last_result)) >> last_op_size - 1) << 11 & flag_overflow;
|
||||
}
|
||||
else
|
||||
{
|
||||
return flags & flag_overflow;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function push16(imm16)
|
||||
{
|
||||
var sp = get_esp_write(-2);
|
||||
|
||||
stack_reg[reg_vsp] -= 2;
|
||||
memory.write16(sp, imm16);
|
||||
}
|
||||
|
||||
function push32(imm32)
|
||||
{
|
||||
var sp = get_esp_write(-4);
|
||||
|
||||
stack_reg[reg_vsp] -= 4;
|
||||
memory.write32(sp, imm32);
|
||||
}
|
||||
|
||||
function pop16()
|
||||
{
|
||||
var sp = get_esp_read(0);
|
||||
|
||||
stack_reg[reg_vsp] += 2;
|
||||
return memory.read16(sp);
|
||||
}
|
||||
|
||||
function pop32s()
|
||||
{
|
||||
var sp = get_esp_read(0);
|
||||
|
||||
stack_reg[reg_vsp] += 4;
|
||||
return memory.read32s(sp);
|
||||
}
|
||||
|
||||
function pusha16()
|
||||
{
|
||||
var temp = reg16[reg_sp];
|
||||
|
||||
// make sure we don't get a pagefault after having
|
||||
// pushed several registers already
|
||||
translate_address_write(temp - 15);
|
||||
|
||||
push16(reg16[reg_ax]);
|
||||
push16(reg16[reg_cx]);
|
||||
push16(reg16[reg_dx]);
|
||||
push16(reg16[reg_bx]);
|
||||
push16(temp);
|
||||
push16(reg16[reg_bp]);
|
||||
push16(reg16[reg_si]);
|
||||
push16(reg16[reg_di]);
|
||||
}
|
||||
|
||||
function pusha32()
|
||||
{
|
||||
var temp = reg32s[reg_esp];
|
||||
|
||||
translate_address_write(temp - 31);
|
||||
|
||||
push32(reg32s[reg_eax]);
|
||||
push32(reg32s[reg_ecx]);
|
||||
push32(reg32s[reg_edx]);
|
||||
push32(reg32s[reg_ebx]);
|
||||
push32(temp);
|
||||
push32(reg32s[reg_ebp]);
|
||||
push32(reg32s[reg_esi]);
|
||||
push32(reg32s[reg_edi]);
|
||||
}
|
||||
|
||||
function popa16()
|
||||
{
|
||||
translate_address_read(stack_reg[reg_vsp] + 15);
|
||||
|
||||
reg16[reg_di] = pop16();
|
||||
reg16[reg_si] = pop16();
|
||||
reg16[reg_bp] = pop16();
|
||||
stack_reg[reg_vsp] += 2;
|
||||
reg16[reg_bx] = pop16();
|
||||
reg16[reg_dx] = pop16();
|
||||
reg16[reg_cx] = pop16();
|
||||
reg16[reg_ax] = pop16();
|
||||
}
|
||||
|
||||
function popa32()
|
||||
{
|
||||
translate_address_read(stack_reg[reg_vsp] + 31);
|
||||
|
||||
reg32[reg_edi] = pop32s();
|
||||
reg32[reg_esi] = pop32s();
|
||||
reg32[reg_ebp] = pop32s();
|
||||
stack_reg[reg_vsp] += 4;
|
||||
reg32[reg_ebx] = pop32s();
|
||||
reg32[reg_edx] = pop32s();
|
||||
reg32[reg_ecx] = pop32s();
|
||||
reg32[reg_eax] = pop32s();
|
||||
}
|
||||
|
||||
function xchg8(memory_data, modrm_byte)
|
||||
{
|
||||
var mod = modrm_byte >> 1 & 0xC | modrm_byte >> 5 & 1,
|
||||
tmp = reg8[mod];
|
||||
|
||||
reg8[mod] = memory_data;
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
function xchg16(memory_data, modrm_byte)
|
||||
{
|
||||
var mod = modrm_byte >> 2 & 14,
|
||||
tmp = reg16[mod];
|
||||
|
||||
reg16[mod] = memory_data;
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
function xchg16r(operand)
|
||||
{
|
||||
var temp = reg16[reg_ax];
|
||||
reg16[reg_ax] = reg16[operand];
|
||||
reg16[operand] = temp;
|
||||
}
|
||||
|
||||
function xchg32(memory_data, modrm_byte)
|
||||
{
|
||||
var mod = modrm_byte >> 3 & 7,
|
||||
tmp = reg32s[mod];
|
||||
|
||||
reg32[mod] = memory_data;
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
function xchg32r(operand)
|
||||
{
|
||||
var temp = reg32s[reg_eax];
|
||||
reg32[reg_eax] = reg32s[operand];
|
||||
reg32[operand] = temp;
|
||||
}
|
||||
|
||||
function lss16(seg, addr, mod)
|
||||
{
|
||||
var new_reg = safe_read16(addr),
|
||||
new_seg = safe_read16(addr + 2);
|
||||
|
||||
switch_seg(seg, new_seg);
|
||||
|
||||
reg16[mod] = new_reg;
|
||||
}
|
||||
|
||||
function lss32(seg, addr, mod)
|
||||
{
|
||||
var new_reg = safe_read32s(addr),
|
||||
new_seg = safe_read16(addr + 4);
|
||||
|
||||
switch_seg(seg, new_seg);
|
||||
|
||||
reg32[mod] = new_reg;
|
||||
}
|
||||
|
||||
function lea16()
|
||||
{
|
||||
var modrm_byte = read_imm8(),
|
||||
mod = modrm_byte >> 3 & 7;
|
||||
|
||||
// override prefix, so modrm16 does not return the segment part
|
||||
segment_prefix = reg_noseg;
|
||||
|
||||
reg16[mod << 1] = modrm_resolve(modrm_byte);
|
||||
|
||||
segment_prefix = -1;
|
||||
}
|
||||
|
||||
function lea32()
|
||||
{
|
||||
var modrm_byte = read_imm8(),
|
||||
mod = modrm_byte >> 3 & 7;
|
||||
|
||||
segment_prefix = reg_noseg;
|
||||
|
||||
reg32[mod] = modrm_resolve(modrm_byte);
|
||||
|
||||
segment_prefix = -1;
|
||||
}
|
||||
|
||||
function enter16()
|
||||
{
|
||||
var size = read_imm16(),
|
||||
nesting_level = read_imm8(),
|
||||
frame_temp;
|
||||
|
||||
push16(reg16[reg_bp]);
|
||||
frame_temp = reg16[reg_sp];
|
||||
|
||||
if(nesting_level > 0)
|
||||
{
|
||||
for(var i = 1; i < nesting_level; i++)
|
||||
{
|
||||
reg16[reg_bp] -= 2;
|
||||
push16(reg16[reg_bp]);
|
||||
}
|
||||
push16(frame_temp);
|
||||
}
|
||||
reg16[reg_bp] = frame_temp;
|
||||
reg16[reg_sp] = frame_temp - size;
|
||||
|
||||
dbg_assert(!page_fault);
|
||||
}
|
||||
|
||||
function enter32()
|
||||
{
|
||||
var size = read_imm16(),
|
||||
nesting_level = read_imm8() & 31,
|
||||
frame_temp;
|
||||
|
||||
push32(reg32s[reg_ebp]);
|
||||
frame_temp = reg32s[reg_esp];
|
||||
|
||||
if(nesting_level > 0)
|
||||
{
|
||||
for(var i = 1; i < nesting_level; i++)
|
||||
{
|
||||
reg32[reg_ebp] -= 4;
|
||||
push32(reg32s[reg_ebp]);
|
||||
}
|
||||
push32(frame_temp);
|
||||
}
|
||||
reg32[reg_ebp] = frame_temp;
|
||||
reg32[reg_esp] -= size;
|
||||
|
||||
dbg_assert(!page_fault);
|
||||
}
|
||||
|
||||
function bswap(reg)
|
||||
{
|
||||
var temp = reg32s[reg];
|
||||
|
||||
reg32[reg] = temp >>> 24 | temp << 24 | (temp >> 8 & 0xFF00) | (temp << 8 & 0xFF0000);
|
||||
}
|
||||
|
176
src/modrm.macro.js
Normal file
176
src/modrm.macro.js
Normal file
|
@ -0,0 +1,176 @@
|
|||
/*
|
||||
* This file contains functions to decode the modrm and sib bytes
|
||||
*
|
||||
* These functions return a virtual address
|
||||
*
|
||||
* Gets #included by cpu.macro.js
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
var modrm_resolve16,
|
||||
modrm_resolve32;
|
||||
|
||||
(function() {
|
||||
|
||||
var modrm_table16 = Array(0xC0),
|
||||
modrm_table32 = Array(0xC0),
|
||||
sib_table = Array(0x100);
|
||||
|
||||
#define ds get_seg_prefix(reg_ds)
|
||||
#define ss get_seg_prefix(reg_ss)
|
||||
|
||||
#define eax reg32s[reg_eax]
|
||||
#define ecx reg32s[reg_ecx]
|
||||
#define edx reg32s[reg_edx]
|
||||
#define ebx reg32s[reg_ebx]
|
||||
#define esp reg32s[reg_esp]
|
||||
#define ebp reg32s[reg_ebp]
|
||||
#define esi reg32s[reg_esi]
|
||||
#define edi reg32s[reg_edi]
|
||||
|
||||
#define imm32 read_imm32s()
|
||||
#define imm16 read_imm16()
|
||||
#define imm8 read_imm8()
|
||||
|
||||
#define entry16(row, seg, value)\
|
||||
entry16_(0x00 | row, seg + ((value) & 0xFFFF))\
|
||||
entry16_(0x40 | row, seg + ((value) + read_imm8s() & 0xFFFF))\
|
||||
entry16_(0x80 | row, seg + ((value) + read_imm16() & 0xFFFF))\
|
||||
|
||||
#define entry16_(n, offset)\
|
||||
modrm_table16[n] = function() { return offset | 0; };
|
||||
|
||||
|
||||
entry16(0, ds, reg16[reg_bx] + reg16[reg_si])
|
||||
entry16(1, ds, reg16[reg_bx] + reg16[reg_di])
|
||||
entry16(2, ss, reg16[reg_bp] + reg16[reg_si])
|
||||
entry16(3, ss, reg16[reg_bp] + reg16[reg_di])
|
||||
entry16(4, ds, reg16[reg_si])
|
||||
entry16(5, ds, reg16[reg_di])
|
||||
entry16(6, ss, reg16[reg_bp])
|
||||
entry16(7, ds, reg16[reg_bx])
|
||||
|
||||
#define entry32(row, value)\
|
||||
entry32_(0x00 | row, (value))\
|
||||
entry32_(0x40 | row, (value) + read_imm8s())\
|
||||
entry32_(0x80 | row, (value) + read_imm32s())\
|
||||
|
||||
#define entry32_(n, offset)\
|
||||
modrm_table32[n] = function() { return offset | 0; };
|
||||
|
||||
|
||||
entry32(0, ds + eax);
|
||||
entry32(1, ds + ecx);
|
||||
entry32(2, ds + edx);
|
||||
entry32(3, ds + ebx);
|
||||
entry32(4, getsib(false));
|
||||
entry32(5, ss + ebp);
|
||||
entry32(6, ds + esi);
|
||||
entry32(7, ds + edi);
|
||||
|
||||
|
||||
// special cases
|
||||
modrm_table16[0x00 | 6] = function() { return ds + read_imm16() | 0; }
|
||||
|
||||
modrm_table32[0x00 | 5] = function() { return ds + read_imm32s() | 0; };
|
||||
|
||||
modrm_table32[0x00 | 4] = function() { return getsib(false) | 0; };
|
||||
modrm_table32[0x40 | 4] = function() { return getsib(true) + read_imm8s() | 0; };
|
||||
modrm_table32[0x80 | 4] = function() { return getsib(true) + read_imm32s() | 0; };
|
||||
|
||||
|
||||
for(var low = 0; low < 8; low++)
|
||||
{
|
||||
for(var high = 0; high < 3; high++)
|
||||
{
|
||||
for(var i = 1; i < 8; i++)
|
||||
{
|
||||
var x = low | high << 6;
|
||||
|
||||
modrm_table32[x | i << 3] = modrm_table32[x];
|
||||
modrm_table16[x | i << 3] = modrm_table16[x];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define entry_sib(n, reg1)\
|
||||
entry_sib2(0x00 | n << 3, reg1)\
|
||||
entry_sib2(0x40 | n << 3, reg1 << 1)\
|
||||
entry_sib2(0x80 | n << 3, reg1 << 2)\
|
||||
entry_sib2(0xC0 | n << 3, reg1 << 3)
|
||||
|
||||
#define entry_sib2(n, offset)\
|
||||
entry_sib3(n | 0, (offset) + ds + eax)\
|
||||
entry_sib3(n | 1, (offset) + ds + ecx)\
|
||||
entry_sib3(n | 2, (offset) + ds + edx)\
|
||||
entry_sib3(n | 3, (offset) + ds + ebx)\
|
||||
entry_sib3(n | 4, (offset) + ss + esp)\
|
||||
entry_sib3(n | 5, (offset) + (mod ? ss + ebp : ds + imm32))\
|
||||
entry_sib3(n | 6, (offset) + ds + esi)\
|
||||
entry_sib3(n | 7, (offset) + ds + edi)
|
||||
|
||||
#define entry_sib3(n, offset)\
|
||||
sib_table[n] = function(mod) { return offset | 0; };
|
||||
|
||||
entry_sib(0, eax);
|
||||
entry_sib(1, ecx);
|
||||
entry_sib(2, edx);
|
||||
entry_sib(3, ebx);
|
||||
entry_sib(4, 0);
|
||||
entry_sib(5, ebp);
|
||||
entry_sib(6, esi);
|
||||
entry_sib(7, edi);
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} modrm_byte
|
||||
* @return {number}
|
||||
*/
|
||||
modrm_resolve16 = function(modrm_byte)
|
||||
{
|
||||
return modrm_table16[modrm_byte]();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} modrm_byte
|
||||
* @return {number}
|
||||
*/
|
||||
modrm_resolve32 = function(modrm_byte)
|
||||
{
|
||||
return modrm_table32[modrm_byte]();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {boolean} mod
|
||||
* @return {number}
|
||||
*/
|
||||
function getsib(mod)
|
||||
{
|
||||
return sib_table[read_imm8()](mod);
|
||||
}
|
||||
|
||||
#undef ds
|
||||
#undef ss
|
||||
|
||||
#undef eax
|
||||
#undef ecx
|
||||
#undef edx
|
||||
#undef ebx
|
||||
#undef esp
|
||||
#undef ebp
|
||||
#undef esi
|
||||
#undef edi
|
||||
|
||||
#undef imm32
|
||||
#undef imm16
|
||||
#undef imm8
|
||||
|
||||
#undef entry16
|
||||
#undef entry16_
|
||||
#undef entry32_
|
||||
|
||||
#undef entry_sib
|
||||
#undef entry_sib2
|
||||
#undef entry_sib3
|
||||
|
||||
})();
|
BIN
src/node/ascii.ttf
Normal file
BIN
src/node/ascii.ttf
Normal file
Binary file not shown.
35
src/node/keyboard_sdl.js
Normal file
35
src/node/keyboard_sdl.js
Normal file
|
@ -0,0 +1,35 @@
|
|||
"use strict";
|
||||
|
||||
function NodeKeyboardSDL(sdl)
|
||||
{
|
||||
var send_code;
|
||||
|
||||
sdl.events.on("KEYDOWN", onkeydown);
|
||||
sdl.events.on("KEYUP", onkeyup);
|
||||
|
||||
this.enabled = true;
|
||||
|
||||
this.destroy = function()
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
this.init = function(send_code_fn)
|
||||
{
|
||||
send_code = send_code_fn;
|
||||
};
|
||||
|
||||
function onkeydown(e)
|
||||
{
|
||||
//console.log("d", e);
|
||||
send_code(e.scancode - 8);
|
||||
}
|
||||
|
||||
function onkeyup(e)
|
||||
{
|
||||
//console.log("u", e);
|
||||
send_code(e.scancode - 8 | 0x80);
|
||||
}
|
||||
}
|
||||
|
||||
|
60
src/node/keyboard_tty.js
Normal file
60
src/node/keyboard_tty.js
Normal file
|
@ -0,0 +1,60 @@
|
|||
"use strict";
|
||||
|
||||
function NodeKeyboardTTY()
|
||||
{
|
||||
var stdin = process.stdin;
|
||||
var send_code;
|
||||
|
||||
var charmap = [
|
||||
// TODO: Fill this in or get it from somewhere
|
||||
];
|
||||
|
||||
//stdin.setRawMode(true);
|
||||
stdin.resume();
|
||||
|
||||
|
||||
stdin.setEncoding('utf8');
|
||||
|
||||
this.enabled = true;
|
||||
this.destroy = function()
|
||||
{
|
||||
|
||||
};
|
||||
this.init = function(send_code_fn)
|
||||
{
|
||||
send_code = send_code_fn;
|
||||
};
|
||||
|
||||
stdin.on("data", function(c)
|
||||
{
|
||||
if(c === '\u0003')
|
||||
{
|
||||
process.exit();
|
||||
}
|
||||
|
||||
var str = "";
|
||||
|
||||
for(var i = 0; i < c.length; i++)
|
||||
{
|
||||
str += c.charCodeAt(i);
|
||||
}
|
||||
|
||||
//dbg_log(str);
|
||||
dbg_log("2 " + JSON.stringify(arguments));
|
||||
});
|
||||
|
||||
stdin.on("keypress", function(c)
|
||||
{
|
||||
if(c === '\u0003')
|
||||
{
|
||||
process.exit();
|
||||
}
|
||||
|
||||
dbg_log("keypress: " + JSON.stringify(arguments));
|
||||
|
||||
var code = charmap[c.charCodeAt(0)];
|
||||
|
||||
send_code(code);
|
||||
//send_code(code | 0x80);
|
||||
});
|
||||
}
|
141
src/node/main.js
Normal file
141
src/node/main.js
Normal file
|
@ -0,0 +1,141 @@
|
|||
"use strict";
|
||||
|
||||
|
||||
|
||||
var path = __dirname + "/../",
|
||||
bios_path = path + "../bios/",
|
||||
image_path = path + "../images/";
|
||||
|
||||
|
||||
// otherwise tty ouput is used
|
||||
var USE_SDL = true,
|
||||
FONT_FILE = path + "node/ascii.ttf";
|
||||
|
||||
(function()
|
||||
{
|
||||
var tick_fn;
|
||||
|
||||
global.set_tick = function(fn)
|
||||
{
|
||||
tick_fn = fn;
|
||||
};
|
||||
|
||||
global.next_tick = function()
|
||||
{
|
||||
setImmediate(tick_fn);
|
||||
};
|
||||
})();
|
||||
|
||||
|
||||
global.log = function(str)
|
||||
{
|
||||
console.log(str);
|
||||
};
|
||||
|
||||
var fs = require('fs'),
|
||||
vm = require('vm'),
|
||||
|
||||
include = function(path)
|
||||
{
|
||||
// ugh ...
|
||||
var code = fs.readFileSync(path);
|
||||
vm.runInThisContext(code, path);
|
||||
}.bind(this);
|
||||
|
||||
include(path + "const.js");
|
||||
include(path + "cpu.js");
|
||||
include(path + "main.js");
|
||||
include(path + "floppy.js");
|
||||
include(path + "memory.js");
|
||||
include(path + "io.js");
|
||||
include(path + "pci.js");
|
||||
include(path + "disk.js");
|
||||
include(path + "dma.js");
|
||||
include(path + "pit.js");
|
||||
include(path + "vga.js");
|
||||
include(path + "ps2.js");
|
||||
include(path + "pic.js");
|
||||
include(path + "uart.js");
|
||||
include(path + "rtc.js");
|
||||
|
||||
|
||||
DEBUG = true;
|
||||
|
||||
|
||||
function read_array_buffer(file)
|
||||
{
|
||||
var buffer = fs.readFileSync(file),
|
||||
ab = new ArrayBuffer(buffer.length),
|
||||
arr = new Uint8Array(ab);
|
||||
|
||||
for (var i = 0; i < buffer.length; i++)
|
||||
{
|
||||
arr[i] = buffer[i];
|
||||
}
|
||||
|
||||
return ab;
|
||||
}
|
||||
|
||||
|
||||
var settings = {
|
||||
load_devices: true,
|
||||
},
|
||||
argv = process.argv;
|
||||
|
||||
|
||||
if(USE_SDL)
|
||||
{
|
||||
var sdl = require("node-sdl");
|
||||
|
||||
include(path + "node/keyboard_sdl.js");
|
||||
include(path + "node/screen_sdl.js");
|
||||
|
||||
settings.screen_adapter = new NodeScreenSDL(sdl, FONT_FILE);
|
||||
settings.keyboard_adapter = new NodeKeyboardSDL(sdl);
|
||||
}
|
||||
else
|
||||
{
|
||||
require('tty').setRawMode(true);
|
||||
|
||||
include(path + "node/keyboard_tty.js");
|
||||
include(path + "node/screen_tty.js");
|
||||
|
||||
settings.screen_adapter = new NodeScreenTTY();
|
||||
settings.keyboard_adapter = new NodeKeyboardTTY();
|
||||
}
|
||||
|
||||
|
||||
// just a prototype of a loader
|
||||
|
||||
if(argv && argv.length === 4 && (argv[2] === "cdrom" || argv[2] === "fda"))
|
||||
{
|
||||
var disk = new SyncBuffer(read_array_buffer(argv[3]));
|
||||
|
||||
if(argv[2] === "cdrom")
|
||||
{
|
||||
settings.cdrom_disk = disk;
|
||||
}
|
||||
else if(argv[2] === "fda")
|
||||
{
|
||||
settings.floppy_disk = disk;
|
||||
}
|
||||
|
||||
|
||||
settings.bios = read_array_buffer(bios_path + "seabios.bin");
|
||||
settings.vga_bios = read_array_buffer(bios_path + "vgabios.bin");
|
||||
|
||||
settings.screen_adapter
|
||||
|
||||
var cpu = new v86();
|
||||
|
||||
cpu.init(settings);
|
||||
cpu.run();
|
||||
}
|
||||
else
|
||||
{
|
||||
console.log("Usage: node main.js [cdrom|fda] disk.img");
|
||||
|
||||
process.exit();
|
||||
}
|
||||
|
||||
|
5
src/node/node_modules/node-sdl/.gitignore
generated
vendored
Normal file
5
src/node/node_modules/node-sdl/.gitignore
generated
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
.svn
|
||||
*.o
|
||||
.lock-wscript
|
||||
build
|
||||
node_modules
|
3
src/node/node_modules/node-sdl/.npmignore
generated
vendored
Normal file
3
src/node/node_modules/node-sdl/.npmignore
generated
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
build
|
||||
examples
|
||||
examples/*
|
72
src/node/node_modules/node-sdl/Makefile
generated
vendored
Normal file
72
src/node/node_modules/node-sdl/Makefile
generated
vendored
Normal file
|
@ -0,0 +1,72 @@
|
|||
# This file is generated by gyp; do not edit.
|
||||
|
||||
TOOLSET := target
|
||||
TARGET := nodesdl
|
||||
DEFS_Default :=
|
||||
|
||||
# Flags passed to all source files.
|
||||
CFLAGS_Default := \
|
||||
-I/usr/include/SDL \
|
||||
-D_GNU_SOURCE=1 \
|
||||
-D_REENTRANT
|
||||
|
||||
# Flags passed to only C files.
|
||||
CFLAGS_C_Default :=
|
||||
|
||||
# Flags passed to only C++ files.
|
||||
CFLAGS_CC_Default :=
|
||||
|
||||
INCS_Default :=
|
||||
|
||||
OBJS := \
|
||||
$(obj).target/$(TARGET)/node/node_modules/node-sdl/src/helpers.o \
|
||||
$(obj).target/$(TARGET)/node/node_modules/node-sdl/src/nodesdl.o
|
||||
|
||||
# Add to the list of files we specially track dependencies for.
|
||||
all_deps += $(OBJS)
|
||||
|
||||
# CFLAGS et al overrides must be target-local.
|
||||
# See "Target-specific Variable Values" in the GNU Make manual.
|
||||
$(OBJS): TOOLSET := $(TOOLSET)
|
||||
$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
|
||||
$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
|
||||
|
||||
# Suffix rules, putting all outputs into $(obj).
|
||||
|
||||
$(obj).$(TOOLSET)/$(TARGET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD
|
||||
@$(call do_cmd,cxx,1)
|
||||
|
||||
# Try building from generated source, too.
|
||||
|
||||
$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD
|
||||
@$(call do_cmd,cxx,1)
|
||||
|
||||
$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.cc FORCE_DO_CMD
|
||||
@$(call do_cmd,cxx,1)
|
||||
|
||||
# End of this set of suffix rules
|
||||
### Rules for final target.
|
||||
LDFLAGS_Default := \
|
||||
-L/usr/lib \
|
||||
-lSDL \
|
||||
-lpthread \
|
||||
-lSDL_ttf \
|
||||
-lSDL_image
|
||||
|
||||
LIBS :=
|
||||
|
||||
$(obj).target/node/node_modules/node-sdl/libnodesdl.a: GYP_LDFLAGS := $(LDFLAGS_$(BUILDTYPE))
|
||||
$(obj).target/node/node_modules/node-sdl/libnodesdl.a: LIBS := $(LIBS)
|
||||
$(obj).target/node/node_modules/node-sdl/libnodesdl.a: TOOLSET := $(TOOLSET)
|
||||
$(obj).target/node/node_modules/node-sdl/libnodesdl.a: $(OBJS) FORCE_DO_CMD
|
||||
$(call do_cmd,alink_thin)
|
||||
|
||||
all_deps += $(obj).target/node/node_modules/node-sdl/libnodesdl.a
|
||||
# Add target alias
|
||||
.PHONY: nodesdl
|
||||
nodesdl: $(obj).target/node/node_modules/node-sdl/libnodesdl.a
|
||||
|
||||
# Add target alias to "all" target.
|
||||
.PHONY: all
|
||||
all: nodesdl
|
||||
|
429
src/node/node_modules/node-sdl/README.md.orig
generated
vendored
Normal file
429
src/node/node_modules/node-sdl/README.md.orig
generated
vendored
Normal file
|
@ -0,0 +1,429 @@
|
|||
# node-sdl ( Simple DirectMedia Layer bindings for node.js )
|
||||
|
||||
## 0. Installation
|
||||
|
||||
Installation of the node-sdl package is straight-forward: first clone the
|
||||
package using git, then build the C++ portion of the package with the
|
||||
node-waf command.
|
||||
|
||||
This package depends on the SDL libraries being present on the target system.
|
||||
The following command was required to install these libraries on a "stock"
|
||||
Ubuntu 11.04 install:
|
||||
|
||||
<pre> sudo apt-get install libsdl1.2-dev libsdl-image1.2-dev libsdl-ttf2.0-dev</pre>
|
||||
|
||||
Now that your library dependencies are satisfied, check out the source from
|
||||
github:
|
||||
|
||||
<pre> git clone https://github.com/creationix/node-sdl.git</pre>
|
||||
|
||||
Second, build the package:
|
||||
|
||||
<pre> cd node-sdl
|
||||
node-waf configure build</pre>
|
||||
|
||||
You can test if the package was properly built by running one or more of the
|
||||
example programs:
|
||||
|
||||
<pre> cd examples
|
||||
node img.js</pre>
|
||||
|
||||
## 1. Usage
|
||||
|
||||
### 1.1. Initialization and Shutdown
|
||||
|
||||
Begin by requiring the node-sdl package and calling the init() function:
|
||||
|
||||
<pre> var SDL = require( 'sdl' );
|
||||
SDL.init( SDL.INIT.VIDEO )</pre>
|
||||
|
||||
The init() function takes a numeric parameter telling the library what
|
||||
subsystems to initialize. The node-sdl package defines the following
|
||||
constants:
|
||||
|
||||
<pre> SDL.INIT.TIMER - initializes timers (not currently supported)
|
||||
SDL.INIT.AUDIO - initialize audio subsystem (not currently supported)
|
||||
SDL.INIT.VIDEO - initialize video subsystem
|
||||
SDL.INIT.CDROM - initialize CD playback subsystem (not currently supported)
|
||||
SDL.INIT.JOYSTICK - initialize joystick support
|
||||
SDL.INIT.EVERYTHING - all of the above
|
||||
SDL.INIT.NOPARACHUTE - don't catch fatal signals
|
||||
</pre>
|
||||
|
||||
Two or more of these parameters may be selected by or-ing them together:
|
||||
|
||||
<pre> SDL.init( SDL.INIT.VIDEO | SDL.INIT.JOYSTICK );</pre>
|
||||
|
||||
The QUIT event signals the closure of a SDL managed window, so adding a
|
||||
function that exits the application when it is received may be useful:
|
||||
|
||||
<pre> SDL.events.on( 'QUIT', function( evt ) { process.exit( 0 ); } );</pre>
|
||||
|
||||
Exiting the application when the user presses Control-C or the Escape key
|
||||
can be achieved by adding a listener to the KEYDOWN event:
|
||||
|
||||
<pre> SDL.events.on( 'KEYDOWN', function ( evt ) {
|
||||
if( ( ( evt.sym === 99 ) && ( evt.mod === 64 ) ) ||
|
||||
( ( evt.sym === 27 ) && ( evt.mod === 0 ) ) ) {
|
||||
process.exit( 0 );
|
||||
}
|
||||
} );</pre>
|
||||
|
||||
### 1.2. Video Functions
|
||||
|
||||
To create a window under SDL control, use the setVideoMode() function to
|
||||
create a "surface".
|
||||
|
||||
<pre> var screen = SDL.setVideoMode( 640, 480, 32, SDL.SURFACE.SWSURFACE );</pre>
|
||||
|
||||
The setVideoMode() function takes four parameters: surface width, surface
|
||||
height, bit depth and surface flags. The flags parameter selects options for
|
||||
the video buffer:
|
||||
|
||||
<pre> SDL.SURFACE.SWSURFACE - video buffer created in system memory
|
||||
SDL.SURFACE.HWSURFACE - video buffer created in video memory
|
||||
SDL.SURFACE.ASYNCBLIT - enable async updates of display surface
|
||||
SDL.SURFACE.ANYFORMAT - don't emulate unavailable BPPs with a shadow surface
|
||||
SDL.SURFACE.HWPALETTE - give SDL exclusive palette access (not supported)
|
||||
SDL.SURFACE.DOUBLEBUF - enable hardware double buffering. (only works with
|
||||
SDL.SURFACE.HWSURFACE)
|
||||
SDL.SURFACE.FULLSCREEN - use fullscreen mode
|
||||
SDL.SURFACE.OPENGL - create an OpenGL rendering context (not supported)
|
||||
SDL.SURFACE.RESIZABLE - create a resizable window
|
||||
SDL.SURFACE.HWACCEL - use hardware accelerated blitter
|
||||
SDL.SURFACE.SRCCOLORKEY - use color key blitter
|
||||
SDL.SURFACE.RLEACCEL - color key blitting is accelerated with RLE
|
||||
SDL.SURFACE.SRCALPHA - surface blit uses alpha blending
|
||||
SDL.SURFACE.PREALLOC - surface uses preallocated memory
|
||||
</pre>
|
||||
|
||||
Like other numeric constants, they may be combined with the or operator:
|
||||
|
||||
<pre> var screen = SDL.setVideoMode( 640, 480, 32, SDL.SURFACE.HWSURFACE | SDL.SURFACE.HWACCEL );</pre>
|
||||
|
||||
The surface created with the setVideoMode() call represents the contents of
|
||||
the displayed window. It's common practice to create a buffer surface to hold
|
||||
video contents in preparation for drawing on the screen. To create a buffer,
|
||||
use the createRGBSurface() call.
|
||||
|
||||
<pre> var surface = SDL.createRGBSurface( SDL.SURFACE.SWSURFACE, 24, 24 );</pre>
|
||||
|
||||
The first parameter describes the type of surface to create, and the remaining
|
||||
parameters are x and y sizes.
|
||||
|
||||
After you're done using a surface, you *should* free it. The freeSurface()
|
||||
function takes a surface (like one returned from the createRGBSurface()
|
||||
function above) and frees memory associated with it:
|
||||
|
||||
<pre> SDL.freeSurface( surface );</pre>
|
||||
|
||||
The displayFormat() function copies a surface into a new surface suitable
|
||||
for blitting into the frame buffer. It takes a surface as it's first (and only)
|
||||
parameter and returns a new surface conformable with the system's frame buffer.
|
||||
This call is extremely useful in conjunction with the SDL.IMG.load() call:
|
||||
|
||||
<pre> var tempSheet = SDL.IMG.load( __dirname + "/sprites.png" );
|
||||
var sheet = SDL.displayFormat( tempSheet );
|
||||
SDL.freeSurface( tempSheet );</pre>
|
||||
|
||||
SDL surfaces may have an Alpha value associated with them. This is a value from
|
||||
0 to 255 and sets the transparency of the surface's contents when blitted into
|
||||
another surface (like the frame buffer).
|
||||
|
||||
<pre> SDL.setAlpha( sheet, SDL.SURFACE.SRCALPHA | SRC.SURFACE.RLEACCEL, 192 );</pre>
|
||||
|
||||
Options to the setAlpha() function include:
|
||||
|
||||
<pre> SDL.SURFACE.SRCALPHA - specifies that alpha blending should be used
|
||||
SLD.SURFACE.RLEACCEL - specifies that RLE acceleration should be used for blitting</pre>
|
||||
|
||||
You can set a specific color to be transparent (i.e. - the color key) using the
|
||||
setColorKey() function. After setting this value, when the surface's contents
|
||||
are blitted to another surface, pixels with the color key value won't be copied.
|
||||
|
||||
<pre> SDL.setColorKey( sheet, SDL.SURFACE.SRCCOLORKEY, 0x01010100 );</pre>
|
||||
|
||||
The first parameter is the surface whose color key you're setting. The second
|
||||
is a set of flags that may be or'd together. The third is a 32 bit integer
|
||||
representing the value of the color key you want to use. Values for the flags
|
||||
include:
|
||||
|
||||
<pre> SDL.SURFACE.SRCCOLORKEY - means you're setting the surface's color key
|
||||
SDL.SURFACE.RLEACCEL - you want to enable RLE accleration
|
||||
0 - means you want to clear the surface's color key
|
||||
</pre>
|
||||
|
||||
It can sometimes be tricky to get the precise color key value if you're using
|
||||
multiple surface geometries. Fortunately, you can use the mapRGB() function
|
||||
to return a color value, modified to account for a surface's color geometry.
|
||||
In other words, do this when you want to set the color key:
|
||||
|
||||
<pre> var colorKey = [ 255, 0, 0 ]; // setting the color key to red
|
||||
SDL.setColorKey( sheet,
|
||||
SDL.SURFACE.SRCCOLORKEY | SDL.SURFACE.RLEACCEL,
|
||||
SDL.mapRGB( sheet.format,
|
||||
colorKey[0],
|
||||
colorKey[1],
|
||||
colorKey[2] ) );</pre>
|
||||
|
||||
To fill a rectangle with a particular color, use the fillRect() function.
|
||||
|
||||
<pre> SDL.fillRect( surface, [0, 0, 24, 24], 0xFF8080AF );</pre>
|
||||
|
||||
To blit (copy) a portion of one surface into anotehr, use the blitSurface()
|
||||
function. It takes as it's parameters: the source surface, a rectangle
|
||||
describing the origin and extent of the pixels to be copied, the destination
|
||||
surface, and a point in the destination you're copying pixels to.
|
||||
|
||||
So the following example copies an 8x16 rectangle from position (10,25) in the
|
||||
spriteSource surface into position (128,15) in the screen surface:
|
||||
|
||||
<pre> SDL.blitSurface( spriteSource, [10, 25, 8, 16], screen, [128, 15] );</pre>
|
||||
|
||||
After making changes to a surface, you use the flip() function to instruct
|
||||
the system to make the changes apparent. In systems that support hardware
|
||||
double-buffering, this call "does the right thing" and waits for a vertical
|
||||
retrace to flip between video screens. On systems with a software surface, it
|
||||
simply makes sure that the contents of the surface are made visible.
|
||||
|
||||
It's very useful to call this command after you make updates to the screen. For
|
||||
example:
|
||||
|
||||
<pre> var screen = SDL.setVideoMode( 640, 480, 32, SDL.SURFACE.SWSURFACE );
|
||||
SDL.fillRect( surface, [0, 0, 24, 24], 0xFF8080AF );
|
||||
SDL.flip( screen );
|
||||
</pre>
|
||||
|
||||
### 1.3. Image Related Functions
|
||||
|
||||
This package uses a supplimentary image library intended to make it easy for
|
||||
node-sdl applications to load and use JPG, PNG or TIFF images. Before using
|
||||
Image functions, you should initalize them with the image init() function:
|
||||
|
||||
<pre> SDL.IMG.init( 0 );</pre>
|
||||
|
||||
To load an image into memory, use the image load() function. It takes a file
|
||||
path as a parameter and returns a reference to it. The following line loads
|
||||
a PNG file called "foo.png" into the variable foo.
|
||||
|
||||
<pre> var foo = SDL.IMG.load( __dirname + '/foo.png' );</pre>
|
||||
|
||||
The foo variable can now be used as a surface blit calls (see below.)
|
||||
|
||||
After you are finished using the image functions, be sure to use the image
|
||||
quit() function:
|
||||
|
||||
<pre> SDL.IMG.quit();</pre>
|
||||
|
||||
### 1.4. Joystick Functions
|
||||
|
||||
If you are developing an application that uses joysticks, you'll need to pass
|
||||
the SDL.INIT.JOYSTICK option along to the SDL.init() call:
|
||||
|
||||
<pre> SDL.init( SDL.INIT.VIDEO | SDL.INIT.JOYSTICK );</pre>
|
||||
|
||||
Now that your app knows you want to use joysticks, you can detect the number of
|
||||
joysticks present with the numJoysticks() function. The following code checks
|
||||
to see if there's at least one joystick and complains if there's not:
|
||||
|
||||
<pre> var numPlayers = SDL.numJoysticks();
|
||||
if( numPlayers < 1 ) {
|
||||
console.log( 'Blargh! At least one joystick is required!' );
|
||||
process.exit( 2 );
|
||||
}</pre>
|
||||
|
||||
On systems with multiple joysticks, it might be useful to offer a player a
|
||||
selection of which joystick to use. The system assigns a human readable name
|
||||
for a joystick which the app can query with the joystickName() function. The
|
||||
following code prints out the name of each joystick:
|
||||
|
||||
<pre> SDL.init( SDL.INIT.VIDEO | SDL.INIT.JOYSTICK );
|
||||
var stickCount = SDL.numJoysticks();
|
||||
|
||||
for( var i = 0; i < stickCount; i ++ ) {
|
||||
console.log( 'joystick ' + i + ': ' + SDL.joystickName( i ) );
|
||||
}
|
||||
|
||||
// etc</pre>
|
||||
|
||||
Now you must explicitly open each joystick you want to receive inputs from. Do
|
||||
this with the joystickOpen() function. This function takes an integer as a
|
||||
parameter and represents the index of the joystick you want to open. Here is
|
||||
some code that opens joystick number zero:
|
||||
|
||||
<pre> SDL.joystickOpen( 0 );</pre>
|
||||
|
||||
After the joystick is opened, it will start to generate events. You can register
|
||||
event handlers with the SDL.events.on() function. Joystick related events are
|
||||
described in the events section below.
|
||||
|
||||
### 1.5. Window Manager Functions
|
||||
|
||||
node-sdl is capable of setting window manager related info with the SDL.WM.*
|
||||
functions.
|
||||
|
||||
To set the title of a SDL window, use the setCaption() function. This fragment
|
||||
sets the window's title to "Window Title" and (if supported by your window
|
||||
manager) sets the name of the minimized icon to "Icon Title"
|
||||
|
||||
<pre> SDL.WM.setCaption( 'Window Title', 'Icon Title' );</pre>
|
||||
|
||||
To set the application's icon, use the setIcon() function. It expects an image
|
||||
to be passed as it's parameter, so it's common practice to use the image load()
|
||||
function. The following example loads an icon from the file 'eight.png' and
|
||||
uses it as the app's icon:
|
||||
|
||||
<pre> SDL.WM.setIcon( SDL.IMG.load( __dirname + '/eight.png' ) );</pre>
|
||||
|
||||
## 2. Events
|
||||
|
||||
node-sdl uses javascript events to communicate certain conditions. The
|
||||
events.on() function is used to set handlers for these events. Event handlers
|
||||
are passed an object describing the event as a parameter.
|
||||
|
||||
### 2.1. Quit
|
||||
|
||||
As described above, the QUIT event is called when the user closes a SDL window.
|
||||
The proper response is to free buffers, and exit:
|
||||
|
||||
<pre> SDL.events.on( 'QUIT', function ( evt ) {
|
||||
SDL.IMG.quit();
|
||||
process.exit( 0 );
|
||||
} );</pre>
|
||||
|
||||
### 2.2. KEYDOWN & KEYUP
|
||||
|
||||
The KEYDOWN and KEYUP events signal the app that the user has pressed (or
|
||||
released) a key. The event passed to the handler includes the following
|
||||
properties:
|
||||
|
||||
<pre> scancode - the scancode of the key pressed
|
||||
sym - the symbol of the key pressed
|
||||
mod - key modifier</pre>
|
||||
|
||||
Key scancodes are hardware and locale dependent; it's recommended they be
|
||||
left alone unless you really are targeting a specific piece of hardware. Key
|
||||
symbols are numbers representing keyboard glyphs. Key modifiers represent
|
||||
shift, meta, alt and control keys. As you might expect, it's possible for
|
||||
multiple modifiers to be pressed simultaneously, so the mod value is a bit
|
||||
field with the following definitions:
|
||||
|
||||
<pre>
|
||||
0x0000 - No modifiers pressed
|
||||
0x0001 - Left Shift
|
||||
0x0002 - Right Shift
|
||||
0x0040 - Left Control Key
|
||||
0x0080 - Right Control Key
|
||||
0x0100 - Left Alt Key
|
||||
0x0200 - Right Alt Key
|
||||
0x0400 - Left Meta Key (for hardware that has a meta key)
|
||||
0x0800 - Right Meta Key (for hardware that has a meta key)
|
||||
0x1000 - Num Lock on
|
||||
0x2000 - Caps Lock on
|
||||
0x4000 - Mode Key Pressed (bonus points if you can find hardware with a mode key)
|
||||
</pre>
|
||||
|
||||
It should probably be noted that SDL keysyms are not exactly ASCII. Most
|
||||
importantly, the system will not return a capital letter ASCII code when the
|
||||
user hits a letter key and the shift key. Instead, you must manually check
|
||||
for the shift key being pressed, check the modifier bits and adjust the key
|
||||
code accordingly.
|
||||
|
||||
The following code converts the modifier and symbol to an ascii value:
|
||||
|
||||
<pre> SDL.events.on( 'KEYDOWN', function( evt ) {
|
||||
var ascii = evt.sym;
|
||||
|
||||
if( ( ascii < 123 ) && ( ascii > 96 ) ) {
|
||||
if( 0 != ( evt.mod && 0x2003 ) ) {
|
||||
ascii -= 32;
|
||||
}
|
||||
}
|
||||
|
||||
console.log( 'ascii: ' + ascii );
|
||||
} );</pre>
|
||||
|
||||
### 2.3. MOUSEMOTION
|
||||
|
||||
When the user moves a mouse over an SDL screen, the system will generate
|
||||
MOUSEMOTION events. If you create a handler for these events, every time the
|
||||
mouse moves, you'll receive an event with the following properties:
|
||||
|
||||
<pre> state - button state (as described above)
|
||||
x - x position of the mouse pointer
|
||||
y - y position of the mouse pointer
|
||||
xrel - relative motion of the mouse pointer along the x axis
|
||||
yrel - relative motion of the mouse pointer along the y axis</pre>
|
||||
|
||||
The button state is a bit field with the following values:
|
||||
|
||||
<pre> 0x0000 - no mouse button pressed
|
||||
0x0001 - left mouse button pressed
|
||||
0x0002 - middle mouse button pressed
|
||||
0x0004 - right mouse button pressed</pre>
|
||||
|
||||
Take mouse chords with a grain of salt, some systems may be configured to
|
||||
emulate a 3 button mouse. In these systems, pressing the left and right button
|
||||
together will generate a middle button press (code 0x0002) instead of the
|
||||
mouse chord you might be expecting (code 0x0005).
|
||||
|
||||
### 2.4. MOUSEBUTTONDOWN & MOUSEBUTTONUP
|
||||
|
||||
The MOUSEBUTTONUP and MOUSEBUTTONDOWN events report more data and have
|
||||
slightly different semantics than the button state in the MOUSEMOTION event.
|
||||
Handlers for these events are passed an object with the following properties:
|
||||
|
||||
<pre> button - mouse button clicked
|
||||
x - x position of the mouse
|
||||
y - y position of the mouse</pre>
|
||||
|
||||
The button property IS NOT a bit field, but an integer. Instead of detecting
|
||||
mouse chords, it reports multiple button clicks. Here is the list of mouse
|
||||
buttons supported:
|
||||
|
||||
<pre> 1 - left button
|
||||
2 - middle button
|
||||
3 - right button
|
||||
4 - scroll wheel up
|
||||
5 - scroll wheel down</pre>
|
||||
|
||||
### 2.5. JOYAXISMOTION (Joystick Axis Motion)
|
||||
|
||||
The JOYAXISMOTION event reports movement of the joystick device along one of
|
||||
its axes. Handlers for this event are passed an object with the following
|
||||
properties:
|
||||
|
||||
<pre> which - which joystick generated the event
|
||||
axis - which axis (x or y) the event is reporting movement upon
|
||||
value - a value from -32768 to 32767 describing the logical position of the joystick</pre>
|
||||
|
||||
### 2.6. JOYBALLMOTION (Joystick Trackball Motion)
|
||||
|
||||
If a user's joystick is equipped with a trackball, it may generate these events
|
||||
when motion along the trackball is detected. Handlers assigned to listen for
|
||||
these events will receive an object with the following properties:
|
||||
|
||||
<pre> which - which joystick generated the event
|
||||
ball - which trackball generated the event
|
||||
xrel - relative trackball motion along the x axis
|
||||
yrel - relative trackball motion along the y axis</pre>
|
||||
|
||||
### 2.7. JOYHATMOTION (Joystick Hat Motion)
|
||||
|
||||
If a user's joystick is equipped with a hat, it may generate these events when
|
||||
hat motion is detected. Handlers for this event will be passed an object with
|
||||
the following properties:
|
||||
|
||||
<pre> which - which joystick generated the event
|
||||
hat - which hat on the joystick generated the event
|
||||
value - the position of the hat</pre>
|
||||
|
||||
### 2.8. JOYBUTTONDOWN & JOYBUTTONUP
|
||||
|
||||
If a user's joystick is equipped with buttons, it may generate these events when
|
||||
a button press is detected. Handlers for these events will be passed an object
|
||||
with the following properties:
|
||||
|
||||
<pre> which - which joystick generated the event
|
||||
button - which button was pressed</pre>
|
||||
|
4
src/node/node_modules/node-sdl/Readme
generated
vendored
Normal file
4
src/node/node_modules/node-sdl/Readme
generated
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
This is a fork from node-sdl (https://github.com/creationix/node-sdl) with a
|
||||
couple of modifications.
|
||||
|
||||
The build process is currently broken. Will be fixed at a later point.
|
21
src/node/node_modules/node-sdl/binding.gyp
generated
vendored
Normal file
21
src/node/node_modules/node-sdl/binding.gyp
generated
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
'targets': [
|
||||
{
|
||||
# have to specify 'liblib' here since gyp will remove the first one :\
|
||||
'target_name': 'nodesdl',
|
||||
'type': 'shared_library',
|
||||
'sources': [
|
||||
'src/helpers.cc',
|
||||
'src/nodesdl.cc',
|
||||
],
|
||||
'ldflags': [
|
||||
'<!@(sdl-config --libs)',
|
||||
"-lSDL_ttf",
|
||||
"-lSDL_image"
|
||||
],
|
||||
'cflags': [
|
||||
'<!@(sdl-config --cflags)'
|
||||
],
|
||||
}
|
||||
]
|
||||
}
|
83
src/node/node_modules/node-sdl/nodesdl.target.mk
generated
vendored
Normal file
83
src/node/node_modules/node-sdl/nodesdl.target.mk
generated
vendored
Normal file
|
@ -0,0 +1,83 @@
|
|||
# This file is generated by gyp; do not edit.
|
||||
|
||||
TOOLSET := target
|
||||
TARGET := nodesdl
|
||||
DEFS_Default :=
|
||||
|
||||
# Flags passed to all source files.
|
||||
CFLAGS_Default := \
|
||||
-I/usr/include/SDL \
|
||||
-D_GNU_SOURCE=1 \
|
||||
-D_REENTRANT
|
||||
|
||||
# Flags passed to only C files.
|
||||
CFLAGS_C_Default :=
|
||||
|
||||
# Flags passed to only C++ files.
|
||||
CFLAGS_CC_Default :=
|
||||
|
||||
INCS_Default :=
|
||||
|
||||
OBJS := \
|
||||
$(obj).target/$(TARGET)/node/node_modules/node-sdl/src/helpers.o \
|
||||
$(obj).target/$(TARGET)/node/node_modules/node-sdl/src/nodesdl.o
|
||||
|
||||
# Add to the list of files we specially track dependencies for.
|
||||
all_deps += $(OBJS)
|
||||
|
||||
# CFLAGS et al overrides must be target-local.
|
||||
# See "Target-specific Variable Values" in the GNU Make manual.
|
||||
$(OBJS): TOOLSET := $(TOOLSET)
|
||||
$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
|
||||
$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
|
||||
|
||||
# Suffix rules, putting all outputs into $(obj).
|
||||
|
||||
$(obj).$(TOOLSET)/$(TARGET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD
|
||||
@$(call do_cmd,cxx,1)
|
||||
|
||||
# Try building from generated source, too.
|
||||
|
||||
$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD
|
||||
@$(call do_cmd,cxx,1)
|
||||
|
||||
$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.cc FORCE_DO_CMD
|
||||
@$(call do_cmd,cxx,1)
|
||||
|
||||
# End of this set of suffix rules
|
||||
### Rules for final target.
|
||||
LDFLAGS_Default := \
|
||||
-L/usr/lib \
|
||||
-lSDL \
|
||||
-lpthread \
|
||||
-lSDL_ttf \
|
||||
-lSDL_image
|
||||
|
||||
LIBS :=
|
||||
|
||||
$(obj).target/node/node_modules/node-sdl/libnodesdl.so: GYP_LDFLAGS := $(LDFLAGS_$(BUILDTYPE))
|
||||
$(obj).target/node/node_modules/node-sdl/libnodesdl.so: LIBS := $(LIBS)
|
||||
$(obj).target/node/node_modules/node-sdl/libnodesdl.so: LD_INPUTS := $(OBJS)
|
||||
$(obj).target/node/node_modules/node-sdl/libnodesdl.so: TOOLSET := $(TOOLSET)
|
||||
$(obj).target/node/node_modules/node-sdl/libnodesdl.so: $(OBJS) FORCE_DO_CMD
|
||||
$(call do_cmd,solink)
|
||||
|
||||
all_deps += $(obj).target/node/node_modules/node-sdl/libnodesdl.so
|
||||
# Add target alias
|
||||
.PHONY: nodesdl
|
||||
nodesdl: $(builddir)/libnodesdl.so
|
||||
|
||||
# Copy this to the shared library output path.
|
||||
$(builddir)/libnodesdl.so: TOOLSET := $(TOOLSET)
|
||||
$(builddir)/libnodesdl.so: $(obj).target/node/node_modules/node-sdl/libnodesdl.so FORCE_DO_CMD
|
||||
$(call do_cmd,copy)
|
||||
|
||||
all_deps += $(builddir)/libnodesdl.so
|
||||
# Short alias for building this shared library.
|
||||
.PHONY: libnodesdl.so
|
||||
libnodesdl.so: $(obj).target/node/node_modules/node-sdl/libnodesdl.so $(builddir)/libnodesdl.so
|
||||
|
||||
# Add shared library to "all" target.
|
||||
.PHONY: all
|
||||
all: $(builddir)/libnodesdl.so
|
||||
|
16
src/node/node_modules/node-sdl/package.json
generated
vendored
Normal file
16
src/node/node_modules/node-sdl/package.json
generated
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"author": "Tim Caswell <tim@creationix.com> (http://creationix.com/)",
|
||||
"name": "sdl",
|
||||
"description": "SDL bindings for node",
|
||||
"version": "0.1.8",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/creationix/node-sdl.git"
|
||||
},
|
||||
"main": "sdl.js",
|
||||
"engines": {
|
||||
"node": ">=0.4.4"
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {}
|
||||
}
|
25
src/node/node_modules/node-sdl/sdl.js
generated
vendored
Executable file
25
src/node/node_modules/node-sdl/sdl.js
generated
vendored
Executable file
|
@ -0,0 +1,25 @@
|
|||
var SDL = module.exports = require('./build/Release/nodesdl.node');
|
||||
|
||||
// Easy event emitter based event loop. Started automatically when the first
|
||||
// listener is added.
|
||||
var events;
|
||||
Object.defineProperty(SDL, 'events', {
|
||||
get: function () {
|
||||
if (events) return events;
|
||||
events = new (require('events').EventEmitter);
|
||||
var now = Date.now();
|
||||
setInterval(function () {
|
||||
var after = Date.now();
|
||||
var delta = after - now;
|
||||
now = after;
|
||||
var data;
|
||||
while (data = SDL.pollEvent()) {
|
||||
events.emit('event', data);
|
||||
events.emit(data.type, data);
|
||||
}
|
||||
events.emit('tick', delta);
|
||||
}, 16);
|
||||
return events;
|
||||
}
|
||||
});
|
||||
|
437
src/node/node_modules/node-sdl/src/helpers.cc
generated
vendored
Normal file
437
src/node/node_modules/node-sdl/src/helpers.cc
generated
vendored
Normal file
|
@ -0,0 +1,437 @@
|
|||
#include <v8.h>
|
||||
#include <node.h>
|
||||
#include <node_buffer.h>
|
||||
#include <SDL.h>
|
||||
#include <SDL_ttf.h>
|
||||
|
||||
#include "helpers.h"
|
||||
|
||||
namespace sdl {
|
||||
|
||||
// Helper for formatting error exceptions
|
||||
Handle<Value> ThrowSDLException(const char* name) {
|
||||
return ThrowException(MakeSDLException(name));
|
||||
}
|
||||
|
||||
Local<Value> MakeSDLException(const char* name) {
|
||||
return Exception::Error(String::Concat(
|
||||
String::Concat(String::New(name), String::New(": ")),
|
||||
String::New(SDL_GetError())
|
||||
));
|
||||
}
|
||||
|
||||
// Wrap/Unwrap Surface
|
||||
|
||||
static Persistent<ObjectTemplate> surface_template_;
|
||||
|
||||
Handle<Value> GetSurfaceFlags(Local<String> name, const AccessorInfo& info) {
|
||||
SDL_Surface* surface = UnwrapSurface(info.Holder());
|
||||
return Number::New(surface->flags);
|
||||
}
|
||||
Handle<Value> GetSurfaceFormat(Local<String> name, const AccessorInfo& info) {
|
||||
HandleScope scope;
|
||||
SDL_Surface* surface = UnwrapSurface(info.Holder());
|
||||
return scope.Close(WrapPixelFormat(surface->format));
|
||||
}
|
||||
Handle<Value> GetSurfaceWidth(Local<String> name, const AccessorInfo& info) {
|
||||
SDL_Surface* surface = UnwrapSurface(info.Holder());
|
||||
return Number::New(surface->w);
|
||||
}
|
||||
Handle<Value> GetSurfaceHeight(Local<String> name, const AccessorInfo& info) {
|
||||
SDL_Surface* surface = UnwrapSurface(info.Holder());
|
||||
return Number::New(surface->h);
|
||||
}
|
||||
Handle<Value> GetSurfacePitch(Local<String> name, const AccessorInfo& info) {
|
||||
SDL_Surface* surface = UnwrapSurface(info.Holder());
|
||||
return Number::New(surface->pitch);
|
||||
}
|
||||
Handle<Value> GetSurfaceRect(Local<String> name, const AccessorInfo& info) {
|
||||
HandleScope scope;
|
||||
SDL_Surface* surface = UnwrapSurface(info.Holder());
|
||||
return scope.Close(WrapRect(&surface->clip_rect));
|
||||
}
|
||||
|
||||
Handle<ObjectTemplate> MakeSurfaceTemplate() {
|
||||
HandleScope handle_scope;
|
||||
|
||||
Handle<ObjectTemplate> result = ObjectTemplate::New();
|
||||
result->SetInternalFieldCount(1);
|
||||
|
||||
// Add accessors for some of the fields of the surface.
|
||||
result->SetAccessor(String::NewSymbol("flags"), GetSurfaceFlags);
|
||||
result->SetAccessor(String::NewSymbol("format"), GetSurfaceFormat);
|
||||
result->SetAccessor(String::NewSymbol("w"), GetSurfaceWidth);
|
||||
result->SetAccessor(String::NewSymbol("h"), GetSurfaceHeight);
|
||||
result->SetAccessor(String::NewSymbol("pitch"), GetSurfacePitch);
|
||||
result->SetAccessor(String::NewSymbol("clip_rect"), GetSurfaceRect);
|
||||
|
||||
// Again, return the result through the current handle scope.
|
||||
return handle_scope.Close(result);
|
||||
}
|
||||
|
||||
Handle<Object> WrapSurface(SDL_Surface* surface) {
|
||||
// Handle scope for temporary handles.
|
||||
HandleScope handle_scope;
|
||||
|
||||
// Fetch the template for creating JavaScript http request wrappers.
|
||||
// It only has to be created once, which we do on demand.
|
||||
if (surface_template_.IsEmpty()) {
|
||||
Handle<ObjectTemplate> raw_template = MakeSurfaceTemplate();
|
||||
surface_template_ = Persistent<ObjectTemplate>::New(raw_template);
|
||||
}
|
||||
Handle<ObjectTemplate> templ = surface_template_;
|
||||
|
||||
// Create an empty http request wrapper.
|
||||
Handle<Object> result = templ->NewInstance();
|
||||
|
||||
// Wrap the raw C++ pointer in an External so it can be referenced
|
||||
// from within JavaScript.
|
||||
Handle<External> request_ptr = External::New(surface);
|
||||
|
||||
// Store the request pointer in the JavaScript wrapper.
|
||||
result->SetInternalField(0, request_ptr);
|
||||
|
||||
// Return the result through the current handle scope. Since each
|
||||
// of these handles will go away when the handle scope is deleted
|
||||
// we need to call Close to let one, the result, escape into the
|
||||
// outer handle scope.
|
||||
return handle_scope.Close(result);
|
||||
}
|
||||
|
||||
SDL_Surface* UnwrapSurface(Handle<Object> obj) {
|
||||
Handle<External> field = Handle<External>::Cast(obj->GetInternalField(0));
|
||||
void* ptr = field->Value();
|
||||
return static_cast<SDL_Surface*>(ptr);
|
||||
}
|
||||
|
||||
// Wrap/Unwrap Rect
|
||||
|
||||
static Persistent<ObjectTemplate> rect_template_;
|
||||
|
||||
Handle<Value> GetRectX(Local<String> name, const AccessorInfo& info) {
|
||||
SDL_Rect* rect = UnwrapRect(info.Holder());
|
||||
return Number::New(rect->x);
|
||||
}
|
||||
Handle<Value> GetRectY(Local<String> name, const AccessorInfo& info) {
|
||||
SDL_Rect* rect = UnwrapRect(info.Holder());
|
||||
return Number::New(rect->y);
|
||||
}
|
||||
Handle<Value> GetRectW(Local<String> name, const AccessorInfo& info) {
|
||||
SDL_Rect* rect = UnwrapRect(info.Holder());
|
||||
return Number::New(rect->w);
|
||||
}
|
||||
Handle<Value> GetRectH(Local<String> name, const AccessorInfo& info) {
|
||||
SDL_Rect* rect = UnwrapRect(info.Holder());
|
||||
return Number::New(rect->h);
|
||||
}
|
||||
|
||||
Handle<ObjectTemplate> MakeRectTemplate() {
|
||||
HandleScope handle_scope;
|
||||
|
||||
Handle<ObjectTemplate> result = ObjectTemplate::New();
|
||||
result->SetInternalFieldCount(1);
|
||||
|
||||
// Add accessors for some of the fields of the rect.
|
||||
result->SetAccessor(String::NewSymbol("x"), GetRectX);
|
||||
result->SetAccessor(String::NewSymbol("y"), GetRectY);
|
||||
result->SetAccessor(String::NewSymbol("w"), GetRectW);
|
||||
result->SetAccessor(String::NewSymbol("h"), GetRectH);
|
||||
|
||||
// Again, return the result through the current handle scope.
|
||||
return handle_scope.Close(result);
|
||||
}
|
||||
|
||||
Handle<Object> WrapRect(SDL_Rect* rect) {
|
||||
// Handle scope for temporary handles.
|
||||
HandleScope handle_scope;
|
||||
|
||||
// Fetch the template for creating JavaScript http request wrappers.
|
||||
// It only has to be created once, which we do on demand.
|
||||
if (rect_template_.IsEmpty()) {
|
||||
Handle<ObjectTemplate> raw_template = MakeRectTemplate();
|
||||
rect_template_ = Persistent<ObjectTemplate>::New(raw_template);
|
||||
}
|
||||
Handle<ObjectTemplate> templ = rect_template_;
|
||||
|
||||
// Create an empty http request wrapper.
|
||||
Handle<Object> result = templ->NewInstance();
|
||||
|
||||
// Wrap the raw C++ pointer in an External so it can be referenced
|
||||
// from within JavaScript.
|
||||
Handle<External> request_ptr = External::New(rect);
|
||||
|
||||
// Store the request pointer in the JavaScript wrapper.
|
||||
result->SetInternalField(0, request_ptr);
|
||||
|
||||
// Return the result through the current handle scope. Since each
|
||||
// of these handles will go away when the handle scope is deleted
|
||||
// we need to call Close to let one, the result, escape into the
|
||||
// outer handle scope.
|
||||
return handle_scope.Close(result);
|
||||
}
|
||||
|
||||
SDL_Rect* UnwrapRect(Handle<Object> obj) {
|
||||
Handle<External> field = Handle<External>::Cast(obj->GetInternalField(0));
|
||||
void* ptr = field->Value();
|
||||
return static_cast<SDL_Rect*>(ptr);
|
||||
}
|
||||
|
||||
// Wrap/Unwrap PixelFormat
|
||||
|
||||
static Persistent<ObjectTemplate> pixelformat_template_;
|
||||
|
||||
Handle<Value> GetFormatBits(Local<String> name, const AccessorInfo& info) {
|
||||
SDL_PixelFormat* format = UnwrapPixelFormat(info.Holder());
|
||||
return Number::New(format->BitsPerPixel);
|
||||
}
|
||||
Handle<Value> GetFormatBytes(Local<String> name, const AccessorInfo& info) {
|
||||
SDL_PixelFormat* format = UnwrapPixelFormat(info.Holder());
|
||||
return Number::New(format->BytesPerPixel);
|
||||
}
|
||||
Handle<Value> GetFormatColorkey(Local<String> name, const AccessorInfo& info) {
|
||||
SDL_PixelFormat* format = UnwrapPixelFormat(info.Holder());
|
||||
return Number::New(format->colorkey);
|
||||
}
|
||||
Handle<Value> GetFormatAlpha(Local<String> name, const AccessorInfo& info) {
|
||||
SDL_PixelFormat* format = UnwrapPixelFormat(info.Holder());
|
||||
return Number::New(format->alpha);
|
||||
}
|
||||
|
||||
Handle<ObjectTemplate> MakePixelFormatTemplate() {
|
||||
HandleScope handle_scope;
|
||||
|
||||
Handle<ObjectTemplate> result = ObjectTemplate::New();
|
||||
result->SetInternalFieldCount(1);
|
||||
|
||||
// Add accessors for some of the fields of the pixelformat.
|
||||
result->SetAccessor(String::NewSymbol("bitsPerPixel"), GetFormatBits);
|
||||
result->SetAccessor(String::NewSymbol("bytesPerPixel"), GetFormatBytes);
|
||||
result->SetAccessor(String::NewSymbol("colorkey"), GetFormatColorkey);
|
||||
result->SetAccessor(String::NewSymbol("alpha"), GetFormatAlpha);
|
||||
|
||||
// Again, return the result through the current handle scope.
|
||||
return handle_scope.Close(result);
|
||||
}
|
||||
|
||||
Handle<Object> WrapPixelFormat(SDL_PixelFormat* pixelformat) {
|
||||
// Handle scope for temporary handles.
|
||||
HandleScope handle_scope;
|
||||
|
||||
// Fetch the template for creating JavaScript http request wrappers.
|
||||
// It only has to be created once, which we do on demand.
|
||||
if (pixelformat_template_.IsEmpty()) {
|
||||
Handle<ObjectTemplate> raw_template = MakePixelFormatTemplate();
|
||||
pixelformat_template_ = Persistent<ObjectTemplate>::New(raw_template);
|
||||
}
|
||||
Handle<ObjectTemplate> templ = pixelformat_template_;
|
||||
|
||||
// Create an empty http request wrapper.
|
||||
Handle<Object> result = templ->NewInstance();
|
||||
|
||||
// Wrap the raw C++ pointer in an External so it can be referenced
|
||||
// from within JavaScript.
|
||||
Handle<External> request_ptr = External::New(pixelformat);
|
||||
|
||||
// Store the request pointer in the JavaScript wrapper.
|
||||
result->SetInternalField(0, request_ptr);
|
||||
|
||||
// Return the result through the current handle scope. Since each
|
||||
// of these handles will go away when the handle scope is deleted
|
||||
// we need to call Close to let one, the result, escape into the
|
||||
// outer handle scope.
|
||||
return handle_scope.Close(result);
|
||||
}
|
||||
|
||||
SDL_PixelFormat* UnwrapPixelFormat(Handle<Object> obj) {
|
||||
Handle<External> field = Handle<External>::Cast(obj->GetInternalField(0));
|
||||
void* ptr = field->Value();
|
||||
return static_cast<SDL_PixelFormat*>(ptr);
|
||||
}
|
||||
|
||||
// Wrap/Unwrap Joystick
|
||||
|
||||
static Persistent<ObjectTemplate> joystick_template_;
|
||||
|
||||
//Handle<Value> GetJoystickFlags(Local<String> name, const AccessorInfo& info) {
|
||||
// SDL_Joystick* joystick = UnwrapJoystick(info.Holder());
|
||||
// return Number::New(joystick->flags);
|
||||
//}
|
||||
//Handle<Value> GetJoystickFormat(Local<String> name, const AccessorInfo& info) {
|
||||
// HandleScope scope;
|
||||
// SDL_Joystick* joystick = UnwrapJoystick(info.Holder());
|
||||
// return scope.Close(WrapPixelFormat(joystick->format));
|
||||
//}
|
||||
//Handle<Value> GetJoystickWidth(Local<String> name, const AccessorInfo& info) {
|
||||
// SDL_Joystick* joystick = UnwrapJoystick(info.Holder());
|
||||
// return Number::New(joystick->w);
|
||||
//}
|
||||
//Handle<Value> GetJoystickHeight(Local<String> name, const AccessorInfo& info) {
|
||||
// SDL_Joystick* joystick = UnwrapJoystick(info.Holder());
|
||||
// return Number::New(joystick->h);
|
||||
//}
|
||||
//Handle<Value> GetJoystickPitch(Local<String> name, const AccessorInfo& info) {
|
||||
// SDL_Joystick* joystick = UnwrapJoystick(info.Holder());
|
||||
// return Number::New(joystick->pitch);
|
||||
//}
|
||||
//Handle<Value> GetJoystickRect(Local<String> name, const AccessorInfo& info) {
|
||||
// HandleScope scope;
|
||||
// SDL_Joystick* joystick = UnwrapJoystick(info.Holder());
|
||||
// return scope.Close(WrapRect(&joystick->clip_rect));
|
||||
//}
|
||||
|
||||
Handle<ObjectTemplate> MakeJoystickTemplate() {
|
||||
HandleScope handle_scope;
|
||||
|
||||
Handle<ObjectTemplate> result = ObjectTemplate::New();
|
||||
result->SetInternalFieldCount(1);
|
||||
|
||||
// Add accessors for some of the fields of the joystick.
|
||||
// result->SetAccessor(String::NewSymbol("flags"), GetJoystickFlags);
|
||||
// result->SetAccessor(String::NewSymbol("format"), GetJoystickFormat);
|
||||
// result->SetAccessor(String::NewSymbol("w"), GetJoystickWidth);
|
||||
// result->SetAccessor(String::NewSymbol("h"), GetJoystickHeight);
|
||||
// result->SetAccessor(String::NewSymbol("pitch"), GetJoystickPitch);
|
||||
// result->SetAccessor(String::NewSymbol("clip_rect"), GetJoystickRect);
|
||||
|
||||
// Again, return the result through the current handle scope.
|
||||
return handle_scope.Close(result);
|
||||
}
|
||||
|
||||
Handle<Object> WrapJoystick(SDL_Joystick* joystick) {
|
||||
// Handle scope for temporary handles.
|
||||
HandleScope handle_scope;
|
||||
|
||||
// Fetch the template for creating JavaScript http request wrappers.
|
||||
// It only has to be created once, which we do on demand.
|
||||
if (joystick_template_.IsEmpty()) {
|
||||
Handle<ObjectTemplate> raw_template = MakeJoystickTemplate();
|
||||
joystick_template_ = Persistent<ObjectTemplate>::New(raw_template);
|
||||
}
|
||||
Handle<ObjectTemplate> templ = joystick_template_;
|
||||
|
||||
// Create an empty http request wrapper.
|
||||
Handle<Object> result = templ->NewInstance();
|
||||
|
||||
// Wrap the raw C++ pointer in an External so it can be referenced
|
||||
// from within JavaScript.
|
||||
Handle<External> request_ptr = External::New(joystick);
|
||||
|
||||
// Store the request pointer in the JavaScript wrapper.
|
||||
result->SetInternalField(0, request_ptr);
|
||||
|
||||
// Return the result through the current handle scope. Since each
|
||||
// of these handles will go away when the handle scope is deleted
|
||||
// we need to call Close to let one, the result, escape into the
|
||||
// outer handle scope.
|
||||
return handle_scope.Close(result);
|
||||
}
|
||||
|
||||
SDL_Joystick* UnwrapJoystick(Handle<Object> obj) {
|
||||
Handle<External> field = Handle<External>::Cast(obj->GetInternalField(0));
|
||||
void* ptr = field->Value();
|
||||
return static_cast<SDL_Joystick*>(ptr);
|
||||
}
|
||||
|
||||
// Wrap/Unwrap Font
|
||||
|
||||
static Persistent<ObjectTemplate> font_template_;
|
||||
|
||||
//Handle<Value> GetFontFlags(Local<String> name, const AccessorInfo& info) {
|
||||
// TTF_Font* font = UnwrapFont(info.Holder());
|
||||
// return Number::New(font->flags);
|
||||
//}
|
||||
//Handle<Value> GetFontFormat(Local<String> name, const AccessorInfo& info) {
|
||||
// HandleScope scope;
|
||||
// TTF_Font* font = UnwrapFont(info.Holder());
|
||||
// return scope.Close(WrapPixelFormat(font->format));
|
||||
//}
|
||||
//Handle<Value> GetFontWidth(Local<String> name, const AccessorInfo& info) {
|
||||
// TTF_Font* font = UnwrapFont(info.Holder());
|
||||
// return Number::New(font->w);
|
||||
//}
|
||||
//Handle<Value> GetFontHeight(Local<String> name, const AccessorInfo& info) {
|
||||
// TTF_Font* font = UnwrapFont(info.Holder());
|
||||
// return Number::New(font->h);
|
||||
//}
|
||||
//Handle<Value> GetFontPitch(Local<String> name, const AccessorInfo& info) {
|
||||
// TTF_Font* font = UnwrapFont(info.Holder());
|
||||
// return Number::New(font->pitch);
|
||||
//}
|
||||
//Handle<Value> GetFontRect(Local<String> name, const AccessorInfo& info) {
|
||||
// HandleScope scope;
|
||||
// TTF_Font* font = UnwrapFont(info.Holder());
|
||||
// return scope.Close(WrapRect(&font->clip_rect));
|
||||
//}
|
||||
|
||||
Handle<ObjectTemplate> MakeFontTemplate() {
|
||||
HandleScope handle_scope;
|
||||
|
||||
Handle<ObjectTemplate> result = ObjectTemplate::New();
|
||||
result->SetInternalFieldCount(1);
|
||||
|
||||
// Add accessors for some of the fields of the font.
|
||||
// result->SetAccessor(String::NewSymbol("flags"), GetFontFlags);
|
||||
// result->SetAccessor(String::NewSymbol("format"), GetFontFormat);
|
||||
// result->SetAccessor(String::NewSymbol("w"), GetFontWidth);
|
||||
// result->SetAccessor(String::NewSymbol("h"), GetFontHeight);
|
||||
// result->SetAccessor(String::NewSymbol("pitch"), GetFontPitch);
|
||||
// result->SetAccessor(String::NewSymbol("clip_rect"), GetFontRect);
|
||||
|
||||
// Again, return the result through the current handle scope.
|
||||
return handle_scope.Close(result);
|
||||
}
|
||||
|
||||
Handle<Object> WrapFont(TTF_Font* font) {
|
||||
// Handle scope for temporary handles.
|
||||
HandleScope handle_scope;
|
||||
|
||||
// Fetch the template for creating JavaScript http request wrappers.
|
||||
// It only has to be created once, which we do on demand.
|
||||
if (font_template_.IsEmpty()) {
|
||||
Handle<ObjectTemplate> raw_template = MakeFontTemplate();
|
||||
font_template_ = Persistent<ObjectTemplate>::New(raw_template);
|
||||
}
|
||||
Handle<ObjectTemplate> templ = font_template_;
|
||||
|
||||
// Create an empty http request wrapper.
|
||||
Handle<Object> result = templ->NewInstance();
|
||||
|
||||
// Wrap the raw C++ pointer in an External so it can be referenced
|
||||
// from within JavaScript.
|
||||
Handle<External> request_ptr = External::New(font);
|
||||
|
||||
// Store the request pointer in the JavaScript wrapper.
|
||||
result->SetInternalField(0, request_ptr);
|
||||
|
||||
// Return the result through the current handle scope. Since each
|
||||
// of these handles will go away when the handle scope is deleted
|
||||
// we need to call Close to let one, the result, escape into the
|
||||
// outer handle scope.
|
||||
return handle_scope.Close(result);
|
||||
}
|
||||
|
||||
TTF_Font* UnwrapFont(Handle<Object> obj) {
|
||||
Handle<External> field = Handle<External>::Cast(obj->GetInternalField(0));
|
||||
void* ptr = field->Value();
|
||||
return static_cast<TTF_Font*>(ptr);
|
||||
}
|
||||
|
||||
|
||||
//char* BufferData(Buffer *b) {
|
||||
// return Buffer::Data(b->handle_);
|
||||
//}
|
||||
|
||||
//size_t BufferLength(Buffer *b) {
|
||||
// return Buffer::Length(b->handle_);
|
||||
//}
|
||||
|
||||
char* BufferData(Local<Object> buf_obj) {
|
||||
return Buffer::Data(buf_obj);
|
||||
}
|
||||
|
||||
size_t BufferLength(Local<Object> buf_obj) {
|
||||
return Buffer::Length(buf_obj);
|
||||
}
|
||||
|
||||
} // node_sdl
|
||||
|
42
src/node/node_modules/node-sdl/src/helpers.h
generated
vendored
Normal file
42
src/node/node_modules/node-sdl/src/helpers.h
generated
vendored
Normal file
|
@ -0,0 +1,42 @@
|
|||
#ifndef HELPERS_H_
|
||||
#define HELPERS_H_
|
||||
|
||||
#include <v8.h>
|
||||
#include <node.h>
|
||||
#include <node_buffer.h>
|
||||
|
||||
using namespace node;
|
||||
using namespace v8;
|
||||
|
||||
namespace sdl {
|
||||
|
||||
// Error reporting helpers
|
||||
Handle<Value> ThrowSDLException(const char* name);
|
||||
Local<Value> MakeSDLException(const char* name);
|
||||
|
||||
// Wrapper and Unwrappers
|
||||
Handle<Object> WrapSurface(SDL_Surface* surface);
|
||||
SDL_Surface* UnwrapSurface(Handle<Object> obj);
|
||||
|
||||
Handle<Object> WrapRect(SDL_Rect* rect);
|
||||
SDL_Rect* UnwrapRect(Handle<Object> obj);
|
||||
|
||||
Handle<Object> WrapPixelFormat(SDL_PixelFormat* pixelformat);
|
||||
SDL_PixelFormat* UnwrapPixelFormat(Handle<Object> obj);
|
||||
|
||||
Handle<Object> WrapJoystick(SDL_Joystick* joystick);
|
||||
SDL_Joystick* UnwrapJoystick(Handle<Object> obj);
|
||||
|
||||
Handle<Object> WrapFont(TTF_Font* font);
|
||||
TTF_Font* UnwrapFont(Handle<Object> obj);
|
||||
|
||||
|
||||
// Helpers to work with buffers
|
||||
//char* BufferData(Buffer *b);
|
||||
//size_t BufferLength(Buffer *b);
|
||||
char* BufferData(Local<Object> buf_obj);
|
||||
size_t BufferLength(Local<Object> buf_obj);
|
||||
|
||||
} // sdl
|
||||
|
||||
#endif // HELPERS_H_
|
1078
src/node/node_modules/node-sdl/src/nodesdl.cc
generated
vendored
Normal file
1078
src/node/node_modules/node-sdl/src/nodesdl.cc
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
93
src/node/node_modules/node-sdl/src/nodesdl.h
generated
vendored
Normal file
93
src/node/node_modules/node-sdl/src/nodesdl.h
generated
vendored
Normal file
|
@ -0,0 +1,93 @@
|
|||
#ifndef NODE_SDL_H_
|
||||
#define NODE_SDL_H_
|
||||
|
||||
#include <node.h>
|
||||
#include <v8.h>
|
||||
#include <SDL.h>
|
||||
#include <SDL_ttf.h>
|
||||
#include <SDL_image.h>
|
||||
|
||||
|
||||
#include "helpers.h"
|
||||
|
||||
using namespace v8;
|
||||
|
||||
namespace sdl {
|
||||
|
||||
static Handle<Value> Init(const Arguments& args);
|
||||
static Handle<Value> InitSubSystem(const Arguments& args);
|
||||
static Handle<Value> Quit(const Arguments& args);
|
||||
static Handle<Value> QuitSubSystem(const Arguments& args);
|
||||
static Handle<Value> WasInit(const Arguments& args);
|
||||
static Handle<Value> ClearError(const Arguments& args);
|
||||
static Handle<Value> GetError(const Arguments& args);
|
||||
static Handle<Value> SetError(const Arguments& args);
|
||||
static Handle<Value> WaitEvent(const Arguments& args);
|
||||
static Handle<Value> PollEvent(const Arguments& args);
|
||||
static Handle<Value> SetVideoMode(const Arguments& args);
|
||||
static Handle<Value> VideoModeOK(const Arguments& args);
|
||||
static Handle<Value> NumJoysticks(const Arguments& args);
|
||||
static Handle<Value> JoystickOpen(const Arguments& args);
|
||||
static Handle<Value> JoystickOpened(const Arguments& args);
|
||||
static Handle<Value> JoystickName(const Arguments& args);
|
||||
static Handle<Value> JoystickNumAxes(const Arguments& args);
|
||||
static Handle<Value> JoystickNumButtons(const Arguments& args);
|
||||
static Handle<Value> JoystickNumBalls(const Arguments& args);
|
||||
static Handle<Value> JoystickNumHats(const Arguments& args);
|
||||
static Handle<Value> JoystickClose(const Arguments& args);
|
||||
static Handle<Value> JoystickUpdate(const Arguments& args);
|
||||
static Handle<Value> JoystickEventState(const Arguments& args);
|
||||
static Handle<Value> Flip(const Arguments& args);
|
||||
static Handle<Value> PutImageData(const Arguments& args);
|
||||
static Handle<Value> FillRect(const Arguments& args);
|
||||
static Handle<Value> UpdateRect(const Arguments& args);
|
||||
static Handle<Value> CreateRGBSurface(const Arguments& args);
|
||||
static Handle<Value> BlitSurface(const Arguments& args);
|
||||
static Handle<Value> FreeSurface(const Arguments& args);
|
||||
static Handle<Value> SetColorKey(const Arguments& args);
|
||||
static Handle<Value> DisplayFormat(const Arguments& args);
|
||||
static Handle<Value> DisplayFormatAlpha(const Arguments& args);
|
||||
static Handle<Value> SetAlpha(const Arguments& args);
|
||||
static Handle<Value> MapRGB(const Arguments& args);
|
||||
static Handle<Value> MapRGBA(const Arguments& args);
|
||||
static Handle<Value> GetRGB(const Arguments& args);
|
||||
static Handle<Value> GetRGBA(const Arguments& args);
|
||||
static Handle<Value> SetClipRect(const Arguments& args);
|
||||
|
||||
namespace TTF {
|
||||
static Handle<Value> Init(const Arguments& args);
|
||||
static Handle<Value> OpenFont(const Arguments& args);
|
||||
static Handle<Value> RenderTextBlended(const Arguments& args);
|
||||
static Handle<Value> RenderTextShaded(const Arguments& args);
|
||||
}
|
||||
|
||||
namespace IMG {
|
||||
static Handle<Value> Load(const Arguments& args);
|
||||
}
|
||||
|
||||
namespace WM {
|
||||
static Handle<Value> SetCaption(const Arguments& args);
|
||||
static Handle<Value> SetIcon(const Arguments& args);
|
||||
}
|
||||
|
||||
namespace GL {
|
||||
static Handle<Value> SetAttribute (const Arguments& args);
|
||||
static Handle<Value> GetAttribute (const Arguments& args);
|
||||
static Handle<Value> SwapBuffers (const Arguments& args);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
typedef struct {
|
||||
Persistent<Function> fn;
|
||||
int status;
|
||||
} closure_t;
|
||||
//static void EIO_WaitEvent(eio_req *req);
|
||||
//static int EIO_OnEvent(eio_req *req);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
124
src/node/screen_sdl.js
Normal file
124
src/node/screen_sdl.js
Normal file
|
@ -0,0 +1,124 @@
|
|||
"use strict";
|
||||
|
||||
function NodeScreenSDL(sdl, font_file)
|
||||
{
|
||||
var ROW_HEIGHT = 16,
|
||||
|
||||
// about right for ascii.ttf
|
||||
CHAR_WIDTH = 10,
|
||||
|
||||
/** @type {number} */
|
||||
cursor_scanline_start,
|
||||
|
||||
/** @type {number} */
|
||||
cursor_scanline_end,
|
||||
|
||||
current_cursor_address,
|
||||
|
||||
graphic_buffer,
|
||||
graphic_buffer8,
|
||||
graphic_buffer32;
|
||||
|
||||
|
||||
sdl.init(sdl.INIT.VIDEO);
|
||||
|
||||
var ttf = sdl.TTF,
|
||||
screen;
|
||||
|
||||
ttf.init();
|
||||
|
||||
var font = ttf.openFont(font_file, 16);
|
||||
|
||||
sdl.events.on("QUIT", function()
|
||||
{
|
||||
process.exit();
|
||||
});
|
||||
|
||||
this.put_char = function(row, col, chr, bg_color, fg_color)
|
||||
{
|
||||
if((chr & 0xff) === 0)
|
||||
{
|
||||
// required, otherwise sdl throws up
|
||||
return;
|
||||
}
|
||||
|
||||
var str = String.fromCharCode(chr & 0xff),
|
||||
s = ttf.renderTextShaded(font, str, fg_color, bg_color);
|
||||
|
||||
sdl.blitSurface(s, null, screen, [col * CHAR_WIDTH, row * ROW_HEIGHT]);
|
||||
sdl.freeSurface(s);
|
||||
};
|
||||
|
||||
this.put_pixel_linear = function(offset, color_part)
|
||||
{
|
||||
graphic_buffer8[offset] = color_part;
|
||||
};
|
||||
|
||||
this.put_pixel = function(x, y, color)
|
||||
{
|
||||
throw "TODO";
|
||||
};
|
||||
|
||||
this.timer_text = function()
|
||||
{
|
||||
sdl.flip(screen);
|
||||
};
|
||||
|
||||
this.timer_graphical = function()
|
||||
{
|
||||
sdl.putImageData(screen, graphic_buffer32);
|
||||
sdl.flip(screen);
|
||||
};
|
||||
|
||||
this.destroy = function()
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
this.set_mode = function(graphical)
|
||||
{
|
||||
// switch between graphical and text mode
|
||||
};
|
||||
|
||||
this.clear_screen = function()
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
this.set_size_text = function(cols, rows)
|
||||
{
|
||||
screen = sdl.setVideoMode(CHAR_WIDTH * cols, ROW_HEIGHT * rows, 32, 0);
|
||||
|
||||
//dbg_log(screen, LOG_VGA);
|
||||
//dbg_log(screen.pixels, LOG_VGA);
|
||||
};
|
||||
|
||||
this.set_size_graphical = function(width, height)
|
||||
{
|
||||
screen = sdl.setVideoMode(width, height, 32, 0);
|
||||
|
||||
graphic_buffer = new ArrayBuffer(width * height * 4);
|
||||
graphic_buffer8 = new Uint8Array(graphic_buffer);
|
||||
graphic_buffer32 = new Int32Array(graphic_buffer);
|
||||
};
|
||||
|
||||
this.update_cursor = function(cursor_row, cursor_col)
|
||||
{
|
||||
refresh_cursor();
|
||||
};
|
||||
|
||||
this.update_cursor_scanline = function(start, end)
|
||||
{
|
||||
cursor_scanline_start = start;
|
||||
cursor_scanline_end = end;
|
||||
|
||||
refresh_cursor();
|
||||
};
|
||||
|
||||
function refresh_cursor()
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
}
|
||||
|
90
src/node/screen_tty.js
Normal file
90
src/node/screen_tty.js
Normal file
|
@ -0,0 +1,90 @@
|
|||
"use strict";
|
||||
|
||||
/*
|
||||
* Very simple prototype, mostly incomplete
|
||||
*/
|
||||
function NodeScreenTTY()
|
||||
{
|
||||
var stdout = process.stdout,
|
||||
cursor_row = 0,
|
||||
cursor_col = 0;
|
||||
|
||||
clear();
|
||||
|
||||
function clear()
|
||||
{
|
||||
stdout.write("\x1b[2J");
|
||||
}
|
||||
|
||||
function set_cursor_pos(row, col)
|
||||
{
|
||||
stdout.write("\x1b[" + row + ";" + col + "H");
|
||||
}
|
||||
|
||||
function hide_cursor()
|
||||
{
|
||||
stdout.write("\x1b[?25l");
|
||||
}
|
||||
|
||||
function show_cursor()
|
||||
{
|
||||
stdout.write("\x1b[?25h");
|
||||
}
|
||||
|
||||
this.timer_text = function()
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
this.destroy = function()
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
this.set_mode = function(is_graphical)
|
||||
{
|
||||
if(is_graphical)
|
||||
{
|
||||
console.log("Graphical Mode is not supported for NodeScreenTTY");
|
||||
}
|
||||
};
|
||||
|
||||
this.clear_screen = function()
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
this.set_size_text = function(cols, rows)
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
this.set_size_graphical = function(width, height)
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
this.update_cursor = function(row, col)
|
||||
{
|
||||
cursor_row = row;
|
||||
cursor_col = col;
|
||||
};
|
||||
|
||||
this.update_cursor_scanline = function(start, end)
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
this.put_char = function(row, col, chr, bg_color, fg_color)
|
||||
{
|
||||
var str = String.fromCharCode(chr);
|
||||
|
||||
hide_cursor();
|
||||
set_cursor_pos(row, col + 1);
|
||||
|
||||
stdout.write(str);
|
||||
|
||||
set_cursor_pos(cursor_row, cursor_col + 2);
|
||||
show_cursor();
|
||||
};
|
||||
}
|
173
src/pci.js
Normal file
173
src/pci.js
Normal file
|
@ -0,0 +1,173 @@
|
|||
"use strict";
|
||||
|
||||
var
|
||||
/** @const */ PCI_VENDOR_ID = 0x00 /* 16 bits */
|
||||
/** @const */ ,PCI_DEVICE_ID = 0x02 /* 16 bits */
|
||||
/** @const */ ,PCI_COMMAND = 0x04 /* 16 bits */
|
||||
/** @const */ ,PCI_BASE_ADDRESS_0 = 0x10 /* 32 bits */
|
||||
/** @const */ ,PCI_BASE_ADDRESS_1 = 0x14 /* 32 bits [htype 0,1 only] */
|
||||
/** @const */ ,PCI_BASE_ADDRESS_2 = 0x18 /* 32 bits [htype 0 only] */
|
||||
/** @const */ ,PCI_BASE_ADDRESS_3 = 0x1c /* 32 bits */
|
||||
/** @const */ ,PCI_BASE_ADDRESS_4 = 0x20 /* 32 bits */
|
||||
/** @const */ ,PCI_BASE_ADDRESS_5 = 0x24 /* 32 bits */
|
||||
/** @const */ ,PCI_INTERRUPT_LINE = 0x3c /* 8 bits */
|
||||
/** @const */ ,PCI_CLASS_REVISION = 0x08; /* High 24 bits are class, low 8 revision */
|
||||
|
||||
/** @constructor */
|
||||
function PCI(dev)
|
||||
{
|
||||
var
|
||||
io = dev.io,
|
||||
pci_data = 0,
|
||||
pci_counter = 0,
|
||||
pci_response = -1,
|
||||
pci_status = -1,
|
||||
self = this;
|
||||
|
||||
// TODO: Change the format of this
|
||||
this.devices = {};
|
||||
|
||||
/*
|
||||
io.register_write(0xCF9, function(value)
|
||||
{
|
||||
dbg_log("PCI reboot: " + h(value, 2), LOG_PCI);
|
||||
|
||||
// PCI reboot
|
||||
if(value & 6)
|
||||
{
|
||||
cpu_restart();
|
||||
}
|
||||
});*/
|
||||
|
||||
io.register_read(0xCFC, function()
|
||||
{
|
||||
return pci_response & 0xFF;
|
||||
});
|
||||
|
||||
io.register_read(0xCFD, function()
|
||||
{
|
||||
return pci_response >> 8 & 0xFF;
|
||||
});
|
||||
io.register_read(0xCFE, function()
|
||||
{
|
||||
return pci_response >> 16 & 0xFF;
|
||||
});
|
||||
io.register_read(0xCFF, function()
|
||||
{
|
||||
return pci_response >> 24 & 0xFF;
|
||||
});
|
||||
|
||||
io.register_read(0xCF8, function()
|
||||
{
|
||||
return pci_status & 0xFF;
|
||||
});
|
||||
io.register_read(0xCF9, function()
|
||||
{
|
||||
return pci_status >> 8 & 0xFF;
|
||||
});
|
||||
io.register_read(0xCFA, function()
|
||||
{
|
||||
return pci_status >> 16 & 0xFF;
|
||||
});
|
||||
io.register_read(0xCFB, function()
|
||||
{
|
||||
return pci_status >> 24 & 0xFF;
|
||||
});
|
||||
|
||||
io.register_write(0xCF8, function(out_byte)
|
||||
{
|
||||
pci_data = pci_data & ~0xFF | out_byte;
|
||||
});
|
||||
io.register_write(0xCF9, function(out_byte)
|
||||
{
|
||||
pci_data = pci_data & ~0xFF00 | out_byte << 8;
|
||||
});
|
||||
io.register_write(0xCFA, function(out_byte)
|
||||
{
|
||||
pci_data = pci_data & ~0xFF0000 | out_byte << 16;
|
||||
});
|
||||
io.register_write(0xCFB, function(out_byte)
|
||||
{
|
||||
pci_data = pci_data & 0xFFFFFF | out_byte << 24;
|
||||
pci_query(pci_data);
|
||||
});
|
||||
|
||||
function pci_query(dword)
|
||||
{
|
||||
var dbg_line = "PCI: ";
|
||||
|
||||
// Bit | .31 .0
|
||||
// Fmt | EBBBBBBBBDDDDDFFFRRRRRR00
|
||||
|
||||
var bdf = (dword & 0x7FFFFFFF) >> 8,
|
||||
addr = dword & 0xFC,
|
||||
devfn = bdf & 0xFF,
|
||||
bus = bdf >> 8,
|
||||
dev = bdf >> 3 & 0x1F,
|
||||
fn = bdf & 7,
|
||||
enabled = dword >> 31 & 1;
|
||||
|
||||
dbg_line += " enabled=" + (enabled);
|
||||
dbg_line += " bdf=" + h(bdf);
|
||||
dbg_line += " addr=" + h(addr);
|
||||
|
||||
dbg_log(dbg_line + " " + h(dword >>> 0, 8), LOG_PCI);
|
||||
|
||||
if(dword === (0x80000000 | 0))
|
||||
{
|
||||
pci_status = 0x80000000;
|
||||
}
|
||||
else if(self.devices[bdf])
|
||||
{
|
||||
var device = self.devices[bdf];
|
||||
|
||||
pci_status = 0x80000000;
|
||||
|
||||
if(addr === PCI_VENDOR_ID)
|
||||
{
|
||||
pci_response = device.vendor_id;
|
||||
}
|
||||
else if(addr === PCI_CLASS_REVISION)
|
||||
{
|
||||
pci_response = device.class_revision;
|
||||
}
|
||||
else if(addr === PCI_BASE_ADDRESS_5)
|
||||
{
|
||||
pci_response = device.iobase;
|
||||
}
|
||||
else if(addr === PCI_INTERRUPT_LINE)
|
||||
{
|
||||
pci_response = device.irq;
|
||||
}
|
||||
else
|
||||
{
|
||||
dbg_log("unimplemented addr " + h(addr) + " for device " + h(bdf), LOG_PCI);
|
||||
pci_response = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pci_response = 0;
|
||||
pci_status = 0;
|
||||
}
|
||||
}
|
||||
|
||||
this.register_device = function(device, device_id)
|
||||
{
|
||||
dbg_assert(!this.devices[device_id]);
|
||||
this.devices[device_id] = device;
|
||||
};
|
||||
|
||||
// ~% lspci -x
|
||||
// 00:00.0 Host bridge: Intel Corporation 4 Series Chipset DRAM Controller (rev 02)
|
||||
// 00: 86 80 20 2e 06 00 90 20 02 00 00 06 00 00 00 00
|
||||
// 10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
// 20: 00 00 00 00 00 00 00 00 00 00 00 00 43 10 d3 82
|
||||
// 30: 00 00 00 00 e0 00 00 00 00 00 00 00 00 00 00 00
|
||||
this.register_device({
|
||||
irq: 0,
|
||||
iobase: 0,
|
||||
vendor_id: 0x8680202e,
|
||||
class_revision: 0x06009020,
|
||||
}, 0);
|
||||
}
|
280
src/pic.js
Normal file
280
src/pic.js
Normal file
|
@ -0,0 +1,280 @@
|
|||
"use strict";
|
||||
|
||||
/**
|
||||
* Programmable Interrupt Controller
|
||||
* http://stanislavs.org/helppc/8259.html
|
||||
*
|
||||
* @constructor
|
||||
* @param {PIC=} master
|
||||
*/
|
||||
function PIC(dev, call_interrupt_vector, handle_irqs, master)
|
||||
{
|
||||
var
|
||||
io = dev.io,
|
||||
|
||||
/**
|
||||
* all irqs off
|
||||
* @type {number}
|
||||
*/
|
||||
irq_mask = 0,
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*
|
||||
* Bogus default value (both master and slave mapped to 0).
|
||||
* Will be initialized by the BIOS
|
||||
*/
|
||||
irq_map = 0,
|
||||
|
||||
/**
|
||||
* in-service register
|
||||
* Holds interrupts that are currently being serviced
|
||||
* @type {number}
|
||||
*/
|
||||
isr = 0,
|
||||
|
||||
/**
|
||||
* interrupt request register
|
||||
* Holds interrupts that have been requested
|
||||
* @type {number}
|
||||
*/
|
||||
irr = 0,
|
||||
|
||||
is_master = master === undefined,
|
||||
|
||||
slave,
|
||||
|
||||
me = this;
|
||||
|
||||
if(is_master)
|
||||
{
|
||||
slave = new PIC(dev, call_interrupt_vector, handle_irqs, this);
|
||||
|
||||
this.handle_irqs = function()
|
||||
{
|
||||
var enabled_irr = irr & irq_mask;
|
||||
|
||||
if(!enabled_irr)
|
||||
{
|
||||
return false
|
||||
}
|
||||
|
||||
var irq = enabled_irr & -enabled_irr;
|
||||
|
||||
if(isr && (isr & -isr) <= irq)
|
||||
{
|
||||
// wait for eoi of higher or same priority interrupt
|
||||
return false;
|
||||
}
|
||||
|
||||
irr &= ~irq;
|
||||
isr |= irq;
|
||||
|
||||
if(irq === 4)
|
||||
{
|
||||
// this should always return true
|
||||
return slave.handle_irqs();
|
||||
}
|
||||
|
||||
call_interrupt_vector(irq_map + log2_table[irq], false, false);
|
||||
|
||||
return true;
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
// is slave
|
||||
this.handle_irqs = function()
|
||||
{
|
||||
var enabled_irr = irr & irq_mask;
|
||||
|
||||
if(!enabled_irr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var irq = enabled_irr & -enabled_irr;
|
||||
|
||||
if(isr && (isr & -isr) <= irq)
|
||||
{
|
||||
// wait for eoi of higher or same priority interrupt
|
||||
return false;
|
||||
}
|
||||
|
||||
irr &= ~irq;
|
||||
isr |= irq;
|
||||
|
||||
call_interrupt_vector(irq_map + log2_table[irq], false, false);
|
||||
|
||||
if(irr)
|
||||
{
|
||||
// tell the master we have one more
|
||||
master.push_irq(2);
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
this.dump = function()
|
||||
{
|
||||
dbg_log("mask: " + h(irq_mask & 0xFF), LOG_PIC);
|
||||
dbg_log("base: " + h(irq_map), LOG_PIC);
|
||||
dbg_log("requested: " + h(irr), LOG_PIC);
|
||||
dbg_log("serviced: " + h(isr), LOG_PIC);
|
||||
|
||||
if(is_master)
|
||||
{
|
||||
slave.dump();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
var expect_icw4,
|
||||
state = 0,
|
||||
read_irr = 1,
|
||||
io_base,
|
||||
auto_eoi;
|
||||
|
||||
|
||||
if(is_master)
|
||||
{
|
||||
io_base = 0x20;
|
||||
}
|
||||
else
|
||||
{
|
||||
io_base = 0xA0;
|
||||
}
|
||||
|
||||
io.register_write(io_base, port20_write);
|
||||
io.register_read(io_base, port20_read);
|
||||
|
||||
io.register_write(io_base | 1, port21_write);
|
||||
io.register_read(io_base | 1, port21_read);
|
||||
|
||||
function port20_write(data_byte)
|
||||
{
|
||||
//dbg_log("20 write: " + h(data_byte), LOG_PIC);
|
||||
if(data_byte & 0x10) // xxxx1xxx
|
||||
{
|
||||
// icw1
|
||||
dbg_log("icw1 = " + h(data_byte), LOG_PIC);
|
||||
expect_icw4 = data_byte & 1;
|
||||
state = 1;
|
||||
}
|
||||
else if(data_byte & 8) // xxx01xxx
|
||||
{
|
||||
// ocw3
|
||||
dbg_log("ocw3: " + h(data_byte), LOG_PIC);
|
||||
read_irr = data_byte & 1;
|
||||
}
|
||||
else // xxx00xxx
|
||||
{
|
||||
// ocw2
|
||||
// end of interrupt
|
||||
//dbg_log("ocw2: " + h(data_byte), LOG_PIC);
|
||||
|
||||
var eoi_type = data_byte >> 5;
|
||||
|
||||
if(eoi_type === 1)
|
||||
{
|
||||
// non-specific eoi
|
||||
isr = 0;
|
||||
}
|
||||
else if(eoi_type === 3)
|
||||
{
|
||||
// specific eoi
|
||||
isr &= ~(1 << (data_byte & 7));
|
||||
}
|
||||
else
|
||||
{
|
||||
dbg_log("Unknown eoi: " + h(data_byte), LOG_PIC);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function port20_read()
|
||||
{
|
||||
if(read_irr)
|
||||
{
|
||||
return irr;
|
||||
}
|
||||
else
|
||||
{
|
||||
return isr;
|
||||
}
|
||||
}
|
||||
|
||||
function port21_write(data_byte)
|
||||
{
|
||||
//dbg_log("21 write: " + h(data_byte), LOG_PIC);
|
||||
if(state === 0)
|
||||
{
|
||||
if(expect_icw4)
|
||||
{
|
||||
// icw4
|
||||
expect_icw4 = false;
|
||||
auto_eoi = data_byte & 2;
|
||||
dbg_log("icw4: " + h(data_byte), LOG_PIC);
|
||||
}
|
||||
else
|
||||
{
|
||||
// ocw1
|
||||
irq_mask = ~data_byte;
|
||||
//dbg_log("interrupt mask: " + (irq_mask & 0xFFFF).toString(2) + " / map " + h(irq_map), LOG_PIC);
|
||||
}
|
||||
}
|
||||
else if(state === 1)
|
||||
{
|
||||
// icw2
|
||||
irq_map = data_byte;
|
||||
dbg_log("interrupts are mapped to " + h(irq_map) +
|
||||
" (" + (is_master ? "master" : "slave") + ")", LOG_PIC);
|
||||
state++;
|
||||
}
|
||||
else if(state === 2)
|
||||
{
|
||||
// icw3
|
||||
state = 0;
|
||||
dbg_log("icw3: " + h(data_byte), LOG_PIC);
|
||||
}
|
||||
};
|
||||
|
||||
function port21_read()
|
||||
{
|
||||
//dbg_log("21h read (" + h(irq_map) + ")", LOG_PIC);
|
||||
return ~irq_mask;
|
||||
};
|
||||
|
||||
if(is_master)
|
||||
{
|
||||
this.push_irq = function(irq_number)
|
||||
{
|
||||
dbg_assert(irq_number >= 0 && irq_number < 16);
|
||||
|
||||
if(irq_number >= 8)
|
||||
{
|
||||
slave.push_irq(irq_number - 8);
|
||||
irq_number = 2;
|
||||
}
|
||||
|
||||
irr |= 1 << irq_number;
|
||||
|
||||
handle_irqs();
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
this.push_irq = function(irq_number)
|
||||
{
|
||||
dbg_assert(irq_number >= 0 && irq_number < 8);
|
||||
|
||||
irr |= 1 << irq_number;
|
||||
};
|
||||
}
|
||||
|
||||
this.get_isr = function()
|
||||
{
|
||||
return isr;
|
||||
};
|
||||
}
|
303
src/pit.js
Normal file
303
src/pit.js
Normal file
|
@ -0,0 +1,303 @@
|
|||
"use strict";
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*
|
||||
* Programmable Interval Timer
|
||||
*/
|
||||
function PIT(dev)
|
||||
{
|
||||
var
|
||||
io = dev.io,
|
||||
pic = dev.pic,
|
||||
|
||||
next_tick = Date.now(),
|
||||
|
||||
me = this,
|
||||
|
||||
/**
|
||||
* @const
|
||||
* In kHz
|
||||
*/
|
||||
OSCILLATOR_FREQ = 1193.1816666, // 1.193182 MHz
|
||||
|
||||
|
||||
counter_next_low = new Uint8Array(3),
|
||||
counter_enabled = new Uint8Array(3),
|
||||
counter_mode = new Uint8Array(3),
|
||||
counter_read_mode = new Uint8Array(3),
|
||||
|
||||
// 2 = latch low, 1 = latch high, 0 = no latch
|
||||
counter_latch = new Uint8Array(3),
|
||||
counter_latch_value = new Uint16Array(3),
|
||||
|
||||
counter_reload = new Uint16Array(3),
|
||||
counter_current = new Uint16Array(3),
|
||||
|
||||
// only counter2 output can be read
|
||||
counter2_out = 0;
|
||||
|
||||
|
||||
// TODO:
|
||||
// - counter2 can be controlled by an input
|
||||
|
||||
|
||||
this.get_timer2 = function()
|
||||
{
|
||||
//dbg_log("timer2 read", LOG_PIT);
|
||||
return counter2_out;
|
||||
};
|
||||
|
||||
var parity = 0;
|
||||
|
||||
io.register_read(0x61, function()
|
||||
{
|
||||
// > xxx1 xxxx 0=RAM parity error enable
|
||||
// > PS/2: Read: This bit tiggles for each refresh request.
|
||||
//
|
||||
// tiggles??
|
||||
|
||||
parity ^= 0x10;
|
||||
return parity | counter2_out << 5;
|
||||
});
|
||||
|
||||
|
||||
this.timer = function(time)
|
||||
{
|
||||
var current,
|
||||
mode,
|
||||
steps = (time - next_tick) * OSCILLATOR_FREQ >>> 0;
|
||||
|
||||
if(!steps)
|
||||
{
|
||||
return;
|
||||
}
|
||||
dbg_assert(steps >= 0);
|
||||
|
||||
next_tick += steps / OSCILLATOR_FREQ;
|
||||
|
||||
// counter 0 produces interrupts
|
||||
if(counter_enabled[0])
|
||||
{
|
||||
current = counter_current[0] -= steps;
|
||||
|
||||
if(current <= 0)
|
||||
{
|
||||
pic.push_irq(0);
|
||||
mode = counter_mode[0];
|
||||
|
||||
if(mode === 0)
|
||||
{
|
||||
counter_enabled[0] = 0;
|
||||
counter_current[0] = 0;
|
||||
}
|
||||
else if(mode === 3 || mode === 2)
|
||||
{
|
||||
counter_current[0] = counter_reload[0] + current % counter_reload[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// counter 2 has an output bit
|
||||
if(counter_enabled[2])
|
||||
{
|
||||
current = counter_current[2] -= steps;
|
||||
|
||||
if(current <= 0)
|
||||
{
|
||||
mode = counter_mode[2];
|
||||
|
||||
if(mode === 0)
|
||||
{
|
||||
counter2_out = 1;
|
||||
counter_enabled[2] = 0;
|
||||
counter_current[2] = 0;
|
||||
}
|
||||
else if(mode === 2)
|
||||
{
|
||||
counter2_out = 1;
|
||||
counter_current[2] = counter_reload[2] + current % counter_reload[2];
|
||||
}
|
||||
else if(mode === 3)
|
||||
{
|
||||
counter2_out ^= 1;
|
||||
counter_current[2] = counter_reload[2] + current % counter_reload[2];
|
||||
}
|
||||
}
|
||||
// cannot really happen, because the counter gets changed by big numbers
|
||||
//else if(current === 1)
|
||||
//{
|
||||
// if(counter_mode[2] === 2)
|
||||
// {
|
||||
// counter2_out = 0;
|
||||
// }
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
io.register_read(0x40, function() { return counter_read(0); });
|
||||
io.register_read(0x41, function() { return counter_read(1); });
|
||||
io.register_read(0x42, function() { return counter_read(2); });
|
||||
|
||||
function counter_read(i)
|
||||
{
|
||||
var latch = counter_latch[i];
|
||||
|
||||
if(latch)
|
||||
{
|
||||
counter_latch[i]--;
|
||||
|
||||
if(latch === 2)
|
||||
{
|
||||
return counter_latch_value[i] & 0xFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
return counter_latch_value[i] >> 8;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var next_low = counter_next_low[i];
|
||||
|
||||
if(counter_mode[i] === 3)
|
||||
{
|
||||
counter_next_low[i] ^= 1;
|
||||
}
|
||||
|
||||
if(next_low)
|
||||
{
|
||||
return counter_current[i] & 0xFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
return counter_current[i] >> 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
io.register_write(0x40, function(value) { counter_write(0, value); });
|
||||
io.register_write(0x41, function(value) { counter_write(1, value); });
|
||||
io.register_write(0x42, function(value) { counter_write(2, value); });
|
||||
|
||||
function counter_write(i, value)
|
||||
{
|
||||
if(counter_next_low[i])
|
||||
{
|
||||
counter_reload[i] = counter_reload[i] & ~0xFF | value;
|
||||
}
|
||||
else
|
||||
{
|
||||
counter_reload[i] = counter_reload[i] & 0xFF | value << 8;
|
||||
}
|
||||
|
||||
if(counter_read_mode[i] !== 3 || !counter_next_low[i])
|
||||
{
|
||||
if(!counter_reload[i])
|
||||
{
|
||||
counter_reload[i] = 0xFFFF;
|
||||
}
|
||||
|
||||
// depends on the mode, should actually
|
||||
// happen on the first tick
|
||||
counter_current[i] = counter_reload[i];
|
||||
|
||||
counter_enabled[i] = true;
|
||||
|
||||
dbg_log("counter" + i + " reload=" + h(counter_reload[i]) +
|
||||
" tick=" + (counter_reload[i] || 0x10000) / OSCILLATOR_FREQ + "ms", LOG_PIT);
|
||||
}
|
||||
|
||||
if(counter_read_mode[i] === 3)
|
||||
{
|
||||
counter_next_low[i] ^= 1;
|
||||
}
|
||||
}
|
||||
|
||||
io.register_write(0x43, port43_write);
|
||||
|
||||
function port43_write(reg_byte)
|
||||
{
|
||||
var mode = reg_byte >> 1 & 7,
|
||||
binary_mode = reg_byte & 1,
|
||||
i = reg_byte >> 6 & 3,
|
||||
read_mode = reg_byte >> 4 & 3,
|
||||
next_low;
|
||||
|
||||
if(i === 1)
|
||||
{
|
||||
dbg_log("Unimplemented timer1", LOG_PIT);
|
||||
}
|
||||
|
||||
if(i === 3)
|
||||
{
|
||||
dbg_log("Unimplemented read back", LOG_PIT);
|
||||
return;
|
||||
}
|
||||
|
||||
if(read_mode === 0)
|
||||
{
|
||||
// latch
|
||||
counter_latch[i] = 2;
|
||||
counter_latch_value[i] = counter_current[i];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if(mode >= 6)
|
||||
{
|
||||
// 6 and 7 are aliased to 2 and 3
|
||||
mode &= ~4;
|
||||
}
|
||||
|
||||
dbg_log("Control: mode=" + mode + " ctr=" + i +
|
||||
" read_mode=" + read_mode + " bcd=" + binary_mode, LOG_PIT);
|
||||
|
||||
if(read_mode === 1)
|
||||
{
|
||||
// lsb
|
||||
counter_next_low[i] = 1;
|
||||
}
|
||||
else if(read_mode === 2)
|
||||
{
|
||||
// msb
|
||||
counter_next_low[i] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// first lsb then msb
|
||||
counter_next_low[i] = 1;
|
||||
}
|
||||
|
||||
|
||||
if(mode === 0)
|
||||
{
|
||||
}
|
||||
else if(mode === 3 || mode === 2)
|
||||
{
|
||||
// what is the difference
|
||||
}
|
||||
else
|
||||
{
|
||||
dbg_log("Unimplemented counter mode: " + h(mode), LOG_PIT);
|
||||
}
|
||||
|
||||
counter_mode[i] = mode;
|
||||
counter_read_mode[i] = read_mode;
|
||||
|
||||
if(i === 2)
|
||||
{
|
||||
if(mode === 0)
|
||||
{
|
||||
counter2_out = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// correct for mode 2 and 3
|
||||
counter2_out = 1;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
432
src/ps2.js
Normal file
432
src/ps2.js
Normal file
|
@ -0,0 +1,432 @@
|
|||
"use strict";
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
function PS2(dev, keyboard, mouse)
|
||||
{
|
||||
var
|
||||
io = dev.io,
|
||||
pic = dev.pic,
|
||||
|
||||
me = this,
|
||||
|
||||
/** @type {boolean} */
|
||||
enable_mouse_stream = false,
|
||||
/** @type {boolean} */
|
||||
enable_mouse = false,
|
||||
|
||||
/** @type {boolean} */
|
||||
have_mouse = false,
|
||||
|
||||
/** @type {number} */
|
||||
mouse_delta_x = 0,
|
||||
/** @type {number} */
|
||||
mouse_delta_y = 0,
|
||||
/** @type {number} */
|
||||
mouse_clicks = 0,
|
||||
|
||||
/** @type {boolean} */
|
||||
have_keyboard = false,
|
||||
|
||||
/** @type {boolean} */
|
||||
next_is_mouse_command = false,
|
||||
|
||||
/** @type {boolean} */
|
||||
next_read_sample = false,
|
||||
|
||||
/** @type {boolean} */
|
||||
next_read_led = false,
|
||||
|
||||
/**
|
||||
* @type {Array.<number>}
|
||||
*/
|
||||
kbd_buffer = [],
|
||||
|
||||
/** @type {number} */
|
||||
sample_rate = 100,
|
||||
|
||||
/** @type {number} */
|
||||
last_mouse_packet = -1,
|
||||
|
||||
/**
|
||||
* @type {Array.<number>}
|
||||
*/
|
||||
mouse_buffer = [];
|
||||
|
||||
|
||||
if(keyboard)
|
||||
{
|
||||
have_keyboard = true;
|
||||
keyboard.init(kbd_send_code);
|
||||
}
|
||||
|
||||
if(mouse)
|
||||
{
|
||||
have_mouse = true;
|
||||
mouse.init(mouse_send_click, mouse_send_delta);
|
||||
|
||||
// TODO: Mouse Wheel
|
||||
// http://www.computer-engineering.org/ps2mouse/
|
||||
}
|
||||
|
||||
|
||||
function mouse_irq()
|
||||
{
|
||||
pic.push_irq(12);
|
||||
}
|
||||
|
||||
function kbd_irq()
|
||||
{
|
||||
pic.push_irq(1);
|
||||
}
|
||||
|
||||
|
||||
function kbd_send_code(code)
|
||||
{
|
||||
//console.log(h(code));
|
||||
kbd_buffer.push(code);
|
||||
kbd_irq();
|
||||
}
|
||||
this.kbd_send_code = kbd_send_code;
|
||||
|
||||
function mouse_send_delta(delta_x, delta_y)
|
||||
{
|
||||
if(have_mouse && enable_mouse)
|
||||
{
|
||||
mouse_delta_x += delta_x;
|
||||
mouse_delta_y += delta_y;
|
||||
|
||||
if(enable_mouse_stream)
|
||||
{
|
||||
var now = Date.now();
|
||||
|
||||
if(now - last_mouse_packet < 1000 / sample_rate)
|
||||
{
|
||||
// TODO: set timeout
|
||||
return;
|
||||
}
|
||||
|
||||
last_mouse_packet = now;
|
||||
|
||||
send_mouse_packet();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function mouse_send_click(left, middle, right)
|
||||
{
|
||||
if(have_mouse && enable_mouse)
|
||||
{
|
||||
mouse_clicks = left | right << 1 | middle << 2;
|
||||
|
||||
if(enable_mouse_stream)
|
||||
{
|
||||
send_mouse_packet();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function send_mouse_packet()
|
||||
{
|
||||
var info_byte =
|
||||
(mouse_delta_y < 0) << 5 |
|
||||
(mouse_delta_x < 0) << 4 |
|
||||
1 << 3 |
|
||||
mouse_clicks;
|
||||
|
||||
mouse_buffer.push(
|
||||
info_byte,
|
||||
mouse_delta_x & 0xFF,
|
||||
mouse_delta_y & 0xFF
|
||||
);
|
||||
|
||||
if(mouse_buffer.length > 15)
|
||||
{
|
||||
var off = mouse_buffer.length % 3;
|
||||
mouse_buffer = mouse_buffer.slice(0, off).concat(mouse_buffer.slice(off + 3));
|
||||
}
|
||||
|
||||
mouse_delta_x = 0;
|
||||
mouse_delta_y = 0;
|
||||
|
||||
mouse_irq();
|
||||
}
|
||||
|
||||
this.destroy = function()
|
||||
{
|
||||
if(have_keyboard)
|
||||
{
|
||||
keyboard.destroy();
|
||||
}
|
||||
|
||||
if(have_mouse)
|
||||
{
|
||||
mouse.destroy();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
var command_register = 0,
|
||||
read_output_register = false,
|
||||
read_command_register = false;
|
||||
|
||||
|
||||
io.register_read(0x60, port60_read);
|
||||
io.register_read(0x64, port64_read);
|
||||
|
||||
io.register_write(0x60, port60_write);
|
||||
io.register_write(0x64, port64_write);
|
||||
|
||||
function port60_read()
|
||||
{
|
||||
//log("port 60 read: " + (buffer[0] || "(none)"));
|
||||
|
||||
if(!kbd_buffer.length && !mouse_buffer.length)
|
||||
{
|
||||
// should not happen
|
||||
dbg_log("Port 60 read: Empty", LOG_PS2);
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
var do_mouse_buffer;
|
||||
|
||||
if(kbd_buffer.length && mouse_buffer.length)
|
||||
{
|
||||
// tough decision, let's ask the PIC
|
||||
do_mouse_buffer = (pic.get_isr() & 2) === 0;
|
||||
}
|
||||
else if(kbd_buffer.length)
|
||||
{
|
||||
do_mouse_buffer = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
do_mouse_buffer = true;
|
||||
}
|
||||
|
||||
|
||||
if(do_mouse_buffer)
|
||||
{
|
||||
dbg_log("Port 60 read (mouse): " + h(mouse_buffer[0]), LOG_PS2);
|
||||
|
||||
if(mouse_buffer.length > 1)
|
||||
{
|
||||
mouse_irq();
|
||||
}
|
||||
|
||||
return mouse_buffer.shift();
|
||||
}
|
||||
else
|
||||
{
|
||||
dbg_log("Port 60 read (kbd) : " + h(kbd_buffer[0]), LOG_PS2);
|
||||
|
||||
if(kbd_buffer.length > 1)
|
||||
{
|
||||
kbd_irq();
|
||||
}
|
||||
|
||||
return kbd_buffer.shift();
|
||||
}
|
||||
};
|
||||
|
||||
function port64_read()
|
||||
{
|
||||
// status port
|
||||
//dbg_log("port 64 read", LOG_PS2);
|
||||
|
||||
var status_byte = 0x10;
|
||||
|
||||
if(mouse_buffer.length || kbd_buffer.length)
|
||||
{
|
||||
status_byte |= 1;
|
||||
}
|
||||
if(mouse_buffer.length)
|
||||
{
|
||||
status_byte |= 0x20;
|
||||
}
|
||||
|
||||
return status_byte;
|
||||
};
|
||||
|
||||
function port60_write(write_byte)
|
||||
{
|
||||
if(read_command_register)
|
||||
{
|
||||
command_register = write_byte;
|
||||
read_command_register = false;
|
||||
|
||||
dbg_log("Keyboard command register = " + h(command_register), LOG_PS2);
|
||||
}
|
||||
else if(read_output_register)
|
||||
{
|
||||
read_output_register = false;
|
||||
mouse_buffer = [write_byte];
|
||||
mouse_irq();
|
||||
}
|
||||
else if(next_read_sample)
|
||||
{
|
||||
next_read_sample = false;
|
||||
mouse_buffer = [0xFA];
|
||||
|
||||
sample_rate = write_byte;
|
||||
mouse_irq();
|
||||
}
|
||||
else if(next_read_led)
|
||||
{
|
||||
// nope
|
||||
next_read_led = false;
|
||||
}
|
||||
else if(next_is_mouse_command)
|
||||
{
|
||||
dbg_log("Port 60 data register write: " + h(write_byte), LOG_PS2);
|
||||
|
||||
if(!have_mouse)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// send ack
|
||||
mouse_buffer = [0xFA];
|
||||
|
||||
if(write_byte === 0xFF)
|
||||
{
|
||||
// reset, send completion code
|
||||
mouse_buffer.push(0xAA, 0x00);
|
||||
|
||||
enable_mouse = true;
|
||||
mouse.enabled = true;
|
||||
}
|
||||
else if(write_byte === 0xF2)
|
||||
{
|
||||
// MouseID Byte
|
||||
mouse_buffer.push(0, 0);
|
||||
}
|
||||
else if(write_byte === 0xF3)
|
||||
{
|
||||
// sample rate
|
||||
next_read_sample = true;
|
||||
}
|
||||
else if(write_byte === 0xF4)
|
||||
{
|
||||
// enable streaming
|
||||
|
||||
enable_mouse_stream = true;
|
||||
enable_mouse = true;
|
||||
|
||||
mouse.enabled = true;
|
||||
}
|
||||
else if(write_byte === 0xF5)
|
||||
{
|
||||
// disable streaming
|
||||
enable_mouse_stream = true;
|
||||
}
|
||||
else if(write_byte === 0xF6)
|
||||
{
|
||||
// reset defaults
|
||||
enable_mouse_stream = false;
|
||||
sample_rate = 100;
|
||||
|
||||
// ... resolution, scaling
|
||||
}
|
||||
else if(write_byte === 0xEB)
|
||||
{
|
||||
// request single packet
|
||||
dbg_log("unimplemented request single packet");
|
||||
}
|
||||
else
|
||||
{
|
||||
dbg_log("new mouse command: " + h(write_byte), LOG_PS2);
|
||||
}
|
||||
|
||||
mouse_irq();
|
||||
}
|
||||
else
|
||||
{
|
||||
dbg_log("Port 60 data register write: " + h(write_byte), LOG_PS2);
|
||||
|
||||
// send ack
|
||||
kbd_buffer.push(0xFA);
|
||||
|
||||
if(write_byte === 0xFF)
|
||||
{
|
||||
kbd_buffer.push(0xAA, 0x00);
|
||||
}
|
||||
else if(write_byte === 0xF2)
|
||||
{
|
||||
// identify
|
||||
kbd_buffer.push(0xAB, 83);
|
||||
}
|
||||
else if(write_byte === 0xF4)
|
||||
{
|
||||
// enable scanning
|
||||
}
|
||||
else if(write_byte === 0xF5)
|
||||
{
|
||||
// disable scanning
|
||||
}
|
||||
else if(write_byte === 0xED)
|
||||
{
|
||||
next_read_led = true;
|
||||
}
|
||||
|
||||
kbd_irq();
|
||||
}
|
||||
};
|
||||
|
||||
function port64_write(write_byte)
|
||||
{
|
||||
dbg_log("port 64 write: " + h(write_byte), LOG_PS2);
|
||||
|
||||
if(write_byte === 0xFE)
|
||||
{
|
||||
dbg_log("CPU reboot via PS2");
|
||||
dev.reboot();
|
||||
}
|
||||
else if(write_byte === 0x20)
|
||||
{
|
||||
kbd_buffer.push(command_register);
|
||||
kbd_irq();
|
||||
}
|
||||
else if(write_byte === 0x60)
|
||||
{
|
||||
read_command_register = true;
|
||||
}
|
||||
else if(write_byte === 0xD3)
|
||||
{
|
||||
read_output_register = true;
|
||||
}
|
||||
else if(write_byte === 0xD4)
|
||||
{
|
||||
next_is_mouse_command = true;
|
||||
}
|
||||
else if(write_byte === 0xA9)
|
||||
{
|
||||
// test second ps/2 port
|
||||
kbd_buffer = [0];
|
||||
kbd_irq();
|
||||
}
|
||||
else if(write_byte === 0xAA)
|
||||
{
|
||||
kbd_buffer = [0x55];
|
||||
kbd_irq();
|
||||
}
|
||||
else if(write_byte === 0xAB)
|
||||
{
|
||||
kbd_buffer = [0];
|
||||
kbd_irq();
|
||||
}
|
||||
/*else if(write_byte === 0xAE)
|
||||
{
|
||||
// not sure if right ...
|
||||
kbd_buffer =[];
|
||||
}*/
|
||||
else
|
||||
{
|
||||
dbg_log("port 64: New command byte: " + h(write_byte), LOG_PS2);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
188
src/rtc.js
Normal file
188
src/rtc.js
Normal file
|
@ -0,0 +1,188 @@
|
|||
/**
|
||||
* RTC (real time clock) and CMOS
|
||||
* @constructor
|
||||
*/
|
||||
function RTC(dev, diskette_type)
|
||||
{
|
||||
var
|
||||
io = dev.io,
|
||||
pic = dev.pic,
|
||||
|
||||
cmos_index = 0,
|
||||
me = this,
|
||||
|
||||
// used for cmos entries
|
||||
rtc_time = Date.now(),
|
||||
last_update = rtc_time,
|
||||
|
||||
// used for periodic interrupt
|
||||
next_interrupt,
|
||||
|
||||
periodic_interrupt = false,
|
||||
|
||||
// corresponds to default value for cmos_a
|
||||
periodic_interrupt_time = 1000 / 1024;
|
||||
|
||||
|
||||
var cmos_a = 0x26,
|
||||
cmos_b = 2;
|
||||
|
||||
this.nmi_disabled = 0;
|
||||
|
||||
this.timer = function(time)
|
||||
{
|
||||
if(periodic_interrupt)
|
||||
{
|
||||
while(next_interrupt < time)
|
||||
{
|
||||
next_interrupt += periodic_interrupt_time;
|
||||
|
||||
pic.push_irq(8);
|
||||
}
|
||||
}
|
||||
|
||||
rtc_time += time - last_update;
|
||||
last_update = time;
|
||||
};
|
||||
|
||||
io.register_write(0x70, function(out_byte)
|
||||
{
|
||||
cmos_index = out_byte & 0x7F;
|
||||
me.nmi_disabled = out_byte >> 7;
|
||||
});
|
||||
|
||||
io.register_write(0x71, cmos_write);
|
||||
io.register_read(0x71, cmos_read);
|
||||
|
||||
function encode_time(t)
|
||||
{
|
||||
if(cmos_b & 4)
|
||||
{
|
||||
// binary mode
|
||||
return t;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Math.bcd_pack(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// TODO
|
||||
// - interrupt on update
|
||||
// - countdown
|
||||
// - letting bios/os set values
|
||||
// (none of these are used by seabios or the OSes we're
|
||||
// currently testing)
|
||||
function cmos_read()
|
||||
{
|
||||
var index = cmos_index;
|
||||
|
||||
cmos_index = 0xD;
|
||||
|
||||
switch(index)
|
||||
{
|
||||
case 0:
|
||||
return encode_time(new Date(rtc_time).getUTCSeconds());
|
||||
case 2:
|
||||
return encode_time(new Date(rtc_time).getUTCMinutes());
|
||||
case 4:
|
||||
// TODO: 12 hour mode
|
||||
return encode_time(new Date(rtc_time).getUTCHours());
|
||||
case 7:
|
||||
return encode_time(new Date(rtc_time).getUTCDate());
|
||||
case 8:
|
||||
return encode_time(new Date(rtc_time).getUTCMonth() + 1);
|
||||
case 9:
|
||||
return encode_time(new Date(rtc_time).getUTCFullYear() % 100);
|
||||
|
||||
case 0xA:
|
||||
return cmos_a;
|
||||
case 0xB:
|
||||
//dbg_log("cmos read from index " + h(index));
|
||||
return cmos_b;
|
||||
|
||||
case 0xE:
|
||||
// post info
|
||||
return 0;
|
||||
case 0xC:
|
||||
//dbg_log("cmos read from index " + h(index));
|
||||
// TODO:
|
||||
// It is important to know that upon a IRQ 8, Status Register C
|
||||
// will contain a bitmask telling which interrupt happened.
|
||||
// What is important is that if register C is not read after an
|
||||
// IRQ 8, then the interrupt will not happen again.
|
||||
|
||||
//dbg_log("cmos Ch read");
|
||||
return 0;
|
||||
// Missing IRQF flag
|
||||
//return cmos_b & 0x70;
|
||||
|
||||
case 0xF:
|
||||
return 0;
|
||||
|
||||
case 0x10:
|
||||
// floppy type
|
||||
return diskette_type;
|
||||
|
||||
case 0x14:
|
||||
// equipment
|
||||
return 0x2D;
|
||||
|
||||
case 0x32:
|
||||
return encode_time(new Date(rtc_time).getUTCFullYear() / 100 | 0);
|
||||
|
||||
case 0x34:
|
||||
return (memory_size - 16 * 1024 * 1024) >> 16 & 0xff;
|
||||
case 0x35:
|
||||
return (memory_size - 16 * 1024 * 1024) >> 24 & 0xff;
|
||||
|
||||
case 0x38:
|
||||
// used by seabios to determine the boot order
|
||||
// bootflag 1, high nibble, lowest priority
|
||||
return 0x30; // hd
|
||||
case 0x3D:
|
||||
// bootflag 2, both nibbles, high and middle priority
|
||||
return 0x21; // floppy first, cd second
|
||||
|
||||
case 0x5B:
|
||||
case 0x5C:
|
||||
case 0x5D:
|
||||
// memory above 4GB
|
||||
return 0;
|
||||
}
|
||||
|
||||
dbg_log("cmos read from index " + h(index), LOG_RTC);
|
||||
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
function cmos_write(data_byte)
|
||||
{
|
||||
switch(cmos_index)
|
||||
{
|
||||
case 0xA:
|
||||
cmos_a = data_byte & 0x7F;
|
||||
periodic_interrupt_time = 1000 / (32768 >> (cmos_a & 0xF) - 1);
|
||||
|
||||
dbg_log("Periodic interrupt, a=" + h(cmos_a, 2) + " t=" + periodic_interrupt_time , LOG_RTC);
|
||||
break;
|
||||
case 0xB:
|
||||
cmos_b = data_byte;
|
||||
if(cmos_b & 0x40)
|
||||
{
|
||||
next_interrupt = Date.now();
|
||||
}
|
||||
|
||||
if(cmos_b & 0x20) dbg_log("Unimplemented: alarm interrupt");
|
||||
if(cmos_b & 0x10) dbg_log("Unimplemented: updated interrupt");
|
||||
|
||||
dbg_log("cmos b=" + h(cmos_b, 2), LOG_RTC);
|
||||
break;
|
||||
default:
|
||||
dbg_log("cmos write index " + h(cmos_index) + ": " + h(data_byte), LOG_RTC);
|
||||
}
|
||||
|
||||
periodic_interrupt = (cmos_b & 0x40) === 0x40 && (cmos_a & 0xF) > 0;
|
||||
}
|
||||
}
|
281
src/string.macro.js
Normal file
281
src/string.macro.js
Normal file
|
@ -0,0 +1,281 @@
|
|||
"use strict";
|
||||
|
||||
/*
|
||||
* string operations
|
||||
*
|
||||
* cmp si di
|
||||
* movs 0 1 1 A4
|
||||
* cmps 1 1 1 A6
|
||||
* stos 0 0 1 AA
|
||||
* lods 0 1 0 AC
|
||||
* scas 1 0 1 AE
|
||||
* ins 0 0 1
|
||||
* outs 0 1 0
|
||||
*/
|
||||
|
||||
#define string_instruction(s, use_cmp, use_di, use_si, fn, aligned_fn)\
|
||||
var src, dest, data_src, data_dest;\
|
||||
var size = flags & flag_direction ? -(s >> 3) : s >> 3;\
|
||||
var ds, es;\
|
||||
if(use_cmp && !use_si) data_src = reg ## s[reg_eax];\
|
||||
if(use_di) es = get_seg(reg_es), dest = es + regv[reg_vdi];\
|
||||
if(use_si) ds = get_seg_prefix(reg_ds), src = ds + regv[reg_vsi];\
|
||||
if(repeat_string_prefix) {\
|
||||
if(regv[reg_vcx] === 0) return;\
|
||||
var aligned = s > 8 && (!use_di || (dest & (s >> 3) - 1) === 0) && (!use_si || (src & (s >> 3) - 1) === 0);\
|
||||
do {\
|
||||
if(aligned) {\
|
||||
aligned_fn;\
|
||||
} else {\
|
||||
fn;\
|
||||
}\
|
||||
if(use_di) dest += size, regv[reg_vdi] += size;\
|
||||
if(use_si) src += size, regv[reg_vsi] += size;\
|
||||
} while(--regv[reg_vcx] && (!use_cmp || (data_src === data_dest) === repeat_string_type));\
|
||||
} else {\
|
||||
fn;\
|
||||
if(use_di) regv[reg_vdi] += size;\
|
||||
if(use_si) regv[reg_vsi] += size;\
|
||||
}\
|
||||
if(use_cmp) cmp ## s(data_src, data_dest);\
|
||||
|
||||
|
||||
function movsb()
|
||||
{
|
||||
string_instruction(8, false, true, true,
|
||||
{
|
||||
safe_write8(dest, safe_read8(src));
|
||||
}, {});
|
||||
}
|
||||
|
||||
function movsw()
|
||||
{
|
||||
string_instruction(16, false, true, true,
|
||||
{
|
||||
safe_write16(dest, safe_read16(src));
|
||||
}, {
|
||||
var phys_src = translate_address_read(src);
|
||||
var phys_dest = translate_address_write(dest);
|
||||
|
||||
memory.write_aligned16(phys_dest, memory.read_aligned16(phys_src));
|
||||
});
|
||||
}
|
||||
|
||||
function movsd()
|
||||
{
|
||||
string_instruction(32, false, true, true,
|
||||
{
|
||||
safe_write32(dest, safe_read32s(src));
|
||||
}, {
|
||||
var phys_src = translate_address_read(src);
|
||||
var phys_dest = translate_address_write(dest);
|
||||
|
||||
memory.write_aligned32(phys_dest, memory.read_aligned32(phys_src));
|
||||
});
|
||||
}
|
||||
|
||||
function cmpsb()
|
||||
{
|
||||
string_instruction(8, true, true, true,
|
||||
{
|
||||
data_dest = safe_read8(dest);
|
||||
data_src = safe_read8(src);
|
||||
}, {});
|
||||
}
|
||||
|
||||
|
||||
function cmpsw()
|
||||
{
|
||||
string_instruction(16, true, true, true,
|
||||
{
|
||||
data_dest = safe_read16(dest);
|
||||
data_src = safe_read16(src);
|
||||
}, {
|
||||
data_dest = memory.read_aligned16(translate_address_read(dest));
|
||||
data_src = memory.read_aligned16(translate_address_read(src));
|
||||
});
|
||||
}
|
||||
|
||||
function cmpsd()
|
||||
{
|
||||
string_instruction(32, true, true, true,
|
||||
{
|
||||
data_dest = safe_read32(dest);
|
||||
data_src = safe_read32(src);
|
||||
}, {
|
||||
data_dest = memory.read_aligned32(translate_address_read(dest)) >>> 0;
|
||||
data_src = memory.read_aligned32(translate_address_read(src)) >>> 0;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function stosb()
|
||||
{
|
||||
var data = reg8[reg_al];
|
||||
|
||||
string_instruction(8, false, true, false,
|
||||
{
|
||||
safe_write8(dest, data);
|
||||
}, {});
|
||||
}
|
||||
|
||||
|
||||
function stosw()
|
||||
{
|
||||
var data = reg16[reg_ax];
|
||||
|
||||
string_instruction(16, false, true, false,
|
||||
{
|
||||
safe_write16(dest, data);
|
||||
}, {
|
||||
memory.write_aligned16(translate_address_write(dest), data);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function stosd()
|
||||
{
|
||||
//dbg_log("stosd " + ((reg32[reg_edi] & 3) ? "mis" : "") + "aligned", LOG_CPU);
|
||||
var data = reg32[reg_eax];
|
||||
|
||||
string_instruction(32, false, true, false,
|
||||
{
|
||||
safe_write32(dest, data);
|
||||
}, {
|
||||
memory.write_aligned32(translate_address_write(dest), data);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function lodsb()
|
||||
{
|
||||
string_instruction(8, false, false, true,
|
||||
{
|
||||
reg8[reg_al] = safe_read8(src);
|
||||
}, {});
|
||||
}
|
||||
|
||||
|
||||
function lodsw()
|
||||
{
|
||||
string_instruction(16, false, false, true,
|
||||
{
|
||||
reg16[reg_ax] = safe_read16(src);
|
||||
}, {
|
||||
reg16[reg_ax] = safe_read16(src);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function lodsd()
|
||||
{
|
||||
string_instruction(32, false, false, true,
|
||||
{
|
||||
reg32[reg_eax] = safe_read32s(src);
|
||||
}, {
|
||||
reg32[reg_eax] = safe_read32s(src);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function scasb()
|
||||
{
|
||||
string_instruction(8, true, true, false,
|
||||
{
|
||||
data_dest = safe_read8(dest);
|
||||
}, {});
|
||||
}
|
||||
|
||||
|
||||
function scasw()
|
||||
{
|
||||
string_instruction(16, true, true, false,
|
||||
{
|
||||
data_dest = safe_read16(dest);
|
||||
}, {
|
||||
data_dest = memory.read_aligned16(translate_address_read(dest));
|
||||
});
|
||||
}
|
||||
|
||||
function scasd()
|
||||
{
|
||||
string_instruction(32, true, true, false,
|
||||
{
|
||||
data_dest = safe_read32(dest);
|
||||
}, {
|
||||
data_dest = memory.read_aligned32(translate_address_read(dest)) >>> 0;
|
||||
});
|
||||
}
|
||||
|
||||
function insb()
|
||||
{
|
||||
var port = reg16[reg_dx];
|
||||
|
||||
string_instruction(8, false, true, false,
|
||||
{
|
||||
safe_write8(dest, in8(port));
|
||||
}, {
|
||||
});
|
||||
}
|
||||
|
||||
function insw()
|
||||
{
|
||||
var port = reg16[reg_dx];
|
||||
|
||||
string_instruction(8, false, true, false,
|
||||
{
|
||||
safe_write16(dest, in16(port));
|
||||
}, {
|
||||
var phys_dest = translate_address_write(dest);
|
||||
memory.write_aligned16(phys_dest, in16(port));
|
||||
});
|
||||
}
|
||||
|
||||
function insd()
|
||||
{
|
||||
var port = reg16[reg_dx];
|
||||
|
||||
string_instruction(32, false, true, false,
|
||||
{
|
||||
safe_write32(dest, in32(port));
|
||||
}, {
|
||||
var phys_dest = translate_address_write(dest);
|
||||
memory.write_aligned32(phys_dest, in32(port));
|
||||
});
|
||||
}
|
||||
|
||||
function outsb()
|
||||
{
|
||||
var port = reg16[reg_dx];
|
||||
|
||||
string_instruction(8, false, false, true,
|
||||
{
|
||||
out8(port, safe_read8(src));
|
||||
}, {
|
||||
out8(port, safe_read8(src));
|
||||
});
|
||||
}
|
||||
|
||||
function outsw()
|
||||
{
|
||||
var port = reg16[reg_dx];
|
||||
|
||||
string_instruction(16, false, false, true,
|
||||
{
|
||||
out16(port, safe_read16(src));
|
||||
}, {
|
||||
out16(port, safe_read16(src));
|
||||
});
|
||||
}
|
||||
|
||||
function outsd()
|
||||
{
|
||||
var port = reg16[reg_dx];
|
||||
|
||||
string_instruction(32, false, false, true,
|
||||
{
|
||||
out32(port, safe_read32s(src));
|
||||
}, {
|
||||
out32(port, safe_read32s(src));
|
||||
});
|
||||
}
|
26
src/uart.js
Normal file
26
src/uart.js
Normal file
|
@ -0,0 +1,26 @@
|
|||
/**
|
||||
* No full implementation, just dumping serial output
|
||||
* to console
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function UART(dev)
|
||||
{
|
||||
var
|
||||
io = dev.io,
|
||||
line = "";
|
||||
|
||||
io.register_write(0x3F8, function(out_byte)
|
||||
{
|
||||
if(out_byte === 0x0A)
|
||||
{
|
||||
log(line);
|
||||
dbg_log(line, LOG_SERIAL);
|
||||
line = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
line += String.fromCharCode(out_byte);
|
||||
}
|
||||
});
|
||||
}
|
8
src/v86_all.js.map
Normal file
8
src/v86_all.js.map
Normal file
File diff suppressed because one or more lines are too long
1023
src/vga.js
Normal file
1023
src/vga.js
Normal file
File diff suppressed because it is too large
Load diff
8
tests/perf/build.sh
Executable file
8
tests/perf/build.sh
Executable file
|
@ -0,0 +1,8 @@
|
|||
nasm test.asm -o test.bin
|
||||
|
||||
echo "var file = [" > test-asm.js
|
||||
cat test.bin|xxd -i >> test-asm.js
|
||||
echo "]" >> test-asm.js
|
||||
|
||||
echo "done."
|
||||
|
59
tests/perf/runtest.js
Normal file
59
tests/perf/runtest.js
Normal file
|
@ -0,0 +1,59 @@
|
|||
// Run with d8, not node
|
||||
|
||||
var path = "../../src/";
|
||||
|
||||
load(path + "const.js");
|
||||
load(path + "io.js");
|
||||
load(path + "cpu.js");
|
||||
load(path + "main.js");
|
||||
load(path + "disk.js");
|
||||
load(path + "pci.js");
|
||||
load(path + "test_helpers.js");
|
||||
load(path + "memory.js");
|
||||
load(path + "dma.js");
|
||||
load(path + "pit.js");
|
||||
load(path + "pic.js");
|
||||
|
||||
|
||||
if(typeof console === "undefined")
|
||||
{
|
||||
var console = {
|
||||
log: print,
|
||||
}
|
||||
}
|
||||
|
||||
var log = print;
|
||||
|
||||
DEBUG = false;
|
||||
|
||||
var cpu = new v86();
|
||||
|
||||
cpu.init({});
|
||||
|
||||
// defines file
|
||||
load("test-asm.js");
|
||||
|
||||
for(var i = 0; i < file.length; i++)
|
||||
{
|
||||
cpu.memory.mem8[i] = file[i];
|
||||
}
|
||||
|
||||
function run()
|
||||
{
|
||||
for(var i = 0; i < count; i++)
|
||||
{
|
||||
cpu.cycle();
|
||||
}
|
||||
}
|
||||
|
||||
var count = 1e7;
|
||||
|
||||
var start = Date.now();
|
||||
|
||||
run();
|
||||
|
||||
var end = Date.now(),
|
||||
duration = (end - start) / 1e3;
|
||||
|
||||
console.log("Finished in " + duration + " seconds, " + (count / duration / 1e6).toFixed(2) + " mips");
|
||||
|
12
tests/perf/test-asm.js
Normal file
12
tests/perf/test-asm.js
Normal file
|
@ -0,0 +1,12 @@
|
|||
var file = [
|
||||
0x66, 0xbb, 0x00, 0x00, 0x10, 0x00, 0x66, 0xb8, 0xff, 0xff, 0xff, 0xff,
|
||||
0xb8, 0xff, 0xff, 0xb0, 0xff, 0x67, 0x8a, 0x03, 0x66, 0x0f, 0xbf, 0xc0,
|
||||
0x0f, 0xbe, 0xc0, 0x66, 0x0f, 0xb6, 0xc0, 0x66, 0x91, 0x67, 0x86, 0x03,
|
||||
0x67, 0x87, 0x03, 0x67, 0xfe, 0x03, 0x66, 0x67, 0xff, 0x03, 0x40, 0xfe,
|
||||
0xc0, 0x67, 0xfe, 0x0b, 0x66, 0x67, 0xff, 0x0b, 0x48, 0xfe, 0xc8, 0x66,
|
||||
0xf7, 0xe1, 0xf7, 0xe1, 0xf6, 0xe1, 0x66, 0xf7, 0xe9, 0xf7, 0xe9, 0xf6,
|
||||
0xe9, 0x66, 0x6b, 0xc0, 0x10, 0x66, 0x69, 0xc0, 0x00, 0x00, 0x00, 0x01,
|
||||
0x6b, 0xc0, 0x10, 0x66, 0x0f, 0xaf, 0xc1, 0x0f, 0xaf, 0xc1, 0x66, 0x50,
|
||||
0x50, 0x5f, 0x66, 0x5f, 0xfb, 0xfa, 0xfd, 0xfc, 0x60, 0x61, 0x66, 0x60,
|
||||
0x66, 0x61, 0x9c, 0x9d, 0x66, 0x9c, 0x66, 0x9d, 0xeb, 0x8a
|
||||
]
|
199
tests/perf/test.asm
Normal file
199
tests/perf/test.asm
Normal file
|
@ -0,0 +1,199 @@
|
|||
;[BITS 32]
|
||||
|
||||
start:
|
||||
mov ebx, 100000h
|
||||
|
||||
%if 0
|
||||
|
||||
add al, [4*ebx+100h]
|
||||
add eax, ecx
|
||||
add [4*ebx+1000h], cl
|
||||
add al, 10h
|
||||
add eax, 1000h
|
||||
add cl, 10h
|
||||
add ecx, 1000h
|
||||
|
||||
or al, [4*ebx+100h]
|
||||
or eax, ecx
|
||||
or [4*ebx+1000h], cl
|
||||
or al, 10h
|
||||
or eax, 1000h
|
||||
or cl, 10h
|
||||
or ecx, 1000h
|
||||
|
||||
adc al, [4*ebx+100h]
|
||||
adc eax, ecx
|
||||
adc [4*ebx+1000h], cl
|
||||
adc al, 10h
|
||||
adc eax, 1000h
|
||||
adc cl, 10h
|
||||
adc ecx, 1000h
|
||||
|
||||
sbb al, [4*ebx+100h]
|
||||
sbb eax, ecx
|
||||
sbb [4*ebx+1000h], cl
|
||||
sbb al, 10h
|
||||
sbb eax, 1000h
|
||||
sbb cl, 10h
|
||||
sbb ecx, 1000h
|
||||
|
||||
and al, [4*ebx+100h]
|
||||
and eax, ecx
|
||||
and [4*ebx+1000h], cl
|
||||
and al, 10h
|
||||
and eax, 1000h
|
||||
and cl, 10h
|
||||
and ecx, 1000h
|
||||
|
||||
sub al, [4*ebx+100h]
|
||||
sub eax, ecx
|
||||
sub [4*ebx+1000h], cl
|
||||
sub al, 10h
|
||||
sub eax, 1000h
|
||||
sub cl, 10h
|
||||
sub ecx, 1000h
|
||||
|
||||
xor al, [4*ebx+100h]
|
||||
xor eax, ecx
|
||||
xor [4*ebx+1000h], cl
|
||||
xor al, 10h
|
||||
xor eax, 1000h
|
||||
xor cl, 10h
|
||||
xor ecx, 1000h
|
||||
|
||||
cmp al, [4*ebx+100h]
|
||||
cmp eax, ecx
|
||||
cmp [4*ebx+1000h], cl
|
||||
cmp al, 10h
|
||||
cmp eax, 1000h
|
||||
cmp cl, 10h
|
||||
cmp ecx, 1000h
|
||||
|
||||
|
||||
test al, [4*ebx+100h]
|
||||
test eax, ecx
|
||||
test [4*ebx+1000h], cl
|
||||
test al, 10h
|
||||
test eax, 1000h
|
||||
%endif
|
||||
|
||||
|
||||
%if 0
|
||||
add eax, 12345671h
|
||||
|
||||
jo $+2
|
||||
jno $+2
|
||||
jp $+2
|
||||
jnp $+2
|
||||
jc $+2
|
||||
jnc $+2
|
||||
js $+2
|
||||
jns $+2
|
||||
jz $+2
|
||||
jnz $+2
|
||||
jl $+2
|
||||
jnl $+2
|
||||
jbe $+2
|
||||
jnbe $+2
|
||||
jle $+2
|
||||
jnle $+2
|
||||
%endif
|
||||
|
||||
%if 0
|
||||
sal eax, 12
|
||||
sal cx, 7
|
||||
sal dl, 1
|
||||
sal dh, 0
|
||||
|
||||
shl eax, 12
|
||||
shl cx, 7
|
||||
shl dl, 1
|
||||
shl dh, 0
|
||||
|
||||
shr eax, 12
|
||||
shr cx, 7
|
||||
shr dl, 1
|
||||
shr dh, 0
|
||||
|
||||
ror eax, 12
|
||||
ror cx, 7
|
||||
ror dl, 1
|
||||
ror dh, 0
|
||||
|
||||
rol eax, 12
|
||||
rol cx, 7
|
||||
rol dl, 1
|
||||
rol dh, 0
|
||||
|
||||
rcr eax, 12
|
||||
rcr cx, 7
|
||||
rcr dl, 1
|
||||
rcr dh, 0
|
||||
|
||||
rcl eax, 12
|
||||
rcl cx, 7
|
||||
rcl dl, 1
|
||||
rcl dh, 0
|
||||
|
||||
|
||||
%endif
|
||||
|
||||
mov eax, -1
|
||||
mov ax, -1
|
||||
mov al, -1
|
||||
mov al, [ebx]
|
||||
|
||||
movsx eax, ax
|
||||
movsx ax, al
|
||||
movzx eax, al
|
||||
|
||||
xchg eax, ecx
|
||||
xchg [ebx], al
|
||||
xchg [ebx], ax
|
||||
|
||||
inc byte [ebx]
|
||||
inc dword [ebx]
|
||||
inc ax
|
||||
inc al
|
||||
dec byte [ebx]
|
||||
dec dword [ebx]
|
||||
dec ax
|
||||
dec al
|
||||
|
||||
mul ecx
|
||||
mul cx
|
||||
mul cl
|
||||
|
||||
imul ecx
|
||||
imul cx
|
||||
imul cl
|
||||
|
||||
|
||||
imul eax, 10h
|
||||
imul eax, 1000000h
|
||||
imul ax, 10h
|
||||
imul eax, ecx
|
||||
imul ax, cx
|
||||
|
||||
push eax
|
||||
push ax
|
||||
pop di
|
||||
pop edi
|
||||
|
||||
sti
|
||||
cli
|
||||
std
|
||||
cld
|
||||
|
||||
pusha
|
||||
popa
|
||||
pushad
|
||||
popad
|
||||
|
||||
pushf
|
||||
popf
|
||||
pushfd
|
||||
popfd
|
||||
|
||||
|
||||
jmp start
|
BIN
tests/perf/test.bin
Normal file
BIN
tests/perf/test.bin
Normal file
Binary file not shown.
16
tests/qemu/LICENSE
Normal file
16
tests/qemu/LICENSE
Normal file
|
@ -0,0 +1,16 @@
|
|||
x86 CPU test
|
||||
|
||||
Copyright (c) 2003 Fabrice Bellard
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
17
tests/qemu/Makefile
Normal file
17
tests/qemu/Makefile
Normal file
|
@ -0,0 +1,17 @@
|
|||
|
||||
CC=gcc
|
||||
CC_I386=$(CC) -m32
|
||||
QEMU_INCLUDES += -I../..
|
||||
CFLAGS=-Wall -O2 -g -fno-strict-aliasing -static
|
||||
LDFLAGS=
|
||||
|
||||
|
||||
# i386/x86_64 emulation test (test various opcodes) */
|
||||
test-i386: test-i386.c test-i386-code16.S test-i386-vm86.S \
|
||||
test-i386.h test-i386-shift.h test-i386-muldiv.h
|
||||
$(CC_I386) $(QEMU_INCLUDES) $(CFLAGS) $(LDFLAGS) -o $@ \
|
||||
$(<D)/test-i386.c $(<D)/test-i386-code16.S $(<D)/test-i386-vm86.S -lm
|
||||
|
||||
|
||||
clean:
|
||||
rm -f test-i386
|
8
tests/qemu/Reame
Normal file
8
tests/qemu/Reame
Normal file
|
@ -0,0 +1,8 @@
|
|||
How to run:
|
||||
|
||||
- Build test-i386
|
||||
- Run test-i386 locally (requires Linux and an x86 machine)
|
||||
- Put the both on a disk (for instance, a cd image built with buildroot)
|
||||
- Run test-i386 in the emulator
|
||||
- Compare the result
|
||||
|
58
tests/qemu/compiler.h
Normal file
58
tests/qemu/compiler.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
/* public domain */
|
||||
|
||||
#ifndef COMPILER_H
|
||||
#define COMPILER_H
|
||||
|
||||
#include "config-host.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| The macro QEMU_GNUC_PREREQ tests for minimum version of the GNU C compiler.
|
||||
| The code is a copy of SOFTFLOAT_GNUC_PREREQ, see softfloat-macros.h.
|
||||
*----------------------------------------------------------------------------*/
|
||||
#if defined(__GNUC__) && defined(__GNUC_MINOR__)
|
||||
# define QEMU_GNUC_PREREQ(maj, min) \
|
||||
((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
|
||||
#else
|
||||
# define QEMU_GNUC_PREREQ(maj, min) 0
|
||||
#endif
|
||||
|
||||
#define QEMU_NORETURN __attribute__ ((__noreturn__))
|
||||
|
||||
#if QEMU_GNUC_PREREQ(3, 4)
|
||||
#define QEMU_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
|
||||
#else
|
||||
#define QEMU_WARN_UNUSED_RESULT
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
# define QEMU_PACKED __attribute__((gcc_struct, packed))
|
||||
#else
|
||||
# define QEMU_PACKED __attribute__((packed))
|
||||
#endif
|
||||
|
||||
#define cat(x,y) x ## y
|
||||
#define cat2(x,y) cat(x,y)
|
||||
#define QEMU_BUILD_BUG_ON(x) \
|
||||
typedef char cat2(qemu_build_bug_on__,__LINE__)[(x)?-1:1];
|
||||
|
||||
#if defined __GNUC__
|
||||
# if !QEMU_GNUC_PREREQ(4, 4)
|
||||
/* gcc versions before 4.4.x don't support gnu_printf, so use printf. */
|
||||
# define GCC_ATTR __attribute__((__unused__, format(printf, 1, 2)))
|
||||
# define GCC_FMT_ATTR(n, m) __attribute__((format(printf, n, m)))
|
||||
# else
|
||||
/* Use gnu_printf when supported (qemu uses standard format strings). */
|
||||
# define GCC_ATTR __attribute__((__unused__, format(gnu_printf, 1, 2)))
|
||||
# define GCC_FMT_ATTR(n, m) __attribute__((format(gnu_printf, n, m)))
|
||||
# if defined(_WIN32)
|
||||
/* Map __printf__ to __gnu_printf__ because we want standard format strings
|
||||
* even when MinGW or GLib include files use __printf__. */
|
||||
# define __printf__ __gnu_printf__
|
||||
# endif
|
||||
# endif
|
||||
#else
|
||||
#define GCC_ATTR /**/
|
||||
#define GCC_FMT_ATTR(n, m)
|
||||
#endif
|
||||
|
||||
#endif /* COMPILER_H */
|
66
tests/qemu/config-host.h
Normal file
66
tests/qemu/config-host.h
Normal file
|
@ -0,0 +1,66 @@
|
|||
/* Automatically generated by create_config - do not modify */
|
||||
#define CONFIG_QEMU_CONFDIR "/usr/local/etc/qemu"
|
||||
#define CONFIG_QEMU_DATADIR "/usr/local/share/qemu"
|
||||
#define CONFIG_QEMU_DOCDIR "/usr/local/share/doc/qemu"
|
||||
#define CONFIG_QEMU_LOCALSTATEDIR "/usr/local/var"
|
||||
#define CONFIG_QEMU_HELPERDIR "/usr/local/libexec"
|
||||
#define HOST_I386 1
|
||||
#define CONFIG_POSIX 1
|
||||
#define CONFIG_LINUX 1
|
||||
#define CONFIG_SLIRP 1
|
||||
#define CONFIG_SMBD_COMMAND "/usr/sbin/smbd"
|
||||
#define CONFIG_AC97 1
|
||||
#define CONFIG_ES1370 1
|
||||
#define CONFIG_SB16 1
|
||||
#define CONFIG_HDA 1
|
||||
#define CONFIG_AUDIO_DRIVERS \
|
||||
&oss_audio_driver,\
|
||||
|
||||
#define CONFIG_OSS 1
|
||||
#define CONFIG_BDRV_WHITELIST \
|
||||
NULL
|
||||
#define CONFIG_VNC 1
|
||||
#define CONFIG_VNC_TLS 1
|
||||
#define CONFIG_VNC_PNG 1
|
||||
#define CONFIG_FNMATCH 1
|
||||
#define QEMU_VERSION "1.3.1"
|
||||
#define QEMU_PKGVERSION ""
|
||||
#define CONFIG_SDL 1
|
||||
#define CONFIG_CURSES 1
|
||||
#define CONFIG_ATFILE 1
|
||||
#define CONFIG_UTIMENSAT 1
|
||||
#define CONFIG_PIPE2 1
|
||||
#define CONFIG_ACCEPT4 1
|
||||
#define CONFIG_SPLICE 1
|
||||
#define CONFIG_EVENTFD 1
|
||||
#define CONFIG_FALLOCATE 1
|
||||
#define CONFIG_SYNC_FILE_RANGE 1
|
||||
#define CONFIG_FIEMAP 1
|
||||
#define CONFIG_DUP3 1
|
||||
#define CONFIG_EPOLL 1
|
||||
#define CONFIG_EPOLL_CREATE1 1
|
||||
#define CONFIG_EPOLL_PWAIT 1
|
||||
#define CONFIG_INOTIFY 1
|
||||
#define CONFIG_INOTIFY1 1
|
||||
#define CONFIG_BYTESWAP_H 1
|
||||
#define CONFIG_CURL 1
|
||||
#define CONFIG_ATTR 1
|
||||
#define CONFIG_IOVEC 1
|
||||
#define CONFIG_PREADV 1
|
||||
#define CONFIG_SIGNALFD 1
|
||||
#define CONFIG_FDATASYNC 1
|
||||
#define CONFIG_MADVISE 1
|
||||
#define CONFIG_POSIX_MADVISE 1
|
||||
#define CONFIG_SIGEV_THREAD_ID 1
|
||||
#define CONFIG_SMARTCARD 1
|
||||
#define CONFIG_OPENGL 1
|
||||
#define CONFIG_UNAME_RELEASE ""
|
||||
#define CONFIG_ZERO_MALLOC 1
|
||||
#define CONFIG_UCONTEXT_COROUTINE 1
|
||||
#define CONFIG_OPEN_BY_HANDLE 1
|
||||
#define CONFIG_LINUX_MAGIC_H 1
|
||||
#define CONFIG_PRAGMA_DISABLE_UNUSED_BUT_SET 1
|
||||
#define CONFIG_HAS_ENVIRON 1
|
||||
#define CONFIG_TRACE_NOP 1
|
||||
#define CONFIG_TRACE_FILE trace
|
||||
#define CONFIG_TRACE_DEFAULT 1
|
79
tests/qemu/test-i386-code16.S
Normal file
79
tests/qemu/test-i386-code16.S
Normal file
|
@ -0,0 +1,79 @@
|
|||
.code16
|
||||
.globl code16_start
|
||||
.globl code16_end
|
||||
|
||||
CS_SEG = 0xf
|
||||
|
||||
code16_start:
|
||||
|
||||
.globl code16_func1
|
||||
|
||||
/* basic test */
|
||||
code16_func1 = . - code16_start
|
||||
mov $1, %eax
|
||||
data32 lret
|
||||
|
||||
/* test push/pop in 16 bit mode */
|
||||
.globl code16_func2
|
||||
code16_func2 = . - code16_start
|
||||
xor %eax, %eax
|
||||
mov $0x12345678, %ebx
|
||||
movl %esp, %ecx
|
||||
push %bx
|
||||
subl %esp, %ecx
|
||||
pop %ax
|
||||
data32 lret
|
||||
|
||||
/* test various jmp opcodes */
|
||||
.globl code16_func3
|
||||
code16_func3 = . - code16_start
|
||||
jmp 1f
|
||||
nop
|
||||
1:
|
||||
mov $4, %eax
|
||||
mov $0x12345678, %ebx
|
||||
xor %bx, %bx
|
||||
jz 2f
|
||||
add $2, %ax
|
||||
2:
|
||||
|
||||
call myfunc
|
||||
|
||||
lcall $CS_SEG, $(myfunc2 - code16_start)
|
||||
|
||||
ljmp $CS_SEG, $(myjmp1 - code16_start)
|
||||
myjmp1_next:
|
||||
|
||||
cs lcall *myfunc2_addr - code16_start
|
||||
|
||||
cs ljmp *myjmp2_addr - code16_start
|
||||
myjmp2_next:
|
||||
|
||||
data32 lret
|
||||
|
||||
myfunc2_addr:
|
||||
.short myfunc2 - code16_start
|
||||
.short CS_SEG
|
||||
|
||||
myjmp2_addr:
|
||||
.short myjmp2 - code16_start
|
||||
.short CS_SEG
|
||||
|
||||
myjmp1:
|
||||
add $8, %ax
|
||||
jmp myjmp1_next
|
||||
|
||||
myjmp2:
|
||||
add $16, %ax
|
||||
jmp myjmp2_next
|
||||
|
||||
myfunc:
|
||||
add $1, %ax
|
||||
ret
|
||||
|
||||
myfunc2:
|
||||
add $4, %ax
|
||||
lret
|
||||
|
||||
|
||||
code16_end:
|
76
tests/qemu/test-i386-muldiv.h
Normal file
76
tests/qemu/test-i386-muldiv.h
Normal file
|
@ -0,0 +1,76 @@
|
|||
|
||||
void glue(glue(test_, OP), b)(long op0, long op1)
|
||||
{
|
||||
long res, s1, s0, flags;
|
||||
s0 = op0;
|
||||
s1 = op1;
|
||||
res = s0;
|
||||
flags = 0;
|
||||
asm ("push %4\n\t"
|
||||
"popf\n\t"
|
||||
stringify(OP)"b %b2\n\t"
|
||||
"pushf\n\t"
|
||||
"pop %1\n\t"
|
||||
: "=a" (res), "=g" (flags)
|
||||
: "q" (s1), "0" (res), "1" (flags));
|
||||
printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CC=%04lx\n",
|
||||
stringify(OP) "b", s0, s1, res, flags & CC_MASK);
|
||||
}
|
||||
|
||||
void glue(glue(test_, OP), w)(long op0h, long op0, long op1)
|
||||
{
|
||||
long res, s1, flags, resh;
|
||||
s1 = op1;
|
||||
resh = op0h;
|
||||
res = op0;
|
||||
flags = 0;
|
||||
asm ("push %5\n\t"
|
||||
"popf\n\t"
|
||||
stringify(OP) "w %w3\n\t"
|
||||
"pushf\n\t"
|
||||
"pop %1\n\t"
|
||||
: "=a" (res), "=g" (flags), "=d" (resh)
|
||||
: "q" (s1), "0" (res), "1" (flags), "2" (resh));
|
||||
printf("%-10s AH=" FMTLX " AL=" FMTLX " B=" FMTLX " RH=" FMTLX " RL=" FMTLX " CC=%04lx\n",
|
||||
stringify(OP) "w", op0h, op0, s1, resh, res, flags & CC_MASK);
|
||||
}
|
||||
|
||||
void glue(glue(test_, OP), l)(long op0h, long op0, long op1)
|
||||
{
|
||||
long res, s1, flags, resh;
|
||||
s1 = op1;
|
||||
resh = op0h;
|
||||
res = op0;
|
||||
flags = 0;
|
||||
asm ("push %5\n\t"
|
||||
"popf\n\t"
|
||||
stringify(OP) "l %k3\n\t"
|
||||
"pushf\n\t"
|
||||
"pop %1\n\t"
|
||||
: "=a" (res), "=g" (flags), "=d" (resh)
|
||||
: "q" (s1), "0" (res), "1" (flags), "2" (resh));
|
||||
printf("%-10s AH=" FMTLX " AL=" FMTLX " B=" FMTLX " RH=" FMTLX " RL=" FMTLX " CC=%04lx\n",
|
||||
stringify(OP) "l", op0h, op0, s1, resh, res, flags & CC_MASK);
|
||||
}
|
||||
|
||||
#if defined(__x86_64__)
|
||||
void glue(glue(test_, OP), q)(long op0h, long op0, long op1)
|
||||
{
|
||||
long res, s1, flags, resh;
|
||||
s1 = op1;
|
||||
resh = op0h;
|
||||
res = op0;
|
||||
flags = 0;
|
||||
asm ("push %5\n\t"
|
||||
"popf\n\t"
|
||||
stringify(OP) "q %3\n\t"
|
||||
"pushf\n\t"
|
||||
"pop %1\n\t"
|
||||
: "=a" (res), "=g" (flags), "=d" (resh)
|
||||
: "q" (s1), "0" (res), "1" (flags), "2" (resh));
|
||||
printf("%-10s AH=" FMTLX " AL=" FMTLX " B=" FMTLX " RH=" FMTLX " RL=" FMTLX " CC=%04lx\n",
|
||||
stringify(OP) "q", op0h, op0, s1, resh, res, flags & CC_MASK);
|
||||
}
|
||||
#endif
|
||||
|
||||
#undef OP
|
185
tests/qemu/test-i386-shift.h
Normal file
185
tests/qemu/test-i386-shift.h
Normal file
|
@ -0,0 +1,185 @@
|
|||
|
||||
#define exec_op glue(exec_, OP)
|
||||
#define exec_opq glue(glue(exec_, OP), q)
|
||||
#define exec_opl glue(glue(exec_, OP), l)
|
||||
#define exec_opw glue(glue(exec_, OP), w)
|
||||
#define exec_opb glue(glue(exec_, OP), b)
|
||||
|
||||
#ifndef OP_SHIFTD
|
||||
|
||||
#ifdef OP_NOBYTE
|
||||
#define EXECSHIFT(size, rsize, res, s1, s2, flags) \
|
||||
asm ("push %4\n\t"\
|
||||
"popf\n\t"\
|
||||
stringify(OP) size " %" rsize "2, %" rsize "0\n\t" \
|
||||
"pushf\n\t"\
|
||||
"pop %1\n\t"\
|
||||
: "=g" (res), "=g" (flags)\
|
||||
: "r" (s1), "0" (res), "1" (flags));
|
||||
#else
|
||||
#define EXECSHIFT(size, rsize, res, s1, s2, flags) \
|
||||
asm ("push %4\n\t"\
|
||||
"popf\n\t"\
|
||||
stringify(OP) size " %%cl, %" rsize "0\n\t" \
|
||||
"pushf\n\t"\
|
||||
"pop %1\n\t"\
|
||||
: "=q" (res), "=g" (flags)\
|
||||
: "c" (s1), "0" (res), "1" (flags));
|
||||
#endif
|
||||
|
||||
#if defined(__x86_64__)
|
||||
void exec_opq(long s2, long s0, long s1, long iflags)
|
||||
{
|
||||
long res, flags;
|
||||
res = s0;
|
||||
flags = iflags;
|
||||
EXECSHIFT("q", "", res, s1, s2, flags);
|
||||
/* overflow is undefined if count != 1 */
|
||||
if (s1 != 1)
|
||||
flags &= ~CC_O;
|
||||
printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CCIN=%04lx CC=%04lx\n",
|
||||
stringify(OP) "q", s0, s1, res, iflags, flags & CC_MASK);
|
||||
}
|
||||
#endif
|
||||
|
||||
void exec_opl(long s2, long s0, long s1, long iflags)
|
||||
{
|
||||
long res, flags;
|
||||
res = s0;
|
||||
flags = iflags;
|
||||
EXECSHIFT("l", "k", res, s1, s2, flags);
|
||||
/* overflow is undefined if count != 1 */
|
||||
if (s1 != 1)
|
||||
flags &= ~CC_O;
|
||||
printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CCIN=%04lx CC=%04lx\n",
|
||||
stringify(OP) "l", s0, s1, res, iflags, flags & CC_MASK);
|
||||
}
|
||||
|
||||
void exec_opw(long s2, long s0, long s1, long iflags)
|
||||
{
|
||||
long res, flags;
|
||||
res = s0;
|
||||
flags = iflags;
|
||||
EXECSHIFT("w", "w", res, s1, s2, flags);
|
||||
/* overflow is undefined if count != 1 */
|
||||
if (s1 != 1)
|
||||
flags &= ~CC_O;
|
||||
printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CCIN=%04lx CC=%04lx\n",
|
||||
stringify(OP) "w", s0, s1, res, iflags, flags & CC_MASK);
|
||||
}
|
||||
|
||||
#else
|
||||
#define EXECSHIFT(size, rsize, res, s1, s2, flags) \
|
||||
asm ("push %4\n\t"\
|
||||
"popf\n\t"\
|
||||
stringify(OP) size " %%cl, %" rsize "5, %" rsize "0\n\t" \
|
||||
"pushf\n\t"\
|
||||
"pop %1\n\t"\
|
||||
: "=g" (res), "=g" (flags)\
|
||||
: "c" (s1), "0" (res), "1" (flags), "r" (s2));
|
||||
|
||||
#if defined(__x86_64__)
|
||||
void exec_opq(long s2, long s0, long s1, long iflags)
|
||||
{
|
||||
long res, flags;
|
||||
res = s0;
|
||||
flags = iflags;
|
||||
EXECSHIFT("q", "", res, s1, s2, flags);
|
||||
/* overflow is undefined if count != 1 */
|
||||
if (s1 != 1)
|
||||
flags &= ~CC_O;
|
||||
printf("%-10s A=" FMTLX " B=" FMTLX " C=" FMTLX " R=" FMTLX " CCIN=%04lx CC=%04lx\n",
|
||||
stringify(OP) "q", s0, s2, s1, res, iflags, flags & CC_MASK);
|
||||
}
|
||||
#endif
|
||||
|
||||
void exec_opl(long s2, long s0, long s1, long iflags)
|
||||
{
|
||||
long res, flags;
|
||||
res = s0;
|
||||
flags = iflags;
|
||||
EXECSHIFT("l", "k", res, s1, s2, flags);
|
||||
/* overflow is undefined if count != 1 */
|
||||
if (s1 != 1)
|
||||
flags &= ~CC_O;
|
||||
printf("%-10s A=" FMTLX " B=" FMTLX " C=" FMTLX " R=" FMTLX " CCIN=%04lx CC=%04lx\n",
|
||||
stringify(OP) "l", s0, s2, s1, res, iflags, flags & CC_MASK);
|
||||
}
|
||||
|
||||
void exec_opw(long s2, long s0, long s1, long iflags)
|
||||
{
|
||||
long res, flags;
|
||||
res = s0;
|
||||
flags = iflags;
|
||||
EXECSHIFT("w", "w", res, s1, s2, flags);
|
||||
/* overflow is undefined if count != 1 */
|
||||
if (s1 != 1)
|
||||
flags &= ~CC_O;
|
||||
printf("%-10s A=" FMTLX " B=" FMTLX " C=" FMTLX " R=" FMTLX " CCIN=%04lx CC=%04lx\n",
|
||||
stringify(OP) "w", s0, s2, s1, res, iflags, flags & CC_MASK);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef OP_NOBYTE
|
||||
void exec_opb(long s0, long s1, long iflags)
|
||||
{
|
||||
long res, flags;
|
||||
res = s0;
|
||||
flags = iflags;
|
||||
EXECSHIFT("b", "b", res, s1, 0, flags);
|
||||
/* overflow is undefined if count != 1 */
|
||||
if (s1 != 1)
|
||||
flags &= ~CC_O;
|
||||
printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CCIN=%04lx CC=%04lx\n",
|
||||
stringify(OP) "b", s0, s1, res, iflags, flags & CC_MASK);
|
||||
}
|
||||
#endif
|
||||
|
||||
void exec_op(long s2, long s0, long s1)
|
||||
{
|
||||
s2 = i2l(s2);
|
||||
s0 = i2l(s0);
|
||||
#if defined(__x86_64__)
|
||||
exec_opq(s2, s0, s1, 0);
|
||||
#endif
|
||||
exec_opl(s2, s0, s1, 0);
|
||||
#ifdef OP_SHIFTD
|
||||
exec_opw(s2, s0, s1, 0);
|
||||
#else
|
||||
exec_opw(s2, s0, s1, 0);
|
||||
#endif
|
||||
#ifndef OP_NOBYTE
|
||||
exec_opb(s0, s1, 0);
|
||||
#endif
|
||||
#ifdef OP_CC
|
||||
#if defined(__x86_64__)
|
||||
exec_opq(s2, s0, s1, CC_C);
|
||||
#endif
|
||||
exec_opl(s2, s0, s1, CC_C);
|
||||
exec_opw(s2, s0, s1, CC_C);
|
||||
exec_opb(s0, s1, CC_C);
|
||||
#endif
|
||||
}
|
||||
|
||||
void glue(test_, OP)(void)
|
||||
{
|
||||
int i, n;
|
||||
#if defined(__x86_64__)
|
||||
n = 64;
|
||||
#else
|
||||
n = 32;
|
||||
#endif
|
||||
for(i = 0; i < n; i++)
|
||||
exec_op(0x21ad3d34, 0x12345678, i);
|
||||
for(i = 0; i < n; i++)
|
||||
exec_op(0x813f3421, 0x82345679, i);
|
||||
}
|
||||
|
||||
void *glue(_test_, OP) __init_call = glue(test_, OP);
|
||||
|
||||
#undef OP
|
||||
#undef OP_CC
|
||||
#undef OP_SHIFTD
|
||||
#undef OP_NOBYTE
|
||||
#undef EXECSHIFT
|
103
tests/qemu/test-i386-vm86.S
Normal file
103
tests/qemu/test-i386-vm86.S
Normal file
|
@ -0,0 +1,103 @@
|
|||
.code16
|
||||
.globl vm86_code_start
|
||||
.globl vm86_code_end
|
||||
|
||||
#define GET_OFFSET(x) ((x) - vm86_code_start + 0x100)
|
||||
|
||||
vm86_code_start:
|
||||
movw $GET_OFFSET(hello_world), %dx
|
||||
movb $0x09, %ah
|
||||
int $0x21
|
||||
|
||||
/* prepare int 0x90 vector */
|
||||
xorw %ax, %ax
|
||||
movw %ax, %es
|
||||
es movw $GET_OFFSET(int90_test), 0x90 * 4
|
||||
es movw %cs, 0x90 * 4 + 2
|
||||
|
||||
/* launch int 0x90 */
|
||||
|
||||
int $0x90
|
||||
|
||||
/* test IF support */
|
||||
movw $GET_OFFSET(IF_msg), %dx
|
||||
movb $0x09, %ah
|
||||
int $0x21
|
||||
|
||||
pushf
|
||||
popw %dx
|
||||
movb $0xff, %ah
|
||||
int $0x21
|
||||
|
||||
cli
|
||||
pushf
|
||||
popw %dx
|
||||
movb $0xff, %ah
|
||||
int $0x21
|
||||
|
||||
sti
|
||||
pushfl
|
||||
popl %edx
|
||||
movb $0xff, %ah
|
||||
int $0x21
|
||||
|
||||
#if 0
|
||||
movw $GET_OFFSET(IF_msg1), %dx
|
||||
movb $0x09, %ah
|
||||
int $0x21
|
||||
|
||||
pushf
|
||||
movw %sp, %bx
|
||||
andw $~0x200, (%bx)
|
||||
popf
|
||||
#else
|
||||
cli
|
||||
#endif
|
||||
|
||||
pushf
|
||||
popw %dx
|
||||
movb $0xff, %ah
|
||||
int $0x21
|
||||
|
||||
pushfl
|
||||
movw %sp, %bx
|
||||
orw $0x200, (%bx)
|
||||
popfl
|
||||
|
||||
pushfl
|
||||
popl %edx
|
||||
movb $0xff, %ah
|
||||
int $0x21
|
||||
|
||||
movb $0x00, %ah
|
||||
int $0x21
|
||||
|
||||
int90_test:
|
||||
pushf
|
||||
pop %dx
|
||||
movb $0xff, %ah
|
||||
int $0x21
|
||||
|
||||
movw %sp, %bx
|
||||
movw 4(%bx), %dx
|
||||
movb $0xff, %ah
|
||||
int $0x21
|
||||
|
||||
movw $GET_OFFSET(int90_msg), %dx
|
||||
movb $0x09, %ah
|
||||
int $0x21
|
||||
iret
|
||||
|
||||
int90_msg:
|
||||
.string "INT90 started\n$"
|
||||
|
||||
hello_world:
|
||||
.string "Hello VM86 world\n$"
|
||||
|
||||
IF_msg:
|
||||
.string "VM86 IF test\n$"
|
||||
|
||||
IF_msg1:
|
||||
.string "If you see a diff here, your Linux kernel is buggy, please update to 2.4.20 kernel\n$"
|
||||
|
||||
vm86_code_end:
|
2774
tests/qemu/test-i386.c
Normal file
2774
tests/qemu/test-i386.c
Normal file
File diff suppressed because it is too large
Load diff
152
tests/qemu/test-i386.h
Normal file
152
tests/qemu/test-i386.h
Normal file
|
@ -0,0 +1,152 @@
|
|||
|
||||
#define exec_op glue(exec_, OP)
|
||||
#define exec_opq glue(glue(exec_, OP), q)
|
||||
#define exec_opl glue(glue(exec_, OP), l)
|
||||
#define exec_opw glue(glue(exec_, OP), w)
|
||||
#define exec_opb glue(glue(exec_, OP), b)
|
||||
|
||||
#define EXECOP2(size, rsize, res, s1, flags) \
|
||||
asm ("push %4\n\t"\
|
||||
"popf\n\t"\
|
||||
stringify(OP) size " %" rsize "2, %" rsize "0\n\t" \
|
||||
"pushf\n\t"\
|
||||
"pop %1\n\t"\
|
||||
: "=q" (res), "=g" (flags)\
|
||||
: "q" (s1), "0" (res), "1" (flags)); \
|
||||
printf("%-10s A=" FMTLX " B=" FMTLX " R=" FMTLX " CCIN=%04lx CC=%04lx\n", \
|
||||
stringify(OP) size, s0, s1, res, iflags, flags & CC_MASK);
|
||||
|
||||
#define EXECOP1(size, rsize, res, flags) \
|
||||
asm ("push %3\n\t"\
|
||||
"popf\n\t"\
|
||||
stringify(OP) size " %" rsize "0\n\t" \
|
||||
"pushf\n\t"\
|
||||
"pop %1\n\t"\
|
||||
: "=q" (res), "=g" (flags)\
|
||||
: "0" (res), "1" (flags)); \
|
||||
printf("%-10s A=" FMTLX " R=" FMTLX " CCIN=%04lx CC=%04lx\n", \
|
||||
stringify(OP) size, s0, res, iflags, flags & CC_MASK);
|
||||
|
||||
#ifdef OP1
|
||||
#if defined(__x86_64__)
|
||||
void exec_opq(long s0, long s1, long iflags)
|
||||
{
|
||||
long res, flags;
|
||||
res = s0;
|
||||
flags = iflags;
|
||||
EXECOP1("q", "", res, flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
void exec_opl(long s0, long s1, long iflags)
|
||||
{
|
||||
long res, flags;
|
||||
res = s0;
|
||||
flags = iflags;
|
||||
EXECOP1("l", "k", res, flags);
|
||||
}
|
||||
|
||||
void exec_opw(long s0, long s1, long iflags)
|
||||
{
|
||||
long res, flags;
|
||||
res = s0;
|
||||
flags = iflags;
|
||||
EXECOP1("w", "w", res, flags);
|
||||
}
|
||||
|
||||
void exec_opb(long s0, long s1, long iflags)
|
||||
{
|
||||
long res, flags;
|
||||
res = s0;
|
||||
flags = iflags;
|
||||
EXECOP1("b", "b", res, flags);
|
||||
}
|
||||
#else
|
||||
#if defined(__x86_64__)
|
||||
void exec_opq(long s0, long s1, long iflags)
|
||||
{
|
||||
long res, flags;
|
||||
res = s0;
|
||||
flags = iflags;
|
||||
EXECOP2("q", "", res, s1, flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
void exec_opl(long s0, long s1, long iflags)
|
||||
{
|
||||
long res, flags;
|
||||
res = s0;
|
||||
flags = iflags;
|
||||
EXECOP2("l", "k", res, s1, flags);
|
||||
}
|
||||
|
||||
void exec_opw(long s0, long s1, long iflags)
|
||||
{
|
||||
long res, flags;
|
||||
res = s0;
|
||||
flags = iflags;
|
||||
EXECOP2("w", "w", res, s1, flags);
|
||||
}
|
||||
|
||||
void exec_opb(long s0, long s1, long iflags)
|
||||
{
|
||||
long res, flags;
|
||||
res = s0;
|
||||
flags = iflags;
|
||||
EXECOP2("b", "b", res, s1, flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
void exec_op(long s0, long s1)
|
||||
{
|
||||
s0 = i2l(s0);
|
||||
s1 = i2l(s1);
|
||||
#if defined(__x86_64__)
|
||||
exec_opq(s0, s1, 0);
|
||||
#endif
|
||||
exec_opl(s0, s1, 0);
|
||||
exec_opw(s0, s1, 0);
|
||||
exec_opb(s0, s1, 0);
|
||||
#ifdef OP_CC
|
||||
#if defined(__x86_64__)
|
||||
exec_opq(s0, s1, CC_C);
|
||||
#endif
|
||||
exec_opl(s0, s1, CC_C);
|
||||
exec_opw(s0, s1, CC_C);
|
||||
exec_opb(s0, s1, CC_C);
|
||||
#endif
|
||||
}
|
||||
|
||||
void glue(test_, OP)(void)
|
||||
{
|
||||
exec_op(0x12345678, 0x812FADA);
|
||||
exec_op(0x12341, 0x12341);
|
||||
exec_op(0x12341, -0x12341);
|
||||
exec_op(0xffffffff, 0);
|
||||
exec_op(0xffffffff, -1);
|
||||
exec_op(0xffffffff, 1);
|
||||
exec_op(0xffffffff, 2);
|
||||
exec_op(0x7fffffff, 0);
|
||||
exec_op(0x7fffffff, 1);
|
||||
exec_op(0x7fffffff, -1);
|
||||
exec_op(0x80000000, -1);
|
||||
exec_op(0x80000000, 1);
|
||||
exec_op(0x80000000, -2);
|
||||
exec_op(0x12347fff, 0);
|
||||
exec_op(0x12347fff, 1);
|
||||
exec_op(0x12347fff, -1);
|
||||
exec_op(0x12348000, -1);
|
||||
exec_op(0x12348000, 1);
|
||||
exec_op(0x12348000, -2);
|
||||
exec_op(0x12347f7f, 0);
|
||||
exec_op(0x12347f7f, 1);
|
||||
exec_op(0x12347f7f, -1);
|
||||
exec_op(0x12348080, -1);
|
||||
exec_op(0x12348080, 1);
|
||||
exec_op(0x12348080, -2);
|
||||
}
|
||||
|
||||
void *glue(_test_, OP) __init_call = glue(test_, OP);
|
||||
|
||||
#undef OP
|
||||
#undef OP_CC
|
60
v86.css
Normal file
60
v86.css
Normal file
|
@ -0,0 +1,60 @@
|
|||
#log {
|
||||
font-family: DejaVu Sans Mono;
|
||||
font-size: 13px;
|
||||
height: 350px;
|
||||
float: right;
|
||||
width: 400px;
|
||||
border: 0 none;
|
||||
background-color: #111;
|
||||
color: #fff;
|
||||
}
|
||||
#screen {
|
||||
white-space: pre;
|
||||
position: relative;
|
||||
font-family: Liberation Mono, DejaVu Sans Mono, Courier New, monospace;
|
||||
font-weight: bold;
|
||||
font-size: 15px;
|
||||
line-height: 1;
|
||||
float: left;
|
||||
}
|
||||
#screen, #vga {
|
||||
border: 1px solid #555;
|
||||
border-width: 2px 1px;
|
||||
display: none;
|
||||
-webkit-transform-origin: top left;
|
||||
-moz-transform-origin: top left;
|
||||
}
|
||||
#vga {
|
||||
image-rendering: -moz-crisp-edges; // FF 6.0+
|
||||
image-rendering: -webkit-optimize-contrast; // Webkit
|
||||
// (Safari now, Chrome soon)
|
||||
image-rendering: -o-crisp-edges; // OS X & Windows Opera (12.02+)
|
||||
image-rendering: optimize-contrast; // Possible future browsers.
|
||||
-ms-interpolation-mode: nearest-neighbor; // IE
|
||||
}
|
||||
#screen > div > span {
|
||||
height: 15px;
|
||||
}
|
||||
#cursor {
|
||||
position: absolute;
|
||||
background-color: #ccc;
|
||||
width: 7px;
|
||||
display: inline-block;
|
||||
}
|
||||
body {
|
||||
background-color: #111;
|
||||
color: #fff;
|
||||
line-height: 1.5;
|
||||
}
|
||||
#info {
|
||||
font-size: 80%;
|
||||
}
|
||||
a {
|
||||
color: wheat;
|
||||
}
|
||||
.phone_keyboard {
|
||||
background-color: #111;
|
||||
border: 1px solid #555;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
247
v86_all.js
Normal file
247
v86_all.js
Normal file
|
@ -0,0 +1,247 @@
|
|||
'use strict';var ea,oa;function Tb(f){f.origin===dc&&mc()}var mc,dc=location.protocol+"//"+location.hostname;oa=function(f){mc=f;window.removeEventListener("message",Tb,!1);window.addEventListener("message",Tb,!1)};ea=function(){window.postMessage(null,dc)};function nc(f){var t=document.getElementById("log");t.textContent+=f+"\n";t.scrollTop=1E9}
|
||||
function Lc(f,t,D){var C=new XMLHttpRequest;C.open("get",f,!0);C.responseType="arraybuffer";C.onload=function(){C.response&&t(C.response)};D&&(C.onprogress=function(f){D(f)});C.send(null)}function Mc(f){var t=f.requestPointerLock||f.mozRequestPointerLock||f.webkitRequestPointerLock;t&&t.call(f)}
|
||||
function Wc(f){var t=vd("loading");t.style.display="block";f.lengthComputable?(f=f.loaded/f.total*50|0,t.textContent="Loading: "+2*f+"% ["+String.a("#",f)+String.a(" ",50-f)+"]"):t.textContent="Loading ..."}function vd(f){return document.getElementById(f)}
|
||||
function Hd(f){var t=new Vd,D=new Wd;vd("boot_options").parentNode.removeChild(vd("boot_options"));vd("loading").style.display="none";vd("runtime_options").style.display="block";document.getElementsByClassName("phone_keyboard")[0].style.display="block";var C=!0;vd("run").onclick=function(){C?(B+=Date.now()-X,vd("run").value="Run",t.v()):(vd("run").value="Pause",t.m(),X=Date.now());C=!C;vd("run").blur()};var O=document.getElementById("running_time"),L=document.getElementById("speed"),X=Date.now(),
|
||||
B=0,G=0;setInterval(function(){if(C){var f=Date.now();B+=f-X;X=f;L.textContent=(t.i-G)/1E3|0;O.textContent=B/1E3|0;G=t.i}},1E3);vd("reset").onclick=function(){t.q();vd("reset").blur()};vd("get_floppy").onclick=function(){var f=t.a.Aa.buffer;f&&(f.Ba(function(f){f=new Blob([f]);var t;t=document.createElement("a");t.download="floppy.img";t.href=window.URL.createObjectURL(f);t.textContent="Download floppy.img";t.onclick=function(){t.parentNode.removeChild(t)};t.dataset.downloadurl=["application/octet-stream",
|
||||
t.download,t.href].join(":");document.body.appendChild(t)}),vd("get_floppy").blur())};vd("ctrlaltdel").onclick=function(){var f=t.a.Pa;f.G(29);f.G(56);f.G(83);f.G(157);f.G(184);f.G(211);vd("ctrlaltdel").blur()};vd("scale").onchange=function(){var f=parseFloat(this.value);f||0<f?D.a(f,f):this.value="1"};vd("fullscreen").onclick=function(){var f=document.getElementById("screen_container"),t=f.requestFullScreen||f.webkitRequestFullscreen||f.mozRequestFullScreen||f.msRequestFullScreen;t&&(t.call(f),document.getElementsByClassName("phone_keyboard")[0].focus());
|
||||
Mc(f)};f.Ua=D;f.Ha=new Xd;f.La=new Yd;t.w(f);t.m()}
|
||||
window.onload=function(){function f(f,C){if(f.files.length){var O=new FileReader;O.onload=function(f){f=new Zd(f.target.result);switch(C){case "floppy":t.K=f;break;case "hd":t.ja=f;break;case "cdrom":t.X=f}Hd(t)};O.readAsArrayBuffer(f.files[0])}}if("responseType"in new XMLHttpRequest){var t={Ja:!0};vd("lock_mouse").onclick=function(){Mc(document.body);vd("lock_mouse").blur()};Lc("bios/seabios.bin",function(f){t.P=f});Lc("bios/vgabios.bin",function(f){t.ea=f});vd("floppy_image").onchange=function(){f(this,
|
||||
"floppy")};vd("cd_image").onchange=function(){f(this,"cdrom")};vd("hd_image").onchange=function(){f(this,"hd")};vd("start_freedos").onclick=function(){Lc("images/freedos722.img",function(f){t.K=new Zd(f);Hd(t)},Wc);vd("start_freedos").blur()};vd("start_win101").onclick=function(){Lc("images/windows101.img",function(f){t.K=new Zd(f);Hd(t)},Wc);vd("start_win101").blur()};vd("start_linux").onclick=function(){Lc("images/linux.iso",function(f){t.X=new Zd(f);Hd(t)},Wc);vd("start_linux").blur()};vd("start_koli").onclick=
|
||||
function(){Lc("images/kolibri.img",function(f){t.K=new Zd(f);Hd(t)},Wc);vd("start_koli").blur()};vd("start_bsd").onclick=function(){Lc("images/openbsd.img",function(f){t.K=new Zd(f);Hd(t)},Wc);vd("start_bsd").blur()}}else nc("Your browser is not supported because it doesn't have XMLHttpRequest.responseType")};if("complete"===document.readyState)window.onload();function $d(){function f(){return 255}function t(){}for(var D=0,C=[],O=[],L=0;65536>L;L++)C[L]=f,O[L]=t;this.h=function(f,t){C[f]=t};this.g=function(f,t){O[f]=t};this.h(146,function(){return D});this.g(146,function(f){D=f});this.g(128,function(){});this.i=function(f,t){O[f](t)};this.a=function(f){return C[f]()}};function Vd(){function f(){if(oc)oc=ec=!1;else{ec=!0;try{C()}catch(b){if(233495534===b)wa=Nc=!1,ab=-1,Cb=Db,zb(),xa=Db,La(),f();else throw b;}}}function t(){wd.n();Xc.n();D(xd);throw 233495534;}function D(b){"undefined"!==typeof oa&&oa(f);xd=b;bb.memory=k=new be;Yc=new Uint8Array(8);yd=new Uint32Array(8);ae=new Uint32Array(8);da=new Int32Array(8);zd=new Int32Array(1048576);Ad=new Int32Array(1048576);Bd=new Int32Array(1048576);Cd=new Int32Array(1048576);Eb=new Uint8Array(1048576);pc=new Uint8Array(1048576);
|
||||
y=new Uint32Array(8);e=new Int32Array(y.buffer);g=new Uint16Array(y.buffer);Ga=new Int16Array(y.buffer);v=new Uint8Array(y.buffer);fc=new Int8Array(y.buffer);ra=new Uint16Array(8);Ma=!1;Dd=Ed=Zc=$c=qc=ad=rc=bd=0;Nc=!1;ya=Oc=cd=Ub=Na=0;J=!1;Fd=0;Cb=dd=xa=Db=!1;L();La();zb();$=g;aa=8;sc=10;Vb=ed=0;oc=ec=fd=!1;Pc=20;q=Ea=Qc;ab=-1;wa=!1;I=0;u=2;Y=ma=ba=K=0;if(b.P){for(var c=new Uint8Array(b.P),d=1048576-b.P.byteLength,h=0;h<b.P.byteLength;h++)k.m[d+h]=c[h];if(b.ea)for(c=new Uint8Array(b.ea),h=0;h<b.ea.byteLength;h++)k.m[786432+
|
||||
h]=c[h];E=1048560;ca(2,48);g[8]=256}else b.H?(E=65536,k.J(new Uint8Array(b.H.kb),1048576),k.J(new Uint8Array(b.H.ib),E),b.H.root&&(k.J(new Uint8Array(b.H.root),4194304),y[3]=b.H.root.byteLength),k.aa(b.H.ab),y[0]=67108864,y[1]=63488,ca(1,0),ca(2,0),ca(3,0),ca(0,0),ca(5,0),ca(4,0),Ma=dd=xa=Cb=Db=!0,La(),zb(),A=y,aa=4,sc=5,Na=1):(ca(2,48),g[8]=256,E=0);bb.a={};b.Ja&&(c={memory:k,Ta:t},c.j=bb.a.j=Ua=new $d,c.s=Gd=new de(c,ha,Da),c.M=new pe(c),c.xa=new qe(c),bb.a.jb=Xc=new re(c,b.Ua),bb.a.Pa=wd=new se(c,
|
||||
b.Ha,b.La),Ha=new Ce,new te(c),bb.a.Aa=ce=new ue(c,b.K),b.X&&(bb.a.$a=new ve(c,b.X)),b.ja&&(bb.a.gb=new we(c,b.ja,0)),b.Da&&(bb.a.hb=new we(c,b.Da,1)),ee=new xe(c),fe=new ye(c,ce.type))}function C(){var b,c=Date.now();Xc.i();for(var d=Pc;d--;){for(b=20001;b--;){Vb=E;var e=m();Ab[e]();ed++}b=Date.now();ee.a(b);fe.a(b)}bb.i+=20001*Pc;33<b-c?Pc--:Pc++;ea()}function O(){var b=0!==(Na&2147483648);Na=Ha.a?Na&-5:Na|4;b!==J&&(J=b,L())}function L(){var b=J?He:Ie;m=b.na;P=b.oa;U=b.la;M=b.ma;ka=b.ta;Rc=b.ua;
|
||||
Q=b.ra;S=b.sa;Va=b.ha;Id=b.ia;X()}function X(){Fb=-1;J?ya?(q=Wb,Ea=gd):(q=Ia,Ea=hb):Ea=q=Qc}function B(b,c){return k.d(b)|k.d(c)<<8}function G(b,c){var d=k.d(b)|k.d(c)<<24;return d=b&1?b&2?d|k.d(c-2)<<8|k.d(c-1)<<16:d|k.d(b+1)<<8|k.d(b+2)<<16:d|k.d(b+1)<<8|k.d(c-1)<<16}function n(b,c,d){k.e(b,d);k.e(c,d>>8)}function H(b,c,d){k.e(b,d);k.e(c,d>>24);b&1?b&2?(k.e(c-2,d>>8),k.e(c-1,d>>16)):(k.e(b+1,d>>8),k.e(b+2,d>>16)):(k.e(b+1,d>>8),k.e(c-1,d>>16))}function V(b,c){k.e(q(b),c)}function R(b,c){var d=q(b);
|
||||
4095===(b&4095)?n(d,q(b+1),c):k.a(d,c)}function N(b,c){var d=q(b);4093<=(b&4095)?H(d,q(b+3),c):k.f(d,c)}function F(){return Cb?h(3)+M():h(3)+U()}function na(){u=u&-2262|Ba()|ge()|Sc()|Gb()|hd()|Tc();K=0}function sa(b){return dd?da[2]+$[aa]+b:da[2]+($[aa]+b&65535)}function pa(){return E-da[1]}function ha(b,c,d){fd&&(E++,fd=!1);if(Ma){if((b<<3|7)>bd)throw ze("#GP handler");var g=rc+(b<<3)|0;J&&(g=hb(g));var h=k.b(g)|k.b(g+6)<<16,l=k.b(g+2),g=k.d(g+5),m=g>>5&3;if(0===(g&128))throw ze("#NP handler");
|
||||
c&&m<ya&&fa(b<<3|2);g&=31;if(14===g)b=!1;else if(15===g)b=!0;else{if(5===g)throw ze("call int to task gate");if(6===g)throw ze("16 bit interrupt gate");if(7===g)throw ze("16 bit trap gate");throw ze("#GP handler");}c=Bb(l);if(c.A)throw ze("#GP handler");if(-1===c)throw ze("#GP handler");if(!c.F||c.l>ya)throw ze("#GP handler");if(!c.B)throw ze("#NP handler");if(u&131072)throw ze("VM flag");if(!c.C&&c.l<ya){m=(c.l<<3)+4;if(m+5>Ed)throw ze("#TS handler");m+=Dd;J&&(m=hb(m));var g=k.c(m),m=k.b(m+4),q=
|
||||
Bb(m);if(q.A)throw ze("#TS handler");if(q.t!==c.l)throw ze("#TS handler");if(q.l!==c.l||!q.ca)throw ze("#TS handler");if(!q.B)throw ze("#TS handler");var q=e[4],p=ra[2];y[4]=g;ra[2]=m;ya=c.l;X();ia(p);ia(q)}na();ia(u);ia(ra[1]);ia(pa());!1!==d&&ia(d);ra[1]=l;E=da[1]+h|0;b?Da():u&=-513}else na(),la(u),la(ra[1]),la(pa()),u&=-513,ca(1,k.b((b<<2)+2)),E=da[1]+k.b(b<<2)|0}function za(b){ha(b,!1,!1);throw 233495534;}function qa(){E=Vb;za(0)}function z(){E=Vb;za(6)}function fa(b){E=Vb;ha(13,!1,b);throw 233495534;
|
||||
}function ja(b){ab=b;Ab[m()]();ab=-1}function h(b){return-1===ab?da[b]:da[ab]}function Ca(b,c){K&=-65;if((b&3)<(g[c]&3))return u|=64,b&-4|g[c]&3;u&=-65;return b}function Da(){Gd&&u&512&&!Nc&&Gd.a()}function Fa(b,c){$a()?Ua.i(b,c):fa(0)}function Xb(b,c){$a()?(Ua.i(b,c&255),Ua.i(b+1,c>>8&255)):fa(0)}function gc(b,c){$a()?(Ua.i(b,c&255),Ua.i(b+1,c>>8&255),Ua.i(b+2,c>>16&255),Ua.i(b+3,c>>24&255)):fa(0)}function hc(b){if($a())return Ua.a(b);fa(0)}function ic(b){if($a())return Ua.a(b)|Ua.a(b+1)<<8;fa(0)}
|
||||
function cb(b){if($a())return Ua.a(b)|Ua.a(b+1)<<8|Ua.a(b+2)<<16|Ua.a(b+3)<<24;fa(0)}function $a(){return!Ma||ya<=(u>>12&3)}function jc(b){u=0!==ya&&Ma?ya<=(u>>12&3)?b&-12289|u&12288:b&-12801|u&12800:b;K=0}function La(){xa?(Ab=s,Jd=w):(Ab=r,Jd=x)}function zb(){Cb?(l=he,A=y,ga=1,W=6,T=7):(l=ie,A=g,ga=2,W=12,T=14)}function Bb(b){var c=0===(b&4),d=b&-8,e;b={t:b&3,ga:c,A:!1,$:!0};c?(c=qc,e=ad):(c=Zc,e=$c);if(0===d)return b.A=!0,b;if(d>>3>e)return b.$=!1,b;c+=d;J&&(c=hb(c));b.W=k.b(c+2)|k.d(c+4)<<16|k.d(c+
|
||||
7)<<24;b.u=k.d(c+5);b.fa=k.d(c+6)>>4;b.V=k.b(c)|(k.d(c+6)&15)<<16;b.type=b.u&15;b.l=b.u>>5&3;b.L=0===(b.u&16);b.B=128===(b.u&128);b.F=8===(b.u&8);b.ca=2===(b.u&2);b.C=4===(b.u&4);b.size=4===(b.fa&4);b.fb=8===(b.fa&8);b.Sa=b.eb?(b.V<<12|4095)>>>0:b.V;b.Fa=b.ca&&!b.F;b.Ea=b.ca||!b.F;return b}function ca(b,c){1===b&&(Ma=1===(Na&1));if(Ma){var d=Bb(c);if(2===b){if(d.A){fa(0);return}if(!d.$||d.L||d.t!==ya||!d.Fa||d.l!==ya){fa(c&-4);return}if(!d.B)throw E=Vb,ha(12,!1,c&-4),233495534;(dd=d.size)?($=e,aa=
|
||||
4,sc=5):($=g,aa=8,sc=10)}else if(1===b){if(!d.F)throw ze("#GP handler");if(d.L)throw ze("load system segment descriptor, type = "+(d.u&15));if(d.C&&d.l!==d.t)throw ze("#GP handler");if(d.t!==ya)throw ze("privilege change");if(!d.C&&d.l<ya)throw ze("inter privilege interrupt");if(!d.C&&d.l!==ya)throw ze("#GP handler");xa=Cb=Db=d.size;La();zb()}else{if(d.A){ra[b]=c;Yc[b]=1;return}if(!d.$||d.L||!d.Ea||(!d.F||!d.C)&&d.t>d.l&&ya>d.l){fa(c&-4);return}if(!d.B)throw E=Vb,ha(11,!1,c&-4),233495534;}Yc[b]=0;
|
||||
yd[b]=d.Sa;ae[b]=0;da[b]=d.W;ra[b]=c}else ra[b]=c,Yc[b]=0,yd[b]=1048575,da[b]=c<<4}function tc(){Fb=-1;Eb.set(pc)}function Qc(b){return b}function Wb(b){var c=b>>>12;return Eb[c]&8?Ad[c]^b:db(b,1,1)|b&4095}function gd(b){var c=b>>>12;return Eb[c]&4?zd[c]^b:db(b,0,1)|b&4095}function Ia(b){var c=b>>>12;return Eb[c]&2?Cd[c]^b:db(b,1,0)|b&4095}function hb(b){var c=b>>>12;return Eb[c]&1?Bd[c]^b:db(b,0,0)|b&4095}function db(b,c,d){var e=b>>>12,g=(cd>>>2)+(e>>10),h=k.i[g],l=!0,m=!0,q=!0;h&1||(Ub=b,ib(c,
|
||||
d,0));0===(h&2)&&(l=!1,c&&(Ub=b,ib(c,d,1)));0===(h&4)&&(q=!1,d&&(Ub=b,ib(c,d,1)));0===(h&16)&&(m=!1);if(h&Fd)k.i[g]=h|32|c<<6,b=h&4290772992|e<<12&4190208,h=h&256;else{var u=((h&4294963200)>>>2)+(e&1023),p=k.i[u];p&1||(Ub=b,ib(c,d,0));0===(p&2)&&(l=!1,c&&(Ub=b,ib(c,d,1)));0===(p&4)&&(q=!1,d&&(Ub=b,ib(c,d,1)));0===(p&16)&&(m=!1);k.i[g]=h|32;k.i[u]=p|32|c<<6;b=p&4294963200;h=p&256}m&&(m=b^e<<12,p=0,q&&(zd[e]=m,p|=4,l&&(Ad[e]=m,p|=8)),Bd[e]=m,p|=1,l&&(Cd[e]=m,p|=2),Eb[e]|=p,h&&(pc[e]=p));return b}function ib(b,
|
||||
c,d){if(Nc)throw ze("Double fault");E=Vb;Nc=!0;ha(14,!1,c<<2|b<<1|d);throw 233495534;}function Z(b,c){var d=b&65535,e=c&65535;return d*e+d*(c&-65536)+(b&-65536)*e}function kc(b,c){ba=b;ma=c;I=ba+c|0;Y=8;K=2261;return I}function eb(b,c){ba=b;ma=c;I=ba+c|0;Y=16;K=2261;return I}function fb(b,c){ba=b;ma=c;I=ba+c;Y=32;K=2261;return I}function uc(b,c){ba=b;ma=c;I=ba+ma+Ba()|0;Y=8;K=2261;return I}function jb(b,c){ba=b;ma=c;I=ba+ma+Ba()|0;Y=16;K=2261;return I}function kb(b,c){ba=b;ma=c;I=ba+ma+Ba();Y=32;
|
||||
K=2261;return I}function lc(b,c){ba=b;ma=~c;I=ba-c;Y=8;K=2261}function Yb(b,c){ba=b;ma=~c;I=ba-c;Y=16;K=2261}function Zb(b,c){ba=b;ma=-c-1;I=ba-c;Y=32;K=2261}function vc(b,c){ba=b;ma=~c;I=ba-c|0;Y=8;K=2261;return I}function lb(b,c){ba=b;ma=~c;I=ba-c|0;Y=16;K=2261;return I}function mb(b,c){ba=b;ma=-c-1;I=ba-c;Y=32;K=2261;return I}function wc(b,c){ba=b;ma=~c;I=ba-c-Ba()|0;Y=8;K=2261;return I}function nb(b,c){ba=b;ma=~c;I=ba-c-Ba()|0;Y=16;K=2261;return I}function ob(b,c){ba=b;ma=-c-1;I=ba-c-Ba();Y=32;
|
||||
K=2261;return I}function je(b){u=u&-2|Ba();ba=b;ma=1;I=ba+1|0;Y=8;K=2260;return I}function pb(b){u=u&-2|Ba();ba=b;ma=1;I=ba+1|0;Y=16;K=2260;return I}function qb(b){u=u&-2|Ba();ba=b;ma=1;I=ba+1;Y=32;K=2260;return I}function ke(b){u=u&-2|Ba();ba=b;ma=-1;I=ba-1|0;Y=8;K=2260;return I}function rb(b){u=u&-2|Ba();ba=b;ma=-1;I=ba-1|0;Y=16;K=2260;return I}function sb(b){u=u&-2|Ba();ba=b;ma=-1;I=ba-1;Y=32;K=2260;return I}function le(b){I=-b;K=2261;Y=8;ba=0;ma=I-1;return I}function Kd(b){I=-b;K=2261;Y=16;ba=
|
||||
0;ma=I-1;return I}function Ld(b){I=-b;K=2261;Y=32;ba=0;ma=I-1;return I}function Md(b,c){var d=b*c;u=32767<d||-32768>d?u|2049:u&-2050;K=0;return d}function Nd(b,c){var d=Z(b,c);u=0===(b*c/4294967296|0)?u&-2050:u|2049;K=0;return d}function me(b,c){var d=v[c];v[c]=b;return kc(b,d)}function Od(b,c){var d=g[c];g[c]=b;return eb(b,d)}function Pd(b,c){var d=y[c];y[c]=b;return fb(b,d)}function xc(b,c){I=b&c;Y=8;u&=-2066;K=196;return I}function tb(b,c){I=b&c;Y=16;u&=-2066;K=196;return I}function ub(b,c){I=
|
||||
b&c;Y=32;u&=-2066;K=196;return I}function id(b,c){I=b&c;Y=8;u&=-2066;K=196}function jd(b,c){I=b&c;Y=16;u&=-2050;K=196}function kd(b,c){I=b&c;Y=32;u&=-2066;K=196}function yc(b,c){I=b|c;Y=8;u&=-2066;K=196;return I}function vb(b,c){I=b|c;Y=16;u&=-2066;K=196;return I}function wb(b,c){I=b|c;Y=32;u&=-2066;K=196;return I}function zc(b,c){I=b^c;Y=8;u&=-2066;K=196;return I}function xb(b,c){I=b^c;Y=16;u&=-2066;K=196;return I}function yb(b,c){I=b^c;Y=32;u&=-2066;K=196;return I}function Ac(b,c){if(!c)return b;
|
||||
c&=7;var d=b<<c|b>>8-c;K&=-2050;u=u&-2050|d&1|(d<<11^d<<4)&2048;return d}function Hb(b,c){if(!c)return b;c&=15;var d=b<<c|b>>16-c;K&=-2050;u=u&-2050|d&1|(d<<11^d>>4)&2048;return d}function Ib(b,c){if(!c)return b;var d=b<<c|b>>>32-c;K&=-2050;u=u&-2050|d&1|(d<<11^d>>20)&2048;return d}function Bc(b,c){c%=9;if(!c)return b;var d=b<<c|Ba()<<c-1|b>>9-c;K&=-2050;u=u&-2050|d>>8&1|(d<<3^d<<4)&2048;return d}function Jb(b,c){c%=17;if(!c)return b;var d=b<<c|Ba()<<c-1|b>>17-c;K&=-2050;u=u&-2050|d>>16&1|(d>>5^d>>
|
||||
4)&2048;return d}function Kb(b,c){if(!c)return b;var d=b<<c|Ba()<<c-1;1<c&&(d|=b>>>33-c);K&=-2050;u=u&-2050|b>>>32-c&1;u|=(u<<11^d>>20)&2048;return d}function Cc(b,c){c&=7;if(!c)return b;var d=b>>c|b<<8-c;K&=-2050;u=u&-2050|d>>7&1|(d<<4^d<<5)&2048;return d}function Lb(b,c){c&=15;if(!c)return b;var d=b>>c|b<<16-c;K&=-2050;u=u&-2050|d>>15&1|(d>>4^d>>3)&2048;return d}function Mb(b,c){if(!c)return b;var d=b>>>c|b<<32-c;K&=-2050;u=u&-2050|d>>31&1|(d>>20^d>>19)&2048;return d}function Dc(b,c){c%=9;if(!c)return b;
|
||||
var d=b>>c|Ba()<<8-c|b<<9-c;K&=-2050;u=u&-2050|d>>8&1|(d<<4^d<<5)&2048;return d}function Nb(b,c){c%=17;if(!c)return b;var d=b>>c|Ba()<<16-c|b<<17-c;K&=-2050;u=u&-2050|d>>16&1|(d>>4^d>>3)&2048;return d}function Ob(b,c){if(!c)return b;var d=b>>>c|Ba()<<32-c;1<c&&(d|=b<<33-c);K&=-2050;u=u&-2050|b>>c-1&1|(d>>20^d>>19)&2048;return d}function gb(b,c){if(0===c)return b;I=b<<c;Y=8;K=212;u=u&-2050|I>>8&1|(I<<3^I<<4)&2048;return I}function Ja(b,c){if(0===c)return b;I=b<<c;Y=16;K=212;u=u&-2050|I>>16&1|(I>>5^
|
||||
I>>4)&2048;return I}function Ka(b,c){if(0===c)return b;I=b<<c;Y=32;K=212;u=u&-2050|b>>>32-c&1;u|=(u&1^I>>31&1)<<11&2048;return I}function Ec(b,c){if(0===c)return b;I=b>>c;Y=8;K=212;u=u&-2050|b>>c-1&1|(b>>7&1)<<11&2048;return I}function Pb(b,c){if(0===c)return b;I=b>>c;Y=16;K=212;u=u&-2050|b>>c-1&1|b>>4&2048;return I}function Qb(b,c){if(0===c)return b;I=b>>>c;Y=32;K=212;u=u&-2050|b>>>c-1&1|b>>20&2048;return I}function Fc(b,c){if(0===c)return b;I=b>>c;Y=8;K=212;u=u&-2050|b>>c-1&1;return I}function Rb(b,
|
||||
c){if(0===c)return b;I=b>>c;Y=16;K=212;u=u&-2050|b>>c-1&1;return I}function Sb(b,c){if(0===c)return b;I=b>>c;Y=32;K=212;u=u&-2050|b>>>c-1&1;return I}function Gc(b,c,d){if(0===d)return b;16>=d?(I=b>>d|c<<16-d,u=u&-2|b>>d-1&1):(I=b<<32-d|c>>d-16,u=u&-2|c>>d-17&1);Y=16;K=212;u=u&-2049|(I^b)>>4&2048;return I}function Hc(b,c,d){if(0===d)return b;I=b>>>d|c<<32-d;Y=32;K=212;u=u&-2|b>>>d-1&1;u=u&-2049|(I^b)>>20&2048;return I}function Ic(b,c,d){if(0===d)return b;16>=d?(I=b<<d|c>>>16-d,u=u&-2|b>>>16-d&1):(I=
|
||||
b>>32-d|c<<d-16,u=u&-2|c>>>32-d&1);Y=16;K=212;u=u&-2049|(u&1^I>>15&1)<<11;return I}function Jc(b,c,d){if(0===d)return b;I=b<<d|c>>>32-d;Y=32;K=212;u=u&-2|b>>>32-d&1;u=u&-2049|(u&1^I>>31&1)<<11;return I}function ld(b,c){u=u&-2|b>>c&1;K=0}function md(b,c){u=u&-2|b>>c&1;K=0;return b^1<<c}function nd(b,c){u=u&-2|b>>c&1;K=0;return b|1<<c}function od(b,c){u=u&-2|b>>c&1;K=0;return b&~(1<<c)}function pd(b,c){var d=ka(b+(c>>3));u=u&-2|d>>(c&7)&1;K=0}function qd(b,c){var d=q(b+(c>>3)),e=k.d(d);c&=7;u=u&-2|
|
||||
e>>c&1;K=0;k.e(d,e^1<<c)}function rd(b,c){var d=q(b+(c>>3)),e=k.d(d);c&=7;u=u&-2|e>>c&1;K=0;k.e(d,e&~(1<<c))}function sd(b,c){var d=q(b+(c>>3)),e=k.d(d);c&=7;u=u&-2|e>>c&1;K=0;k.e(d,e|1<<c)}function Qd(b){var c=da[1];E-=c;E=E+b&65535;E=E+c|0}function Oa(b){b?Qd(U()):E+=2}function Pa(b){b?(b=M(),E=E+b|0):E=E+4|0}function Qa(){return Ba()||Gb()}function Wa(){return!hd()!==!Tc()}function Xa(){return Gb()||!hd()!==!Tc()}function Ba(){return K&1?32===Y?4294967295<I|0>I:I>>Y&1:u&1}function ge(){return K&
|
||||
4?154020>>((I^I>>4)&15)&4:u&4}function Sc(){return K&16?(ba^ma^I^(0>ma)<<4)&16:u&16}function Gb(){return K&64?(~I&I-1)>>Y-7&64:u&64}function hd(){return K&128?I>>Y-8&128:u&128}function Tc(){return K&2048?((ba^I)&(ma^I))>>Y-1<<11&2048:u&2048}function la(b){var c=Id(-2);$[aa]-=2;k.a(c,b)}function ia(b){var c=Id(-4);$[aa]-=4;k.f(c,b)}function Aa(){var b=Va(0);$[aa]+=2;return k.b(b)}function ua(){var b=Va(0);$[aa]+=4;return k.c(b)}function ne(b,c){var d=c>>1&12|c>>5&1,e=v[d];v[d]=b;return e}function Rd(b,
|
||||
c){var d=c>>2&14,e=g[d];g[d]=b;return e}function $b(b){var c=g[0];g[0]=g[b];g[b]=c}function Sd(b,c){var d=c>>3&7,g=e[d];y[d]=b;return g}function ac(b){var c=e[0];y[0]=e[b];y[b]=c}function Uc(b,c,d){var e=Q(c);c=Q(c+2);ca(b,c);g[d]=e}function Vc(b,c,d){var e=S(c);c=Q(c+4);ca(b,c);y[d]=e}function bc(b){var c=e[b];y[b]=c>>>24|c<<24|c>>8&65280|c<<8&16711680}function Ce(){function b(b){var c=r();Z&=-18177;c>b||(Z=b>c?Z|256:c===b?Z|16384:Z|17664)}function c(b){var c=n[F];K&=-70;u&=-70;c>b||(u=b>c?u|1:c===
|
||||
b?u|64:u|69)}function d(){J=895;M=sa=L=Z=0;E=255;F=0}function e(b){if(xa){R(b,J);R(b+4,Z&-14337|F<<11);for(var c=0,d,g=0;8>g;g++)if(d=n[g],E>>g&1)c|=3<<(g<<1);else if(0===d)c|=1<<(g<<1);else if(isNaN(d)||Infinity===d||-Infinity===d)c|=2<<(g<<1);R(b+8,c);N(b+12,L);R(b+16,V);R(b+18,M);N(b+20,sa);R(b+24,P)}else z()}function k(b){if(xa){J=Q(b);var c=Q(b+4);Z=c&-14337;F=c>>11&7;for(var c=Q(b+8),d=E=0;8>d;d++)E|=c>>d&c>>d+1&1<<d;L=S(b+12)>>>0;V=Q(b+16);M=Q(b+18);sa=S(b+20)>>>0;P=Q(b+24)}else z()}function h(b){var c=
|
||||
J>>10&3;return 0===c?(c=Math.round(b),0.5===c-b&&c&1&&c--,c):1===c||3===c&&0<b?Math.floor(b):Math.ceil(b)}function l(b){return 0<b?Math.floor(b):Math.ceil(b)}function m(b){F=F-1&7;E>>F&1?(Z&=-513,E&=~(1<<F),n[F]=b):(Z|=512,Z=Z|t|A,n[F]=NaN)}function p(){E|=1<<F;F=F+1&7}function s(b){b=b+F&7;return E>>b&1?(Z&=-513,Z=Z|t|A,NaN):n[b]}function r(){return E>>F&1?(Z&=-513,Z=Z|t|A,NaN):n[F]}function v(b){var c=Q(b+8),d=S(b)>>>0,e=S(b+4)>>>0;b=c>>15;c&=-32769;if(0===c)return 0;if(!(32767>c))return I[7]=127|
|
||||
b<<7,I[6]=240|e>>30<<3&8,I[5]=0,I[4]=0,D[0]=0,G[0];d+=4294967296*e;b&&(d=-d);return d*Math.pow(2,c-16383-63)}function w(b,c){G[0]=n[F+c&7];var d=I[7]&128,e=(I[7]&127)<<4|I[6]>>4,g,k;2047===e?(e=32767,g=0,k=2147483648|(D[1]&524288)<<11):0===e?k=g=0:(e+=15360,g=D[0]<<11,k=2147483648|(D[1]&1048575)<<11|D[0]>>>21);N(b,g);N(b+4,k);R(b+8,d<<8|e)}function x(b){D[0]=S(b);D[1]=S(b+4);return G[0]}function y(b){q(b+7);G[0]=s(0);N(b,D[0]);N(b+4,D[1])}function f(b){H[0]=S(b);return C[0]}this.a=1;var t=64,A=1,
|
||||
n=new Float64Array(8),B=new Uint8Array(n.buffer);new Uint32Array(n.buffer);var E=255,F=0,C=new Float32Array(1);new Uint8Array(C.buffer);var H=new Uint32Array(C.buffer),G=new Float64Array(1),I=new Uint8Array(G.buffer),D=new Uint32Array(G.buffer);new Uint8Array(10);var J=895,Z=0,L=0,V=0,M=0,sa=0,P=0,O=new Float64Array([1,Math.log(10)/Math.LN2,Math.LOG2E,Math.PI,Math.log(2)/Math.LN10,Math.LN2,0]);this.m=function(c){var d=c>>3&7;c=s(c&7);var e=r();switch(d){case 0:n[F]=e+c;break;case 1:n[F]=e*c;break;
|
||||
case 2:b(c);break;case 3:b(c);p();break;case 4:n[F]=e-c;break;case 5:n[F]=c-e;break;case 6:n[F]=e/c;break;case 7:n[F]=c/e;break;default:z()}};this.i=function(c,d){var e=c>>3&7,g=f(d),k=r();switch(e){case 0:n[F]=k+g;break;case 1:n[F]=k*g;break;case 2:b(g);break;case 3:b(g);p();break;case 4:n[F]=k-g;break;case 5:n[F]=g-k;break;case 6:n[F]=k/g;break;case 7:n[F]=g/k;break;default:z()}};this.v=function(b){var c=b&7;switch(b>>3&7){case 0:b=s(c);m(b);break;case 1:b=s(c);n[F+c&7]=r();n[F]=b;break;case 4:switch(c){case 0:n[F]=
|
||||
-r();break;case 1:n[F]=Math.abs(r());break;case 4:c=r();Z&=-18177;isNaN(c)?Z|=17664:0===c?Z|=16384:0>c&&(Z|=256);break;case 5:c=r();Z&=-18177;Z|=B[(F+0&7)<<3|7]>>7<<9;Z=E>>F&1?Z|16640:isNaN(c)?Z|256:0===c?Z|16384:Infinity===c||-Infinity===c?Z|1280:Z|1024;break;default:z()}break;case 5:m(O[c]);break;case 6:switch(c){case 0:n[F]=Math.pow(2,r())-1;break;case 1:n[F+1&7]=s(1)*Math.log(r())/Math.LN2;p();break;case 2:n[F]=Math.tan(r());m(1);break;case 3:n[F+1&7]=Math.atan2(s(1),r());p();break;case 5:n[F]=
|
||||
r()%s(1);break;default:z()}break;case 7:switch(c){case 0:n[F]=r()%s(1);break;case 2:n[F]=Math.sqrt(r());break;case 3:c=r();n[F]=Math.sin(c);m(Math.cos(c));break;case 4:n[F]=h(r());break;case 5:n[F]=r()*Math.pow(2,l(s(1)));break;case 6:n[F]=Math.sin(r());break;case 7:n[F]=Math.cos(r());break;default:z()}break;default:z()}};this.q=function(b,c){switch(b>>3&7){case 0:var d=f(c);m(d);break;case 2:C[0]=s(0);N(c,H[0]);break;case 3:C[0]=s(0);N(c,H[0]);p();break;case 4:k(c);break;case 5:J=Q(c);break;case 6:e(c);
|
||||
break;case 7:R(c,J);break;default:z()}};this.Q=function(c){var d=c&7;switch(c>>3&7){case 0:Ra()&&(n[F]=s(d),E&=~(1<<F));break;case 1:Sa()&&(n[F]=s(d),E&=~(1<<F));break;case 2:Qa()&&(n[F]=s(d),E&=~(1<<F));break;case 3:Ta()&&(n[F]=s(d),E&=~(1<<F));break;case 5:1===d?(c=s(1),b(c),p(),p()):z();break;default:z()}};this.D=function(c,d){var e=c>>3&7,g=S(d),k=r();switch(e){case 0:n[F]=k+g;break;case 1:n[F]=k*g;break;case 2:b(g);break;case 3:b(g);p();break;case 4:n[F]=k-g;break;case 5:n[F]=g-k;break;case 6:n[F]=
|
||||
k/g;break;case 7:n[F]=g/k;break;default:z()}};this.S=function(b){var e=b&7;switch(b>>3&7){case 0:Ra()||(n[F]=s(e),E&=~(1<<F));break;case 1:Sa()||(n[F]=s(e),E&=~(1<<F));break;case 2:Qa()||(n[F]=s(e),E&=~(1<<F));break;case 3:Ta()||(n[F]=s(e),E&=~(1<<F));break;case 4:227===b?d():228!==b&&z();break;case 5:b=s(e);c(b);break;case 6:c(s(e));break;default:z()}};this.R=function(b,c){switch(b>>3&7){case 0:var d=S(c);m(d);break;case 2:d=r();isNaN(d)||2147483647<d||-2147483648>d?(Z|=A,N(c,2147483648)):N(c,h(d));
|
||||
break;case 3:d=r();isNaN(d)||2147483647<d||-2147483648>d?(Z|=A,N(c,2147483648)):N(c,h(d));p();break;case 5:m(v(c));break;case 7:w(c,0);p();break;default:z()}};this.Ga=function(c){var d=c>>3&7,e=c&7;c=F+e&7;var e=s(e),g=r();switch(d){case 0:n[c]=e+g;break;case 1:n[c]=e*g;break;case 2:b(e);break;case 3:b(e);p();break;case 4:n[c]=g-e;break;case 5:n[c]=e-g;break;case 6:n[c]=g/e;break;case 7:n[c]=e/g;break;default:z()}};this.aa=function(c,d){var e=c>>3&7,g=x(d),k=r();switch(e){case 0:n[F]=k+g;break;case 1:n[F]=
|
||||
k*g;break;case 2:b(g);break;case 3:b(g);p();break;case 4:n[F]=k-g;break;case 5:n[F]=g-k;break;case 6:n[F]=k/g;break;case 7:n[F]=g/k;break;default:z()}};this.Ka=function(c){var d=c&7;switch(c>>3&7){case 0:E|=1<<(F+d&7);break;case 2:n[F+d&7]=r();break;case 3:0!==d&&(n[F+d&7]=r());p();break;case 4:c=s(d);b(c);break;case 5:c=s(d);b(c);p();break;default:z()}};this.Ia=function(b,c){switch(b>>3&7){case 0:var g=x(c);m(g);break;case 2:y(c);break;case 3:y(c);p();break;case 4:g=c;k(g);for(var g=g+28,h=0;8>h;h++)n[h]=
|
||||
v(g),g+=10;break;case 6:g=c;e(g);g+=28;for(h=0;8>h;h++)w(g,h-F&7),g+=10;d();break;case 7:R(c,Z&-14337|F<<11);break;default:z()}};this.Na=function(c){var d=c>>3&7;c=c&7;var e=F+c&7,g=s(c),k=r();switch(d){case 0:n[e]=g+k;break;case 1:n[e]=g*k;break;case 2:b(g);break;case 3:1===c?(b(n[e]),p()):z();break;case 4:n[e]=k-g;break;case 5:n[e]=g-k;break;case 6:n[e]=k/g;break;case 7:n[e]=g/k;break;default:z()}p()};this.Ma=function(c,d){var e=c>>3&7,g=Q(d)<<16>>16,k=r();switch(e){case 0:n[F]=k+g;break;case 1:n[F]=
|
||||
k*g;break;case 2:b(g);break;case 3:b(g);p();break;case 4:n[F]=k-g;break;case 5:n[F]=g-k;break;case 6:n[F]=k/g;break;case 7:n[F]=g/k;break;default:z()}};this.Ra=function(b){var d=b&7;switch(b>>3&7){case 4:224===b?g[0]=Z&-14337|F<<11:z();break;case 5:b=s(d);c(b);p();break;default:z()}};this.Oa=function(b,c){switch(b>>3&7){case 0:var d=Q(c)<<16>>16;m(d);break;case 2:d=r();isNaN(d)||32767<d||-32768>d?(Z|=A,R(c,32768)):R(c,h(d));break;case 3:d=r();isNaN(d)||32767<d||-32768>d?(Z|=A,R(c,32768)):R(c,h(d));
|
||||
p();break;case 5:var e=S(c)>>>0,d=S(c+4)>>>0,e=e+4294967296*d;d>>31&&(e-=1.8446744073709552E19);m(e);break;case 7:d=h(r());if(isNaN(d)||9223372036854775E3<d||-9223372036854775E3>d)d=9223372036854775E3,Z|=A;p();N(c,d);d/=4294967296;0>d&&-1<d&&(d=-1);N(c+4,d);break;default:z()}}}var bb=this;this.m=function(){ec||f()};this.v=function(){ec&&(oc=!0)};this.w=D;this.q=function(){var b=ec;oc=!0;ec=!1;setTimeout(function(){wd.n();Xc.n();D(xd);b&&f()},10)};this.a={};this.i=0;var Yc,da,yd,ae,zd,Ad,Bd,Cd,Eb,
|
||||
pc,Ma,bd,rc,ad,qc,$c,Zc,Ed,Dd,Nc,Na,Ub,cd,Oc,ya,J,Fd,Db,xa,dd,ed,Vb,fd,Xc,wd,ee,fe,ce,ec,oc,Pc,k,Ha,Gd,Ua,Ea,q,Cb,E,Fb,Kc,ab,wa,cc,I,u,K,ba,ma,Y,y,e,g,Ga,v,fc,ra,$,aa,sc,A,ga,W,T,m,P,U,M,ka,Rc,Q,S,Va,Id,Ab,Jd,l,xd;"undefined"!==typeof window&&(window.a=C);bb.D=function(){Ab[m()]()};var Ie={ha:sa,ia:sa,na:function(){return k.m[E++]},oa:function(){return k.Q[E++]},la:function(){var b=k.b(E);E=E+2|0;return b},ma:function(){var b=k.c(E);E=E+4|0;return b},ta:function(b){return k.d(b)},ua:function(b){return k.R(b)},
|
||||
ra:function(b){return k.b(b)},sa:function(b){return k.c(b)}},He={ha:function(b){return Ea(da[2]+$[aa]+b)},ia:function(b){return q(da[2]+$[aa]+b)},na:function(){E&-4096^Fb&&(Kc=Ea(E)^E,Fb=E&-4096);return k.m[Kc^E++]},oa:function(){E&-4096^Fb&&(Kc=Ea(E)^E,Fb=E&-4096);return k.Q[Kc^E++]},la:function(){if(4094<(E^Fb))return m()|m()<<8;var b=k.b(Kc^E);E=E+2|0;return b},ma:function(){if(4092<(E^Fb))return U()|U()<<16;var b=k.c(Kc^E);E=E+4|0;return b},ta:function(b){return k.d(Ea(b))},ua:function(b){return k.R(Ea(b))},
|
||||
ra:function(b){return 4095===(b&4095)?ka(b)|ka(b+1)<<8:k.b(Ea(b))},sa:function(b){return 4093<=(b&4095)?Q(b)|Q(b+2)<<16:k.c(Ea(b))}};"use strict";"use strict";var ie,he,va=Array(192),ta=Array(192),p=Array(256);va[0]=function(){return h(3)+(g[6]+g[12]&65535)|0};va[64]=function(){return h(3)+(g[6]+g[12]+P()&65535)|0};va[128]=function(){return h(3)+(g[6]+g[12]+U()&65535)|0};va[1]=function(){return h(3)+(g[6]+g[14]&65535)|0};va[65]=function(){return h(3)+(g[6]+g[14]+P()&65535)|0};va[129]=function(){return h(3)+
|
||||
(g[6]+g[14]+U()&65535)|0};va[2]=function(){return h(2)+(g[10]+g[12]&65535)|0};va[66]=function(){return h(2)+(g[10]+g[12]+P()&65535)|0};va[130]=function(){return h(2)+(g[10]+g[12]+U()&65535)|0};va[3]=function(){return h(2)+(g[10]+g[14]&65535)|0};va[67]=function(){return h(2)+(g[10]+g[14]+P()&65535)|0};va[131]=function(){return h(2)+(g[10]+g[14]+U()&65535)|0};va[4]=function(){return h(3)+(g[12]&65535)|0};va[68]=function(){return h(3)+(g[12]+P()&65535)|0};va[132]=function(){return h(3)+(g[12]+U()&65535)|
|
||||
0};va[5]=function(){return h(3)+(g[14]&65535)|0};va[69]=function(){return h(3)+(g[14]+P()&65535)|0};va[133]=function(){return h(3)+(g[14]+U()&65535)|0};va[6]=function(){return h(2)+(g[10]&65535)|0};va[70]=function(){return h(2)+(g[10]+P()&65535)|0};va[134]=function(){return h(2)+(g[10]+U()&65535)|0};va[7]=function(){return h(3)+(g[6]&65535)|0};va[71]=function(){return h(3)+(g[6]+P()&65535)|0};va[135]=function(){return h(3)+(g[6]+U()&65535)|0};ta[0]=function(){return h(3)+e[0]|0};ta[64]=function(){return h(3)+
|
||||
e[0]+P()|0};ta[128]=function(){return h(3)+e[0]+M()|0};ta[1]=function(){return h(3)+e[1]|0};ta[65]=function(){return h(3)+e[1]+P()|0};ta[129]=function(){return h(3)+e[1]+M()|0};ta[2]=function(){return h(3)+e[2]|0};ta[66]=function(){return h(3)+e[2]+P()|0};ta[130]=function(){return h(3)+e[2]+M()|0};ta[3]=function(){return h(3)+e[3]|0};ta[67]=function(){return h(3)+e[3]+P()|0};ta[131]=function(){return h(3)+e[3]+M()|0};ta[4]=function(){return p[m()](!1)|0};ta[68]=function(){return p[m()](!1)+P()|0};
|
||||
ta[132]=function(){return p[m()](!1)+M()|0};ta[5]=function(){return h(2)+e[5]|0};ta[69]=function(){return h(2)+e[5]+P()|0};ta[133]=function(){return h(2)+e[5]+M()|0};ta[6]=function(){return h(3)+e[6]|0};ta[70]=function(){return h(3)+e[6]+P()|0};ta[134]=function(){return h(3)+e[6]+M()|0};ta[7]=function(){return h(3)+e[7]|0};ta[71]=function(){return h(3)+e[7]+P()|0};ta[135]=function(){return h(3)+e[7]+M()|0};va[6]=function(){return h(3)+U()|0};ta[5]=function(){return h(3)+M()|0};ta[4]=function(){return p[m()](!1)|
|
||||
0};ta[68]=function(){return p[m()](!0)+P()|0};ta[132]=function(){return p[m()](!0)+M()|0};for(var Td=0;8>Td;Td++)for(var Ud=0;3>Ud;Ud++)for(var td=1;8>td;td++){var ud=Td|Ud<<6;ta[ud|td<<3]=ta[ud];va[ud|td<<3]=va[ud]}p[0]=function(){return e[0]+h(3)+e[0]|0};p[1]=function(){return e[0]+h(3)+e[1]|0};p[2]=function(){return e[0]+h(3)+e[2]|0};p[3]=function(){return e[0]+h(3)+e[3]|0};p[4]=function(){return e[0]+h(2)+e[4]|0};p[5]=function(b){return e[0]+(b?h(2)+e[5]:h(3)+M())|0};p[6]=function(){return e[0]+
|
||||
h(3)+e[6]|0};p[7]=function(){return e[0]+h(3)+e[7]|0};p[64]=function(){return(e[0]<<1)+h(3)+e[0]|0};p[65]=function(){return(e[0]<<1)+h(3)+e[1]|0};p[66]=function(){return(e[0]<<1)+h(3)+e[2]|0};p[67]=function(){return(e[0]<<1)+h(3)+e[3]|0};p[68]=function(){return(e[0]<<1)+h(2)+e[4]|0};p[69]=function(b){return(e[0]<<1)+(b?h(2)+e[5]:h(3)+M())|0};p[70]=function(){return(e[0]<<1)+h(3)+e[6]|0};p[71]=function(){return(e[0]<<1)+h(3)+e[7]|0};p[128]=function(){return(e[0]<<2)+h(3)+e[0]|0};p[129]=function(){return(e[0]<<
|
||||
2)+h(3)+e[1]|0};p[130]=function(){return(e[0]<<2)+h(3)+e[2]|0};p[131]=function(){return(e[0]<<2)+h(3)+e[3]|0};p[132]=function(){return(e[0]<<2)+h(2)+e[4]|0};p[133]=function(b){return(e[0]<<2)+(b?h(2)+e[5]:h(3)+M())|0};p[134]=function(){return(e[0]<<2)+h(3)+e[6]|0};p[135]=function(){return(e[0]<<2)+h(3)+e[7]|0};p[192]=function(){return(e[0]<<3)+h(3)+e[0]|0};p[193]=function(){return(e[0]<<3)+h(3)+e[1]|0};p[194]=function(){return(e[0]<<3)+h(3)+e[2]|0};p[195]=function(){return(e[0]<<3)+h(3)+e[3]|0};p[196]=
|
||||
function(){return(e[0]<<3)+h(2)+e[4]|0};p[197]=function(b){return(e[0]<<3)+(b?h(2)+e[5]:h(3)+M())|0};p[198]=function(){return(e[0]<<3)+h(3)+e[6]|0};p[199]=function(){return(e[0]<<3)+h(3)+e[7]|0};p[8]=function(){return e[1]+h(3)+e[0]|0};p[9]=function(){return e[1]+h(3)+e[1]|0};p[10]=function(){return e[1]+h(3)+e[2]|0};p[11]=function(){return e[1]+h(3)+e[3]|0};p[12]=function(){return e[1]+h(2)+e[4]|0};p[13]=function(b){return e[1]+(b?h(2)+e[5]:h(3)+M())|0};p[14]=function(){return e[1]+h(3)+e[6]|0};
|
||||
p[15]=function(){return e[1]+h(3)+e[7]|0};p[72]=function(){return(e[1]<<1)+h(3)+e[0]|0};p[73]=function(){return(e[1]<<1)+h(3)+e[1]|0};p[74]=function(){return(e[1]<<1)+h(3)+e[2]|0};p[75]=function(){return(e[1]<<1)+h(3)+e[3]|0};p[76]=function(){return(e[1]<<1)+h(2)+e[4]|0};p[77]=function(b){return(e[1]<<1)+(b?h(2)+e[5]:h(3)+M())|0};p[78]=function(){return(e[1]<<1)+h(3)+e[6]|0};p[79]=function(){return(e[1]<<1)+h(3)+e[7]|0};p[136]=function(){return(e[1]<<2)+h(3)+e[0]|0};p[137]=function(){return(e[1]<<
|
||||
2)+h(3)+e[1]|0};p[138]=function(){return(e[1]<<2)+h(3)+e[2]|0};p[139]=function(){return(e[1]<<2)+h(3)+e[3]|0};p[140]=function(){return(e[1]<<2)+h(2)+e[4]|0};p[141]=function(b){return(e[1]<<2)+(b?h(2)+e[5]:h(3)+M())|0};p[142]=function(){return(e[1]<<2)+h(3)+e[6]|0};p[143]=function(){return(e[1]<<2)+h(3)+e[7]|0};p[200]=function(){return(e[1]<<3)+h(3)+e[0]|0};p[201]=function(){return(e[1]<<3)+h(3)+e[1]|0};p[202]=function(){return(e[1]<<3)+h(3)+e[2]|0};p[203]=function(){return(e[1]<<3)+h(3)+e[3]|0};p[204]=
|
||||
function(){return(e[1]<<3)+h(2)+e[4]|0};p[205]=function(b){return(e[1]<<3)+(b?h(2)+e[5]:h(3)+M())|0};p[206]=function(){return(e[1]<<3)+h(3)+e[6]|0};p[207]=function(){return(e[1]<<3)+h(3)+e[7]|0};p[16]=function(){return e[2]+h(3)+e[0]|0};p[17]=function(){return e[2]+h(3)+e[1]|0};p[18]=function(){return e[2]+h(3)+e[2]|0};p[19]=function(){return e[2]+h(3)+e[3]|0};p[20]=function(){return e[2]+h(2)+e[4]|0};p[21]=function(b){return e[2]+(b?h(2)+e[5]:h(3)+M())|0};p[22]=function(){return e[2]+h(3)+e[6]|0};
|
||||
p[23]=function(){return e[2]+h(3)+e[7]|0};p[80]=function(){return(e[2]<<1)+h(3)+e[0]|0};p[81]=function(){return(e[2]<<1)+h(3)+e[1]|0};p[82]=function(){return(e[2]<<1)+h(3)+e[2]|0};p[83]=function(){return(e[2]<<1)+h(3)+e[3]|0};p[84]=function(){return(e[2]<<1)+h(2)+e[4]|0};p[85]=function(b){return(e[2]<<1)+(b?h(2)+e[5]:h(3)+M())|0};p[86]=function(){return(e[2]<<1)+h(3)+e[6]|0};p[87]=function(){return(e[2]<<1)+h(3)+e[7]|0};p[144]=function(){return(e[2]<<2)+h(3)+e[0]|0};p[145]=function(){return(e[2]<<
|
||||
2)+h(3)+e[1]|0};p[146]=function(){return(e[2]<<2)+h(3)+e[2]|0};p[147]=function(){return(e[2]<<2)+h(3)+e[3]|0};p[148]=function(){return(e[2]<<2)+h(2)+e[4]|0};p[149]=function(b){return(e[2]<<2)+(b?h(2)+e[5]:h(3)+M())|0};p[150]=function(){return(e[2]<<2)+h(3)+e[6]|0};p[151]=function(){return(e[2]<<2)+h(3)+e[7]|0};p[208]=function(){return(e[2]<<3)+h(3)+e[0]|0};p[209]=function(){return(e[2]<<3)+h(3)+e[1]|0};p[210]=function(){return(e[2]<<3)+h(3)+e[2]|0};p[211]=function(){return(e[2]<<3)+h(3)+e[3]|0};p[212]=
|
||||
function(){return(e[2]<<3)+h(2)+e[4]|0};p[213]=function(b){return(e[2]<<3)+(b?h(2)+e[5]:h(3)+M())|0};p[214]=function(){return(e[2]<<3)+h(3)+e[6]|0};p[215]=function(){return(e[2]<<3)+h(3)+e[7]|0};p[24]=function(){return e[3]+h(3)+e[0]|0};p[25]=function(){return e[3]+h(3)+e[1]|0};p[26]=function(){return e[3]+h(3)+e[2]|0};p[27]=function(){return e[3]+h(3)+e[3]|0};p[28]=function(){return e[3]+h(2)+e[4]|0};p[29]=function(b){return e[3]+(b?h(2)+e[5]:h(3)+M())|0};p[30]=function(){return e[3]+h(3)+e[6]|0};
|
||||
p[31]=function(){return e[3]+h(3)+e[7]|0};p[88]=function(){return(e[3]<<1)+h(3)+e[0]|0};p[89]=function(){return(e[3]<<1)+h(3)+e[1]|0};p[90]=function(){return(e[3]<<1)+h(3)+e[2]|0};p[91]=function(){return(e[3]<<1)+h(3)+e[3]|0};p[92]=function(){return(e[3]<<1)+h(2)+e[4]|0};p[93]=function(b){return(e[3]<<1)+(b?h(2)+e[5]:h(3)+M())|0};p[94]=function(){return(e[3]<<1)+h(3)+e[6]|0};p[95]=function(){return(e[3]<<1)+h(3)+e[7]|0};p[152]=function(){return(e[3]<<2)+h(3)+e[0]|0};p[153]=function(){return(e[3]<<
|
||||
2)+h(3)+e[1]|0};p[154]=function(){return(e[3]<<2)+h(3)+e[2]|0};p[155]=function(){return(e[3]<<2)+h(3)+e[3]|0};p[156]=function(){return(e[3]<<2)+h(2)+e[4]|0};p[157]=function(b){return(e[3]<<2)+(b?h(2)+e[5]:h(3)+M())|0};p[158]=function(){return(e[3]<<2)+h(3)+e[6]|0};p[159]=function(){return(e[3]<<2)+h(3)+e[7]|0};p[216]=function(){return(e[3]<<3)+h(3)+e[0]|0};p[217]=function(){return(e[3]<<3)+h(3)+e[1]|0};p[218]=function(){return(e[3]<<3)+h(3)+e[2]|0};p[219]=function(){return(e[3]<<3)+h(3)+e[3]|0};p[220]=
|
||||
function(){return(e[3]<<3)+h(2)+e[4]|0};p[221]=function(b){return(e[3]<<3)+(b?h(2)+e[5]:h(3)+M())|0};p[222]=function(){return(e[3]<<3)+h(3)+e[6]|0};p[223]=function(){return(e[3]<<3)+h(3)+e[7]|0};p[32]=function(){return 0+h(3)+e[0]|0};p[33]=function(){return 0+h(3)+e[1]|0};p[34]=function(){return 0+h(3)+e[2]|0};p[35]=function(){return 0+h(3)+e[3]|0};p[36]=function(){return 0+h(2)+e[4]|0};p[37]=function(b){return 0+(b?h(2)+e[5]:h(3)+M())|0};p[38]=function(){return 0+h(3)+e[6]|0};p[39]=function(){return 0+
|
||||
h(3)+e[7]|0};p[96]=function(){return 0+h(3)+e[0]|0};p[97]=function(){return 0+h(3)+e[1]|0};p[98]=function(){return 0+h(3)+e[2]|0};p[99]=function(){return 0+h(3)+e[3]|0};p[100]=function(){return 0+h(2)+e[4]|0};p[101]=function(b){return 0+(b?h(2)+e[5]:h(3)+M())|0};p[102]=function(){return 0+h(3)+e[6]|0};p[103]=function(){return 0+h(3)+e[7]|0};p[160]=function(){return 0+h(3)+e[0]|0};p[161]=function(){return 0+h(3)+e[1]|0};p[162]=function(){return 0+h(3)+e[2]|0};p[163]=function(){return 0+h(3)+e[3]|0};
|
||||
p[164]=function(){return 0+h(2)+e[4]|0};p[165]=function(b){return 0+(b?h(2)+e[5]:h(3)+M())|0};p[166]=function(){return 0+h(3)+e[6]|0};p[167]=function(){return 0+h(3)+e[7]|0};p[224]=function(){return 0+h(3)+e[0]|0};p[225]=function(){return 0+h(3)+e[1]|0};p[226]=function(){return 0+h(3)+e[2]|0};p[227]=function(){return 0+h(3)+e[3]|0};p[228]=function(){return 0+h(2)+e[4]|0};p[229]=function(b){return 0+(b?h(2)+e[5]:h(3)+M())|0};p[230]=function(){return 0+h(3)+e[6]|0};p[231]=function(){return 0+h(3)+e[7]|
|
||||
0};p[40]=function(){return e[5]+h(3)+e[0]|0};p[41]=function(){return e[5]+h(3)+e[1]|0};p[42]=function(){return e[5]+h(3)+e[2]|0};p[43]=function(){return e[5]+h(3)+e[3]|0};p[44]=function(){return e[5]+h(2)+e[4]|0};p[45]=function(b){return e[5]+(b?h(2)+e[5]:h(3)+M())|0};p[46]=function(){return e[5]+h(3)+e[6]|0};p[47]=function(){return e[5]+h(3)+e[7]|0};p[104]=function(){return(e[5]<<1)+h(3)+e[0]|0};p[105]=function(){return(e[5]<<1)+h(3)+e[1]|0};p[106]=function(){return(e[5]<<1)+h(3)+e[2]|0};p[107]=
|
||||
function(){return(e[5]<<1)+h(3)+e[3]|0};p[108]=function(){return(e[5]<<1)+h(2)+e[4]|0};p[109]=function(b){return(e[5]<<1)+(b?h(2)+e[5]:h(3)+M())|0};p[110]=function(){return(e[5]<<1)+h(3)+e[6]|0};p[111]=function(){return(e[5]<<1)+h(3)+e[7]|0};p[168]=function(){return(e[5]<<2)+h(3)+e[0]|0};p[169]=function(){return(e[5]<<2)+h(3)+e[1]|0};p[170]=function(){return(e[5]<<2)+h(3)+e[2]|0};p[171]=function(){return(e[5]<<2)+h(3)+e[3]|0};p[172]=function(){return(e[5]<<2)+h(2)+e[4]|0};p[173]=function(b){return(e[5]<<
|
||||
2)+(b?h(2)+e[5]:h(3)+M())|0};p[174]=function(){return(e[5]<<2)+h(3)+e[6]|0};p[175]=function(){return(e[5]<<2)+h(3)+e[7]|0};p[232]=function(){return(e[5]<<3)+h(3)+e[0]|0};p[233]=function(){return(e[5]<<3)+h(3)+e[1]|0};p[234]=function(){return(e[5]<<3)+h(3)+e[2]|0};p[235]=function(){return(e[5]<<3)+h(3)+e[3]|0};p[236]=function(){return(e[5]<<3)+h(2)+e[4]|0};p[237]=function(b){return(e[5]<<3)+(b?h(2)+e[5]:h(3)+M())|0};p[238]=function(){return(e[5]<<3)+h(3)+e[6]|0};p[239]=function(){return(e[5]<<3)+h(3)+
|
||||
e[7]|0};p[48]=function(){return e[6]+h(3)+e[0]|0};p[49]=function(){return e[6]+h(3)+e[1]|0};p[50]=function(){return e[6]+h(3)+e[2]|0};p[51]=function(){return e[6]+h(3)+e[3]|0};p[52]=function(){return e[6]+h(2)+e[4]|0};p[53]=function(b){return e[6]+(b?h(2)+e[5]:h(3)+M())|0};p[54]=function(){return e[6]+h(3)+e[6]|0};p[55]=function(){return e[6]+h(3)+e[7]|0};p[112]=function(){return(e[6]<<1)+h(3)+e[0]|0};p[113]=function(){return(e[6]<<1)+h(3)+e[1]|0};p[114]=function(){return(e[6]<<1)+h(3)+e[2]|0};p[115]=
|
||||
function(){return(e[6]<<1)+h(3)+e[3]|0};p[116]=function(){return(e[6]<<1)+h(2)+e[4]|0};p[117]=function(b){return(e[6]<<1)+(b?h(2)+e[5]:h(3)+M())|0};p[118]=function(){return(e[6]<<1)+h(3)+e[6]|0};p[119]=function(){return(e[6]<<1)+h(3)+e[7]|0};p[176]=function(){return(e[6]<<2)+h(3)+e[0]|0};p[177]=function(){return(e[6]<<2)+h(3)+e[1]|0};p[178]=function(){return(e[6]<<2)+h(3)+e[2]|0};p[179]=function(){return(e[6]<<2)+h(3)+e[3]|0};p[180]=function(){return(e[6]<<2)+h(2)+e[4]|0};p[181]=function(b){return(e[6]<<
|
||||
2)+(b?h(2)+e[5]:h(3)+M())|0};p[182]=function(){return(e[6]<<2)+h(3)+e[6]|0};p[183]=function(){return(e[6]<<2)+h(3)+e[7]|0};p[240]=function(){return(e[6]<<3)+h(3)+e[0]|0};p[241]=function(){return(e[6]<<3)+h(3)+e[1]|0};p[242]=function(){return(e[6]<<3)+h(3)+e[2]|0};p[243]=function(){return(e[6]<<3)+h(3)+e[3]|0};p[244]=function(){return(e[6]<<3)+h(2)+e[4]|0};p[245]=function(b){return(e[6]<<3)+(b?h(2)+e[5]:h(3)+M())|0};p[246]=function(){return(e[6]<<3)+h(3)+e[6]|0};p[247]=function(){return(e[6]<<3)+h(3)+
|
||||
e[7]|0};p[56]=function(){return e[7]+h(3)+e[0]|0};p[57]=function(){return e[7]+h(3)+e[1]|0};p[58]=function(){return e[7]+h(3)+e[2]|0};p[59]=function(){return e[7]+h(3)+e[3]|0};p[60]=function(){return e[7]+h(2)+e[4]|0};p[61]=function(b){return e[7]+(b?h(2)+e[5]:h(3)+M())|0};p[62]=function(){return e[7]+h(3)+e[6]|0};p[63]=function(){return e[7]+h(3)+e[7]|0};p[120]=function(){return(e[7]<<1)+h(3)+e[0]|0};p[121]=function(){return(e[7]<<1)+h(3)+e[1]|0};p[122]=function(){return(e[7]<<1)+h(3)+e[2]|0};p[123]=
|
||||
function(){return(e[7]<<1)+h(3)+e[3]|0};p[124]=function(){return(e[7]<<1)+h(2)+e[4]|0};p[125]=function(b){return(e[7]<<1)+(b?h(2)+e[5]:h(3)+M())|0};p[126]=function(){return(e[7]<<1)+h(3)+e[6]|0};p[127]=function(){return(e[7]<<1)+h(3)+e[7]|0};p[184]=function(){return(e[7]<<2)+h(3)+e[0]|0};p[185]=function(){return(e[7]<<2)+h(3)+e[1]|0};p[186]=function(){return(e[7]<<2)+h(3)+e[2]|0};p[187]=function(){return(e[7]<<2)+h(3)+e[3]|0};p[188]=function(){return(e[7]<<2)+h(2)+e[4]|0};p[189]=function(b){return(e[7]<<
|
||||
2)+(b?h(2)+e[5]:h(3)+M())|0};p[190]=function(){return(e[7]<<2)+h(3)+e[6]|0};p[191]=function(){return(e[7]<<2)+h(3)+e[7]|0};p[248]=function(){return(e[7]<<3)+h(3)+e[0]|0};p[249]=function(){return(e[7]<<3)+h(3)+e[1]|0};p[250]=function(){return(e[7]<<3)+h(3)+e[2]|0};p[251]=function(){return(e[7]<<3)+h(3)+e[3]|0};p[252]=function(){return(e[7]<<3)+h(2)+e[4]|0};p[253]=function(b){return(e[7]<<3)+(b?h(2)+e[5]:h(3)+M())|0};p[254]=function(){return(e[7]<<3)+h(3)+e[6]|0};p[255]=function(){return(e[7]<<3)+h(3)+
|
||||
e[7]|0};ie=function(b){return va[b]()};he=function(b){return ta[b]()};"use strict";var oe=new Uint8Array([32,0,1,26,2,23,27,0,3,16,24,30,28,11,0,13,4,7,17,0,25,22,31,15,29,10,12,6,0,21,14,9,5,20,8,19,18]);"use strict";var Ya=Tc,Ra=Ba,Sa=Gb,Za=hd,Ta=ge;"use strict";"use strict";"use strict";var r=[],s=[],x=[],w=[];r[0]=s[0]=function(){var b=m(),c,d;192>b?(d=q(l(b)),c=k.d(d),k.e(d,kc(c,v[b>>1&12|b>>5&1]))):(c=v[b<<2&12|b>>2&1],v[b<<2&12|b>>2&1]=kc(c,v[b>>1&12|b>>5&1]))};r[1]=function(){var b=m(),c,
|
||||
d,e;192>b?(c=l(b),d=q(c),J&&4095===(c&4095)?(e=q(c+1),c=B(d,e),n(d,e,eb(c,g[b>>2&14]))):(c=k.b(d),k.a(d,eb(c,g[b>>2&14])))):(c=g[b<<1&14],g[b<<1&14]=eb(c,g[b>>2&14]))};s[1]=function(){var b=m(),c,d,g;192>b?(c=l(b),d=q(c),J&&4093<=(c&4095)?(g=q(c+3),c=G(d,g)>>>0,H(d,g,fb(c,y[b>>3&7]))):(c=k.c(d)>>>0,k.f(d,fb(c,y[b>>3&7])))):(c=y[b&7],e[b&7]=fb(c,y[b>>3&7]))};r[2]=s[2]=function(){var b=m(),c=192>b?ka(l(b)):v[b<<2&12|b>>2&1];v[b>>1&12|b>>5&1]=kc(v[b>>1&12|b>>5&1],c)};r[3]=function(){var b=m(),c=192>
|
||||
b?Q(l(b)):g[b<<1&14];g[b>>2&14]=eb(g[b>>2&14],c)};s[3]=function(){var b=m(),c=192>b?S(l(b))>>>0:y[b&7];e[b>>3&7]=fb(y[b>>3&7],c)};r[4]=s[4]=function(){v[0]=kc(v[0],m())};r[5]=function(){g[0]=eb(g[0],U())};s[5]=function(){y[0]=fb(y[0],M()>>>0)};r[6]=function(){la(ra[0])};s[6]=function(){ia(ra[0])};r[7]=function(){ca(0,k.b(Va(0)));$[aa]+=2};s[7]=function(){ca(0,k.b(Va(0)));$[aa]+=4};r[8]=s[8]=function(){var b=m(),c,d;192>b?(d=q(l(b)),c=k.d(d),k.e(d,yc(c,v[b>>1&12|b>>5&1]))):(c=v[b<<2&12|b>>2&1],v[b<<
|
||||
2&12|b>>2&1]=yc(c,v[b>>1&12|b>>5&1]))};r[9]=function(){var b=m(),c,d,e;192>b?(c=l(b),d=q(c),J&&4095===(c&4095)?(e=q(c+1),c=B(d,e),n(d,e,vb(c,g[b>>2&14]))):(c=k.b(d),k.a(d,vb(c,g[b>>2&14])))):(c=g[b<<1&14],g[b<<1&14]=vb(c,g[b>>2&14]))};s[9]=function(){var b=m(),c,d,g;192>b?(c=l(b),d=q(c),J&&4093<=(c&4095)?(g=q(c+3),c=G(d,g),H(d,g,wb(c,e[b>>3&7]))):(c=k.c(d),k.f(d,wb(c,e[b>>3&7])))):(c=e[b&7],e[b&7]=wb(c,e[b>>3&7]))};r[10]=s[10]=function(){var b=m(),c=192>b?ka(l(b)):v[b<<2&12|b>>2&1];v[b>>1&12|b>>5&
|
||||
1]=yc(v[b>>1&12|b>>5&1],c)};r[11]=function(){var b=m(),c=192>b?Q(l(b)):g[b<<1&14];g[b>>2&14]=vb(g[b>>2&14],c)};s[11]=function(){var b=m(),c=192>b?S(l(b)):e[b&7];e[b>>3&7]=wb(e[b>>3&7],c)};r[12]=s[12]=function(){v[0]=yc(v[0],m())};r[13]=function(){g[0]=vb(g[0],U())};s[13]=function(){y[0]=wb(e[0],M())};r[14]=function(){la(ra[1])};s[14]=function(){ia(ra[1])};r[15]=s[15]=function(){Jd[m()]()};r[16]=s[16]=function(){var b=m(),c,d;192>b?(d=q(l(b)),c=k.d(d),k.e(d,uc(c,v[b>>1&12|b>>5&1]))):(c=v[b<<2&12|b>>
|
||||
2&1],v[b<<2&12|b>>2&1]=uc(c,v[b>>1&12|b>>5&1]))};r[17]=function(){var b=m(),c,d,e;192>b?(c=l(b),d=q(c),J&&4095===(c&4095)?(e=q(c+1),c=B(d,e),n(d,e,jb(c,g[b>>2&14]))):(c=k.b(d),k.a(d,jb(c,g[b>>2&14])))):(c=g[b<<1&14],g[b<<1&14]=jb(c,g[b>>2&14]))};s[17]=function(){var b=m(),c,d,g;192>b?(c=l(b),d=q(c),J&&4093<=(c&4095)?(g=q(c+3),c=G(d,g)>>>0,H(d,g,kb(c,y[b>>3&7]))):(c=k.c(d)>>>0,k.f(d,kb(c,y[b>>3&7])))):(c=y[b&7],e[b&7]=kb(c,y[b>>3&7]))};r[18]=s[18]=function(){var b=m(),c=192>b?ka(l(b)):v[b<<2&12|b>>
|
||||
2&1];v[b>>1&12|b>>5&1]=uc(v[b>>1&12|b>>5&1],c)};r[19]=function(){var b=m(),c=192>b?Q(l(b)):g[b<<1&14];g[b>>2&14]=jb(g[b>>2&14],c)};s[19]=function(){var b=m(),c=192>b?S(l(b))>>>0:y[b&7];e[b>>3&7]=kb(y[b>>3&7],c)};r[20]=s[20]=function(){v[0]=uc(v[0],m())};r[21]=function(){g[0]=jb(g[0],U())};s[21]=function(){y[0]=kb(y[0],M()>>>0)};r[22]=function(){la(ra[2])};s[22]=function(){ia(ra[2])};r[23]=function(){ca(2,k.b(Va(0)));$[aa]+=2};s[23]=function(){ca(2,k.b(Va(0)));$[aa]+=4};r[24]=s[24]=function(){var b=
|
||||
m(),c,d;192>b?(d=q(l(b)),c=k.d(d),k.e(d,wc(c,v[b>>1&12|b>>5&1]))):(c=v[b<<2&12|b>>2&1],v[b<<2&12|b>>2&1]=wc(c,v[b>>1&12|b>>5&1]))};r[25]=function(){var b=m(),c,d,e;192>b?(c=l(b),d=q(c),J&&4095===(c&4095)?(e=q(c+1),c=B(d,e),n(d,e,nb(c,g[b>>2&14]))):(c=k.b(d),k.a(d,nb(c,g[b>>2&14])))):(c=g[b<<1&14],g[b<<1&14]=nb(c,g[b>>2&14]))};s[25]=function(){var b=m(),c,d,g;192>b?(c=l(b),d=q(c),J&&4093<=(c&4095)?(g=q(c+3),c=G(d,g)>>>0,H(d,g,ob(c,y[b>>3&7]))):(c=k.c(d)>>>0,k.f(d,ob(c,y[b>>3&7])))):(c=y[b&7],e[b&7]=
|
||||
ob(c,y[b>>3&7]))};r[26]=s[26]=function(){var b=m(),c=192>b?ka(l(b)):v[b<<2&12|b>>2&1];v[b>>1&12|b>>5&1]=wc(v[b>>1&12|b>>5&1],c)};r[27]=function(){var b=m(),c=192>b?Q(l(b)):g[b<<1&14];g[b>>2&14]=nb(g[b>>2&14],c)};s[27]=function(){var b=m(),c=192>b?S(l(b))>>>0:y[b&7];e[b>>3&7]=ob(y[b>>3&7],c)};r[28]=s[28]=function(){v[0]=wc(v[0],m())};r[29]=function(){g[0]=nb(g[0],U())};s[29]=function(){y[0]=ob(y[0],M()>>>0)};r[30]=function(){la(ra[3])};s[30]=function(){ia(ra[3])};r[31]=function(){ca(3,k.b(Va(0)));
|
||||
$[aa]+=2};s[31]=function(){ca(3,k.b(Va(0)));$[aa]+=4};r[32]=s[32]=function(){var b=m(),c,d;192>b?(d=q(l(b)),c=k.d(d),k.e(d,xc(c,v[b>>1&12|b>>5&1]))):(c=v[b<<2&12|b>>2&1],v[b<<2&12|b>>2&1]=xc(c,v[b>>1&12|b>>5&1]))};r[33]=function(){var b=m(),c,d,e;192>b?(c=l(b),d=q(c),J&&4095===(c&4095)?(e=q(c+1),c=B(d,e),n(d,e,tb(c,g[b>>2&14]))):(c=k.b(d),k.a(d,tb(c,g[b>>2&14])))):(c=g[b<<1&14],g[b<<1&14]=tb(c,g[b>>2&14]))};s[33]=function(){var b=m(),c,d,g;192>b?(c=l(b),d=q(c),J&&4093<=(c&4095)?(g=q(c+3),c=G(d,g),
|
||||
H(d,g,ub(c,e[b>>3&7]))):(c=k.c(d),k.f(d,ub(c,e[b>>3&7])))):(c=e[b&7],e[b&7]=ub(c,e[b>>3&7]))};r[34]=s[34]=function(){var b=m(),c=192>b?ka(l(b)):v[b<<2&12|b>>2&1];v[b>>1&12|b>>5&1]=xc(v[b>>1&12|b>>5&1],c)};r[35]=function(){var b=m(),c=192>b?Q(l(b)):g[b<<1&14];g[b>>2&14]=tb(g[b>>2&14],c)};s[35]=function(){var b=m(),c=192>b?S(l(b)):e[b&7];e[b>>3&7]=ub(e[b>>3&7],c)};r[36]=s[36]=function(){v[0]=xc(v[0],m())};r[37]=function(){g[0]=tb(g[0],U())};s[37]=function(){y[0]=ub(e[0],M())};r[38]=s[38]=function(){ja(0)};
|
||||
r[39]=s[39]=function(){var b=v[0],c=Ba(),d=Sc();u&=-18;if(9<(b&15)||d)v[0]+=6,u|=16;if(153<b||c)v[0]+=96,u|=1;I=v[0];Y=8;ba=ma=0;K=196};r[40]=s[40]=function(){var b=m(),c,d;192>b?(d=q(l(b)),c=k.d(d),k.e(d,vc(c,v[b>>1&12|b>>5&1]))):(c=v[b<<2&12|b>>2&1],v[b<<2&12|b>>2&1]=vc(c,v[b>>1&12|b>>5&1]))};r[41]=function(){var b=m(),c,d,e;192>b?(c=l(b),d=q(c),J&&4095===(c&4095)?(e=q(c+1),c=B(d,e),n(d,e,lb(c,g[b>>2&14]))):(c=k.b(d),k.a(d,lb(c,g[b>>2&14])))):(c=g[b<<1&14],g[b<<1&14]=lb(c,g[b>>2&14]))};s[41]=function(){var b=
|
||||
m(),c,d,g;192>b?(c=l(b),d=q(c),J&&4093<=(c&4095)?(g=q(c+3),c=G(d,g)>>>0,H(d,g,mb(c,y[b>>3&7]))):(c=k.c(d)>>>0,k.f(d,mb(c,y[b>>3&7])))):(c=y[b&7],e[b&7]=mb(c,y[b>>3&7]))};r[42]=s[42]=function(){var b=m(),c=192>b?ka(l(b)):v[b<<2&12|b>>2&1];v[b>>1&12|b>>5&1]=vc(v[b>>1&12|b>>5&1],c)};r[43]=function(){var b=m(),c=192>b?Q(l(b)):g[b<<1&14];g[b>>2&14]=lb(g[b>>2&14],c)};s[43]=function(){var b=m(),c=192>b?S(l(b))>>>0:y[b&7];e[b>>3&7]=mb(y[b>>3&7],c)};r[44]=s[44]=function(){v[0]=vc(v[0],m())};r[45]=function(){g[0]=
|
||||
lb(g[0],U())};s[45]=function(){y[0]=mb(y[0],M()>>>0)};r[46]=s[46]=function(){ja(1)};r[47]=s[47]=function(){var b=v[0],c=Ba();u&=-2;9<(b&15)||Sc()?(v[0]-=6,u|=16,u=u&-2|c|v[0]>>7):u&=-17;if(153<b||c)v[0]-=96,u|=1;I=v[0];Y=8;ba=ma=0;K=196};r[48]=s[48]=function(){var b=m(),c,d;192>b?(d=q(l(b)),c=k.d(d),k.e(d,zc(c,v[b>>1&12|b>>5&1]))):(c=v[b<<2&12|b>>2&1],v[b<<2&12|b>>2&1]=zc(c,v[b>>1&12|b>>5&1]))};r[49]=function(){var b=m(),c,d,e;192>b?(c=l(b),d=q(c),J&&4095===(c&4095)?(e=q(c+1),c=B(d,e),n(d,e,xb(c,
|
||||
g[b>>2&14]))):(c=k.b(d),k.a(d,xb(c,g[b>>2&14])))):(c=g[b<<1&14],g[b<<1&14]=xb(c,g[b>>2&14]))};s[49]=function(){var b=m(),c,d,g;192>b?(c=l(b),d=q(c),J&&4093<=(c&4095)?(g=q(c+3),c=G(d,g),H(d,g,yb(c,e[b>>3&7]))):(c=k.c(d),k.f(d,yb(c,e[b>>3&7])))):(c=e[b&7],e[b&7]=yb(c,e[b>>3&7]))};r[50]=s[50]=function(){var b=m(),c=192>b?ka(l(b)):v[b<<2&12|b>>2&1];v[b>>1&12|b>>5&1]=zc(v[b>>1&12|b>>5&1],c)};r[51]=function(){var b=m(),c=192>b?Q(l(b)):g[b<<1&14];g[b>>2&14]=xb(g[b>>2&14],c)};s[51]=function(){var b=m(),c=
|
||||
192>b?S(l(b)):e[b&7];e[b>>3&7]=yb(e[b>>3&7],c)};r[52]=s[52]=function(){v[0]=zc(v[0],m())};r[53]=function(){g[0]=xb(g[0],U())};s[53]=function(){y[0]=yb(e[0],M())};r[54]=s[54]=function(){ja(2)};r[55]=s[55]=function(){9<(v[0]&15)||Sc()?(g[0]+=6,v[1]+=1,u|=17):u&=-18;v[0]&=15;K&=-18};r[56]=s[56]=function(){var b=m(),c=192>b?ka(l(b)):v[b<<2&12|b>>2&1];lc(c,v[b>>1&12|b>>5&1])};r[57]=function(){var b=m(),c=192>b?Q(l(b)):g[b<<1&14];Yb(c,g[b>>2&14])};s[57]=function(){var b=m(),c=192>b?S(l(b))>>>0:y[b&7];Zb(c,
|
||||
y[b>>3&7])};r[58]=s[58]=function(){var b=m(),c=192>b?ka(l(b)):v[b<<2&12|b>>2&1];lc(v[b>>1&12|b>>5&1],c)};r[59]=function(){var b=m(),c=192>b?Q(l(b)):g[b<<1&14];Yb(g[b>>2&14],c)};s[59]=function(){var b=m(),c=192>b?S(l(b))>>>0:y[b&7];Zb(y[b>>3&7],c)};r[60]=s[60]=function(){lc(v[0],m())};r[61]=function(){Yb(g[0],U())};s[61]=function(){Zb(y[0],M()>>>0)};r[62]=s[62]=function(){ja(3)};r[63]=s[63]=function(){9<(v[0]&15)||Sc()?(g[0]-=6,v[1]-=1,u|=17):u&=-18;v[0]&=15;K&=-18};r[64]=function(){g[0]=pb(g[0])};
|
||||
s[64]=function(){y[0]=qb(y[0])};r[65]=function(){g[2]=pb(g[2])};s[65]=function(){y[1]=qb(y[1])};r[66]=function(){g[4]=pb(g[4])};s[66]=function(){y[2]=qb(y[2])};r[67]=function(){g[6]=pb(g[6])};s[67]=function(){y[3]=qb(y[3])};r[68]=function(){g[8]=pb(g[8])};s[68]=function(){y[4]=qb(y[4])};r[69]=function(){g[10]=pb(g[10])};s[69]=function(){y[5]=qb(y[5])};r[70]=function(){g[12]=pb(g[12])};s[70]=function(){y[6]=qb(y[6])};r[71]=function(){g[14]=pb(g[14])};s[71]=function(){y[7]=qb(y[7])};r[72]=function(){g[0]=
|
||||
rb(g[0])};s[72]=function(){y[0]=sb(y[0])};r[73]=function(){g[2]=rb(g[2])};s[73]=function(){y[1]=sb(y[1])};r[74]=function(){g[4]=rb(g[4])};s[74]=function(){y[2]=sb(y[2])};r[75]=function(){g[6]=rb(g[6])};s[75]=function(){y[3]=sb(y[3])};r[76]=function(){g[8]=rb(g[8])};s[76]=function(){y[4]=sb(y[4])};r[77]=function(){g[10]=rb(g[10])};s[77]=function(){y[5]=sb(y[5])};r[78]=function(){g[12]=rb(g[12])};s[78]=function(){y[6]=sb(y[6])};r[79]=function(){g[14]=rb(g[14])};s[79]=function(){y[7]=sb(y[7])};r[80]=
|
||||
function(){la(g[0])};s[80]=function(){ia(e[0])};r[81]=function(){la(g[2])};s[81]=function(){ia(e[1])};r[82]=function(){la(g[4])};s[82]=function(){ia(e[2])};r[83]=function(){la(g[6])};s[83]=function(){ia(e[3])};r[84]=function(){la(g[8])};s[84]=function(){ia(e[4])};r[85]=function(){la(g[10])};s[85]=function(){ia(e[5])};r[86]=function(){la(g[12])};s[86]=function(){ia(e[6])};r[87]=function(){la(g[14])};s[87]=function(){ia(e[7])};r[88]=function(){g[0]=Aa()};s[88]=function(){y[0]=ua()};r[89]=function(){g[2]=
|
||||
Aa()};s[89]=function(){y[1]=ua()};r[90]=function(){g[4]=Aa()};s[90]=function(){y[2]=ua()};r[91]=function(){g[6]=Aa()};s[91]=function(){y[3]=ua()};r[92]=function(){g[8]=Aa()};s[92]=function(){y[4]=ua()};r[93]=function(){g[10]=Aa()};s[93]=function(){y[5]=ua()};r[94]=function(){g[12]=Aa()};s[94]=function(){y[6]=ua()};r[95]=function(){g[14]=Aa()};s[95]=function(){y[7]=ua()};r[96]=function(){var b=g[8];q(b-15);la(g[0]);la(g[2]);la(g[4]);la(g[6]);la(b);la(g[10]);la(g[12]);la(g[14])};s[96]=function(){var b=
|
||||
e[4];q(b-31);ia(e[0]);ia(e[1]);ia(e[2]);ia(e[3]);ia(b);ia(e[5]);ia(e[6]);ia(e[7])};r[97]=function(){Ea($[aa]+15);g[14]=Aa();g[12]=Aa();g[10]=Aa();$[aa]+=2;g[6]=Aa();g[4]=Aa();g[2]=Aa();g[0]=Aa()};s[97]=function(){Ea($[aa]+31);y[7]=ua();y[6]=ua();y[5]=ua();$[aa]+=4;y[3]=ua();y[2]=ua();y[1]=ua();y[0]=ua()};r[98]=s[98]=function(){throw ze("bound instruction");};r[99]=s[99]=function(){var b=m(),c,d,e;192>b?(c=l(b),d=q(c),J&&4095===(c&4095)?(e=q(c+1),c=B(d,e),n(d,e,Ca(c,b>>2&14))):(c=k.b(d),k.a(d,Ca(c,
|
||||
b>>2&14)))):(c=g[b<<1&14],g[b<<1&14]=Ca(c,b>>2&14))};r[100]=s[100]=function(){ja(4)};r[101]=s[101]=function(){ja(5)};r[102]=s[102]=function(){xa=!Db;La();Ab[m()]();xa=Db;La()};r[103]=s[103]=function(){Cb=!Db;zb();Ab[m()]();Cb=Db;zb()};r[104]=function(){la(U())};s[104]=function(){ia(M())};r[105]=function(){var b=m(),c=192>b?Q(l(b))<<16>>16:Ga[b<<1&14];g[b>>2&14]=Md(U()<<16>>16,c)};s[105]=function(){var b=m(),c=192>b?S(l(b)):e[b&7];y[b>>3&7]=Nd(M(),c)};r[106]=function(){la(P())};s[106]=function(){ia(P())};
|
||||
r[107]=function(){var b=m(),c=192>b?Q(l(b))<<16>>16:Ga[b<<1&14];g[b>>2&14]=Md(P(),c)};s[107]=function(){var b=m(),c=192>b?S(l(b)):e[b&7];y[b>>3&7]=Nd(P(),c)};r[108]=s[108]=function(){var b=g[4],c,d=u&1024?-1:1;c=da[0]+A[T];if(wa){if(0!==A[ga]){do V(c,hc(b)),c+=d,A[T]+=d;while(--A[ga])}}else V(c,hc(b)),A[T]+=d};r[109]=function(){var b=g[4],c,d=u&1024?-1:1;c=da[0]+A[T];if(wa){if(0!==A[ga]){do R(c,ic(b)),c+=d,A[T]+=d;while(--A[ga])}}else R(c,ic(b)),A[T]+=d};s[109]=function(){var b=g[4],c,d=u&1024?-4:
|
||||
4;c=da[0]+A[T];if(wa){if(0!==A[ga]){var e=0===(c&3)&&!0;do{if(e){var h=q(c);k.D(h,cb(b))}else N(c,cb(b));c+=d;A[T]+=d}while(--A[ga])}}else N(c,cb(b)),A[T]+=d};r[110]=s[110]=function(){var b=g[4],c,d=u&1024?-1:1;c=h(3)+A[W];if(wa){if(0!==A[ga]){do Fa(b,ka(c)),c+=d,A[W]+=d;while(--A[ga])}}else Fa(b,ka(c)),A[W]+=d};r[111]=function(){var b=g[4],c,d=u&1024?-2:2;c=h(3)+A[W];if(wa){if(0!==A[ga]){do Xb(b,Q(c)),c+=d,A[W]+=d;while(--A[ga])}}else Xb(b,Q(c)),A[W]+=d};s[111]=function(){var b=g[4],c,d=u&1024?-4:
|
||||
4;c=h(3)+A[W];if(wa){if(0!==A[ga]){do gc(b,S(c)),c+=d,A[W]+=d;while(--A[ga])}}else gc(b,S(c)),A[W]+=d};r[112]=s[112]=function(){Ya()&&(E=E+P()|0);E++};r[113]=s[113]=function(){Ya()||(E=E+P()|0);E++};r[114]=s[114]=function(){Ra()&&(E=E+P()|0);E++};r[115]=s[115]=function(){Ra()||(E=E+P()|0);E++};r[116]=s[116]=function(){Sa()&&(E=E+P()|0);E++};r[117]=s[117]=function(){Sa()||(E=E+P()|0);E++};r[118]=s[118]=function(){Qa()&&(E=E+P()|0);E++};r[119]=s[119]=function(){Qa()||(E=E+P()|0);E++};r[120]=s[120]=
|
||||
function(){Za()&&(E=E+P()|0);E++};r[121]=s[121]=function(){Za()||(E=E+P()|0);E++};r[122]=s[122]=function(){Ta()&&(E=E+P()|0);E++};r[123]=s[123]=function(){Ta()||(E=E+P()|0);E++};r[124]=s[124]=function(){Wa()&&(E=E+P()|0);E++};r[125]=s[125]=function(){Wa()||(E=E+P()|0);E++};r[126]=s[126]=function(){Xa()&&(E=E+P()|0);E++};r[127]=s[127]=function(){Xa()||(E=E+P()|0);E++};r[128]=s[128]=function(){var b=m();switch(b>>3&7){case 0:var c;192>b?(b=q(l(b)),c=k.d(b),k.e(b,kc(c,m()))):(c=v[b<<2&12|b>>2&1],v[b<<
|
||||
2&12|b>>2&1]=kc(c,m()));break;case 1:192>b?(b=q(l(b)),c=k.d(b),k.e(b,yc(c,m()))):(c=v[b<<2&12|b>>2&1],v[b<<2&12|b>>2&1]=yc(c,m()));break;case 2:192>b?(b=q(l(b)),c=k.d(b),k.e(b,uc(c,m()))):(c=v[b<<2&12|b>>2&1],v[b<<2&12|b>>2&1]=uc(c,m()));break;case 3:192>b?(b=q(l(b)),c=k.d(b),k.e(b,wc(c,m()))):(c=v[b<<2&12|b>>2&1],v[b<<2&12|b>>2&1]=wc(c,m()));break;case 4:192>b?(b=q(l(b)),c=k.d(b),k.e(b,xc(c,m()))):(c=v[b<<2&12|b>>2&1],v[b<<2&12|b>>2&1]=xc(c,m()));break;case 5:192>b?(b=q(l(b)),c=k.d(b),k.e(b,vc(c,
|
||||
m()))):(c=v[b<<2&12|b>>2&1],v[b<<2&12|b>>2&1]=vc(c,m()));break;case 6:192>b?(b=q(l(b)),c=k.d(b),k.e(b,zc(c,m()))):(c=v[b<<2&12|b>>2&1],v[b<<2&12|b>>2&1]=zc(c,m()));break;case 7:c=192>b?ka(l(b)):v[b<<2&12|b>>2&1],lc(c,m())}};r[129]=function(){var b=m();switch(b>>3&7){case 0:var c,d;192>b?(c=l(b),b=q(c),J&&4095===(c&4095)?(d=q(c+1),c=B(b,d),n(b,d,eb(c,U()))):(c=k.b(b),k.a(b,eb(c,U())))):(c=g[b<<1&14],g[b<<1&14]=eb(c,U()));break;case 1:192>b?(c=l(b),b=q(c),J&&4095===(c&4095)?(d=q(c+1),c=B(b,d),n(b,d,
|
||||
vb(c,U()))):(c=k.b(b),k.a(b,vb(c,U())))):(c=g[b<<1&14],g[b<<1&14]=vb(c,U()));break;case 2:192>b?(c=l(b),b=q(c),J&&4095===(c&4095)?(d=q(c+1),c=B(b,d),n(b,d,jb(c,U()))):(c=k.b(b),k.a(b,jb(c,U())))):(c=g[b<<1&14],g[b<<1&14]=jb(c,U()));break;case 3:192>b?(c=l(b),b=q(c),J&&4095===(c&4095)?(d=q(c+1),c=B(b,d),n(b,d,nb(c,U()))):(c=k.b(b),k.a(b,nb(c,U())))):(c=g[b<<1&14],g[b<<1&14]=nb(c,U()));break;case 4:192>b?(c=l(b),b=q(c),J&&4095===(c&4095)?(d=q(c+1),c=B(b,d),n(b,d,tb(c,U()))):(c=k.b(b),k.a(b,tb(c,U())))):
|
||||
(c=g[b<<1&14],g[b<<1&14]=tb(c,U()));break;case 5:192>b?(c=l(b),b=q(c),J&&4095===(c&4095)?(d=q(c+1),c=B(b,d),n(b,d,lb(c,U()))):(c=k.b(b),k.a(b,lb(c,U())))):(c=g[b<<1&14],g[b<<1&14]=lb(c,U()));break;case 6:192>b?(c=l(b),b=q(c),J&&4095===(c&4095)?(d=q(c+1),c=B(b,d),n(b,d,xb(c,U()))):(c=k.b(b),k.a(b,xb(c,U())))):(c=g[b<<1&14],g[b<<1&14]=xb(c,U()));break;case 7:c=192>b?Q(l(b)):g[b<<1&14],Yb(c,U())}};s[129]=function(){var b=m();switch(b>>3&7){case 0:var c,d;192>b?(c=l(b),b=q(c),J&&4093<=(c&4095)?(d=q(c+
|
||||
3),c=G(b,d)>>>0,H(b,d,fb(c,M()>>>0))):(c=k.c(b)>>>0,k.f(b,fb(c,M()>>>0)))):(c=y[b&7],e[b&7]=fb(c,M()>>>0));break;case 1:192>b?(c=l(b),b=q(c),J&&4093<=(c&4095)?(d=q(c+3),c=G(b,d),H(b,d,wb(c,M()))):(c=k.c(b),k.f(b,wb(c,M())))):(c=e[b&7],e[b&7]=wb(c,M()));break;case 2:192>b?(c=l(b),b=q(c),J&&4093<=(c&4095)?(d=q(c+3),c=G(b,d)>>>0,H(b,d,kb(c,M()>>>0))):(c=k.c(b)>>>0,k.f(b,kb(c,M()>>>0)))):(c=y[b&7],e[b&7]=kb(c,M()>>>0));break;case 3:192>b?(c=l(b),b=q(c),J&&4093<=(c&4095)?(d=q(c+3),c=G(b,d)>>>0,H(b,d,ob(c,
|
||||
M()>>>0))):(c=k.c(b)>>>0,k.f(b,ob(c,M()>>>0)))):(c=y[b&7],e[b&7]=ob(c,M()>>>0));break;case 4:192>b?(c=l(b),b=q(c),J&&4093<=(c&4095)?(d=q(c+3),c=G(b,d),H(b,d,ub(c,M()))):(c=k.c(b),k.f(b,ub(c,M())))):(c=e[b&7],e[b&7]=ub(c,M()));break;case 5:192>b?(c=l(b),b=q(c),J&&4093<=(c&4095)?(d=q(c+3),c=G(b,d)>>>0,H(b,d,mb(c,M()>>>0))):(c=k.c(b)>>>0,k.f(b,mb(c,M()>>>0)))):(c=y[b&7],e[b&7]=mb(c,M()>>>0));break;case 6:192>b?(c=l(b),b=q(c),J&&4093<=(c&4095)?(d=q(c+3),c=G(b,d),H(b,d,yb(c,M()))):(c=k.c(b),k.f(b,yb(c,
|
||||
M())))):(c=e[b&7],e[b&7]=yb(c,M()));break;case 7:192>b?c=S(l(b))>>>0:c=y[b&7],Zb(c,M()>>>0)}};r[130]=s[130]=function(){Ab[128]()};r[131]=function(){var b=m();switch(b>>3&7){case 0:var c,d;192>b?(c=l(b),b=q(c),J&&4095===(c&4095)?(d=q(c+1),c=B(b,d),n(b,d,eb(c,P()&65535))):(c=k.b(b),k.a(b,eb(c,P()&65535)))):(c=g[b<<1&14],g[b<<1&14]=eb(c,P()&65535));break;case 1:192>b?(c=l(b),b=q(c),J&&4095===(c&4095)?(d=q(c+1),c=B(b,d),n(b,d,vb(c,P()))):(c=k.b(b),k.a(b,vb(c,P())))):(c=g[b<<1&14],g[b<<1&14]=vb(c,P()));
|
||||
break;case 2:192>b?(c=l(b),b=q(c),J&&4095===(c&4095)?(d=q(c+1),c=B(b,d),n(b,d,jb(c,P()&65535))):(c=k.b(b),k.a(b,jb(c,P()&65535)))):(c=g[b<<1&14],g[b<<1&14]=jb(c,P()&65535));break;case 3:192>b?(c=l(b),b=q(c),J&&4095===(c&4095)?(d=q(c+1),c=B(b,d),n(b,d,nb(c,P()&65535))):(c=k.b(b),k.a(b,nb(c,P()&65535)))):(c=g[b<<1&14],g[b<<1&14]=nb(c,P()&65535));break;case 4:192>b?(c=l(b),b=q(c),J&&4095===(c&4095)?(d=q(c+1),c=B(b,d),n(b,d,tb(c,P()))):(c=k.b(b),k.a(b,tb(c,P())))):(c=g[b<<1&14],g[b<<1&14]=tb(c,P()));
|
||||
break;case 5:192>b?(c=l(b),b=q(c),J&&4095===(c&4095)?(d=q(c+1),c=B(b,d),n(b,d,lb(c,P()&65535))):(c=k.b(b),k.a(b,lb(c,P()&65535)))):(c=g[b<<1&14],g[b<<1&14]=lb(c,P()&65535));break;case 6:192>b?(c=l(b),b=q(c),J&&4095===(c&4095)?(d=q(c+1),c=B(b,d),n(b,d,xb(c,P()))):(c=k.b(b),k.a(b,xb(c,P())))):(c=g[b<<1&14],g[b<<1&14]=xb(c,P()));break;case 7:c=192>b?Q(l(b)):g[b<<1&14],Yb(c,P()&65535)}};s[131]=function(){var b=m();switch(b>>3&7){case 0:var c,d;192>b?(c=l(b),b=q(c),J&&4093<=(c&4095)?(d=q(c+3),c=G(b,d)>>>
|
||||
0,H(b,d,fb(c,P()>>>0))):(c=k.c(b)>>>0,k.f(b,fb(c,P()>>>0)))):(c=y[b&7],e[b&7]=fb(c,P()>>>0));break;case 1:192>b?(c=l(b),b=q(c),J&&4093<=(c&4095)?(d=q(c+3),c=G(b,d),H(b,d,wb(c,P()))):(c=k.c(b),k.f(b,wb(c,P())))):(c=e[b&7],e[b&7]=wb(c,P()));break;case 2:192>b?(c=l(b),b=q(c),J&&4093<=(c&4095)?(d=q(c+3),c=G(b,d)>>>0,H(b,d,kb(c,P()>>>0))):(c=k.c(b)>>>0,k.f(b,kb(c,P()>>>0)))):(c=y[b&7],e[b&7]=kb(c,P()>>>0));break;case 3:192>b?(c=l(b),b=q(c),J&&4093<=(c&4095)?(d=q(c+3),c=G(b,d)>>>0,H(b,d,ob(c,P()>>>0))):
|
||||
(c=k.c(b)>>>0,k.f(b,ob(c,P()>>>0)))):(c=y[b&7],e[b&7]=ob(c,P()>>>0));break;case 4:192>b?(c=l(b),b=q(c),J&&4093<=(c&4095)?(d=q(c+3),c=G(b,d),H(b,d,ub(c,P()))):(c=k.c(b),k.f(b,ub(c,P())))):(c=e[b&7],e[b&7]=ub(c,P()));break;case 5:192>b?(c=l(b),b=q(c),J&&4093<=(c&4095)?(d=q(c+3),c=G(b,d)>>>0,H(b,d,mb(c,P()>>>0))):(c=k.c(b)>>>0,k.f(b,mb(c,P()>>>0)))):(c=y[b&7],e[b&7]=mb(c,P()>>>0));break;case 6:192>b?(c=l(b),b=q(c),J&&4093<=(c&4095)?(d=q(c+3),c=G(b,d),H(b,d,yb(c,P()))):(c=k.c(b),k.f(b,yb(c,P())))):(c=
|
||||
e[b&7],e[b&7]=yb(c,P()));break;case 7:192>b?c=S(l(b))>>>0:c=y[b&7],Zb(c,P()>>>0)}};r[132]=s[132]=function(){var b=m(),c=192>b?ka(l(b)):v[b<<2&12|b>>2&1];id(c,v[b>>1&12|b>>5&1])};r[133]=function(){var b=m(),c=192>b?Q(l(b)):g[b<<1&14];jd(c,g[b>>2&14])};s[133]=function(){var b=m(),c=192>b?S(l(b)):e[b&7];kd(c,e[b>>3&7])};r[134]=s[134]=function(){var b=m(),c,d;192>b?(d=q(l(b)),c=k.d(d),k.e(d,ne(c,b))):(c=v[b<<2&12|b>>2&1],v[b<<2&12|b>>2&1]=ne(c,b))};r[135]=function(){var b=m(),c,d,e;192>b?(c=l(b),d=q(c),
|
||||
J&&4095===(c&4095)?(e=q(c+1),c=B(d,e),n(d,e,Rd(c,b))):(c=k.b(d),k.a(d,Rd(c,b)))):(c=g[b<<1&14],g[b<<1&14]=Rd(c,b))};s[135]=function(){var b=m(),c,d,g;192>b?(c=l(b),d=q(c),J&&4093<=(c&4095)?(g=q(c+3),c=G(d,g)>>>0,H(d,g,Sd(c,b))):(c=k.c(d)>>>0,k.f(d,Sd(c,b)))):(c=y[b&7],e[b&7]=Sd(c,b))};r[136]=s[136]=function(){var b=m();192>b?V(l(b),v[b>>1&12|b>>5&1]):v[b<<2&12|b>>2&1]=v[b>>1&12|b>>5&1]};r[137]=function(){var b=m();192>b?R(l(b),g[b>>2&14]):g[b<<1&14]=g[b>>2&14]};s[137]=function(){var b=m();192>b?N(l(b),
|
||||
e[b>>3&7]):y[b&7]=e[b>>3&7]};r[138]=s[138]=function(){var b=m(),c=192>b?ka(l(b)):v[b<<2&12|b>>2&1];v[b>>1&12|b>>5&1]=c};r[139]=function(){var b=m(),c=192>b?Q(l(b)):g[b<<1&14];g[b>>2&14]=c};s[139]=function(){var b=m(),c=192>b?S(l(b)):e[b&7];e[b>>3&7]=c};r[140]=function(){var b=m();192>b?R(l(b),ra[b>>3&7]):g[b<<1&14]=ra[b>>3&7]};s[140]=function(){var b=m();192>b?N(l(b),ra[b>>3&7]):y[b&7]=ra[b>>3&7]};r[141]=function(){var b=m();ab=6;g[(b>>3&7)<<1]=l(b);ab=-1};s[141]=function(){var b=m();ab=6;y[b>>3&
|
||||
7]=l(b);ab=-1};r[142]=s[142]=function(){var b=m(),c=b>>3&7,b=192>b?Q(l(b)):g[b<<1&14];ca(c,b)};r[143]=s[143]=function(){var b=m();if(xa){var c=Va(0);$[aa]+=4;192>b?N(l(b),k.c(c)):y[b&7]=k.c(c)}else c=Va(0),$[aa]+=2,192>b?R(l(b),k.b(c)):g[b<<1&14]=k.b(c)};r[144]=function(){$b(0)};s[144]=function(){ac(0)};r[145]=function(){$b(2)};s[145]=function(){ac(1)};r[146]=function(){$b(4)};s[146]=function(){ac(2)};r[147]=function(){$b(6)};s[147]=function(){ac(3)};r[148]=function(){$b(8)};s[148]=function(){ac(4)};
|
||||
r[149]=function(){$b(10)};s[149]=function(){ac(5)};r[150]=function(){$b(12)};s[150]=function(){ac(6)};r[151]=function(){$b(14)};s[151]=function(){ac(7)};r[144]=s[144]=function(){};r[152]=function(){g[0]=fc[0]};s[152]=function(){y[0]=Ga[0]};r[153]=function(){g[4]=Ga[0]>>15};s[153]=function(){y[2]=e[0]>>31};r[154]=function(){if(Ma)throw ze("16 bit callf in protected mode");var b=U(),c=U();la(ra[1]);la(pa());ca(1,c);E=da[1]+b|0};s[154]=function(){if(Ma)throw ze("callf");var b=M(),c=U();ia(ra[1]);ia(pa());
|
||||
ca(1,c);E=da[1]+b|0};r[155]=s[155]=function(){};r[156]=function(){na();la(u)};s[156]=function(){na();ia(u)};r[157]=function(){var b;b=Aa();jc(b);Da()};s[157]=function(){jc(ua());Da()};r[158]=s[158]=function(){u=u&-256|v[1];u=u&4161493|2;K=0};r[159]=s[159]=function(){na();v[1]=u};r[160]=s[160]=function(){var b=ka(F());v[0]=b};r[161]=function(){var b=Q(F());g[0]=b};s[161]=function(){var b=S(F());y[0]=b};r[162]=s[162]=function(){V(F(),v[0])};r[163]=function(){R(F(),g[0])};s[163]=function(){N(F(),e[0])};
|
||||
r[164]=s[164]=function(){var b,c,d=u&1024?-1:1;c=da[0]+A[T];b=h(3)+A[W];if(wa){if(0!==A[ga]){do V(c,ka(b)),c+=d,A[T]+=d,b+=d,A[W]+=d;while(--A[ga])}}else V(c,ka(b)),A[T]+=d,A[W]+=d};r[165]=function(){var b,c,d=u&1024?-2:2;c=da[0]+A[T];b=h(3)+A[W];if(wa){if(0!==A[ga]){var e=0===(c&1)&&0===(b&1);do{if(e){var g=Ea(b),l=q(c);k.S(l,k.q(g))}else R(c,Q(b));c+=d;A[T]+=d;b+=d;A[W]+=d}while(--A[ga])}}else R(c,Q(b)),A[T]+=d,A[W]+=d};s[165]=function(){var b,c,d=u&1024?-4:4;c=da[0]+A[T];b=h(3)+A[W];if(wa){if(0!==
|
||||
A[ga]){var e=0===(c&3)&&0===(b&3);do{if(e){var g=Ea(b),l=q(c);k.D(l,k.v(g))}else N(c,S(b));c+=d;A[T]+=d;b+=d;A[W]+=d}while(--A[ga])}}else N(c,S(b)),A[T]+=d,A[W]+=d};r[166]=s[166]=function(){a:{var b,c,d,e,g=u&1024?-1:1;c=da[0]+A[T];b=h(3)+A[W];if(wa){if(0===A[ga])break a;do e=ka(c),d=ka(b),c+=g,A[T]+=g,b+=g,A[W]+=g;while(--A[ga]&&d===e===cc)}else e=ka(c),d=ka(b),A[T]+=g,A[W]+=g;lc(d,e)}};r[167]=function(){a:{var b,c,d,e,g=u&1024?-2:2;c=da[0]+A[T];b=h(3)+A[W];if(wa){if(0===A[ga])break a;var l=0===
|
||||
(c&1)&&0===(b&1);do l?(e=k.q(Ea(c)),d=k.q(Ea(b))):(e=Q(c),d=Q(b)),c+=g,A[T]+=g,b+=g,A[W]+=g;while(--A[ga]&&d===e===cc)}else e=Q(c),d=Q(b),A[T]+=g,A[W]+=g;Yb(d,e)}};s[167]=function(){a:{var b,c,d,e,g=u&1024?-4:4;c=da[0]+A[T];b=h(3)+A[W];if(wa){if(0===A[ga])break a;var l=0===(c&3)&&0===(b&3);do l?(e=k.v(Ea(c))>>>0,d=k.v(Ea(b))>>>0):(e=S(c)>>>0,d=S(b)>>>0),c+=g,A[T]+=g,b+=g,A[W]+=g;while(--A[ga]&&d===e===cc)}else e=S(c)>>>0,d=S(b)>>>0,A[T]+=g,A[W]+=g;Zb(d,e)}};r[168]=s[168]=function(){id(v[0],m())};
|
||||
r[169]=function(){jd(g[0],U())};s[169]=function(){kd(e[0],M())};r[170]=s[170]=function(){var b=v[0],c,d=u&1024?-1:1;c=da[0]+A[T];if(wa){if(0!==A[ga]){do V(c,b),c+=d,A[T]+=d;while(--A[ga])}}else V(c,b),A[T]+=d};r[171]=function(){var b=g[0],c,d=u&1024?-2:2;c=da[0]+A[T];if(wa){if(0!==A[ga]){var e=0===(c&1)&&!0;do e?k.S(q(c),b):R(c,b),c+=d,A[T]+=d;while(--A[ga])}}else R(c,b),A[T]+=d};s[171]=function(){var b=y[0],c,d=u&1024?-4:4;c=da[0]+A[T];if(wa){if(0!==A[ga]){var e=0===(c&3)&&!0;do e?k.D(q(c),b):N(c,
|
||||
b),c+=d,A[T]+=d;while(--A[ga])}}else N(c,b),A[T]+=d};r[172]=s[172]=function(){var b,c=u&1024?-1:1;b=h(3)+A[W];if(wa){if(0!==A[ga]){do v[0]=ka(b),b+=c,A[W]+=c;while(--A[ga])}}else v[0]=ka(b),A[W]+=c};r[173]=function(){var b,c=u&1024?-2:2;b=h(3)+A[W];if(wa){if(0!==A[ga]){do g[0]=Q(b),b+=c,A[W]+=c;while(--A[ga])}}else g[0]=Q(b),A[W]+=c};s[173]=function(){var b,c=u&1024?-4:4;b=h(3)+A[W];if(wa){if(0!==A[ga]){do y[0]=S(b),b+=c,A[W]+=c;while(--A[ga])}}else y[0]=S(b),A[W]+=c};r[174]=s[174]=function(){a:{var b,
|
||||
c,d,e=u&1024?-1:1;c=v[0];b=da[0]+A[T];if(wa){if(0===A[ga])break a;do d=ka(b),b+=e,A[T]+=e;while(--A[ga]&&c===d===cc)}else d=ka(b),A[T]+=e;lc(c,d)}};r[175]=function(){a:{var b,c,d,e=u&1024?-2:2;c=g[0];b=da[0]+A[T];if(wa){if(0===A[ga])break a;var h=0===(b&1)&&!0;do d=h?k.q(Ea(b)):Q(b),b+=e,A[T]+=e;while(--A[ga]&&c===d===cc)}else d=Q(b),A[T]+=e;Yb(c,d)}};s[175]=function(){a:{var b,c,d,e=u&1024?-4:4;c=y[0];b=da[0]+A[T];if(wa){if(0===A[ga])break a;var g=0===(b&3)&&!0;do d=g?k.v(Ea(b))>>>0:S(b)>>>0,b+=
|
||||
e,A[T]+=e;while(--A[ga]&&c===d===cc)}else d=S(b)>>>0,A[T]+=e;Zb(c,d)}};r[176]=s[176]=function(){v[0]=m()};r[177]=s[177]=function(){v[4]=m()};r[178]=s[178]=function(){v[8]=m()};r[179]=s[179]=function(){v[12]=m()};r[180]=s[180]=function(){v[1]=m()};r[181]=s[181]=function(){v[5]=m()};r[182]=s[182]=function(){v[9]=m()};r[183]=s[183]=function(){v[13]=m()};r[184]=function(){g[0]=U()};s[184]=function(){e[0]=M()};r[185]=function(){g[2]=U()};s[185]=function(){e[1]=M()};r[186]=function(){g[4]=U()};s[186]=function(){e[2]=
|
||||
M()};r[187]=function(){g[6]=U()};s[187]=function(){e[3]=M()};r[188]=function(){g[8]=U()};s[188]=function(){e[4]=M()};r[189]=function(){g[10]=U()};s[189]=function(){e[5]=M()};r[190]=function(){g[12]=U()};s[190]=function(){e[6]=M()};r[191]=function(){g[14]=U()};s[191]=function(){e[7]=M()};r[192]=s[192]=function(){var b=m();switch(b>>3&7){case 0:var c;192>b?(b=q(l(b)),c=k.d(b),k.e(b,Ac(c,m()&31))):(c=v[b<<2&12|b>>2&1],v[b<<2&12|b>>2&1]=Ac(c,m()&31));break;case 1:192>b?(b=q(l(b)),c=k.d(b),k.e(b,Cc(c,
|
||||
m()&31))):(c=v[b<<2&12|b>>2&1],v[b<<2&12|b>>2&1]=Cc(c,m()&31));break;case 2:192>b?(b=q(l(b)),c=k.d(b),k.e(b,Bc(c,m()&31))):(c=v[b<<2&12|b>>2&1],v[b<<2&12|b>>2&1]=Bc(c,m()&31));break;case 3:192>b?(b=q(l(b)),c=k.d(b),k.e(b,Dc(c,m()&31))):(c=v[b<<2&12|b>>2&1],v[b<<2&12|b>>2&1]=Dc(c,m()&31));break;case 4:192>b?(b=q(l(b)),c=k.d(b),k.e(b,gb(c,m()&31))):(c=v[b<<2&12|b>>2&1],v[b<<2&12|b>>2&1]=gb(c,m()&31));break;case 5:192>b?(b=q(l(b)),c=k.d(b),k.e(b,Ec(c,m()&31))):(c=v[b<<2&12|b>>2&1],v[b<<2&12|b>>2&1]=
|
||||
Ec(c,m()&31));break;case 6:192>b?(b=q(l(b)),c=k.d(b),k.e(b,gb(c,m()&31))):(c=v[b<<2&12|b>>2&1],v[b<<2&12|b>>2&1]=gb(c,m()&31));break;case 7:192>b?(b=q(l(b)),c=k.d(b),k.e(b,Fc(c,m()&31))):(c=v[b<<2&12|b>>2&1],v[b<<2&12|b>>2&1]=Fc(c,m()&31))}};r[193]=function(){var b=m();switch(b>>3&7){case 0:var c,d;192>b?(c=l(b),b=q(c),J&&4095===(c&4095)?(d=q(c+1),c=B(b,d),n(b,d,Hb(c,m()&31))):(c=k.b(b),k.a(b,Hb(c,m()&31)))):(c=g[b<<1&14],g[b<<1&14]=Hb(c,m()&31));break;case 1:192>b?(c=l(b),b=q(c),J&&4095===(c&4095)?
|
||||
(d=q(c+1),c=B(b,d),n(b,d,Lb(c,m()&31))):(c=k.b(b),k.a(b,Lb(c,m()&31)))):(c=g[b<<1&14],g[b<<1&14]=Lb(c,m()&31));break;case 2:192>b?(c=l(b),b=q(c),J&&4095===(c&4095)?(d=q(c+1),c=B(b,d),n(b,d,Jb(c,m()&31))):(c=k.b(b),k.a(b,Jb(c,m()&31)))):(c=g[b<<1&14],g[b<<1&14]=Jb(c,m()&31));break;case 3:192>b?(c=l(b),b=q(c),J&&4095===(c&4095)?(d=q(c+1),c=B(b,d),n(b,d,Nb(c,m()&31))):(c=k.b(b),k.a(b,Nb(c,m()&31)))):(c=g[b<<1&14],g[b<<1&14]=Nb(c,m()&31));break;case 4:192>b?(c=l(b),b=q(c),J&&4095===(c&4095)?(d=q(c+1),
|
||||
c=B(b,d),n(b,d,Ja(c,m()&31))):(c=k.b(b),k.a(b,Ja(c,m()&31)))):(c=g[b<<1&14],g[b<<1&14]=Ja(c,m()&31));break;case 5:192>b?(c=l(b),b=q(c),J&&4095===(c&4095)?(d=q(c+1),c=B(b,d),n(b,d,Pb(c,m()&31))):(c=k.b(b),k.a(b,Pb(c,m()&31)))):(c=g[b<<1&14],g[b<<1&14]=Pb(c,m()&31));break;case 6:192>b?(c=l(b),b=q(c),J&&4095===(c&4095)?(d=q(c+1),c=B(b,d),n(b,d,Ja(c,m()&31))):(c=k.b(b),k.a(b,Ja(c,m()&31)))):(c=g[b<<1&14],g[b<<1&14]=Ja(c,m()&31));break;case 7:192>b?(c=l(b),b=q(c),J&&4095===(c&4095)?(d=q(c+1),c=B(b,d),
|
||||
n(b,d,Rb(c,m()&31))):(c=k.b(b),k.a(b,Rb(c,m()&31)))):(c=g[b<<1&14],g[b<<1&14]=Rb(c,m()&31))}};s[193]=function(){var b=m();switch(b>>3&7){case 0:var c,d;192>b?(c=l(b),b=q(c),J&&4093<=(c&4095)?(d=q(c+3),c=G(b,d)>>>0,H(b,d,Ib(c,m()&31))):(c=k.c(b)>>>0,k.f(b,Ib(c,m()&31)))):(c=y[b&7],e[b&7]=Ib(c,m()&31));break;case 1:192>b?(c=l(b),b=q(c),J&&4093<=(c&4095)?(d=q(c+3),c=G(b,d)>>>0,H(b,d,Mb(c,m()&31))):(c=k.c(b)>>>0,k.f(b,Mb(c,m()&31)))):(c=y[b&7],e[b&7]=Mb(c,m()&31));break;case 2:192>b?(c=l(b),b=q(c),J&&
|
||||
4093<=(c&4095)?(d=q(c+3),c=G(b,d)>>>0,H(b,d,Kb(c,m()&31))):(c=k.c(b)>>>0,k.f(b,Kb(c,m()&31)))):(c=y[b&7],e[b&7]=Kb(c,m()&31));break;case 3:192>b?(c=l(b),b=q(c),J&&4093<=(c&4095)?(d=q(c+3),c=G(b,d)>>>0,H(b,d,Ob(c,m()&31))):(c=k.c(b)>>>0,k.f(b,Ob(c,m()&31)))):(c=y[b&7],e[b&7]=Ob(c,m()&31));break;case 4:192>b?(c=l(b),b=q(c),J&&4093<=(c&4095)?(d=q(c+3),c=G(b,d)>>>0,H(b,d,Ka(c,m()&31))):(c=k.c(b)>>>0,k.f(b,Ka(c,m()&31)))):(c=y[b&7],e[b&7]=Ka(c,m()&31));break;case 5:192>b?(c=l(b),b=q(c),J&&4093<=(c&4095)?
|
||||
(d=q(c+3),c=G(b,d)>>>0,H(b,d,Qb(c,m()&31))):(c=k.c(b)>>>0,k.f(b,Qb(c,m()&31)))):(c=y[b&7],e[b&7]=Qb(c,m()&31));break;case 6:192>b?(c=l(b),b=q(c),J&&4093<=(c&4095)?(d=q(c+3),c=G(b,d)>>>0,H(b,d,Ka(c,m()&31))):(c=k.c(b)>>>0,k.f(b,Ka(c,m()&31)))):(c=y[b&7],e[b&7]=Ka(c,m()&31));break;case 7:192>b?(c=l(b),b=q(c),J&&4093<=(c&4095)?(d=q(c+3),c=G(b,d)>>>0,H(b,d,Sb(c,m()&31))):(c=k.c(b)>>>0,k.f(b,Sb(c,m()&31)))):(c=y[b&7],e[b&7]=Sb(c,m()&31))}};r[194]=function(){var b=U();E=da[1]+Aa()|0;y[4]+=b};s[194]=function(){var b=
|
||||
U();E=da[1]+ua()|0;y[4]+=b};r[195]=function(){E=da[1]+Aa()|0};s[195]=function(){E=da[1]+ua()|0};r[196]=s[196]=function(){var b=m();192<=b?za(6):xa?Vc(0,l(b),b>>3&7):Uc(0,l(b),b>>2&14)};r[197]=s[197]=function(){var b=m();192<=b?za(6):xa?Vc(3,l(b),b>>3&7):Uc(3,l(b),b>>2&14)};r[198]=s[198]=function(){var b=m();192>b?V(l(b),m()):v[b<<2&12|b>>2&1]=m()};r[199]=function(){var b=m();192>b?R(l(b),U()):g[b<<1&14]=U()};s[199]=function(){var b=m();192>b?N(l(b),M()):y[b&7]=M()};r[200]=function(){var b=U(),c=m(),
|
||||
d;la(g[10]);d=g[8];if(0<c){for(var e=1;e<c;e++)g[10]-=2,la(g[10]);la(d)}g[10]=d;g[8]=d-b};s[200]=function(){var b=U(),c=m()&31,d;ia(e[5]);d=e[4];if(0<c){for(var g=1;g<c;g++)y[5]-=4,ia(e[5]);ia(d)}y[5]=d;y[4]-=b};r[201]=function(){$[aa]=$[sc];g[10]=Aa()};s[201]=function(){$[aa]=$[sc];y[5]=ua()};r[202]=function(){if(Ma)throw ze("16 bit retf in protected mode");var b=U(),c=Aa();ca(1,Aa());E=da[1]+c|0;g[8]+=b};s[202]=function(){var b=U();if(Ma){var c=ua();ca(1,ua()&65535);E=da[1]+c|0;$[aa]+=b}else throw ze("32 bit retf in real mode");
|
||||
};r[203]=function(){if(Ma)throw ze("16 bit retf in protected mode");var b=Aa();ca(1,Aa());E=da[1]+b|0};s[203]=function(){var b=ua();ca(1,ua()&65535);E=da[1]+b|0};r[204]=s[204]=function(){ha(3,!0,!1)};r[205]=s[205]=function(){var b=m();ha(b,!0,!1)};r[206]=s[206]=function(){Tc()&&ha(4,!0,!1)};r[207]=function(){if(Ma)throw ze("16 bit iret in protected mode");var b=Aa();ca(1,Aa());var c=Aa();E=b+da[1]|0;u=c;K=0;Da()};s[207]=function(){if(!Ma)throw ze("32 bit iret in real mode");E=ua();ra[1]=ua();var b=
|
||||
ua(),c=Bb(ra[1]);if(c.A)throw ze("is null");if(!c.B)throw ze("not present");if(!c.F)throw ze("not exec");if(c.t<ya)throw ze("rpl < cpl");if(c.C&&c.l>c.t)throw ze("conforming and dpl > rpl");if(c.t>ya){var d=ua(),e=ua();y[4]=d;jc(b);ya=c.t;ca(2,e&65535);X()}else jc(b);Da()};r[208]=s[208]=function(){var b=m();switch(b>>3&7){case 0:var c;192>b?(b=q(l(b)),c=k.d(b),k.e(b,Ac(c,1))):(c=v[b<<2&12|b>>2&1],v[b<<2&12|b>>2&1]=Ac(c,1));break;case 1:192>b?(b=q(l(b)),c=k.d(b),k.e(b,Cc(c,1))):(c=v[b<<2&12|b>>2&1],
|
||||
v[b<<2&12|b>>2&1]=Cc(c,1));break;case 2:192>b?(b=q(l(b)),c=k.d(b),k.e(b,Bc(c,1))):(c=v[b<<2&12|b>>2&1],v[b<<2&12|b>>2&1]=Bc(c,1));break;case 3:192>b?(b=q(l(b)),c=k.d(b),k.e(b,Dc(c,1))):(c=v[b<<2&12|b>>2&1],v[b<<2&12|b>>2&1]=Dc(c,1));break;case 4:192>b?(b=q(l(b)),c=k.d(b),k.e(b,gb(c,1))):(c=v[b<<2&12|b>>2&1],v[b<<2&12|b>>2&1]=gb(c,1));break;case 5:192>b?(b=q(l(b)),c=k.d(b),k.e(b,Ec(c,1))):(c=v[b<<2&12|b>>2&1],v[b<<2&12|b>>2&1]=Ec(c,1));break;case 6:192>b?(b=q(l(b)),c=k.d(b),k.e(b,gb(c,1))):(c=v[b<<
|
||||
2&12|b>>2&1],v[b<<2&12|b>>2&1]=gb(c,1));break;case 7:192>b?(b=q(l(b)),c=k.d(b),k.e(b,Fc(c,1))):(c=v[b<<2&12|b>>2&1],v[b<<2&12|b>>2&1]=Fc(c,1))}};r[209]=function(){var b=m();switch(b>>3&7){case 0:var c,d;192>b?(c=l(b),b=q(c),J&&4095===(c&4095)?(d=q(c+1),c=B(b,d),n(b,d,Hb(c,1))):(c=k.b(b),k.a(b,Hb(c,1)))):(c=g[b<<1&14],g[b<<1&14]=Hb(c,1));break;case 1:192>b?(c=l(b),b=q(c),J&&4095===(c&4095)?(d=q(c+1),c=B(b,d),n(b,d,Lb(c,1))):(c=k.b(b),k.a(b,Lb(c,1)))):(c=g[b<<1&14],g[b<<1&14]=Lb(c,1));break;case 2:192>
|
||||
b?(c=l(b),b=q(c),J&&4095===(c&4095)?(d=q(c+1),c=B(b,d),n(b,d,Jb(c,1))):(c=k.b(b),k.a(b,Jb(c,1)))):(c=g[b<<1&14],g[b<<1&14]=Jb(c,1));break;case 3:192>b?(c=l(b),b=q(c),J&&4095===(c&4095)?(d=q(c+1),c=B(b,d),n(b,d,Nb(c,1))):(c=k.b(b),k.a(b,Nb(c,1)))):(c=g[b<<1&14],g[b<<1&14]=Nb(c,1));break;case 4:192>b?(c=l(b),b=q(c),J&&4095===(c&4095)?(d=q(c+1),c=B(b,d),n(b,d,Ja(c,1))):(c=k.b(b),k.a(b,Ja(c,1)))):(c=g[b<<1&14],g[b<<1&14]=Ja(c,1));break;case 5:192>b?(c=l(b),b=q(c),J&&4095===(c&4095)?(d=q(c+1),c=B(b,d),
|
||||
n(b,d,Pb(c,1))):(c=k.b(b),k.a(b,Pb(c,1)))):(c=g[b<<1&14],g[b<<1&14]=Pb(c,1));break;case 6:192>b?(c=l(b),b=q(c),J&&4095===(c&4095)?(d=q(c+1),c=B(b,d),n(b,d,Ja(c,1))):(c=k.b(b),k.a(b,Ja(c,1)))):(c=g[b<<1&14],g[b<<1&14]=Ja(c,1));break;case 7:192>b?(c=l(b),b=q(c),J&&4095===(c&4095)?(d=q(c+1),c=B(b,d),n(b,d,Rb(c,1))):(c=k.b(b),k.a(b,Rb(c,1)))):(c=g[b<<1&14],g[b<<1&14]=Rb(c,1))}};s[209]=function(){var b=m();switch(b>>3&7){case 0:var c,d;192>b?(c=l(b),b=q(c),J&&4093<=(c&4095)?(d=q(c+3),c=G(b,d)>>>0,H(b,
|
||||
d,Ib(c,1))):(c=k.c(b)>>>0,k.f(b,Ib(c,1)))):(c=y[b&7],e[b&7]=Ib(c,1));break;case 1:192>b?(c=l(b),b=q(c),J&&4093<=(c&4095)?(d=q(c+3),c=G(b,d)>>>0,H(b,d,Mb(c,1))):(c=k.c(b)>>>0,k.f(b,Mb(c,1)))):(c=y[b&7],e[b&7]=Mb(c,1));break;case 2:192>b?(c=l(b),b=q(c),J&&4093<=(c&4095)?(d=q(c+3),c=G(b,d)>>>0,H(b,d,Kb(c,1))):(c=k.c(b)>>>0,k.f(b,Kb(c,1)))):(c=y[b&7],e[b&7]=Kb(c,1));break;case 3:192>b?(c=l(b),b=q(c),J&&4093<=(c&4095)?(d=q(c+3),c=G(b,d)>>>0,H(b,d,Ob(c,1))):(c=k.c(b)>>>0,k.f(b,Ob(c,1)))):(c=y[b&7],e[b&
|
||||
7]=Ob(c,1));break;case 4:192>b?(c=l(b),b=q(c),J&&4093<=(c&4095)?(d=q(c+3),c=G(b,d)>>>0,H(b,d,Ka(c,1))):(c=k.c(b)>>>0,k.f(b,Ka(c,1)))):(c=y[b&7],e[b&7]=Ka(c,1));break;case 5:192>b?(c=l(b),b=q(c),J&&4093<=(c&4095)?(d=q(c+3),c=G(b,d)>>>0,H(b,d,Qb(c,1))):(c=k.c(b)>>>0,k.f(b,Qb(c,1)))):(c=y[b&7],e[b&7]=Qb(c,1));break;case 6:192>b?(c=l(b),b=q(c),J&&4093<=(c&4095)?(d=q(c+3),c=G(b,d)>>>0,H(b,d,Ka(c,1))):(c=k.c(b)>>>0,k.f(b,Ka(c,1)))):(c=y[b&7],e[b&7]=Ka(c,1));break;case 7:192>b?(c=l(b),b=q(c),J&&4093<=(c&
|
||||
4095)?(d=q(c+3),c=G(b,d)>>>0,H(b,d,Sb(c,1))):(c=k.c(b)>>>0,k.f(b,Sb(c,1)))):(c=y[b&7],e[b&7]=Sb(c,1))}};r[210]=s[210]=function(){var b=m(),c=v[4]&31;switch(b>>3&7){case 0:var d;192>b?(b=q(l(b)),d=k.d(b),k.e(b,Ac(d,c))):(d=v[b<<2&12|b>>2&1],v[b<<2&12|b>>2&1]=Ac(d,c));break;case 1:192>b?(b=q(l(b)),d=k.d(b),k.e(b,Cc(d,c))):(d=v[b<<2&12|b>>2&1],v[b<<2&12|b>>2&1]=Cc(d,c));break;case 2:192>b?(b=q(l(b)),d=k.d(b),k.e(b,Bc(d,c))):(d=v[b<<2&12|b>>2&1],v[b<<2&12|b>>2&1]=Bc(d,c));break;case 3:192>b?(b=q(l(b)),
|
||||
d=k.d(b),k.e(b,Dc(d,c))):(d=v[b<<2&12|b>>2&1],v[b<<2&12|b>>2&1]=Dc(d,c));break;case 4:192>b?(b=q(l(b)),d=k.d(b),k.e(b,gb(d,c))):(d=v[b<<2&12|b>>2&1],v[b<<2&12|b>>2&1]=gb(d,c));break;case 5:192>b?(b=q(l(b)),d=k.d(b),k.e(b,Ec(d,c))):(d=v[b<<2&12|b>>2&1],v[b<<2&12|b>>2&1]=Ec(d,c));break;case 6:192>b?(b=q(l(b)),d=k.d(b),k.e(b,gb(d,c))):(d=v[b<<2&12|b>>2&1],v[b<<2&12|b>>2&1]=gb(d,c));break;case 7:192>b?(b=q(l(b)),d=k.d(b),k.e(b,Fc(d,c))):(d=v[b<<2&12|b>>2&1],v[b<<2&12|b>>2&1]=Fc(d,c))}};r[211]=function(){var b=
|
||||
m(),c=v[4]&31;switch(b>>3&7){case 0:var d,e;192>b?(d=l(b),b=q(d),J&&4095===(d&4095)?(e=q(d+1),d=B(b,e),n(b,e,Hb(d,c))):(d=k.b(b),k.a(b,Hb(d,c)))):(d=g[b<<1&14],g[b<<1&14]=Hb(d,c));break;case 1:192>b?(d=l(b),b=q(d),J&&4095===(d&4095)?(e=q(d+1),d=B(b,e),n(b,e,Lb(d,c))):(d=k.b(b),k.a(b,Lb(d,c)))):(d=g[b<<1&14],g[b<<1&14]=Lb(d,c));break;case 2:192>b?(d=l(b),b=q(d),J&&4095===(d&4095)?(e=q(d+1),d=B(b,e),n(b,e,Jb(d,c))):(d=k.b(b),k.a(b,Jb(d,c)))):(d=g[b<<1&14],g[b<<1&14]=Jb(d,c));break;case 3:192>b?(d=l(b),
|
||||
b=q(d),J&&4095===(d&4095)?(e=q(d+1),d=B(b,e),n(b,e,Nb(d,c))):(d=k.b(b),k.a(b,Nb(d,c)))):(d=g[b<<1&14],g[b<<1&14]=Nb(d,c));break;case 4:192>b?(d=l(b),b=q(d),J&&4095===(d&4095)?(e=q(d+1),d=B(b,e),n(b,e,Ja(d,c))):(d=k.b(b),k.a(b,Ja(d,c)))):(d=g[b<<1&14],g[b<<1&14]=Ja(d,c));break;case 5:192>b?(d=l(b),b=q(d),J&&4095===(d&4095)?(e=q(d+1),d=B(b,e),n(b,e,Pb(d,c))):(d=k.b(b),k.a(b,Pb(d,c)))):(d=g[b<<1&14],g[b<<1&14]=Pb(d,c));break;case 6:192>b?(d=l(b),b=q(d),J&&4095===(d&4095)?(e=q(d+1),d=B(b,e),n(b,e,Ja(d,
|
||||
c))):(d=k.b(b),k.a(b,Ja(d,c)))):(d=g[b<<1&14],g[b<<1&14]=Ja(d,c));break;case 7:192>b?(d=l(b),b=q(d),J&&4095===(d&4095)?(e=q(d+1),d=B(b,e),n(b,e,Rb(d,c))):(d=k.b(b),k.a(b,Rb(d,c)))):(d=g[b<<1&14],g[b<<1&14]=Rb(d,c))}};s[211]=function(){var b=m(),c=v[4]&31;switch(b>>3&7){case 0:var d,g;192>b?(d=l(b),b=q(d),J&&4093<=(d&4095)?(g=q(d+3),d=G(b,g)>>>0,H(b,g,Ib(d,c))):(d=k.c(b)>>>0,k.f(b,Ib(d,c)))):(d=y[b&7],e[b&7]=Ib(d,c));break;case 1:192>b?(d=l(b),b=q(d),J&&4093<=(d&4095)?(g=q(d+3),d=G(b,g)>>>0,H(b,g,
|
||||
Mb(d,c))):(d=k.c(b)>>>0,k.f(b,Mb(d,c)))):(d=y[b&7],e[b&7]=Mb(d,c));break;case 2:192>b?(d=l(b),b=q(d),J&&4093<=(d&4095)?(g=q(d+3),d=G(b,g)>>>0,H(b,g,Kb(d,c))):(d=k.c(b)>>>0,k.f(b,Kb(d,c)))):(d=y[b&7],e[b&7]=Kb(d,c));break;case 3:192>b?(d=l(b),b=q(d),J&&4093<=(d&4095)?(g=q(d+3),d=G(b,g)>>>0,H(b,g,Ob(d,c))):(d=k.c(b)>>>0,k.f(b,Ob(d,c)))):(d=y[b&7],e[b&7]=Ob(d,c));break;case 4:192>b?(d=l(b),b=q(d),J&&4093<=(d&4095)?(g=q(d+3),d=G(b,g)>>>0,H(b,g,Ka(d,c))):(d=k.c(b)>>>0,k.f(b,Ka(d,c)))):(d=y[b&7],e[b&7]=
|
||||
Ka(d,c));break;case 5:192>b?(d=l(b),b=q(d),J&&4093<=(d&4095)?(g=q(d+3),d=G(b,g)>>>0,H(b,g,Qb(d,c))):(d=k.c(b)>>>0,k.f(b,Qb(d,c)))):(d=y[b&7],e[b&7]=Qb(d,c));break;case 6:192>b?(d=l(b),b=q(d),J&&4093<=(d&4095)?(g=q(d+3),d=G(b,g)>>>0,H(b,g,Ka(d,c))):(d=k.c(b)>>>0,k.f(b,Ka(d,c)))):(d=y[b&7],e[b&7]=Ka(d,c));break;case 7:192>b?(d=l(b),b=q(d),J&&4093<=(d&4095)?(g=q(d+3),d=G(b,g)>>>0,H(b,g,Sb(d,c))):(d=k.c(b)>>>0,k.f(b,Sb(d,c)))):(d=y[b&7],e[b&7]=Sb(d,c))}};r[212]=s[212]=function(){var b=m();if(0===b)qa();
|
||||
else{var c=v[0];v[1]=c/b;v[0]=c%b;I=v[0];K=2261}};r[213]=s[213]=function(){var b=m();I=v[0]+v[1]*b;g[0]=I&255;Y=8;K=2261};r[214]=s[214]=function(){throw ze("salc instruction");};r[215]=s[215]=function(){v[0]=Cb?ka(h(3)+e[3]+v[0]):ka(h(3)+g[6]+v[0])};r[216]=s[216]=function(){var b=m();192>b?Ha.i(b,l(b)):Ha.m(b)};r[217]=s[217]=function(){var b=m();192>b?Ha.q(b,l(b)):Ha.v(b)};r[218]=s[218]=function(){var b=m();192>b?Ha.D(b,l(b)):Ha.Q(b)};r[219]=s[219]=function(){var b=m();192>b?Ha.R(b,l(b)):Ha.S(b)};
|
||||
r[220]=s[220]=function(){var b=m();192>b?Ha.aa(b,l(b)):Ha.Ga(b)};r[221]=s[221]=function(){var b=m();192>b?Ha.Ia(b,l(b)):Ha.Ka(b)};r[222]=s[222]=function(){var b=m();192>b?Ha.Ma(b,l(b)):Ha.Na(b)};r[223]=s[223]=function(){var b=m();192>b?Ha.Oa(b,l(b)):Ha.Ra(b)};r[224]=s[224]=function(){if(--A[ga]&&!Gb()){var b=P();E=E+b|0}else E++};r[225]=s[225]=function(){if(--A[ga]&&Gb()){var b=P();E=E+b|0}else E++};r[226]=s[226]=function(){if(--A[ga]){var b=P();E=E+b|0}else E++};r[227]=s[227]=function(){var b=P();
|
||||
0===A[ga]&&(E=E+b|0)};r[228]=s[228]=function(){v[0]=hc(m())};r[229]=function(){g[0]=ic(m())};s[229]=function(){y[0]=cb(m())};r[230]=s[230]=function(){Fa(m(),v[0])};r[231]=function(){Xb(m(),g[0])};s[231]=function(){gc(m(),e[0])};r[232]=function(){var b=U()<<16>>16;la(pa());Qd(b)};s[232]=function(){var b=M();ia(pa());E=E+b|0};r[233]=function(){var b=U()<<16>>16;Qd(b)};s[233]=function(){var b=M();E=E+b|0};r[234]=function(){var b=U();ca(1,U());E=b+da[1]|0};s[234]=function(){var b=M();ca(1,U());E=b+da[1]|
|
||||
0};r[235]=s[235]=function(){var b=P();E=E+b|0};r[236]=s[236]=function(){v[0]=hc(g[4])};r[237]=function(){g[0]=ic(g[4])};s[237]=function(){y[0]=cb(g[4])};r[238]=s[238]=function(){Fa(g[4],v[0])};r[239]=function(){Xb(g[4],g[0])};s[239]=function(){gc(g[4],e[0])};r[240]=s[240]=function(){};r[241]=s[241]=function(){throw ze("int1 instruction");};r[242]=s[242]=function(){wa=!0;cc=!1;Ab[m()]();wa=!1};r[243]=s[243]=function(){cc=wa=!0;Ab[m()]();wa=!1};r[244]=s[244]=function(){ya&&fa(0);if(0===(u&512))throw nc("cpu halted"),
|
||||
oc=!0,"HALT";E--;fd=!0};r[245]=s[245]=function(){u=(u|1)^Ba();K&=-2};r[246]=s[246]=function(){var b=m();switch(b>>3&7){case 0:var c=192>b?ka(l(b)):v[b<<2&12|b>>2&1];id(c,m());break;case 1:c=192>b?ka(l(b)):v[b<<2&12|b>>2&1];id(c,m());break;case 2:192>b?(b=q(l(b)),c=k.d(b),k.e(b,~c)):(c=v[b<<2&12|b>>2&1],v[b<<2&12|b>>2&1]=~c);break;case 3:192>b?(b=q(l(b)),c=k.d(b),k.e(b,le(c))):(c=v[b<<2&12|b>>2&1],v[b<<2&12|b>>2&1]=le(c));break;case 4:c=192>b?ka(l(b)):v[b<<2&12|b>>2&1];c=c*v[0];g[0]=c;u=256>c?u&-2050:
|
||||
u|2049;K=0;break;case 5:c=192>b?Rc(l(b)):fc[b<<2&12|b>>2&1];c=c*fc[0];g[0]=c;u=127<c||-128>c?u|2049:u&-2050;K=0;break;case 6:var c=192>b?ka(l(b)):v[b<<2&12|b>>2&1],b=g[0],d=b/c|0;255<d||0===c?qa():(v[0]=d,v[1]=b%c);break;case 7:c=192>b?Rc(l(b)):fc[b<<2&12|b>>2&1],b=Ga[0],d=b/c|0,127<d||-128>d||0===c?qa():(v[0]=d,v[1]=b%c)}};r[247]=function(){var b=m();switch(b>>3&7){case 0:var c=192>b?Q(l(b)):g[b<<1&14];jd(c,U());break;case 1:c=192>b?Q(l(b)):g[b<<1&14];jd(c,U());break;case 2:var d;192>b?(c=l(b),b=
|
||||
q(c),J&&4095===(c&4095)?(d=q(c+1),c=B(b,d),n(b,d,~c)):(c=k.b(b),k.a(b,~c))):(c=g[b<<1&14],g[b<<1&14]=~c);break;case 3:192>b?(c=l(b),b=q(c),J&&4095===(c&4095)?(d=q(c+1),c=B(b,d),n(b,d,Kd(c))):(c=k.b(b),k.a(b,Kd(c)))):(c=g[b<<1&14],g[b<<1&14]=Kd(c));break;case 4:c=192>b?Q(l(b)):g[b<<1&14];c=c*g[0];b=c>>>16;g[0]=c;g[4]=b;u=0===b?u&-2050:u|2049;K=0;break;case 5:192>b?c=Q(l(b))<<16>>16:c=Ga[b<<1&14];c=c*Ga[0];g[0]=c;g[4]=c>>16;u=32767<c||-32768>c?u|2049:u&-2050;K=0;break;case 6:c=192>b?Q(l(b)):g[b<<1&
|
||||
14];b=(g[0]|g[4]<<16)>>>0;d=b/c|0;65535<d||0===c?qa():(g[0]=d,g[4]=b%c);break;case 7:192>b?c=Q(l(b))<<16>>16:c=Ga[b<<1&14],b=g[0]|g[4]<<16,d=b/c|0,32767<d||-32768>d||0===c?qa():(g[0]=d,g[4]=b%c)}};s[247]=function(){var b=m();switch(b>>3&7){case 0:var c=192>b?S(l(b)):e[b&7];kd(c,M());break;case 1:c=192>b?S(l(b)):e[b&7];kd(c,M());break;case 2:var d;192>b?(c=l(b),b=q(c),J&&4093<=(c&4095)?(d=q(c+3),c=G(b,d)>>>0,H(b,d,~c)):(c=k.c(b)>>>0,k.f(b,~c))):(c=y[b&7],e[b&7]=~c);break;case 3:192>b?(c=l(b),b=q(c),
|
||||
J&&4093<=(c&4095)?(d=q(c+3),c=G(b,d)>>>0,H(b,d,Ld(c))):(c=k.c(b)>>>0,k.f(b,Ld(c)))):(c=y[b&7],e[b&7]=Ld(c));break;case 4:192>b?c=S(l(b))>>>0:c=y[b&7];b=y[0];d=c*b/4294967296|0;y[0]=Z(c,b);y[2]=d;u=0===d?u&-2050:u|2049;K=0;break;case 5:b=c=192>b?S(l(b)):e[b&7];d=e[0];c=b*d/4294967296|0;b=Z(b,d);0===c&&0>b&&(c=-1);y[0]=b;y[2]=c;u=c===(2147483648>y[0]?0:-1)?u&-2050:u|2049;K=0;break;case 6:192>b?c=S(l(b))>>>0:c=y[b&7];d=y[0];var g=y[2],b=(4294967296*g%c+d%c)%c;d=d/c+4294967296*g/c;4294967295<d||0===c?
|
||||
qa():(y[0]=d,y[2]=b);break;case 7:c=192>b?S(l(b)):e[b&7],d=y[0],g=e[2],b=(4294967296*g%c+d%c)%c,d=d/c+4294967296*g/c,2147483647<d||-2147483648>d||0===c?qa():(y[0]=d,y[2]=b)}};r[248]=s[248]=function(){u&=-2;K&=-2};r[249]=s[249]=function(){u|=1;K&=-2};r[250]=s[250]=function(){$a()?u&=-513:fa(0)};r[251]=s[251]=function(){$a()?(u|=512,Da()):fa(0)};r[252]=s[252]=function(){u&=-1025};r[253]=s[253]=function(){u|=1024};r[254]=s[254]=function(){var b=m(),c=b&56;0===c?192>b?(b=q(l(b)),c=k.d(b),k.e(b,je(c))):
|
||||
(c=v[b<<2&12|b>>2&1],v[b<<2&12|b>>2&1]=je(c)):8===c?192>b?(b=q(l(b)),c=k.d(b),k.e(b,ke(c))):(c=v[b<<2&12|b>>2&1],v[b<<2&12|b>>2&1]=ke(c)):z()};r[255]=function(){var b=m();switch(b>>3&7){case 0:var c,d;192>b?(c=l(b),b=q(c),J&&4095===(c&4095)?(d=q(c+1),c=B(b,d),n(b,d,pb(c))):(c=k.b(b),k.a(b,pb(c)))):(c=g[b<<1&14],g[b<<1&14]=pb(c));break;case 1:192>b?(c=l(b),b=q(c),J&&4095===(c&4095)?(d=q(c+1),c=B(b,d),n(b,d,rb(c))):(c=k.b(b),k.a(b,rb(c)))):(c=g[b<<1&14],g[b<<1&14]=rb(c));break;case 2:c=192>b?Q(l(b)):
|
||||
g[b<<1&14];la(pa());E=da[1]+c|0;break;case 3:192<=b&&za(6);c=l(b);la(ra[1]);la(pa());ca(1,Q(c+2));E=da[1]+Q(c)|0;break;case 4:c=192>b?Q(l(b)):g[b<<1&14];E=da[1]+c|0;break;case 5:192<=b&&za(6);c=l(b);ca(1,Q(c+2));E=da[1]+Q(c)|0;break;case 6:c=192>b?Q(l(b)):g[b<<1&14];la(c);break;case 7:z()}};s[255]=function(){var b=m();switch(b>>3&7){case 0:var c,d;192>b?(c=l(b),b=q(c),J&&4093<=(c&4095)?(d=q(c+3),c=G(b,d)>>>0,H(b,d,qb(c))):(c=k.c(b)>>>0,k.f(b,qb(c)))):(c=y[b&7],e[b&7]=qb(c));break;case 1:192>b?(c=
|
||||
l(b),b=q(c),J&&4093<=(c&4095)?(d=q(c+3),c=G(b,d)>>>0,H(b,d,sb(c))):(c=k.c(b)>>>0,k.f(b,sb(c)))):(c=y[b&7],e[b&7]=sb(c));break;case 2:c=192>b?S(l(b)):e[b&7];ia(pa());E=da[1]+c|0;break;case 3:192<=b&&za(6);c=l(b);b=Q(c+4);c=S(c);ia(ra[1]);ia(pa());ca(1,b);E=da[1]+c|0;break;case 4:c=192>b?S(l(b)):e[b&7];E=da[1]+c|0;break;case 5:192<=b&&za(6);c=l(b);b=Q(c+4);c=S(c);ca(1,b);E=da[1]+c|0;break;case 6:c=192>b?S(l(b)):e[b&7];ia(c);break;case 7:z()}};x[0]=w[0]=function(){var b=m(),c=192>b?Q(l(b)):g[b<<1&14];
|
||||
Ma||z();ya&&fa(0);switch(b>>3&7){case 2:b=Bb(c);if(b.A)Zc=$c=0;else{if(!b.ga)throw ze("LDTR can only be loaded from GDT");if(!b.B)throw ze("#GP handler");if(!b.L)throw ze("#GP handler");if(2!==b.type)throw ze("#GP handler");$c=b.V;Zc=b.W}break;case 3:b=Bb(c);if(!b.ga)throw ze("TR can only be loaded from GDT");if(b.A)throw ze("#GP handler");if(!b.B)throw ze("#GP handler");if(!b.L)throw ze("#GP handler");if(9!==b.type)throw ze("#GP handler");Ed=b.V;Dd=b.W;break;default:z()}};x[1]=w[1]=function(){var b=
|
||||
m();ya&&fa(0);var c=b>>3&7;if(4===c)192>b?R(l(b),Na):g[b<<1&14]=Na;else if(6===c)c=192>b?Q(l(b)):g[b<<1&14],Na=Na&-16|c&15,O();else switch(192<=b&&za(6),2!==c&&3!==c||!Ma||(ab=6),b=l(b),ab=-1,c){case 0:R(b,ad);N(b+2,qc);break;case 1:R(b,bd);N(b+2,rc);break;case 2:c=Q(b);b=S(b+2);ad=c;qc=b;xa||(qc&=16777215);break;case 3:c=Q(b);b=S(b+2);bd=c;rc=b;xa||(rc&=16777215);break;case 7:c=b>>>12;Eb[c]=0;pc[c]=0;Fb=-1;break;default:z()}};x[2]=w[2]=function(){m();z()};x[3]=w[3]=function(){m();z()};x[4]=w[4]=
|
||||
function(){z()};x[5]=w[5]=function(){z()};x[6]=w[6]=function(){ya?fa(0):Na&=-9};x[7]=w[7]=function(){z()};x[8]=w[8]=function(){z()};x[9]=w[9]=function(){ya&&fa(0)};x[10]=w[10]=function(){z()};x[11]=w[11]=function(){z()};x[12]=w[12]=function(){z()};x[13]=w[13]=function(){z()};x[14]=w[14]=function(){z()};x[15]=w[15]=function(){z()};x[16]=w[16]=function(){z()};x[17]=w[17]=function(){z()};x[18]=w[18]=function(){z()};x[19]=w[19]=function(){z()};x[20]=w[20]=function(){z()};x[21]=w[21]=function(){z()};x[22]=
|
||||
w[22]=function(){z()};x[23]=w[23]=function(){z()};x[24]=w[24]=function(){var b=m();xa?192>b&&S(l(b)):192>b&&Q(l(b))};x[25]=w[25]=function(){z()};x[26]=w[26]=function(){z()};x[27]=w[27]=function(){z()};x[28]=w[28]=function(){z()};x[29]=w[29]=function(){z()};x[30]=w[30]=function(){z()};x[31]=w[31]=function(){z()};x[32]=w[32]=function(){var b=m();ya&&fa(0);switch(b>>3&7){case 0:y[b&7]=Na;break;case 2:y[b&7]=Ub;break;case 3:y[b&7]=cd;break;case 4:y[b&7]=Oc;break;default:z()}};x[33]=w[33]=function(){m();
|
||||
ya&&fa(0)};x[34]=w[34]=function(){var b=m();ya&&fa(0);var c=y[b&7];switch(b>>3&7){case 0:if(-2147483648===(c&2147483649))throw ze("#GP handler");Na&2147483648&&!(c&2147483648)&&(pc=new Uint8Array(1048576),tc());Na=c;O();break;case 3:cd=c;tc();break;case 4:(Oc^c)&128&&(pc=new Uint8Array(1048576),tc());Oc=c;Fd=Oc&16?128:0;break;default:z()}};x[35]=w[35]=function(){m();ya&&fa(0)};x[36]=w[36]=function(){z()};x[37]=w[37]=function(){z()};x[38]=w[38]=function(){z()};x[39]=w[39]=function(){z()};x[40]=w[40]=
|
||||
function(){z()};x[41]=w[41]=function(){z()};x[42]=w[42]=function(){z()};x[43]=w[43]=function(){z()};x[44]=w[44]=function(){z()};x[45]=w[45]=function(){z()};x[46]=w[46]=function(){z()};x[47]=w[47]=function(){z()};x[48]=w[48]=function(){z()};x[49]=w[49]=function(){y[0]=ed;y[2]=ed/4294967296};x[50]=w[50]=function(){z()};x[51]=w[51]=function(){z()};x[52]=w[52]=function(){z()};x[53]=w[53]=function(){z()};x[54]=w[54]=function(){z()};x[55]=w[55]=function(){z()};x[56]=w[56]=function(){z()};x[57]=w[57]=function(){z()};
|
||||
x[58]=w[58]=function(){z()};x[59]=w[59]=function(){z()};x[60]=w[60]=function(){z()};x[61]=w[61]=function(){z()};x[62]=w[62]=function(){z()};x[63]=w[63]=function(){z()};x[64]=function(){var b=m();if(Ya()){var c=192>b?Q(l(b)):g[b<<1&14];g[b>>2&14]=c}else 192>b&&l(b)};w[64]=function(){var b=m();if(Ya()){var c=192>b?S(l(b)):e[b&7];e[b>>3&7]=c}else 192>b&&l(b)};x[65]=function(){var b=m();if(Ya())192>b&&l(b);else{var c=192>b?Q(l(b)):g[b<<1&14];g[b>>2&14]=c}};w[65]=function(){var b=m();if(Ya())192>b&&l(b);
|
||||
else{var c=192>b?S(l(b)):e[b&7];e[b>>3&7]=c}};x[66]=function(){var b=m();if(Ra()){var c=192>b?Q(l(b)):g[b<<1&14];g[b>>2&14]=c}else 192>b&&l(b)};w[66]=function(){var b=m();if(Ra()){var c=192>b?S(l(b)):e[b&7];e[b>>3&7]=c}else 192>b&&l(b)};x[67]=function(){var b=m();if(Ra())192>b&&l(b);else{var c=192>b?Q(l(b)):g[b<<1&14];g[b>>2&14]=c}};w[67]=function(){var b=m();if(Ra())192>b&&l(b);else{var c=192>b?S(l(b)):e[b&7];e[b>>3&7]=c}};x[68]=function(){var b=m();if(Sa()){var c=192>b?Q(l(b)):g[b<<1&14];g[b>>2&
|
||||
14]=c}else 192>b&&l(b)};w[68]=function(){var b=m();if(Sa()){var c=192>b?S(l(b)):e[b&7];e[b>>3&7]=c}else 192>b&&l(b)};x[69]=function(){var b=m();if(Sa())192>b&&l(b);else{var c=192>b?Q(l(b)):g[b<<1&14];g[b>>2&14]=c}};w[69]=function(){var b=m();if(Sa())192>b&&l(b);else{var c=192>b?S(l(b)):e[b&7];e[b>>3&7]=c}};x[70]=function(){var b=m();if(Qa()){var c=192>b?Q(l(b)):g[b<<1&14];g[b>>2&14]=c}else 192>b&&l(b)};w[70]=function(){var b=m();if(Qa()){var c=192>b?S(l(b)):e[b&7];e[b>>3&7]=c}else 192>b&&l(b)};x[71]=
|
||||
function(){var b=m();if(Qa())192>b&&l(b);else{var c=192>b?Q(l(b)):g[b<<1&14];g[b>>2&14]=c}};w[71]=function(){var b=m();if(Qa())192>b&&l(b);else{var c=192>b?S(l(b)):e[b&7];e[b>>3&7]=c}};x[72]=function(){var b=m();if(Za()){var c=192>b?Q(l(b)):g[b<<1&14];g[b>>2&14]=c}else 192>b&&l(b)};w[72]=function(){var b=m();if(Za()){var c=192>b?S(l(b)):e[b&7];e[b>>3&7]=c}else 192>b&&l(b)};x[73]=function(){var b=m();if(Za())192>b&&l(b);else{var c=192>b?Q(l(b)):g[b<<1&14];g[b>>2&14]=c}};w[73]=function(){var b=m();
|
||||
if(Za())192>b&&l(b);else{var c=192>b?S(l(b)):e[b&7];e[b>>3&7]=c}};x[74]=function(){var b=m();if(Ta()){var c=192>b?Q(l(b)):g[b<<1&14];g[b>>2&14]=c}else 192>b&&l(b)};w[74]=function(){var b=m();if(Ta()){var c=192>b?S(l(b)):e[b&7];e[b>>3&7]=c}else 192>b&&l(b)};x[75]=function(){var b=m();if(Ta())192>b&&l(b);else{var c=192>b?Q(l(b)):g[b<<1&14];g[b>>2&14]=c}};w[75]=function(){var b=m();if(Ta())192>b&&l(b);else{var c=192>b?S(l(b)):e[b&7];e[b>>3&7]=c}};x[76]=function(){var b=m();if(Wa()){var c=192>b?Q(l(b)):
|
||||
g[b<<1&14];g[b>>2&14]=c}else 192>b&&l(b)};w[76]=function(){var b=m();if(Wa()){var c=192>b?S(l(b)):e[b&7];e[b>>3&7]=c}else 192>b&&l(b)};x[77]=function(){var b=m();if(Wa())192>b&&l(b);else{var c=192>b?Q(l(b)):g[b<<1&14];g[b>>2&14]=c}};w[77]=function(){var b=m();if(Wa())192>b&&l(b);else{var c=192>b?S(l(b)):e[b&7];e[b>>3&7]=c}};x[78]=function(){var b=m();if(Xa()){var c=192>b?Q(l(b)):g[b<<1&14];g[b>>2&14]=c}else 192>b&&l(b)};w[78]=function(){var b=m();if(Xa()){var c=192>b?S(l(b)):e[b&7];e[b>>3&7]=c}else 192>
|
||||
b&&l(b)};x[79]=function(){var b=m();if(Xa())192>b&&l(b);else{var c=192>b?Q(l(b)):g[b<<1&14];g[b>>2&14]=c}};w[79]=function(){var b=m();if(Xa())192>b&&l(b);else{var c=192>b?S(l(b)):e[b&7];e[b>>3&7]=c}};x[80]=w[80]=function(){z()};x[81]=w[81]=function(){z()};x[82]=w[82]=function(){z()};x[83]=w[83]=function(){z()};x[84]=w[84]=function(){z()};x[85]=w[85]=function(){z()};x[86]=w[86]=function(){z()};x[87]=w[87]=function(){z()};x[88]=w[88]=function(){z()};x[89]=w[89]=function(){z()};x[90]=w[90]=function(){z()};
|
||||
x[91]=w[91]=function(){z()};x[92]=w[92]=function(){z()};x[93]=w[93]=function(){z()};x[94]=w[94]=function(){z()};x[95]=w[95]=function(){z()};x[96]=w[96]=function(){z()};x[97]=w[97]=function(){z()};x[98]=w[98]=function(){z()};x[99]=w[99]=function(){z()};x[100]=w[100]=function(){z()};x[101]=w[101]=function(){z()};x[102]=w[102]=function(){z()};x[103]=w[103]=function(){z()};x[104]=w[104]=function(){z()};x[105]=w[105]=function(){z()};x[106]=w[106]=function(){z()};x[107]=w[107]=function(){z()};x[108]=w[108]=
|
||||
function(){z()};x[109]=w[109]=function(){z()};x[110]=w[110]=function(){z()};x[111]=w[111]=function(){z()};x[112]=w[112]=function(){z()};x[113]=w[113]=function(){z()};x[114]=w[114]=function(){z()};x[115]=w[115]=function(){z()};x[116]=w[116]=function(){z()};x[117]=w[117]=function(){z()};x[118]=w[118]=function(){z()};x[119]=w[119]=function(){z()};x[120]=w[120]=function(){z()};x[121]=w[121]=function(){z()};x[122]=w[122]=function(){z()};x[123]=w[123]=function(){z()};x[124]=w[124]=function(){z()};x[125]=
|
||||
w[125]=function(){z()};x[126]=w[126]=function(){z()};x[127]=w[127]=function(){z()};x[128]=function(){Oa(Ya())};w[128]=function(){Pa(Ya())};x[129]=function(){Oa(!Ya())};w[129]=function(){Pa(!Ya())};x[130]=function(){Oa(Ra())};w[130]=function(){Pa(Ra())};x[131]=function(){Oa(!Ra())};w[131]=function(){Pa(!Ra())};x[132]=function(){Oa(Sa())};w[132]=function(){Pa(Sa())};x[133]=function(){Oa(!Sa())};w[133]=function(){Pa(!Sa())};x[134]=function(){Oa(Qa())};w[134]=function(){Pa(Qa())};x[135]=function(){Oa(!Qa())};
|
||||
w[135]=function(){Pa(!Qa())};x[136]=function(){Oa(Za())};w[136]=function(){Pa(Za())};x[137]=function(){Oa(!Za())};w[137]=function(){Pa(!Za())};x[138]=function(){Oa(Ta())};w[138]=function(){Pa(Ta())};x[139]=function(){Oa(!Ta())};w[139]=function(){Pa(!Ta())};x[140]=function(){Oa(Wa())};w[140]=function(){Pa(Wa())};x[141]=function(){Oa(!Wa())};w[141]=function(){Pa(!Wa())};x[142]=function(){Oa(Xa())};w[142]=function(){Pa(Xa())};x[143]=function(){Oa(!Xa())};w[143]=function(){Pa(!Xa())};x[144]=w[144]=function(){var b=
|
||||
m();192>b?V(l(b),!Ya()^1):v[b<<2&12|b>>2&1]=!Ya()^1};x[145]=w[145]=function(){var b=m();192>b?V(l(b),!!Ya()^1):v[b<<2&12|b>>2&1]=!!Ya()^1};x[146]=w[146]=function(){var b=m();192>b?V(l(b),!Ra()^1):v[b<<2&12|b>>2&1]=!Ra()^1};x[147]=w[147]=function(){var b=m();192>b?V(l(b),!!Ra()^1):v[b<<2&12|b>>2&1]=!!Ra()^1};x[148]=w[148]=function(){var b=m();192>b?V(l(b),!Sa()^1):v[b<<2&12|b>>2&1]=!Sa()^1};x[149]=w[149]=function(){var b=m();192>b?V(l(b),!!Sa()^1):v[b<<2&12|b>>2&1]=!!Sa()^1};x[150]=w[150]=function(){var b=
|
||||
m();192>b?V(l(b),!Qa()^1):v[b<<2&12|b>>2&1]=!Qa()^1};x[151]=w[151]=function(){var b=m();192>b?V(l(b),!!Qa()^1):v[b<<2&12|b>>2&1]=!!Qa()^1};x[152]=w[152]=function(){var b=m();192>b?V(l(b),!Za()^1):v[b<<2&12|b>>2&1]=!Za()^1};x[153]=w[153]=function(){var b=m();192>b?V(l(b),!!Za()^1):v[b<<2&12|b>>2&1]=!!Za()^1};x[154]=w[154]=function(){var b=m();192>b?V(l(b),!Ta()^1):v[b<<2&12|b>>2&1]=!Ta()^1};x[155]=w[155]=function(){var b=m();192>b?V(l(b),!!Ta()^1):v[b<<2&12|b>>2&1]=!!Ta()^1};x[156]=w[156]=function(){var b=
|
||||
m();192>b?V(l(b),!Wa()^1):v[b<<2&12|b>>2&1]=!Wa()^1};x[157]=w[157]=function(){var b=m();192>b?V(l(b),!!Wa()^1):v[b<<2&12|b>>2&1]=!!Wa()^1};x[158]=w[158]=function(){var b=m();192>b?V(l(b),!Xa()^1):v[b<<2&12|b>>2&1]=!Xa()^1};x[159]=w[159]=function(){var b=m();192>b?V(l(b),!!Xa()^1):v[b<<2&12|b>>2&1]=!!Xa()^1};x[160]=function(){la(ra[4])};w[160]=function(){ia(ra[4])};x[161]=function(){ca(4,k.b(Va(0)));$[aa]+=2};w[161]=function(){ca(4,k.b(Va(0)));$[aa]+=4};x[162]=w[162]=function(){var b=e[0];0===(b&2147483647)?
|
||||
(y[0]=2,0===b&&(y[3]=1970169159,y[2]=1231384169,y[1]=1818588270)):1===b?(y[0]=1299,y[3]=0,y[1]=0,y[2]=Ha.a|41240):2===b?(y[0]=1717260289,y[3]=0,y[1]=0,y[2]=8024064):-2138701824===b&&(y[0]=0,y[3]=0,y[1]=0,y[2]=0)};x[163]=w[163]=function(){var b=m();xa?192>b?pd(l(b),e[b>>3&7]):ld(y[b&7],y[b>>3&7]&31):192>b?pd(l(b),Ga[b>>2&14]):ld(g[b<<1&14],g[b>>2&14]&15)};x[164]=function(){var b=m(),c,d,e;192>b?(c=l(b),d=q(c),J&&4095===(c&4095)?(e=q(c+1),c=B(d,e),n(d,e,Ic(c,g[b>>2&14],m()&31))):(c=k.b(d),k.a(d,Ic(c,
|
||||
g[b>>2&14],m()&31)))):(c=g[b<<1&14],g[b<<1&14]=Ic(c,g[b>>2&14],m()&31))};w[164]=function(){var b=m(),c,d,g;192>b?(c=l(b),d=q(c),J&&4093<=(c&4095)?(g=q(c+3),c=G(d,g)>>>0,H(d,g,Jc(c,y[b>>3&7],m()&31))):(c=k.c(d)>>>0,k.f(d,Jc(c,y[b>>3&7],m()&31)))):(c=y[b&7],e[b&7]=Jc(c,y[b>>3&7],m()&31))};x[165]=function(){var b=m(),c,d,e;192>b?(c=l(b),d=q(c),J&&4095===(c&4095)?(e=q(c+1),c=B(d,e),n(d,e,Ic(c,g[b>>2&14],v[4]&31))):(c=k.b(d),k.a(d,Ic(c,g[b>>2&14],v[4]&31)))):(c=g[b<<1&14],g[b<<1&14]=Ic(c,g[b>>2&14],v[4]&
|
||||
31))};w[165]=function(){var b=m(),c,d,g;192>b?(c=l(b),d=q(c),J&&4093<=(c&4095)?(g=q(c+3),c=G(d,g)>>>0,H(d,g,Jc(c,y[b>>3&7],v[4]&31))):(c=k.c(d)>>>0,k.f(d,Jc(c,y[b>>3&7],v[4]&31)))):(c=y[b&7],e[b&7]=Jc(c,y[b>>3&7],v[4]&31))};x[166]=w[166]=function(){z()};x[167]=w[167]=function(){z()};x[168]=function(){la(ra[5])};w[168]=function(){ia(ra[5])};x[169]=function(){ca(5,k.b(Va(0)));$[aa]+=2};w[169]=function(){ca(5,k.b(Va(0)));$[aa]+=4};x[170]=w[170]=function(){z()};x[171]=w[171]=function(){var b=m();xa?192>
|
||||
b?sd(l(b),e[b>>3&7]):y[b&7]=nd(e[b&7],e[b>>3&7]&31):192>b?sd(l(b),Ga[b>>2&14]):g[b<<1&14]=nd(g[b<<1&14],Ga[b>>2&14]&15)};x[172]=function(){var b=m(),c,d,e;192>b?(c=l(b),d=q(c),J&&4095===(c&4095)?(e=q(c+1),c=B(d,e),n(d,e,Gc(c,g[b>>2&14],m()&31))):(c=k.b(d),k.a(d,Gc(c,g[b>>2&14],m()&31)))):(c=g[b<<1&14],g[b<<1&14]=Gc(c,g[b>>2&14],m()&31))};w[172]=function(){var b=m(),c,d,g;192>b?(c=l(b),d=q(c),J&&4093<=(c&4095)?(g=q(c+3),c=G(d,g)>>>0,H(d,g,Hc(c,y[b>>3&7],m()&31))):(c=k.c(d)>>>0,k.f(d,Hc(c,y[b>>3&7],
|
||||
m()&31)))):(c=y[b&7],e[b&7]=Hc(c,y[b>>3&7],m()&31))};x[173]=function(){var b=m(),c,d,e;192>b?(c=l(b),d=q(c),J&&4095===(c&4095)?(e=q(c+1),c=B(d,e),n(d,e,Gc(c,g[b>>2&14],v[4]&31))):(c=k.b(d),k.a(d,Gc(c,g[b>>2&14],v[4]&31)))):(c=g[b<<1&14],g[b<<1&14]=Gc(c,g[b>>2&14],v[4]&31))};w[173]=function(){var b=m(),c,d,g;192>b?(c=l(b),d=q(c),J&&4093<=(c&4095)?(g=q(c+3),c=G(d,g)>>>0,H(d,g,Hc(c,y[b>>3&7],v[4]&31))):(c=k.c(d)>>>0,k.f(d,Hc(c,y[b>>3&7],v[4]&31)))):(c=y[b&7],e[b&7]=Hc(c,y[b>>3&7],v[4]&31))};x[174]=w[174]=
|
||||
function(){z()};x[175]=function(){var b=m(),c=192>b?Q(l(b))<<16>>16:Ga[b<<1&14];g[b>>2&14]=Md(Ga[b>>2&14],c)};w[175]=function(){var b=m(),c=192>b?S(l(b)):e[b&7];y[b>>3&7]=Nd(e[b>>3&7],c)};x[176]=w[176]=function(){var b=m();if(192>b)var c=l(b),d=ka(c);else d=v[b<<2&12|b>>2&1];lc(d,v[0]);Gb()?192>b?V(c,v[b>>1&12|b>>5&1]):v[b<<2&12|b>>2&1]=v[b>>1&12|b>>5&1]:v[0]=d};x[177]=w[177]=function(){var b=m();if(xa){if(192>b)var c=l(b),d=S(c)>>>0;else d=y[b&7];Zb(d,y[0]);Gb()?192>b?N(c,y[b>>3&7]):y[b&7]=y[b>>
|
||||
3&7]:y[0]=d}else 192>b?(c=l(b),d=Q(c)):d=g[b<<1&14],Yb(d,g[0]),Gb()?192>b?R(c,g[b>>2&14]):g[b<<1&14]=g[b>>2&14]:g[0]=d};x[178]=w[178]=function(){var b=m();192<=b?za(6):xa?Vc(2,l(b),b>>3&7):Uc(2,l(b),b>>2&14)};x[179]=w[179]=function(){var b=m();xa?192>b?rd(l(b),e[b>>3&7]):y[b&7]=od(e[b&7],e[b>>3&7]&31):192>b?rd(l(b),Ga[b>>2&14]):g[b<<1&14]=od(g[b<<1&14],Ga[b>>2&14]&15)};x[180]=w[180]=function(){var b=m();192<=b?za(6):xa?Vc(4,l(b),b>>3&7):Uc(4,l(b),b>>2&14)};x[181]=w[181]=function(){var b=m();192<=
|
||||
b?za(6):xa?Vc(5,l(b),b>>3&7):Uc(5,l(b),b>>2&14)};x[182]=function(){var b=m(),c=192>b?ka(l(b)):v[b<<2&12|b>>2&1];g[b>>2&14]=c};w[182]=function(){var b=m(),c=192>b?ka(l(b)):v[b<<2&12|b>>2&1];y[b>>3&7]=c};x[183]=w[183]=function(){var b=m(),c=192>b?Q(l(b)):g[b<<1&14];y[b>>3&7]=c};x[184]=w[184]=function(){z()};x[185]=w[185]=function(){z()};x[186]=w[186]=function(){var b=m();switch(b>>3&7){case 4:xa?192>b?pd(l(b),m()&31):ld(y[b&7],m()&31):192>b?pd(l(b),m()&31):ld(g[b<<1&14],m()&15);break;case 5:xa?192>
|
||||
b?sd(l(b),m()&31):y[b&7]=nd(e[b&7],m()&31):192>b?sd(l(b),m()&31):g[b<<1&14]=nd(g[b<<1&14],m()&15);break;case 6:xa?192>b?rd(l(b),m()&31):y[b&7]=od(e[b&7],m()&31):192>b?rd(l(b),m()&31):g[b<<1&14]=od(g[b<<1&14],m()&15);break;case 7:xa?192>b?qd(l(b),m()&31):y[b&7]=md(e[b&7],m()&31):192>b?qd(l(b),m()&31):g[b<<1&14]=md(g[b<<1&14],m()&15);break;default:z()}};x[187]=w[187]=function(){var b=m();xa?192>b?qd(l(b),e[b>>3&7]):y[b&7]=md(e[b&7],e[b>>3&7]&31):192>b?qd(l(b),Ga[b>>2&14]):g[b<<1&14]=md(g[b<<1&14],Ga[b>>
|
||||
2&14]&15)};x[188]=function(){var b=m(),c=192>b?Q(l(b)):g[b<<1&14],d=g;var e=g[b>>2&14];K=0;0===c?(u|=64,c=e):(u&=-65,c=oe[((-c&c)>>>0)%37]);d[b>>2&14]=c};w[188]=function(){var b=m(),c=192>b?S(l(b)):e[b&7],d=y;var g=y[b>>3&7];K=0;0===c?(u|=64,c=g):(u&=-65,c=oe[((-c&c)>>>0)%37]);d[b>>3&7]=c};x[189]=function(){var b=m(),c=192>b?Q(l(b)):g[b<<1&14],d=g;var e=g[b>>2&14];K=0;0===c?(u|=64,c=e):(u&=-65,c=(e=c>>>8)?8+Ae[e]:Ae[c]);d[b>>2&14]=c};w[189]=function(){var b=m(),c=192>b?S(l(b)):e[b&7],d=y;var g=y[b>>
|
||||
3&7];K=0;if(0===c)u|=64,c=g;else{u&=-65;var g=c>>>16,k;c=g?(k=g>>>8)?24+Ae[k]:16+Ae[g]:(k=c>>>8)?8+Ae[k]:Ae[c]}d[b>>3&7]=c};x[190]=function(){var b=m(),c=192>b?Rc(l(b)):fc[b<<2&12|b>>2&1];g[b>>2&14]=c};w[190]=function(){var b=m(),c=192>b?Rc(l(b)):fc[b<<2&12|b>>2&1];e[b>>3&7]=c};x[191]=w[191]=function(){var b=m(),c=192>b?Q(l(b))<<16>>16:Ga[b<<1&14];e[b>>3&7]=c};x[192]=w[192]=function(){var b=m(),c,d;192>b?(d=q(l(b)),c=k.d(d),k.e(d,me(c,b>>1&12|b>>5&1))):(c=v[b<<2&12|b>>2&1],v[b<<2&12|b>>2&1]=me(c,
|
||||
b>>1&12|b>>5&1))};x[193]=function(){var b=m(),c,d,e;192>b?(c=l(b),d=q(c),J&&4095===(c&4095)?(e=q(c+1),c=B(d,e),n(d,e,Od(c,b>>2&14))):(c=k.b(d),k.a(d,Od(c,b>>2&14)))):(c=g[b<<1&14],g[b<<1&14]=Od(c,b>>2&14))};w[193]=function(){var b=m(),c,d,g;192>b?(c=l(b),d=q(c),J&&4093<=(c&4095)?(g=q(c+3),c=G(d,g)>>>0,H(d,g,Pd(c,b>>3&7))):(c=k.c(d)>>>0,k.f(d,Pd(c,b>>3&7)))):(c=y[b&7],e[b&7]=Pd(c,b>>3&7))};x[194]=w[194]=function(){z()};x[195]=w[195]=function(){z()};x[196]=w[196]=function(){z()};x[197]=w[197]=function(){z()};
|
||||
x[198]=w[198]=function(){z()};x[199]=w[199]=function(){var b=m(),b=l(b),c=S(b)>>>0,d=S(b+4)>>>0;y[0]===c&&y[2]===d?(u|=64,N(b,y[3]),N(b+4,y[1])):(u&=-65,y[0]=c,y[2]=d);K&=-65};x[200]=w[200]=function(){bc(0)};x[201]=w[201]=function(){bc(1)};x[202]=w[202]=function(){bc(2)};x[203]=w[203]=function(){bc(3)};x[204]=w[204]=function(){bc(4)};x[205]=w[205]=function(){bc(5)};x[206]=w[206]=function(){bc(6)};x[207]=w[207]=function(){bc(7)};x[208]=w[208]=function(){z()};x[209]=w[209]=function(){z()};x[210]=w[210]=
|
||||
function(){z()};x[211]=w[211]=function(){z()};x[212]=w[212]=function(){z()};x[213]=w[213]=function(){z()};x[214]=w[214]=function(){z()};x[215]=w[215]=function(){z()};x[216]=w[216]=function(){z()};x[217]=w[217]=function(){z()};x[218]=w[218]=function(){z()};x[219]=w[219]=function(){z()};x[220]=w[220]=function(){z()};x[221]=w[221]=function(){z()};x[222]=w[222]=function(){z()};x[223]=w[223]=function(){z()};x[224]=w[224]=function(){z()};x[225]=w[225]=function(){z()};x[226]=w[226]=function(){z()};x[227]=
|
||||
w[227]=function(){z()};x[228]=w[228]=function(){z()};x[229]=w[229]=function(){z()};x[230]=w[230]=function(){z()};x[231]=w[231]=function(){z()};x[232]=w[232]=function(){z()};x[233]=w[233]=function(){z()};x[234]=w[234]=function(){z()};x[235]=w[235]=function(){z()};x[236]=w[236]=function(){z()};x[237]=w[237]=function(){z()};x[238]=w[238]=function(){z()};x[239]=w[239]=function(){z()};x[240]=w[240]=function(){z()};x[241]=w[241]=function(){z()};x[242]=w[242]=function(){z()};x[243]=w[243]=function(){z()};
|
||||
x[244]=w[244]=function(){z()};x[245]=w[245]=function(){z()};x[246]=w[246]=function(){z()};x[247]=w[247]=function(){z()};x[248]=w[248]=function(){z()};x[249]=w[249]=function(){z()};x[250]=w[250]=function(){z()};x[251]=w[251]=function(){z()};x[252]=w[252]=function(){z()};x[253]=w[253]=function(){z()};x[254]=w[254]=function(){z()};x[255]=w[255]=function(){z()}};Object.bb=function(f){for(var t={},D=0;D<f.length;D++)t[f[D][0]]=f[D][1];return t};Object.cb=function(f,t){for(var D=Object.keys(t),C=0;C<D.length;C++)f[D[C]]=t[D[C]]};String.m=function(f){for(f=f?f+"":"";20>f.length;)f=f+" ";return f};String.i=function(f,t){for(f=f?f+"":"";f.length<t;)f="0"+f;return f};Array.a=function(f){for(var t=[],D=0;D<f;D++)t[D]=D;return t};function Be(f,t){return f?t?String.i(f.toString(16).toUpperCase(),t):f.toString(16).toUpperCase():String.i("",t||1)}
|
||||
Number.a=function(f){for(var t=[],D=31;-1<D;D--)f&1<<D&&t.push(D);return t.join(", ")};String.a=function(f,t){for(var D="";t--;)D+=f;return D};Math.wa=function(f){for(var t=0,D=0,C;f;)C=f%10,D|=C<<4*t,t++,f=(f-C)/10;return D};function ze(f){f="Unimplemented"+(f?": "+f:"");nc(f);nc("Execution stopped");return f}
|
||||
function Zd(f){this.byteLength=f.byteLength;this.get=function(t,D,C){C(new Uint8Array(f,t,D))};this.set=function(t,D,C){(new Uint8Array(f,t,D.byteLength)).set(D);C()};this.Ba=function(t){t(f)}}Math.Ya=function(f){return f>>>24|f>>8&65280|f<<8&16711680|f<<24};Math.Xa=function(f){return f>>>8&255|f<<8&65280};for(var Ae,De=new Int8Array(256),Ee=0,Fe=-2;256>Ee;Ee++)Ee&Ee-1||Fe++,De[Ee]=Fe;Ae=De;Math.qa=function(f){return 0<f?Math.ceil(f):Math.floor(f)};function ve(f,t){this.j=f.j;this.memory=f.memory;this.s=f.s;this.M=f.M;this.da=4098;this.Y=17170688;this.U=14;this.T=4293984256;this.a=2048;this.buffer=t;this.m=!0;this.q=8;this.w()}ve.prototype=new Ge;
|
||||
function we(f,t,D){function C(){var f=80;n<H.length&&(f|=8);return f}function O(){X.k(B.U)}var L=0===D?496:368,X=f.s;this.j=f.j;this.memory=f.memory;this.s=f.s;this.M=f.M;this.da=4098;this.Y=17170688;this.U=0===D?14:15;this.T=4293918720;this.a=512;this.o=t.byteLength/this.a;this.buffer=t;this.m=!1;this.q=16;this.i=t.byteLength/16/64/this.a;var B=this;this.j.h(L|7,C);this.j.h(L|518,C);var G=255,n=0,H=[];this.j.g(L|6,function(f){f&16||(G=f)});this.j.g(L|2,function(){});this.j.g(L|3,function(){});this.j.g(L|
|
||||
4,function(){});this.j.g(L|5,function(){});this.j.g(L|7,function(f){236===f?(n=0,H=new Uint8Array([64,0,B.i,B.i>>8,0,0,16,0,0,0,0,0,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,2,4,0,0,0,0,0,0,0,0,0,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,0,0,1,0,0,3,0,0,0,2,0,2,7,0,B.i,B.i>>8,16,0,63,0,this.o&255,this.o>>8&255,this.o>>16&255,this.o>>24&255,0,0,this.o&255,this.o>>8&255,this.o>>16&255,this.o>>24&255,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,126,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,this.o&255,this.o>>8&255,this.o>>16&255,this.o>>24&255]),O()):145===f?O():16===f?O():(O(),H=[0,0,0,0,t.byteLength&255,t.byteLength>>8&255,t.byteLength>>16&255,t.byteLength>>24&255,0,0,0,0])});this.j.h(L|0,function(){return n<H.length?(0===(n&511)&&O(),H[n++]&255):0});this.j.h(L|1,function(){return 255});this.j.h(L|2,function(){return 255});this.j.h(L|
|
||||
3,function(){return 255});this.j.h(L|6,function(){return G});this.w()}we.prototype=new Ge;
|
||||
function Ge(){function f(f,n,t){var F=O.c(f+4)&16777215;f=O.b(f+12)*C.a;t?this.buffer.get(F*C.a,f,function(f){O.J(f,n)}):this.buffer.set(F*C.a,new Uint8Array(O.buffer,n,f),function(){})}function t(f){switch(f){case 0:return X;case 4:return L;case 12:return B;case 296:return 3;case 272:return G}}function D(t,B){switch(t){case 256:n=B;break;case 264:H=B;break;case 312:var N=O.c(n+8),F=N+128;O.b(n);var G=O.c(F)+4294967296*O.c(F+4);O.c(N+128+12);var F=O.d(N+64),D=O.d(N+2),L=N+0;if((160===D||161===D)&&
|
||||
!C.m)break;O.e(H+64+2,64);O.c(L+4);O.b(n+2);O.c(n+4);O.c(N+128+12);200===D||202===D?f(L,G,200===D):236===D?O.f(G+120,C.buffer.byteLength/C.a):161===D?O.f(G,1280):160===D&&40===F&&(N=N+64,F=Math.Ya(O.c(N+2)),D=Math.Xa(O.b(N+7)),O.d(N+1),C.buffer.get(F*C.a,D*C.a,function(f){O.J(f,G)}))}}var C,O;this.w=function(){C=this;O=this.memory;this.M.pa(this,this.q);this.memory.ba(this.T,16384,!0,t,D)};var L=0,X=1,B=1,G=1,n,H};function pe(f){f=f.j;var t=0,D=-1,C=-1,O=this;this.a={};f.h(3324,function(){return D&255});f.h(3325,function(){return D>>8&255});f.h(3326,function(){return D>>16&255});f.h(3327,function(){return D>>24&255});f.h(3320,function(){return C&255});f.h(3321,function(){return C>>8&255});f.h(3322,function(){return C>>16&255});f.h(3323,function(){return C>>24&255});f.g(3320,function(f){t=t&-256|f});f.g(3321,function(f){t=t&-65281|f<<8});f.g(3322,function(f){t=t&-16711681|f<<16});f.g(3323,function(f){var X=
|
||||
t=t&16777215|f<<24,B=(X&2147483647)>>8;f=X&252;-2147483648===X?C=2147483648:O.a[B]?(X=O.a[B],C=2147483648,0===f?D=X.da:8===f?D=X.Y:36===f?D=X.T:60===f?D=X.U:D=0):C=D=0});this.pa=function(f,t){this.a[t]=f};this.pa({U:0,T:0,da:2256543790,Y:100700192},0)};function ue(f,t){function D(){return 0}function C(){var f=128;ja<h&&(f|=80);0===(Fa&8)&&(f|=32);return f}function O(){return 0}function L(){return ja<h?fa[ja++]:255}function X(f){if(0<ha)za[qa++]=f,ha--,0===ha&&z(za);else{switch(f){case 3:z=N;ha=2;break;case 4:z=n;ha=1;break;case 5:case 197:z=function(h){R(!0,h)};ha=8;break;case 230:z=function(h){R(!1,h)};ha=8;break;case 7:z=V;ha=1;break;case 8:ja=0;h=2;fa[0]=32;fa[1]=Da;break;case 74:z=F;ha=1;break;case 15:ha=2;z=H;break;case 14:fa[0]=128,ja=0,h=
|
||||
1,ha=0}qa=0}}function B(){return Fa}function G(h){4===(h&4)&&0===(Fa&4)&&sa.k(6);Fa=h}function n(){ja=0;h=1;fa[0]=32}function H(h){Da=h[1];Fa&8&&sa.k(6)}function V(){Fa&8&&sa.k(6)}function R(f,z){function n(){B++;B>Ca&&(B=1,F++,1<F&&(F=0,N++));Da=N;ja=0;h=7;fa[0]=F<<2|32;fa[1]=0;fa[2]=0;fa[3]=N;fa[4]=F;fa[5]=B;fa[6]=z[4];Fa&8&&sa.k(6)}var F=z[2],N=z[1],B=z[3],G=128*(1<<z[4]),D=z[5]-z[3]+1,C=((F+2*N)*Ca+B-1)*G;f?pa.za(t,C,n):pa.ya(t,C,D*G,n)}function N(){}function F(){ja=0;h=7;fa[0]=0;fa[1]=0;fa[2]=
|
||||
0;fa[3]=0;fa[4]=0;fa[5]=0;fa[6]=0;Fa&8&&sa.k(6)}var na=f.j,sa=f.s,pa=f.xa,ha=0,za=new Uint8Array(10),qa=0,z,fa=new Uint8Array(10),ja=0,h=0;if(this.buffer=t){var Ca;368640===t.byteLength&&(this.type=1,Ca=9);if(1228800===t.byteLength)this.type=2,Ca=15;else if(737280===t.byteLength)this.type=3,Ca=9;else if(1474560===t.byteLength)this.type=4,Ca=18;else if(2949120===t.byteLength)this.type=5,Ca=36;else if(1763328===t.byteLength)this.type=5,Ca=21;else throw ze("Unknown floppy size: "+Be(t.byteLength));var Da=
|
||||
0;na.h(1008,D);na.h(1012,C);na.h(1013,L);na.h(1015,O);na.g(1013,X);var Fa=0;na.h(1010,B);na.g(1010,G)}else this.type=0};function be(){var f=new ArrayBuffer(67108864);function t(f){var F=f>>>14,n=V[F];return 1===H[F]?n(f):C(f&-4)>>8*(f&3)&255}function D(f,F){var n=R[f>>>14];1===H[f>>>14]&&n(f,F)}function C(f){var F=V[f>>>14];return 0===(f&3)&&H[f>>>14]===n?F(f):t(f)|t(f+1)<<8|t(f+2)<<16|t(f+3)<<24}function O(f,F){var t=R[f>>>14];0===(f&3)&&H[f>>>14]===n?t(f,F):(D(f,F&255),D(f+1,F>>8&255),D(f+2,F>>16&255),D(f+3,F>>24&255))}var L=new Uint8Array(f),X=new Uint16Array(f),B=new Int8Array(f),G=new Int32Array(f);this.m=L;this.Q=
|
||||
B;this.i=G;this.buffer=f;for(var n=4,H=new Int8Array(262144),V=[],R=[],f=0;262144>f;f++)V[f]=R[f]=void 0;this.ba=function(f,F,t,B,G){var D=f>>>14;for(t=t?n:1;0<F;D++)H[D]=t,V[D]=function(n){return B(n-f|0)},R[D]=function(n,F){G(n-f|0,F)},F-=16384};this.R=function(f){return H[f>>>14]?t(f)<<24>>24:B[f]};this.d=function(f){return H[f>>>14]?t(f):L[f]};this.b=function(f){return H[f>>>14]?t(f)|t(f+1)<<8:L[f]|L[f+1]<<8};this.q=function(f){return H[f>>>14]?t(f)|t(f+1)<<8:X[f>>1]};this.c=function(f){return H[f>>>
|
||||
14]?C(f)|0:L[f]|L[f+1]<<8|L[f+2]<<16|L[f+3]<<24};this.v=function(f){return H[f>>>14]?C(f)|0:G[f>>2]};this.e=function(f,n){H[f>>>14]?D(f,n):L[f]=n};this.a=function(f,n){H[f>>>14]?(D(f,n&255),D(f+1,n>>8&255)):(L[f]=n,L[f+1]=n>>8)};this.S=function(f,n){H[f>>>14]?(D(f,n&255),D(f+1,n>>8&255)):X[f>>1]=n};this.f=function(f,n){H[f>>>14]?O(f,n):(L[f]=n,L[f+1]=n>>8,L[f+2]=n>>16,L[f+3]=n>>24)};this.D=function(f,n){H[f>>>14]?O(f,n):G[f>>2]=n};this.J=function(f,n){L.set(f,n)};this.aa=function(f){for(var n=0;n<
|
||||
f.length;n++)this.e(63488+n,f.charCodeAt(n))}};function qe(f){function t(f,t){if(8>f){var n=f>>1;f&1?L[n].count=D(L[n].count,t):L[n].p=D(L[n].p,t)}}function D(f,t){return(X^=1)?f&-256|t:f&-65281|t<<8}var C=f.j,O=f.memory,L=[{p:0,count:0},{p:0,count:0},{p:0,count:0},{p:0,count:0}],X=0;C.g(4,t.bind(0,4));C.g(5,t.bind(0,5));C.g(10,function(){});C.g(11,function(){});C.g(12,function(){X=0});C.g(129,function(f){L[2].p=L[2].p&65535|f<<16});this.ya=function(f,t,n,D){var C=L[2].p;L[2].p+=n;f.get(t,n,function(f){O.J(f,C);D()})};this.za=function(f,t,n){f.set(t,
|
||||
new Uint8Array(O.buffer,L[2].p,L[2].count+1),function(){n()})}};function xe(f){function t(f){var n=H[f];if(n)return H[f]--,2===n?V[f]&255:V[f]>>8;n=X[f];3===G[f]&&(X[f]^=1);return n?N[f]&255:N[f]>>8}function D(f,t){R[f]=X[f]?R[f]&-256|t:R[f]&255|t<<8;3===n[f]&&X[f]||(R[f]||(R[f]=65535),N[f]=R[f],B[f]=!0);3===n[f]&&(X[f]^=1)}var C=f.j,O=f.s,L=Date.now(),X=new Uint8Array(3),B=new Uint8Array(3),G=new Uint8Array(3),n=new Uint8Array(3),H=new Uint8Array(3),V=new Uint16Array(3),R=new Uint16Array(3),N=new Uint16Array(3),F=0,na=0;C.h(97,function(){na^=16;return na|F<<
|
||||
5});this.a=function(f){var n,t=1193.1816666*(f-L)>>>0;if(t){L+=t/1193.1816666;if(B[0]&&(f=N[0]-=t,0>=f))if(O.k(0),n=G[0],0===n)B[0]=0,N[0]=0;else if(3===n||2===n)N[0]=R[0]+f%R[0];B[2]&&(f=N[2]-=t,0>=f&&(n=G[2],0===n?(F=1,B[2]=0,N[2]=0):2===n?(F=1,N[2]=R[2]+f%R[2]):3===n&&(F^=1,N[2]=R[2]+f%R[2])))}};C.h(64,function(){return t(0)});C.h(65,function(){return t(1)});C.h(66,function(){return t(2)});C.g(64,function(f){D(0,f)});C.g(65,function(f){D(1,f)});C.g(66,function(f){D(2,f)});C.g(67,function(f){var t=
|
||||
f>>1&7,D=f>>6&3;f=f>>4&3;3!==D&&(0===f?(H[D]=2,V[D]=N[D]):(6<=t&&(t&=-5),X[D]=1===f?1:2===f?0:1,G[D]=t,n[D]=f,2===D&&(F=0===t?0:1)))})};function re(f,t){function D(){var f=(L-N)/n|0,h=(L-N)%n,f=Math.min(H-1,f);t.Za(f,h)}var C=f.j,O=f.memory,L=0,X=14,B=15,G=this,n,H,V,R,N=0,F=!0,na=!1,sa=!1,pa=new Int32Array(256),ha=new Uint8Array(262144),za=new Uint8Array(ha.buffer,0,65536),qa=new Uint8Array(ha.buffer,65536,65536),z=new Uint8Array(ha.buffer,131072,65536),fa=new Uint8Array(ha.buffer,196608,65536),ja=0,h=0,Ca=0,Da=0,Fa=new Uint8Array(8388608),Xb=!1,gc=0,hc=0,ic=0;this.i=function(){if(sa)if(sa=!1,na){if(!F)for(var f=0,h,D=0;D<R;D++)for(var B=
|
||||
0;B<V;B+=8){for(var C=0;8>C;C++)h=za[f]>>C&1|qa[f]>>C<<1&2|z[f]>>C<<2&4|fa[f]>>C<<3&8,t.Qa(B+7-C,D,pa[zb[h]]);f++}}else for(f=98304|N<<1,B=0;B<H;B++)for(C=0;C<n;C++)h=ha[f],D=ha[f|1],t.ka(B,C,h,pa[D>>4&15],pa[D&15]),f+=2;na||Xb?t.Va():t.Wa()};this.N=function(f,h){n=f;H=h;t.N(f,h)};this.I=function(f,h){t.I(f,h)};this.O=function(){t.O(X,B)};this.Z=function(){t.Z()};this.a=function(f){var h=!1;switch(f){case 3:this.N(80,25);break;case 16:this.I(640,350);V=640;R=350;h=!0;F=!1;break;case 18:this.I(640,
|
||||
480);V=640;R=480;h=!0;F=!1;break;case 19:this.I(320,200),V=320,R=200,F=h=!0}t.va(h);na=h};this.n=function(){};var cb=0,$a=0;C.g(967,function(){});C.g(968,function(f){$a=3*f});C.g(969,function(f){var h=$a/3|0,n=$a%3,z=pa[h];f=f<<2&255|3;pa[h]=0===n?z&-16711681|f<<16:1===n?z&-65281|f<<8:z&-256|f;$a++;sa=!0});C.g(980,function(f){cb=f});C.g(981,function(f){switch(cb){case 2:G.N(f,25);break;case 10:X=f;G.O();break;case 11:B=f;G.O();break;case 12:N=N&255|f<<8;sa=!0;break;case 13:N=N&65280|f;sa=!0;break;
|
||||
case 14:L=L&255|f<<8;D();break;case 15:L=L&65280|f,D()}});C.h(981,function(){return 10===cb?X:11===cb?B:14===cb?L>>8:15===cb?L&255:0});var jc=255;C.h(972,function(){return jc});C.g(962,function(f){jc=f;103===f?G.a(3):227===f?G.a(18):99===f?G.a(19):163===f?G.a(16):G.a(3)});C.h(986,function(){La=-1;return 255});var La=-1;C.h(961,function(){return La=-1});var zb=new Uint8Array(16);C.g(960,function(f){-1===La?La=f:(16>La&&(zb[La]=f),La=-1)});C.h(960,function(){var f=La;La=-1;return f});var Bb=-1;C.g(964,
|
||||
function(f){Bb=f});var ca=15;C.g(965,function(f){switch(Bb){case 2:ca=f}});C.h(965,function(){switch(Bb){case 6:return 18}});var tc=-1;C.g(974,function(f){tc=f});var Qc=0,Wb=0,gd=0,Ia=255;C.g(975,function(f){switch(tc){case 3:gd=f;break;case 4:Qc=f;break;case 5:Wb=f;break;case 8:Ia=f}});var hb=-1,db=-1,ib=!0;C.g(462,function(f){hb=f;ib=!0});C.g(463,function(f){ib?(hb|=f<<8,ib=!1):(ib=!0,db=f)});C.g(464,function(f){db|=f<<8;switch(hb){case 1:gc=db;break;case 2:hc=db;break;case 3:ic=db;break;case 4:Xb=
|
||||
1===(db&1)}Xb&&(G.I(gc,hc),t.va(!0))});C.h(463,function(){switch(hb){case 0:return 192;case 1:return 1280;case 2:return 1024;case 3:return 32;case 10:return 128}});C.h(464,function(){switch(hb){case 0:return 176;case 1:return 5;case 2:return 4;case 3:return 0;case 10:return 0}});G.N(80,25);G.O();O.ba(655360,131072,!1,function(f){if(!na||F)return ha[f];f&=65535;ja=za[f];h=qa[f];Ca=z[f];Da=fa[f];return ha[Qc<<16|f]},function(f,D){if(na)if(F){var C=f<<2,B=pa[D];t.r(C|2,B>>16&255);t.r(C|1,B>>8&255);t.r(C,
|
||||
B&255);ha[f]=D}else{if(!(65535<f)){var G,H;0===Wb?C=B=G=H=D:2===Wb&&(ca&1&&(C=ja&~Ia|(D&1?255:0)&Ia),ca&2&&(B=h&~Ia|(D&2?255:0)&Ia),ca&4&&(G=Ca&~Ia|(D&4?255:0)&Ia),ca&8&&(H=Da&~Ia|(D&8?255:0)&Ia));if(0===Wb||2===Wb){switch(gd&24){case 8:C&=ja;B&=h;G&=Ca;H&=Da;break;case 16:C|=ja;B|=h;G|=Ca;H|=Da;break;case 24:C^=ja,B^=h,G^=Ca,H^=Da}ca&1&&(C=ja&~Ia|C&Ia);ca&2&&(B=h&~Ia|B&Ia);ca&4&&(G=Ca&~Ia|G&Ia);ca&8&&(H=Da&~Ia|H&Ia)}else 1===Wb&&(C=ja,B=h,G=Ca,H=Da);ca&1?za[f]=C:C=za[f];ca&2?qa[f]=B:B=qa[f];ca&4?
|
||||
z[f]=G:G=z[f];ca&8?fa[f]=H:H=fa[f];if(!(f>=V*R<<3)){B<<=1;G<<=2;H<<=3;for(var L=(f<<3|7)<<2,O=0;8>O;O++){var Fa=pa[zb[C>>O&1|B>>O&2|G>>O&4|H>>O&8]];t.r(L|2,Fa>>16);t.r(L|1,Fa>>8&255);t.r(L,Fa&255);L-=4}}}}else 98304>f||(B=(f-98304>>1)-N,C=B/n|0,B%=n,f&1?(H=D,G=ha[f&-2]):(G=D,H=ha[f|1]),t.ka(C,B,G,pa[H>>4&15],pa[H&15]),ha[f]=D)});O.ba(3758096384,8388608,!1,function(f){return Fa[f]},function(f,h){Fa[f]=h;switch(ic){case 32:if(3===(f&3))break;t.r(f,h);break;case 24:t.r(4/3*f|0,h);break;case 16:if(f&
|
||||
1){var n=Fa[f^1]>>5&7|h<<3&56,z;z=255*(h>>3&31)/31|0;f<<=1;t.r(f-1,255*n/63|0);t.r(f-2,z)}else n=255*(h&31)/31|0,t.r((f<<1)+2,n)}})};function se(f,t,D){function C(){n.k(1)}function O(f){qa.push(f);C()}function L(f,h){if(R&&V&&(N+=f,F+=h,H)){var n=Date.now();n-fa<1E3/z||(fa=n,B())}}function X(f,h,n){R&&V&&(na=f|n<<1|h<<2,H&&B())}function B(){ja.push((0>F)<<5|(0>N)<<4|8|na,N&255,F&255);if(15<ja.length){var f=ja.length%3;ja=ja.slice(0,f).concat(ja.slice(f+3))}F=N=0;n.k(12)}var G=f.j,n=f.s,H=!1,V=!1,R=!1,N=0,F=0,na=0,sa=!1,pa=!1,ha=!1,za=!1,qa=[],z=100,fa=-1,ja=[];t&&(sa=!0,t.w(O));D&&(R=!0,D.w(X,L));this.G=O;this.n=function(){sa&&
|
||||
t.n();R&&D.n()};var h=0,Ca=!1,Da=!1;G.h(96,function(){if(!qa.length&&!ja.length)return 255;if(qa.length&&ja.length?0===(n.Ca()&2):!qa.length)return 1<ja.length&&n.k(12),ja.shift();1<qa.length&&C();return qa.shift()});G.h(100,function(){var f=16;if(ja.length||qa.length)f|=1;ja.length&&(f|=32);return f});G.g(96,function(f){Da?(h=f,Da=!1):Ca?(Ca=!1,ja=[f],n.k(12)):ha?(ha=!1,ja=[250],z=f,n.k(12)):za?za=!1:pa?R&&(ja=[250],255===f?(ja.push(170,0),V=!0,D.enabled=!0):242===f?ja.push(0,0):243===f?ha=!0:244===
|
||||
f?(V=H=!0,D.enabled=!0):245===f?H=!0:246===f&&(H=!1,z=100),n.k(12)):(qa.push(250),255===f?qa.push(170,0):242===f?qa.push(171,83):244!==f&&245!==f&&237===f&&(za=!0),C())});G.g(100,function(n){254===n?f.Ta():32===n?(qa.push(h),C()):96===n?Da=!0:211===n?Ca=!0:212===n?pa=!0:169===n?(qa=[0],C()):170===n?(qa=[85],C()):171===n&&(qa=[0],C())})};function de(f,t,D,C){var O=f.j,L=0,X=0,B=0,G=0,n=void 0===C,H;n?(H=new de(f,t,D,this),this.a=function(){var f=G&L;if(!f)return!1;f&=-f;if(B&&(B&-B)<=f)return!1;G&=~f;B|=f;if(4===f)return H.a();t(X+Ae[f],!1,!1);return!0}):this.a=function(){var f=G&L;if(!f)return!1;f&=-f;if(B&&(B&-B)<=f)return!1;G&=~f;B|=f;t(X+Ae[f],!1,!1);G&&C.k(2);return!0};this.i=function(){n&&H.i()};var V,R=0,N=1;f=n?32:160;O.g(f,function(f){if(f&16)V=f&1,R=1;else if(f&8)N=f&1;else{var n=f>>5;1===n?B=0:3===n&&(B&=~(1<<(f&7)))}});
|
||||
O.h(f,function(){return N?G:B});O.g(f|1,function(f){0===R?V?V=!1:L=~f:1===R?(X=f,R++):2===R&&(R=0)});O.h(f|1,function(){return~L});this.k=n?function(f){8<=f&&(H.k(f-8),f=2);G|=1<<f;D()}:function(f){G|=1<<f};this.Ca=function(){return B}};function ye(f,t){function D(f){return N&4?f:Math.wa(f)}var C=f.j,O=f.s,L=0,X=this,B=Date.now(),G=B,n,H=!1,V=0.9765625,R=38,N=2;this.i=0;this.a=function(f){if(H)for(;n<f;)n+=V,O.k(8);B+=f-G;G=f};C.g(112,function(f){L=f&127;X.i=f>>7});C.g(113,function(f){switch(L){case 10:R=f&127;V=1E3/(32768>>(R&15)-1);break;case 11:N=f,N&64&&(n=Date.now())}H=64===(N&64)&&0<(R&15)});C.h(113,function(){var f=L;L=13;switch(f){case 0:return D((new Date(B)).getUTCSeconds());case 2:return D((new Date(B)).getUTCMinutes());
|
||||
case 4:return D((new Date(B)).getUTCHours());case 7:return D((new Date(B)).getUTCDate());case 8:return D((new Date(B)).getUTCMonth()+1);case 9:return D((new Date(B)).getUTCFullYear()%100);case 10:return R;case 11:return N;case 14:return 0;case 12:return 0;case 15:return 0;case 16:return t;case 20:return 45;case 50:return D((new Date(B)).getUTCFullYear()/100|0);case 52:return 0;case 53:return 3;case 56:return 48;case 61:return 33;case 91:case 92:case 93:return 0}return 255})};function te(f){var t="";f.j.g(1016,function(f){10===f?(nc(t),t=""):t+=String.fromCharCode(f)})};window.requestAnimationFrame||(window.requestAnimationFrame=window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame);
|
||||
function Wd(){function f(){na=!0;for(var f=0;f<ha;f++)F[f]&&(N.i(f),F[f]=0)}function t(f,n,t){n=""+(1===n?"":" scaleX("+n+")")+(1===t?"":" scaleY("+t+")");f.style.webkitTransform=f.style.MozTransform=n}var D=document.getElementById("screen"),C=document.getElementById("vga"),O=C.getContext("2d"),L=document.createElement("div"),X,B,G,n,H=1,V=1,R,N=this,F,na=!0,sa,pa,ha,za=new Uint16Array([199,252,233,226,228,224,229,231,234,235,232,239,238,236,196,197,201,230,198,244,246,242,251,249,255,214,220,162,
|
||||
163,165,8359,402,225,237,243,250,241,209,170,186,191,8976,172,189,188,161,171,187,9617,9618,9619,9474,9508,9569,9570,9558,9557,9571,9553,9559,9565,9564,9563,9488,9492,9524,9516,9500,9472,9532,9566,9567,9562,9556,9577,9574,9568,9552,9580,9575,9576,9572,9573,9561,9560,9554,9555,9579,9578,9496,9484,9608,9604,9612,9616,9600,945,223,915,960,931,963,181,964,934,920,937,948,8734,966,949,8745,8801,177,8805,8804,8992,8993,247,8776,176,8729,183,8730,8319,178,9632,160]),qa=new Uint16Array([32,9786,9787,9829,
|
||||
9830,9827,9824,8226,9688,9675,9689,9794,9792,9834,9835,9788,9658,9668,8597,8252,182,167,9644,8616,8593,8595,8594,8592,8735,8596,9650,9660]);O.imageSmoothingEnabled=!1;O.mozImageSmoothingEnabled=!1;O.webkitImageSmoothingEnabled=!1;L.id="cursor";D.style.display="block";C.style.display="none";this.ka=function(f,n,t,h,B){F[f]=1;f=3*(f*pa+n);sa[f]=t;sa[f+1]=h;sa[f+2]=B};this.Wa=function(){na&&(na=!1,requestAnimationFrame(f))};this.Qa=function(f,n,t){f=n*R+f<<2;B[f]=t>>16&255;B[f+1]=t>>8&255;B[f+2]=t&255};
|
||||
this.r=function(f,n){B[(f^3)-1]=n};this.Va=function(){na&&(na=!1,requestAnimationFrame(function(){na=!0;O.putImageData(X,0,0)}))};this.n=function(){};this.va=function(f){f?(D.style.display="none",C.style.display="block"):(D.style.display="block",C.style.display="none")};this.Z=function(){O.fillStyle="#000";O.fillRect(0,0,C.width,C.height)};this.N=function(f,n){F=new Int8Array(n);sa=new Int32Array(f*n*3);pa=f;for(ha=n;D.firstChild;)D.removeChild(D.firstChild);for(var t=0;t<n;t++)D.appendChild(document.createElement("div"))};
|
||||
this.I=function(f,n){C.style.display="block";C.width=f;C.height=n;N.Z();X=O.getImageData(0,0,f,n);B=X.data;R=f};this.a=function(f,n){H=f;V=n;t(C,H,V);t(D,H,V)};this.a(H,V);this.O=function(f,n){f&32?L.style.display="none":(L.style.display="inline",L.style.height=n-f+"px",L.style.marginTop=f+"px")};this.Za=function(f,t){if(f!==G||t!==n)F[f]=1,F[G]=1,G=f,n=t};this.i=function(f){var t=3*f*pa,B,h,C,F,H;B=document.createElement("div");for(var R=0;R<pa;){h=document.createElement("span");C=sa[t+1];F=sa[t+
|
||||
2];h.style.backgroundColor="#"+Be(C,6);h.style.color="#"+Be(F,6);for(H="";R<pa&&sa[t+1]===C&&sa[t+2]===F;){var N=sa[t];H+=127<N?String.fromCharCode(za[N-128]):32>N?String.fromCharCode(qa[N]):String.fromCharCode(N);R++;t+=3;if(f===G)if(R===n)break;else if(R===n+1){B.appendChild(L);break}}h.textContent=H;B.appendChild(h)}D.replaceChild(B,D.childNodes[f])}};function Xd(){function f(f){return f.shiftKey&&f.ctrlKey&&74===f.keyCode||116===f.keyCode||!X.enabled?!1:f.target?"phone_keyboard"===f.target.className||"INPUT"!==f.target.nodeName&&"TEXTAREA"!==f.target.nodeName:!0}function t(n){if(f(n)){var t=n.keyCode;if(!L[t])return!1;L[t]=!1;O(t,!1)||n.preventDefault()}}function D(n){if(f(n)){var t=n.keyCode;L[t]&&O(t,!1);L[t]=!0;O(t,!0)||n.preventDefault()}}function C(){for(var f=Object.keys(L),t,B=0;B<f.length;B++)t=+f[B],L[t]&&O(t,!1);L={}}function O(f,t){if(f>=
|
||||
G.length||0===G[f])return!0;var C=G[f];t||(C|=128);255<C?(B(C>>8),B(C&255)):B(C);return!1}var L={},X=this,B;this.enabled=!0;var G=new Uint16Array([0,0,0,0,0,0,0,0,14,15,0,0,0,28,0,0,42,29,56,0,58,0,0,0,0,0,0,1,0,0,0,0,57,57417,57425,79,71,75,72,77,80,0,0,0,0,82,83,0,11,2,3,4,5,6,7,8,9,10,0,39,0,13,0,0,0,30,48,46,32,18,33,34,35,23,36,37,38,50,49,24,25,16,19,31,20,22,47,17,45,21,44,0,0,0,0,0,82,79,80,81,75,76,77,71,72,73,0,0,0,0,0,0,59,60,61,62,63,64,65,66,67,68,87,88,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,0,39,13,51,12,52,53,41,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,26,43,27,40,0]);this.w=function(f){this.n();B=f;window.addEventListener("keyup",t,!1);window.addEventListener("keydown",D,!1);window.addEventListener("blur",C,!1)};this.n=function(){window.removeEventListener("keyup",t,!1);window.removeEventListener("keydown",D,!1);window.removeEventListener("blur",C,!1)}};function Yd(){function f(f){return V.enabled&&(!f.target||"mousemove"===f.type||"INPUT"!==f.target.nodeName&&"TEXTAREA"!==f.target.nodeName)}function t(n){if(f(n)){var t;t=n.webkitMovementX||n.mozMovementX||0;n=n.webkitMovementY||n.mozMovementY||0;t=Math.qa(0.5*t);n=Math.qa(0.5*n);H(t,-n)}}function D(n){f(n)&&n.preventDefault()}function C(n){f(n)&&L(n,!0)}function O(n){f(n)&&L(n,!1)}function L(f,t){1===f.which?X=t:2===f.which?G=t:3===f.which&&(B=t);n(X,G,B);f.preventDefault()}var X=!1,B=!1,G=!1,n,
|
||||
H,V=this;this.enabled=!1;this.n=function(){window.removeEventListener("mousemove",t,!1);document.removeEventListener("contextmenu",D,!1);window.removeEventListener("mousedown",C,!1);window.removeEventListener("mouseup",O,!1)};this.w=function(f,B){this.n();n=f;H=B;window.addEventListener("mousemove",t,!1);document.addEventListener("contextmenu",D,!1);window.addEventListener("mousedown",C,!1);window.addEventListener("mouseup",O,!1)}};
|
||||
//# sourceMappingURL=src/v86_all.js.map
|
Loading…
Reference in a new issue