Compare commits

..

10 commits

92 changed files with 792 additions and 481962 deletions

9
.gitmodules vendored
View file

@ -7,3 +7,12 @@
[submodule "source/engine/thirdparty/cgltf"] [submodule "source/engine/thirdparty/cgltf"]
path = source/engine/thirdparty/cgltf path = source/engine/thirdparty/cgltf
url = https://github.com/jkuhlmann/cgltf.git url = https://github.com/jkuhlmann/cgltf.git
[submodule "quickjs"]
path = quickjs
url = https://github.com/bellard/quickjs.git
[submodule "source/engine/thirdparty/TinySoundFont"]
path = source/engine/thirdparty/TinySoundFont
url = https://github.com/schellingb/TinySoundFont.git
[submodule "source/engine/thirdparty/dr_libs"]
path = source/engine/thirdparty/dr_libs
url = https://github.com/mackron/dr_libs.git

View file

@ -9,9 +9,14 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in (1) The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software. all copies or substantial portions of the Software.
(2) Any games or other derivative software must display the "Prosperon" logo
at near the beginning of the software's startup, before the chief purpose
of the software is underway.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL

View file

@ -24,9 +24,6 @@ LEAK ?= 0
INFO := INFO :=
LD = $(CC) LD = $(CC)
#ifeq ($(CC), clang)
# AR = llvm-ar
#endif
ifeq ($(CC), x86_64-w64-mingw32-gcc) ifeq ($(CC), x86_64-w64-mingw32-gcc)
AR = x86_64-w64-mingw32-ar AR = x86_64-w64-mingw32-ar
endif endif
@ -53,6 +50,14 @@ endif
CPPFLAGS += -ffast-math CPPFLAGS += -ffast-math
ifeq ($(CC), emcc)
LDFLAGS += #--closure 1
CPPFLAGS += -O0
OPT = 0
DBG = 0
AR = emar
endif
ifeq ($(DBG),1) ifeq ($(DBG),1)
CPPFLAGS += -g CPPFLAGS += -g
INFO += _dbg INFO += _dbg
@ -123,12 +128,10 @@ ifeq ($(OS), Windows_NT)
UNZIP = unzip -o -q $(DISTDIR)/$(DIST) -d $(DESTDIR) UNZIP = unzip -o -q $(DISTDIR)/$(DIST) -d $(DESTDIR)
else ifeq ($(CC), emcc) else ifeq ($(CC), emcc)
OS := Web OS := Web
LDFLAGS += -sMIN_WEBGL_VERSION=2 -sMAX_WEBGL_VERSION=2 -pthread -sTOTAL_MEMORY=450MB LDFLAGS += -sMIN_WEBGL_VERSION=2 -sMAX_WEBGL_VERSION=2 -pthread -sTOTAL_MEMORY=128MB
CPPFLAGS += -pthread CPPFLAGS += -pthread
LDLIBS += pthread quickjs GL openal c m dl LDLIBS += pthread quickjs GL openal c m dl
CC = emcc
EXT = .html EXT = .html
else else
UNAME != uname -s UNAME != uname -s
ifeq ($(UNAME), Linux) ifeq ($(UNAME), Linux)
@ -155,8 +158,8 @@ endif
OBJDIR = $(BIN)/obj OBJDIR = $(BIN)/obj
# All other sources # All other sources
OBJS != find source/engine -type f -name '*.c' | grep -vE 'test|tool' OBJS != find source/engine -type f -name '*.c' | grep -vE 'test|tool|example'
CPPOBJS != find source/engine -type f -name '*.cpp' | grep -vE 'test|tool' CPPOBJS != find source/engine -type f -name '*.cpp' | grep -vE 'test|tool|example'
OBJS += $(CPPOBJS) OBJS += $(CPPOBJS)
OBJS += $(shell find source/engine -type f -name '*.m') OBJS += $(shell find source/engine -type f -name '*.m')
OBJS := $(patsubst %.cpp, %.o, $(OBJS)) OBJS := $(patsubst %.cpp, %.o, $(OBJS))
@ -166,7 +169,7 @@ OBJS := $(addprefix $(BIN)/obj/, $(OBJS))
engineincs != find source/engine -maxdepth 1 -type d engineincs != find source/engine -maxdepth 1 -type d
includeflag != find source -type d -name include includeflag != find source -type d -name include
includeflag += $(engineincs) source/engine/thirdparty/tinycdb source/shaders source/engine/thirdparty/sokol source/engine/thirdparty/stb source/engine/thirdparty/cgltf includeflag += $(engineincs) source/engine/thirdparty/tinycdb source/shaders source/engine/thirdparty/sokol source/engine/thirdparty/stb source/engine/thirdparty/cgltf source/engine/thirdparty/TinySoundFont source/engine/thirdparty/dr_libs
includeflag := $(addprefix -I, $(includeflag)) includeflag := $(addprefix -I, $(includeflag))
# Adding different SDKs # Adding different SDKs
@ -256,7 +259,7 @@ input.md: $(INPUTMD)
$(BIN)/libquickjs.a: $(QUICKJS_O) $(BIN)/libquickjs.a: $(QUICKJS_O)
make -C quickjs clean make -C quickjs clean
make -C quickjs SYSRT=$(SYSRT) TTARGET=$(TTARGET) ARCH=$(ARCH) DBG=$(DBG) OPT=$(OPT) AR=$(AR) OS=$(OS) libquickjs.a libquickjs.lto.a HOST_CC=$(CC) LEAK=$(LEAK) make -C quickjs SYSRT=$(SYSRT) TTARGET=$(TTARGET) ARCH=$(ARCH) DBG=$(DBG) OPT=$(OPT) AR=$(AR) OS=$(OS) libquickjs.a HOST_CC=$(CC) LEAK=$(LEAK)
@mkdir -p $(BIN) @mkdir -p $(BIN)
cp -rf quickjs/libquickjs.* $(BIN) cp -rf quickjs/libquickjs.* $(BIN)

6
README Normal file
View file

@ -0,0 +1,6 @@
![alt text](doc/prosperon_orb_horizontal.gif)
The easily moddable, programming minded, 2D-first game engine. The aim is to make the fastest way to make games.
See the [documentation](doc/prosperon.org) for more information, including how to compile.
*Prosperon is useful, but is a work in progress. Breaking changes are frequent.*

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -33,6 +33,9 @@ Install the most [[https://prosperon.dev/download][recent binaries]] into your ~
*** Windows *** Windows
Copy the executable into any folder and run it. If no game is deteced, it scaffolds for you. Copy the executable into any folder and run it. If no game is deteced, it scaffolds for you.
*** Building
You will need ~sokol-shdc~ in the top of your directory. Then, ~make shaders~ and ~make~. The command ~make install~ copies it to your home's ~.bin~ path.
** Playing your first game ** Playing your first game
Download any of the completed example projects. Run ~prosperon play~ in the folder. Download any of the completed example projects. Run ~prosperon play~ in the folder.

View file

@ -1,4 +0,0 @@
(font
:path "LessPerfectDOSVGA.ttf"
:size 16
)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 298 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 187 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 225 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 293 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 157 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 197 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 226 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 108 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 339 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 234 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 187 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 224 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 206 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

1
quickjs Submodule

@ -0,0 +1 @@
Subproject commit 6a89d7c27099be84e5312a7ec73205d6a7abe1b4

View file

@ -1,148 +0,0 @@
2021-03-27:
- faster Array.prototype.push and Array.prototype.unshift
- added JS_UpdateStackTop()
- fixed Windows console
- misc bug fixes
2020-11-08:
- improved function parameter initializers
- added std.setenv(), std.unsetenv() and std.getenviron()
- added JS_EvalThis()
- misc bug fixes
2020-09-06:
- added logical assignment operators
- added IsHTMLDDA support
- faster for-of loops
- os.Worker now takes a module filename as parameter
- qjsc: added -D option to compile dynamically loaded modules or workers
- misc bug fixes
2020-07-05:
- modified JS_GetPrototype() to return a live value
- REPL: support unicode characters larger than 16 bits
- added os.Worker
- improved object serialization
- added std.parseExtJSON
- misc bug fixes
2020-04-12:
- added cross realm support
- added AggregateError and Promise.any
- added env, uid and gid options in os.exec()
- misc bug fixes
2020-03-16:
- reworked error handling in std and os libraries: suppressed I/O
exceptions in std FILE functions and return a positive errno value
when it is explicit
- output exception messages to stderr
- added std.loadFile(), std.strerror(), std.FILE.prototype.tello()
- added JS_GetRuntimeOpaque(), JS_SetRuntimeOpaque(), JS_NewUint32()
- updated to Unicode 13.0.0
- misc bug fixes
2020-01-19:
- keep CONFIG_BIGNUM in the makefile
- added os.chdir()
- qjs: added -I option
- more memory checks in the bignum operations
- modified operator overloading semantics to be closer to the TC39
proposal
- suppressed "use bigint" mode. Simplified "use math" mode
- BigDecimal: changed suffix from 'd' to 'm'
- misc bug fixes
2020-01-05:
- always compile the bignum code. Added '--bignum' option to qjs.
- added BigDecimal
- added String.prototype.replaceAll
- misc bug fixes
2019-12-21:
- added nullish coalescing operator (ES2020)
- added optional chaining (ES2020)
- removed recursions in garbage collector
- test stack overflow in the parser
- improved backtrace logic
- added JS_SetHostPromiseRejectionTracker()
- allow exotic constructors
- improved c++ compatibility
- misc bug fixes
2019-10-27:
- added example of C class in a module (examples/test_point.js)
- added JS_GetTypedArrayBuffer()
- misc bug fixes
2019-09-18:
- added os.exec and other system calls
- exported JS_ValueToAtom()
- qjsc: added 'qjsc_' prefix to the generated C identifiers
- added cross-compilation support
- misc bug fixes
2019-09-01:
- added globalThis
- documented JS_EVAL_FLAG_COMPILE_ONLY
- added import.meta.url and import.meta.main
- added 'debugger' statement
- misc bug fixes
2019-08-18:
- added os.realpath, os.getcwd, os.mkdir, os.stat, os.lstat,
os.readlink, os.readdir, os.utimes, std.popen
- module autodetection
- added import.meta
- misc bug fixes
2019-08-10:
- added public class fields and private class fields, methods and
accessors (TC39 proposal)
- changed JS_ToCStringLen() prototype
- qjsc: handle '-' in module names and modules with the same filename
- added std.urlGet
- exported JS_GetOwnPropertyNames() and JS_GetOwnProperty()
- exported some bigint C functions
- added support for eshost in run-test262
- misc bug fixes
2019-07-28:
- added dynamic import
- added Promise.allSettled
- added String.prototype.matchAll
- added Object.fromEntries
- reduced number of ticks in await
- added BigInt support in Atomics
- exported JS_NewPromiseCapability()
- misc async function and async generator fixes
- enabled hashbang support by default
2019-07-21:
- updated test262 tests
- updated to Unicode version 12.1.0
- fixed missing Date object in qjsc
- fixed multi-context creation
- misc ES2020 related fixes
- simplified power and division operators in bignum extension
- fixed several crash conditions
2019-07-09:
- first public release

View file

@ -1,22 +0,0 @@
QuickJS Javascript Engine
Copyright (c) 2017-2021 Fabrice Bellard
Copyright (c) 2017-2021 Charlie Gordon
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View file

@ -1,486 +0,0 @@
#
# QuickJS Javascript Engine
#
# Copyright (c) 2017-2021 Fabrice Bellard
# Copyright (c) 2017-2021 Charlie Gordon
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
ifeq ($(shell uname -s),Darwin)
ifeq ($(HOST_CC),clang)
CFLAGS += -arch $(ARCH)
endif
endif
# Windows cross compilation from Linux
#CONFIG_WIN32=y
# use link time optimization (smaller and faster executables but slower build)
CONFIG_LTO=y
# consider warnings as errors (for development)
#CONFIG_WERROR=y
# force 32 bit build for some utilities
#CONFIG_M32=y
# use clang instead of gcc
ifeq ($(HOST_CC),clang)
CONFIG_CLANG=y
CONFIG_DEFAULT_AR=y
endif
# installation directory
prefix=/usr/local
# use the gprof profiler
#CONFIG_PROFILE=y
# use address sanitizer
#CONFIG_ASAN=y
# include the code for BigInt/BigFloat/BigDecimal and math mode
CONFIG_BIGNUM=y
OBJDIR=.obj
ifdef CONFIG_WIN32
ifdef CONFIG_M32
CROSS_PREFIX=i686-w64-mingw32-
else
CROSS_PREFIX=x86_64-w64-mingw32-
endif
EXE=.exe
else
CROSS_PREFIX=
EXE=
endif
ifeq ($(CC), clang)
CC=$(CROSS_PREFIX)clang
CFLAGS += -g -Wall -MMD -MF $(OBJDIR)/$(@F).d
CFLAGS += -Wextra
CFLAGS += -Wno-sign-compare
CFLAGS += -Wno-missing-field-initializers
CFLAGS += -Wno-unused-function -Wno-unused-const-variable
CFLAGS += -Wundef -Wuninitialized
CFLAGS += -Wunused -Wno-unused-parameter
CFLAGS += -Wwrite-strings
CFLAGS += -Wchar-subscripts -funsigned-char
CFLAGS += -MMD -MF $(OBJDIR)/$(@F).d
ifneq ($(TTARGET),)
CFLAGS += --target=$(TTARGET)
CFLAGS += -isysroot $(SYSRT)
endif
ifdef CONFIG_DEFAULT_AR
AR=$(CROSS_PREFIX)ar
else
ifdef CONFIG_LTO
AR=$(CROSS_PREFIX)llvm-ar
else
AR=$(CROSS_PREFIX)ar
endif
endif
else
CC=$(CROSS_PREFIX)gcc
CFLAGS += -g -Wall -MMD -MF $(OBJDIR)/$(@F).d
CFLAGS += -Wno-array-bounds -Wno-format-truncation
CFLAGS += -Wno-unused-function -Wno-unused-const-variable
ifdef CONFIG_LTO
AR=$(CROSS_PREFIX)gcc-ar
else
AR=$(CROSS_PREFIX)ar
endif
endif
STRIP=$(CROSS_PREFIX)strip
ifdef CONFIG_WERROR
CFLAGS+=-Werror
endif
DEFINES:=-D_GNU_SOURCE -DCONFIG_VERSION=\"$(shell cat VERSION)\"
ifdef CONFIG_BIGNUM
DEFINES+=-DCONFIG_BIGNUM
endif
ifdef CONFIG_WIN32
DEFINES+=-D__USE_MINGW_ANSI_STDIO # for standard snprintf behavior
endif
CFLAGS+=$(DEFINES)
CFLAGS_DEBUG=$(CFLAGS) -O0
CFLAGS_SMALL=$(CFLAGS) -Os
CFLAGS_OPT=$(CFLAGS) -O2
CFLAGS_NOLTO:=$(CFLAGS_OPT)
LDFLAGS=-g
ifdef CONFIG_LTO
CFLAGS_SMALL+=-flto
CFLAGS_OPT+=-flto
LDFLAGS+=-flto
endif
ifdef CONFIG_PROFILE
CFLAGS+=-p
LDFLAGS+=-p
endif
ifdef CONFIG_ASAN
CFLAGS+=-fsanitize=address -fno-omit-frame-pointer
LDFLAGS+=-fsanitize=address -fno-omit-frame-pointer
endif
ifdef CONFIG_WIN32
LDEXPORT=
else
LDEXPORT=-rdynamic
endif
ifeq ($(OPT), small)
USEFLAGS = $(CFLAGS_SMALL)
else ifeq ($(OPT), 1)
USEFLAGS = $(CFLAGS_OPT)
else
USEFLAGS = $(CFLAGS_DEBUG)
endif
PROGS=qjs$(EXE) qjsc$(EXE) run-test262
ifneq ($(CROSS_PREFIX),)
QJSC_CC=gcc
QJSC=./host-qjsc
PROGS+=$(QJSC)
else
QJSC_CC=$(CC)
QJSC=./qjsc$(EXE)
endif
ifndef CONFIG_WIN32
PROGS+=qjscalc
endif
ifdef CONFIG_M32
PROGS+=qjs32 qjs32_s
endif
PROGS+=libquickjs.a
ifdef CONFIG_LTO
PROGS+=libquickjs.lto.a
endif
# examples
ifeq ($(CROSS_PREFIX),)
ifdef CONFIG_ASAN
PROGS+=
else
PROGS+=examples/hello examples/hello_module examples/test_fib
ifndef CONFIG_DARWIN
PROGS+=examples/fib.so examples/point.so
endif
endif
endif
all: $(OBJDIR) $(OBJDIR)/quickjs.check.o $(OBJDIR)/qjs.check.o $(PROGS)
QJS_LIB_OBJS=$(OBJDIR)/quickjs.o $(OBJDIR)/libregexp.o $(OBJDIR)/libunicode.o $(OBJDIR)/cutils.o $(OBJDIR)/quickjs-libc.o
QJS_OBJS=$(OBJDIR)/qjs.o $(OBJDIR)/repl.o $(QJS_LIB_OBJS)
ifdef CONFIG_BIGNUM
QJS_LIB_OBJS+=$(OBJDIR)/libbf.o
QJS_OBJS+=$(OBJDIR)/qjscalc.o
endif
HOST_LIBS=-lm -ldl -lpthread
LIBS=-lm
ifndef CONFIG_WIN32
LIBS+=-ldl -lpthread
endif
LIBS+=$(EXTRA_LIBS)
$(OBJDIR):
mkdir -p $(OBJDIR) $(OBJDIR)/examples $(OBJDIR)/tests
qjs$(EXE): $(QJS_OBJS)
$(CC) $(LDFLAGS) $(LDEXPORT) -o $@ $^ $(LIBS)
qjs-debug$(EXE): $(patsubst %.o, %.debug.o, $(QJS_OBJS))
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
qjsc$(EXE): $(OBJDIR)/qjsc.o $(QJS_LIB_OBJS)
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
ifneq ($(CROSS_PREFIX),)
$(QJSC): $(OBJDIR)/qjsc.host.o \
$(patsubst %.o, %.host.o, $(QJS_LIB_OBJS))
$(HOST_CC) $(LDFLAGS) -o $@ $^ $(HOST_LIBS)
endif #CROSS_PREFIX
QJSC_DEFINES:=-DCONFIG_CC=\"$(QJSC_CC)\" -DCONFIG_PREFIX=\"$(prefix)\"
ifdef CONFIG_LTO
QJSC_DEFINES+=-DCONFIG_LTO
endif
QJSC_HOST_DEFINES:=-DCONFIG_CC=\"$(HOST_CC)\" -DCONFIG_PREFIX=\"$(prefix)\"
$(OBJDIR)/qjsc.o: CFLAGS+=$(QJSC_DEFINES)
$(OBJDIR)/qjsc.host.o: CFLAGS+=$(QJSC_HOST_DEFINES)
qjs32: $(patsubst %.o, %.m32.o, $(QJS_OBJS))
$(CC) -m32 $(LDFLAGS) $(LDEXPORT) -o $@ $^ $(LIBS)
qjs32_s: $(patsubst %.o, %.m32s.o, $(QJS_OBJS))
$(CC) -m32 $(LDFLAGS) -o $@ $^ $(LIBS)
@size $@
qjscalc: qjs
ln -sf $< $@
ifdef CONFIG_LTO
LTOEXT=.lto
else
LTOEXT=
endif
libquickjs$(LTOEXT).a: $(QJS_LIB_OBJS)
$(AR) rcs $@ $^
ifdef CONFIG_LTO
libquickjs.a: $(patsubst %.o, %.nolto.o, $(QJS_LIB_OBJS))
$(AR) rcs $@ $^
endif # CONFIG_LTO
repl.c: $(QJSC) repl.js
$(QJSC) -c -o $@ -m repl.js
qjscalc.c: $(QJSC) qjscalc.js
$(QJSC) -fbignum -c -o $@ qjscalc.js
ifneq ($(wildcard unicode/UnicodeData.txt),)
$(OBJDIR)/libunicode.o $(OBJDIR)/libunicode.m32.o $(OBJDIR)/libunicode.m32s.o \
$(OBJDIR)/libunicode.nolto.o: libunicode-table.h
libunicode-table.h: unicode_gen
./unicode_gen unicode $@
endif
run-test262: $(OBJDIR)/run-test262.o $(QJS_LIB_OBJS)
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
run-test262-debug: $(patsubst %.o, %.debug.o, $(OBJDIR)/run-test262.o $(QJS_LIB_OBJS))
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
run-test262-32: $(patsubst %.o, %.m32.o, $(OBJDIR)/run-test262.o $(QJS_LIB_OBJS))
$(CC) -m32 $(LDFLAGS) -o $@ $^ $(LIBS)
# object suffix order: nolto, [m32|m32s]
$(OBJDIR)/%.o: %.c | $(OBJDIR)
$(CC) $(CFLAGS_OPT) -c -o $@ $<
$(OBJDIR)/%.host.o: %.c | $(OBJDIR)
$(HOST_CC) $(CFLAGS_OPT) -c -o $@ $<
$(OBJDIR)/%.pic.o: %.c | $(OBJDIR)
$(CC) $(CFLAGS_OPT) -fPIC -DJS_SHARED_LIBRARY -c -o $@ $<
$(OBJDIR)/%.nolto.o: %.c | $(OBJDIR)
$(CC) $(CFLAGS_NOLTO) -c -o $@ $<
$(OBJDIR)/%.m32.o: %.c | $(OBJDIR)
$(CC) -m32 $(CFLAGS_OPT) -c -o $@ $<
$(OBJDIR)/%.m32s.o: %.c | $(OBJDIR)
$(CC) -m32 $(CFLAGS_SMALL) -c -o $@ $<
$(OBJDIR)/%.debug.o: %.c | $(OBJDIR)
$(CC) $(CFLAGS_DEBUG) -c -o $@ $<
$(OBJDIR)/%.check.o: %.c | $(OBJDIR)
$(CC) $(CFLAGS) -DCONFIG_CHECK_JSVALUE -c -o $@ $<
regexp_test: libregexp.c libunicode.c cutils.c
$(CC) $(LDFLAGS) $(CFLAGS) -DTEST -o $@ libregexp.c libunicode.c cutils.c $(LIBS)
unicode_gen: $(OBJDIR)/unicode_gen.host.o $(OBJDIR)/cutils.host.o libunicode.c unicode_gen_def.h
$(HOST_CC) $(LDFLAGS) $(CFLAGS) -o $@ $(OBJDIR)/unicode_gen.host.o $(OBJDIR)/cutils.host.o
clean:
rm -f repl.c qjscalc.c out.c
rm -f *.a *.o *.d *~ unicode_gen regexp_test $(PROGS)
rm -f hello.c test_fib.c
rm -f examples/*.so tests/*.so
rm -rf $(OBJDIR)/ *.dSYM/ qjs-debug
rm -rf run-test262-debug run-test262-32
install: all
mkdir -p "$(DESTDIR)$(prefix)/bin"
$(STRIP) qjs qjsc
install -m755 qjs qjsc "$(DESTDIR)$(prefix)/bin"
ln -sf qjs "$(DESTDIR)$(prefix)/bin/qjscalc"
mkdir -p "$(DESTDIR)$(prefix)/lib/quickjs"
install -m644 libquickjs.a "$(DESTDIR)$(prefix)/lib/quickjs"
ifdef CONFIG_LTO
install -m644 libquickjs.lto.a "$(DESTDIR)$(prefix)/lib/quickjs"
endif
mkdir -p "$(DESTDIR)$(prefix)/include/quickjs"
install -m644 quickjs.h quickjs-libc.h "$(DESTDIR)$(prefix)/include/quickjs"
###############################################################################
# examples
# example of static JS compilation
HELLO_SRCS=examples/hello.js
HELLO_OPTS=-fno-string-normalize -fno-map -fno-promise -fno-typedarray \
-fno-typedarray -fno-regexp -fno-json -fno-eval -fno-proxy \
-fno-date -fno-module-loader
ifdef CONFIG_BIGNUM
HELLO_OPTS+=-fno-bigint
endif
hello.c: $(QJSC) $(HELLO_SRCS)
$(QJSC) -e $(HELLO_OPTS) -o $@ $(HELLO_SRCS)
ifdef CONFIG_M32
examples/hello: $(OBJDIR)/hello.m32s.o $(patsubst %.o, %.m32s.o, $(QJS_LIB_OBJS))
$(CC) -m32 $(LDFLAGS) -o $@ $^ $(LIBS)
else
examples/hello: $(OBJDIR)/hello.o $(QJS_LIB_OBJS)
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
endif
# example of static JS compilation with modules
HELLO_MODULE_SRCS=examples/hello_module.js
HELLO_MODULE_OPTS=-fno-string-normalize -fno-map -fno-promise -fno-typedarray \
-fno-typedarray -fno-regexp -fno-json -fno-eval -fno-proxy \
-fno-date -m
examples/hello_module: $(QJSC) libquickjs$(LTOEXT).a $(HELLO_MODULE_SRCS)
$(QJSC) $(HELLO_MODULE_OPTS) -o $@ $(HELLO_MODULE_SRCS)
# use of an external C module (static compilation)
test_fib.c: $(QJSC) examples/test_fib.js
$(QJSC) -e -M examples/fib.so,fib -m -o $@ examples/test_fib.js
examples/test_fib: $(OBJDIR)/test_fib.o $(OBJDIR)/examples/fib.o libquickjs$(LTOEXT).a
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
examples/fib.so: $(OBJDIR)/examples/fib.pic.o
$(CC) $(LDFLAGS) -shared -o $@ $^
examples/point.so: $(OBJDIR)/examples/point.pic.o
$(CC) $(LDFLAGS) -shared -o $@ $^
###############################################################################
# documentation
DOCS=doc/quickjs.pdf doc/quickjs.html doc/jsbignum.pdf doc/jsbignum.html
build_doc: $(DOCS)
clean_doc:
rm -f $(DOCS)
doc/%.pdf: doc/%.texi
texi2pdf --clean -o $@ -q $<
doc/%.html.pre: doc/%.texi
makeinfo --html --no-headers --no-split --number-sections -o $@ $<
doc/%.html: doc/%.html.pre
sed -e 's|</style>|</style>\n<meta name="viewport" content="width=device-width, initial-scale=1.0">|' < $< > $@
###############################################################################
# tests
ifndef CONFIG_DARWIN
test: tests/bjson.so examples/point.so
endif
ifdef CONFIG_M32
test: qjs32
endif
test: qjs
./qjs tests/test_closure.js
./qjs tests/test_language.js
./qjs tests/test_builtin.js
./qjs tests/test_loop.js
./qjs tests/test_std.js
./qjs tests/test_worker.js
ifndef CONFIG_DARWIN
ifdef CONFIG_BIGNUM
./qjs --bignum tests/test_bjson.js
else
./qjs tests/test_bjson.js
endif
./qjs examples/test_point.js
endif
ifdef CONFIG_BIGNUM
./qjs --bignum tests/test_op_overloading.js
./qjs --bignum tests/test_bignum.js
./qjs --qjscalc tests/test_qjscalc.js
endif
ifdef CONFIG_M32
./qjs32 tests/test_closure.js
./qjs32 tests/test_language.js
./qjs32 tests/test_builtin.js
./qjs32 tests/test_loop.js
./qjs32 tests/test_std.js
./qjs32 tests/test_worker.js
ifdef CONFIG_BIGNUM
./qjs32 --bignum tests/test_op_overloading.js
./qjs32 --bignum tests/test_bignum.js
./qjs32 --qjscalc tests/test_qjscalc.js
endif
endif
stats: qjs qjs32
./qjs -qd
./qjs32 -qd
microbench: qjs
./qjs tests/microbench.js
microbench-32: qjs32
./qjs32 tests/microbench.js
# ES5 tests (obsolete)
test2o: run-test262
time ./run-test262 -m -c test262o.conf
test2o-32: run-test262-32
time ./run-test262-32 -m -c test262o.conf
test2o-update: run-test262
./run-test262 -u -c test262o.conf
# Test262 tests
test2-default: run-test262
time ./run-test262 -m -c test262.conf
test2: run-test262
time ./run-test262 -m -c test262.conf -a
test2-32: run-test262-32
time ./run-test262-32 -m -c test262.conf -a
test2-update: run-test262
./run-test262 -u -c test262.conf -a
test2-check: run-test262
time ./run-test262 -m -c test262.conf -E -a
testall: all test microbench test2o test2
testall-32: all test-32 microbench-32 test2o-32 test2-32
testall-complete: testall testall-32
bench-v8: qjs
make -C tests/bench-v8
./qjs -d tests/bench-v8/combined.js
tests/bjson.so: $(OBJDIR)/tests/bjson.pic.o
$(CC) $(LDFLAGS) -shared -o $@ $^ $(LIBS)
-include $(wildcard $(OBJDIR)/*.d)

View file

@ -1,70 +0,0 @@
Bugs:
- modules: better error handling with cyclic module references
Misc ideas:
- use custom printf to avoid compatibility issues with floating point numbers
- consistent naming for preprocessor defines
- unify coding style and naming conventions
- use names from the ECMA spec in library implementation
- use byte code emitters with typed arguments (for clarity)
- use 2 bytecode DynBufs in JSFunctionDef, one for reading, one for writing
and use the same wrappers in all phases
- use more generic method for line numbers in resolve_variables and resolve_labels
- use custom timezone support to avoid C library compatibility issues
Memory:
- use memory pools for objects, etc?
- test border cases for max number of atoms, object properties, string length
- add emergency malloc mode for out of memory exceptions.
- test all DynBuf memory errors
- test all js_realloc memory errors
- improve JS_ComputeMemoryUsage() with more info
Built-in standard library:
- BSD sockets
- modules: use realpath in module name normalizer and put it in quickjs-libc
- modules: if no ".", use a well known module loading path ?
- get rid of __loadScript, use more common name
REPL:
- debugger
- readline: support MS Windows terminal
- readline: handle dynamic terminal resizing
- readline: handle double width unicode characters
- multiline editing
- runtime object and function inspectors
- interactive object browser
- use more generic approach to display evaluation results
- improve directive handling: dispatch, colorize, completion...
- save history
- close all predefined methods in repl.js and jscalc.js
Optimization ideas:
- 64-bit atoms in 64-bit mode ?
- 64-bit small bigint in 64-bit mode ?
- reuse stack slots for disjoint scopes, if strip
- add heuristic to avoid some cycles in closures
- small String (0-2 charcodes) with immediate storage
- perform static string concatenation at compile time
- optimize string concatenation with ropes or miniropes?
- add implicit numeric strings for Uint32 numbers?
- optimize `s += a + b`, `s += a.b` and similar simple expressions
- ensure string canonical representation and optimise comparisons and hashes?
- remove JSObject.first_weak_ref, use bit+context based hashed array for weak references
- property access optimization on the global object, functions,
prototypes and special non extensible objects.
- create object literals with the correct length by backpatching length argument
- remove redundant set_loc_uninitialized/check_uninitialized opcodes
- peephole optim: push_atom_value, to_propkey -> push_atom_value
- peephole optim: put_loc x, get_loc_check x -> set_loc x
- convert slow array to fast array when all properties != length are numeric
- optimize destructuring assignments for global and local variables
- implement some form of tail-call-optimization
- optimize OP_apply
- optimize f(...b)
Test262o: 0/11262 errors, 463 excluded
Test262o commit: 7da91bceb9ce7613f87db47ddd1292a2dda58b42 (es5-tests branch)
Result: 35/75280 errors, 909 excluded, 585 skipped
Test262 commit: 31126581e7290f9233c29cefd93f66c6ac78f1c9

View file

@ -1 +0,0 @@
2021-03-27

View file

@ -1,631 +0,0 @@
/*
* C utilities
*
* Copyright (c) 2017 Fabrice Bellard
* Copyright (c) 2018 Charlie Gordon
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include "cutils.h"
void pstrcpy(char *buf, int buf_size, const char *str)
{
int c;
char *q = buf;
if (buf_size <= 0)
return;
for(;;) {
c = *str++;
if (c == 0 || q >= buf + buf_size - 1)
break;
*q++ = c;
}
*q = '\0';
}
/* strcat and truncate. */
char *pstrcat(char *buf, int buf_size, const char *s)
{
int len;
len = strlen(buf);
if (len < buf_size)
pstrcpy(buf + len, buf_size - len, s);
return buf;
}
int strstart(const char *str, const char *val, const char **ptr)
{
const char *p, *q;
p = str;
q = val;
while (*q != '\0') {
if (*p != *q)
return 0;
p++;
q++;
}
if (ptr)
*ptr = p;
return 1;
}
int has_suffix(const char *str, const char *suffix)
{
size_t len = strlen(str);
size_t slen = strlen(suffix);
return (len >= slen && !memcmp(str + len - slen, suffix, slen));
}
/* Dynamic buffer package */
static void *dbuf_default_realloc(void *opaque, void *ptr, size_t size)
{
return realloc(ptr, size);
}
void dbuf_init2(DynBuf *s, void *opaque, DynBufReallocFunc *realloc_func)
{
memset(s, 0, sizeof(*s));
if (!realloc_func)
realloc_func = dbuf_default_realloc;
s->opaque = opaque;
s->realloc_func = realloc_func;
}
void dbuf_init(DynBuf *s)
{
dbuf_init2(s, NULL, NULL);
}
/* return < 0 if error */
int dbuf_realloc(DynBuf *s, size_t new_size)
{
size_t size;
uint8_t *new_buf;
if (new_size > s->allocated_size) {
if (s->error)
return -1;
size = s->allocated_size * 3 / 2;
if (size > new_size)
new_size = size;
new_buf = s->realloc_func(s->opaque, s->buf, new_size);
if (!new_buf) {
s->error = TRUE;
return -1;
}
s->buf = new_buf;
s->allocated_size = new_size;
}
return 0;
}
int dbuf_write(DynBuf *s, size_t offset, const uint8_t *data, size_t len)
{
size_t end;
end = offset + len;
if (dbuf_realloc(s, end))
return -1;
memcpy(s->buf + offset, data, len);
if (end > s->size)
s->size = end;
return 0;
}
int dbuf_put(DynBuf *s, const uint8_t *data, size_t len)
{
if (unlikely((s->size + len) > s->allocated_size)) {
if (dbuf_realloc(s, s->size + len))
return -1;
}
memcpy(s->buf + s->size, data, len);
s->size += len;
return 0;
}
int dbuf_put_self(DynBuf *s, size_t offset, size_t len)
{
if (unlikely((s->size + len) > s->allocated_size)) {
if (dbuf_realloc(s, s->size + len))
return -1;
}
memcpy(s->buf + s->size, s->buf + offset, len);
s->size += len;
return 0;
}
int dbuf_putc(DynBuf *s, uint8_t c)
{
return dbuf_put(s, &c, 1);
}
int dbuf_putstr(DynBuf *s, const char *str)
{
return dbuf_put(s, (const uint8_t *)str, strlen(str));
}
int __attribute__((format(printf, 2, 3))) dbuf_printf(DynBuf *s,
const char *fmt, ...)
{
va_list ap;
char buf[128];
int len;
va_start(ap, fmt);
len = vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
if (len < sizeof(buf)) {
/* fast case */
return dbuf_put(s, (uint8_t *)buf, len);
} else {
if (dbuf_realloc(s, s->size + len + 1))
return -1;
va_start(ap, fmt);
vsnprintf((char *)(s->buf + s->size), s->allocated_size - s->size,
fmt, ap);
va_end(ap);
s->size += len;
}
return 0;
}
void dbuf_free(DynBuf *s)
{
/* we test s->buf as a fail safe to avoid crashing if dbuf_free()
is called twice */
if (s->buf) {
s->realloc_func(s->opaque, s->buf, 0);
}
memset(s, 0, sizeof(*s));
}
/* Note: at most 31 bits are encoded. At most UTF8_CHAR_LEN_MAX bytes
are output. */
int unicode_to_utf8(uint8_t *buf, unsigned int c)
{
uint8_t *q = buf;
if (c < 0x80) {
*q++ = c;
} else {
if (c < 0x800) {
*q++ = (c >> 6) | 0xc0;
} else {
if (c < 0x10000) {
*q++ = (c >> 12) | 0xe0;
} else {
if (c < 0x00200000) {
*q++ = (c >> 18) | 0xf0;
} else {
if (c < 0x04000000) {
*q++ = (c >> 24) | 0xf8;
} else if (c < 0x80000000) {
*q++ = (c >> 30) | 0xfc;
*q++ = ((c >> 24) & 0x3f) | 0x80;
} else {
return 0;
}
*q++ = ((c >> 18) & 0x3f) | 0x80;
}
*q++ = ((c >> 12) & 0x3f) | 0x80;
}
*q++ = ((c >> 6) & 0x3f) | 0x80;
}
*q++ = (c & 0x3f) | 0x80;
}
return q - buf;
}
static const unsigned int utf8_min_code[5] = {
0x80, 0x800, 0x10000, 0x00200000, 0x04000000,
};
static const unsigned char utf8_first_code_mask[5] = {
0x1f, 0xf, 0x7, 0x3, 0x1,
};
/* return -1 if error. *pp is not updated in this case. max_len must
be >= 1. The maximum length for a UTF8 byte sequence is 6 bytes. */
int unicode_from_utf8(const uint8_t *p, int max_len, const uint8_t **pp)
{
int l, c, b, i;
c = *p++;
if (c < 0x80) {
*pp = p;
return c;
}
switch(c) {
case 0xc0: case 0xc1: case 0xc2: case 0xc3:
case 0xc4: case 0xc5: case 0xc6: case 0xc7:
case 0xc8: case 0xc9: case 0xca: case 0xcb:
case 0xcc: case 0xcd: case 0xce: case 0xcf:
case 0xd0: case 0xd1: case 0xd2: case 0xd3:
case 0xd4: case 0xd5: case 0xd6: case 0xd7:
case 0xd8: case 0xd9: case 0xda: case 0xdb:
case 0xdc: case 0xdd: case 0xde: case 0xdf:
l = 1;
break;
case 0xe0: case 0xe1: case 0xe2: case 0xe3:
case 0xe4: case 0xe5: case 0xe6: case 0xe7:
case 0xe8: case 0xe9: case 0xea: case 0xeb:
case 0xec: case 0xed: case 0xee: case 0xef:
l = 2;
break;
case 0xf0: case 0xf1: case 0xf2: case 0xf3:
case 0xf4: case 0xf5: case 0xf6: case 0xf7:
l = 3;
break;
case 0xf8: case 0xf9: case 0xfa: case 0xfb:
l = 4;
break;
case 0xfc: case 0xfd:
l = 5;
break;
default:
return -1;
}
/* check that we have enough characters */
if (l > (max_len - 1))
return -1;
c &= utf8_first_code_mask[l - 1];
for(i = 0; i < l; i++) {
b = *p++;
if (b < 0x80 || b >= 0xc0)
return -1;
c = (c << 6) | (b & 0x3f);
}
if (c < utf8_min_code[l - 1])
return -1;
*pp = p;
return c;
}
#if 0
#if defined(EMSCRIPTEN) || defined(__ANDROID__)
static void *rqsort_arg;
static int (*rqsort_cmp)(const void *, const void *, void *);
static int rqsort_cmp2(const void *p1, const void *p2)
{
return rqsort_cmp(p1, p2, rqsort_arg);
}
/* not reentrant, but not needed with emscripten */
void rqsort(void *base, size_t nmemb, size_t size,
int (*cmp)(const void *, const void *, void *),
void *arg)
{
rqsort_arg = arg;
rqsort_cmp = cmp;
qsort(base, nmemb, size, rqsort_cmp2);
}
#endif
#else
typedef void (*exchange_f)(void *a, void *b, size_t size);
typedef int (*cmp_f)(const void *, const void *, void *opaque);
static void exchange_bytes(void *a, void *b, size_t size) {
uint8_t *ap = (uint8_t *)a;
uint8_t *bp = (uint8_t *)b;
while (size-- != 0) {
uint8_t t = *ap;
*ap++ = *bp;
*bp++ = t;
}
}
static void exchange_one_byte(void *a, void *b, size_t size) {
uint8_t *ap = (uint8_t *)a;
uint8_t *bp = (uint8_t *)b;
uint8_t t = *ap;
*ap = *bp;
*bp = t;
}
static void exchange_int16s(void *a, void *b, size_t size) {
uint16_t *ap = (uint16_t *)a;
uint16_t *bp = (uint16_t *)b;
for (size /= sizeof(uint16_t); size-- != 0;) {
uint16_t t = *ap;
*ap++ = *bp;
*bp++ = t;
}
}
static void exchange_one_int16(void *a, void *b, size_t size) {
uint16_t *ap = (uint16_t *)a;
uint16_t *bp = (uint16_t *)b;
uint16_t t = *ap;
*ap = *bp;
*bp = t;
}
static void exchange_int32s(void *a, void *b, size_t size) {
uint32_t *ap = (uint32_t *)a;
uint32_t *bp = (uint32_t *)b;
for (size /= sizeof(uint32_t); size-- != 0;) {
uint32_t t = *ap;
*ap++ = *bp;
*bp++ = t;
}
}
static void exchange_one_int32(void *a, void *b, size_t size) {
uint32_t *ap = (uint32_t *)a;
uint32_t *bp = (uint32_t *)b;
uint32_t t = *ap;
*ap = *bp;
*bp = t;
}
static void exchange_int64s(void *a, void *b, size_t size) {
uint64_t *ap = (uint64_t *)a;
uint64_t *bp = (uint64_t *)b;
for (size /= sizeof(uint64_t); size-- != 0;) {
uint64_t t = *ap;
*ap++ = *bp;
*bp++ = t;
}
}
static void exchange_one_int64(void *a, void *b, size_t size) {
uint64_t *ap = (uint64_t *)a;
uint64_t *bp = (uint64_t *)b;
uint64_t t = *ap;
*ap = *bp;
*bp = t;
}
static void exchange_int128s(void *a, void *b, size_t size) {
uint64_t *ap = (uint64_t *)a;
uint64_t *bp = (uint64_t *)b;
for (size /= sizeof(uint64_t) * 2; size-- != 0; ap += 2, bp += 2) {
uint64_t t = ap[0];
uint64_t u = ap[1];
ap[0] = bp[0];
ap[1] = bp[1];
bp[0] = t;
bp[1] = u;
}
}
static void exchange_one_int128(void *a, void *b, size_t size) {
uint64_t *ap = (uint64_t *)a;
uint64_t *bp = (uint64_t *)b;
uint64_t t = ap[0];
uint64_t u = ap[1];
ap[0] = bp[0];
ap[1] = bp[1];
bp[0] = t;
bp[1] = u;
}
static inline exchange_f exchange_func(const void *base, size_t size) {
switch (((uintptr_t)base | (uintptr_t)size) & 15) {
case 0:
if (size == sizeof(uint64_t) * 2)
return exchange_one_int128;
else
return exchange_int128s;
case 8:
if (size == sizeof(uint64_t))
return exchange_one_int64;
else
return exchange_int64s;
case 4:
case 12:
if (size == sizeof(uint32_t))
return exchange_one_int32;
else
return exchange_int32s;
case 2:
case 6:
case 10:
case 14:
if (size == sizeof(uint16_t))
return exchange_one_int16;
else
return exchange_int16s;
default:
if (size == 1)
return exchange_one_byte;
else
return exchange_bytes;
}
}
static void heapsortx(void *base, size_t nmemb, size_t size, cmp_f cmp, void *opaque)
{
uint8_t *basep = (uint8_t *)base;
size_t i, n, c, r;
exchange_f swap = exchange_func(base, size);
if (nmemb > 1) {
i = (nmemb / 2) * size;
n = nmemb * size;
while (i > 0) {
i -= size;
for (r = i; (c = r * 2 + size) < n; r = c) {
if (c < n - size && cmp(basep + c, basep + c + size, opaque) <= 0)
c += size;
if (cmp(basep + r, basep + c, opaque) > 0)
break;
swap(basep + r, basep + c, size);
}
}
for (i = n - size; i > 0; i -= size) {
swap(basep, basep + i, size);
for (r = 0; (c = r * 2 + size) < i; r = c) {
if (c < i - size && cmp(basep + c, basep + c + size, opaque) <= 0)
c += size;
if (cmp(basep + r, basep + c, opaque) > 0)
break;
swap(basep + r, basep + c, size);
}
}
}
}
static inline void *med3(void *a, void *b, void *c, cmp_f cmp, void *opaque)
{
return cmp(a, b, opaque) < 0 ?
(cmp(b, c, opaque) < 0 ? b : (cmp(a, c, opaque) < 0 ? c : a )) :
(cmp(b, c, opaque) > 0 ? b : (cmp(a, c, opaque) < 0 ? a : c ));
}
/* pointer based version with local stack and insertion sort threshhold */
void rqsort(void *base, size_t nmemb, size_t size, cmp_f cmp, void *opaque)
{
struct { uint8_t *base; size_t count; int depth; } stack[50], *sp = stack;
uint8_t *ptr, *pi, *pj, *plt, *pgt, *top, *m;
size_t m4, i, lt, gt, span, span2;
int c, depth;
exchange_f swap = exchange_func(base, size);
exchange_f swap_block = exchange_func(base, size | 128);
if (nmemb < 2 || size <= 0)
return;
sp->base = (uint8_t *)base;
sp->count = nmemb;
sp->depth = 0;
sp++;
while (sp > stack) {
sp--;
ptr = sp->base;
nmemb = sp->count;
depth = sp->depth;
while (nmemb > 6) {
if (++depth > 50) {
/* depth check to ensure worst case logarithmic time */
heapsortx(ptr, nmemb, size, cmp, opaque);
nmemb = 0;
break;
}
/* select median of 3 from 1/4, 1/2, 3/4 positions */
/* should use median of 5 or 9? */
m4 = (nmemb >> 2) * size;
m = med3(ptr + m4, ptr + 2 * m4, ptr + 3 * m4, cmp, opaque);
swap(ptr, m, size); /* move the pivot to the start or the array */
i = lt = 1;
pi = plt = ptr + size;
gt = nmemb;
pj = pgt = top = ptr + nmemb * size;
for (;;) {
while (pi < pj && (c = cmp(ptr, pi, opaque)) >= 0) {
if (c == 0) {
swap(plt, pi, size);
lt++;
plt += size;
}
i++;
pi += size;
}
while (pi < (pj -= size) && (c = cmp(ptr, pj, opaque)) <= 0) {
if (c == 0) {
gt--;
pgt -= size;
swap(pgt, pj, size);
}
}
if (pi >= pj)
break;
swap(pi, pj, size);
i++;
pi += size;
}
/* array has 4 parts:
* from 0 to lt excluded: elements identical to pivot
* from lt to pi excluded: elements smaller than pivot
* from pi to gt excluded: elements greater than pivot
* from gt to n excluded: elements identical to pivot
*/
/* move elements identical to pivot in the middle of the array: */
/* swap values in ranges [0..lt[ and [i-lt..i[
swapping the smallest span between lt and i-lt is sufficient
*/
span = plt - ptr;
span2 = pi - plt;
lt = i - lt;
if (span > span2)
span = span2;
swap_block(ptr, pi - span, span);
/* swap values in ranges [gt..top[ and [i..top-(top-gt)[
swapping the smallest span between top-gt and gt-i is sufficient
*/
span = top - pgt;
span2 = pgt - pi;
pgt = top - span2;
gt = nmemb - (gt - i);
if (span > span2)
span = span2;
swap_block(pi, top - span, span);
/* now array has 3 parts:
* from 0 to lt excluded: elements smaller than pivot
* from lt to gt excluded: elements identical to pivot
* from gt to n excluded: elements greater than pivot
*/
/* stack the larger segment and keep processing the smaller one
to minimize stack use for pathological distributions */
if (lt > nmemb - gt) {
sp->base = ptr;
sp->count = lt;
sp->depth = depth;
sp++;
ptr = pgt;
nmemb -= gt;
} else {
sp->base = pgt;
sp->count = nmemb - gt;
sp->depth = depth;
sp++;
nmemb = lt;
}
}
/* Use insertion sort for small fragments */
for (pi = ptr + size, top = ptr + nmemb * size; pi < top; pi += size) {
for (pj = pi; pj > ptr && cmp(pj - size, pj, opaque) > 0; pj -= size)
swap(pj, pj - size, size);
}
}
}
#endif

View file

@ -1,300 +0,0 @@
/*
* C utilities
*
* Copyright (c) 2017 Fabrice Bellard
* Copyright (c) 2018 Charlie Gordon
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef CUTILS_H
#define CUTILS_H
#include <stdlib.h>
#include <inttypes.h>
/* set if CPU is big endian */
#undef WORDS_BIGENDIAN
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
#define force_inline inline __attribute__((always_inline))
#define no_inline __attribute__((noinline))
#define __maybe_unused __attribute__((unused))
#define xglue(x, y) x ## y
#define glue(x, y) xglue(x, y)
#define stringify(s) tostring(s)
#define tostring(s) #s
#ifndef offsetof
#define offsetof(type, field) ((size_t) &((type *)0)->field)
#endif
#ifndef countof
#define countof(x) (sizeof(x) / sizeof((x)[0]))
#endif
/* return the pointer of type 'type *' containing 'ptr' as field 'member' */
#define container_of(ptr, type, member) ((type *)((uint8_t *)(ptr) - offsetof(type, member)))
typedef int BOOL;
#ifndef FALSE
enum {
FALSE = 0,
TRUE = 1,
};
#endif
void pstrcpy(char *buf, int buf_size, const char *str);
char *pstrcat(char *buf, int buf_size, const char *s);
int strstart(const char *str, const char *val, const char **ptr);
int has_suffix(const char *str, const char *suffix);
static inline int max_int(int a, int b)
{
if (a > b)
return a;
else
return b;
}
static inline int min_int(int a, int b)
{
if (a < b)
return a;
else
return b;
}
static inline uint32_t max_uint32(uint32_t a, uint32_t b)
{
if (a > b)
return a;
else
return b;
}
static inline uint32_t min_uint32(uint32_t a, uint32_t b)
{
if (a < b)
return a;
else
return b;
}
static inline int64_t max_int64(int64_t a, int64_t b)
{
if (a > b)
return a;
else
return b;
}
static inline int64_t min_int64(int64_t a, int64_t b)
{
if (a < b)
return a;
else
return b;
}
/* WARNING: undefined if a = 0 */
static inline int clz32(unsigned int a)
{
return __builtin_clz(a);
}
/* WARNING: undefined if a = 0 */
static inline int clz64(uint64_t a)
{
return __builtin_clzll(a);
}
/* WARNING: undefined if a = 0 */
static inline int ctz32(unsigned int a)
{
return __builtin_ctz(a);
}
/* WARNING: undefined if a = 0 */
static inline int ctz64(uint64_t a)
{
return __builtin_ctzll(a);
}
struct __attribute__((packed)) packed_u64 {
uint64_t v;
};
struct __attribute__((packed)) packed_u32 {
uint32_t v;
};
struct __attribute__((packed)) packed_u16 {
uint16_t v;
};
static inline uint64_t get_u64(const uint8_t *tab)
{
return ((const struct packed_u64 *)tab)->v;
}
static inline int64_t get_i64(const uint8_t *tab)
{
return (int64_t)((const struct packed_u64 *)tab)->v;
}
static inline void put_u64(uint8_t *tab, uint64_t val)
{
((struct packed_u64 *)tab)->v = val;
}
static inline uint32_t get_u32(const uint8_t *tab)
{
return ((const struct packed_u32 *)tab)->v;
}
static inline int32_t get_i32(const uint8_t *tab)
{
return (int32_t)((const struct packed_u32 *)tab)->v;
}
static inline void put_u32(uint8_t *tab, uint32_t val)
{
((struct packed_u32 *)tab)->v = val;
}
static inline uint32_t get_u16(const uint8_t *tab)
{
return ((const struct packed_u16 *)tab)->v;
}
static inline int32_t get_i16(const uint8_t *tab)
{
return (int16_t)((const struct packed_u16 *)tab)->v;
}
static inline void put_u16(uint8_t *tab, uint16_t val)
{
((struct packed_u16 *)tab)->v = val;
}
static inline uint32_t get_u8(const uint8_t *tab)
{
return *tab;
}
static inline int32_t get_i8(const uint8_t *tab)
{
return (int8_t)*tab;
}
static inline void put_u8(uint8_t *tab, uint8_t val)
{
*tab = val;
}
static inline uint16_t bswap16(uint16_t x)
{
return (x >> 8) | (x << 8);
}
static inline uint32_t bswap32(uint32_t v)
{
return ((v & 0xff000000) >> 24) | ((v & 0x00ff0000) >> 8) |
((v & 0x0000ff00) << 8) | ((v & 0x000000ff) << 24);
}
static inline uint64_t bswap64(uint64_t v)
{
return ((v & ((uint64_t)0xff << (7 * 8))) >> (7 * 8)) |
((v & ((uint64_t)0xff << (6 * 8))) >> (5 * 8)) |
((v & ((uint64_t)0xff << (5 * 8))) >> (3 * 8)) |
((v & ((uint64_t)0xff << (4 * 8))) >> (1 * 8)) |
((v & ((uint64_t)0xff << (3 * 8))) << (1 * 8)) |
((v & ((uint64_t)0xff << (2 * 8))) << (3 * 8)) |
((v & ((uint64_t)0xff << (1 * 8))) << (5 * 8)) |
((v & ((uint64_t)0xff << (0 * 8))) << (7 * 8));
}
/* XXX: should take an extra argument to pass slack information to the caller */
typedef void *DynBufReallocFunc(void *opaque, void *ptr, size_t size);
typedef struct DynBuf {
uint8_t *buf;
size_t size;
size_t allocated_size;
BOOL error; /* true if a memory allocation error occurred */
DynBufReallocFunc *realloc_func;
void *opaque; /* for realloc_func */
} DynBuf;
void dbuf_init(DynBuf *s);
void dbuf_init2(DynBuf *s, void *opaque, DynBufReallocFunc *realloc_func);
int dbuf_realloc(DynBuf *s, size_t new_size);
int dbuf_write(DynBuf *s, size_t offset, const uint8_t *data, size_t len);
int dbuf_put(DynBuf *s, const uint8_t *data, size_t len);
int dbuf_put_self(DynBuf *s, size_t offset, size_t len);
int dbuf_putc(DynBuf *s, uint8_t c);
int dbuf_putstr(DynBuf *s, const char *str);
static inline int dbuf_put_u16(DynBuf *s, uint16_t val)
{
return dbuf_put(s, (uint8_t *)&val, 2);
}
static inline int dbuf_put_u32(DynBuf *s, uint32_t val)
{
return dbuf_put(s, (uint8_t *)&val, 4);
}
static inline int dbuf_put_u64(DynBuf *s, uint64_t val)
{
return dbuf_put(s, (uint8_t *)&val, 8);
}
int __attribute__((format(printf, 2, 3))) dbuf_printf(DynBuf *s,
const char *fmt, ...);
void dbuf_free(DynBuf *s);
static inline BOOL dbuf_error(DynBuf *s) {
return s->error;
}
static inline void dbuf_set_error(DynBuf *s)
{
s->error = TRUE;
}
#define UTF8_CHAR_LEN_MAX 6
int unicode_to_utf8(uint8_t *buf, unsigned int c);
int unicode_from_utf8(const uint8_t *p, int max_len, const uint8_t **pp);
static inline int from_hex(int c)
{
if (c >= '0' && c <= '9')
return c - '0';
else if (c >= 'A' && c <= 'F')
return c - 'A' + 10;
else if (c >= 'a' && c <= 'f')
return c - 'a' + 10;
else
return -1;
}
void rqsort(void *base, size_t nmemb, size_t size,
int (*cmp)(const void *, const void *, void *),
void *arg);
#endif /* CUTILS_H */

View file

@ -1,589 +0,0 @@
\input texinfo
@iftex
@afourpaper
@headings double
@end iftex
@titlepage
@afourpaper
@sp 7
@center @titlefont{Javascript Bignum Extensions}
@sp 3
@center Version 2020-01-11
@sp 3
@center Author: Fabrice Bellard
@end titlepage
@setfilename jsbignum.info
@settitle Javascript Bignum Extensions
@contents
@chapter Introduction
The Bignum extensions add the following features to the Javascript
language while being 100% backward compatible:
@itemize
@item Operator overloading with a dispatch logic inspired from the proposal available at @url{https://github.com/tc39/proposal-operator-overloading/}.
@item Arbitrarily large floating point numbers (@code{BigFloat}) in base 2 using the IEEE 754 semantics.
@item Arbitrarily large floating point numbers (@code{BigDecimal}) in base 10 based on the proposal available at
@url{https://github.com/littledan/proposal-bigdecimal}.
@item @code{math} mode: arbitrarily large integers and floating point numbers are available by default. The integer division and power can be overloaded for example to return a fraction. The modulo operator (@code{%}) is defined as the Euclidian
remainder. @code{^} is an alias to the power operator
(@code{**}). @code{^^} is used as the exclusive or operator.
@end itemize
The extensions are independent from each other except the @code{math}
mode which relies on BigFloat and operator overloading.
@chapter Operator overloading
Operator overloading is inspired from the proposal available at
@url{https://github.com/tc39/proposal-operator-overloading/}. It
implements the same dispatch logic but finds the operator sets by
looking at the @code{Symbol.operatorSet} property in the objects. The
changes were done in order to simplify the implementation.
More precisely, the following modifications were made:
@itemize
@item @code{with operators from} is not supported. Operator overloading is always enabled.
@item The dispatch is not based on a static @code{[[OperatorSet]]} field in all instances. Instead, a dynamic lookup of the @code{Symbol.operatorSet} property is done. This property is typically added in the prototype of each object.
@item @code{Operators.create(...dictionaries)} is used to create a new OperatorSet object. The @code{Operators} function is supported as an helper to be closer to the TC39 proposal.
@item @code{[]} cannot be overloaded.
@item In math mode, the BigInt division and power operators can be overloaded with @code{Operators.updateBigIntOperators(dictionary)}.
@end itemize
@chapter BigInt extensions
A few properties are added to the BigInt object:
@table @code
@item tdiv(a, b)
Return @math{trunc(a/b)}. @code{b = 0} raises a RangeError
exception.
@item fdiv(a, b)
Return @math{\lfloor a/b \rfloor}. @code{b = 0} raises a RangeError
exception.
@item cdiv(a, b)
Return @math{\lceil a/b \rceil}. @code{b = 0} raises a RangeError
exception.
@item ediv(a, b)
Return @math{sgn(b) \lfloor a/{|b|} \rfloor} (Euclidian
division). @code{b = 0} raises a RangeError exception.
@item tdivrem(a, b)
@item fdivrem(a, b)
@item cdivrem(a, b)
@item edivrem(a, b)
Return an array of two elements. The first element is the quotient,
the second is the remainder. The same rounding is done as the
corresponding division operation.
@item sqrt(a)
Return @math{\lfloor \sqrt(a) \rfloor}. A RangeError exception is
raised if @math{a < 0}.
@item sqrtrem(a)
Return an array of two elements. The first element is @math{\lfloor
\sqrt{a} \rfloor}. The second element is @math{a-\lfloor \sqrt{a}
\rfloor^2}. A RangeError exception is raised if @math{a < 0}.
@item floorLog2(a)
Return -1 if @math{a \leq 0} otherwise return @math{\lfloor \log2(a) \rfloor}.
@item ctz(a)
Return the number of trailing zeros in the two's complement binary representation of a. Return -1 if @math{a=0}.
@end table
@chapter BigFloat
@section Introduction
This extension adds the @code{BigFloat} primitive type. The
@code{BigFloat} type represents floating point numbers in base 2
with the IEEE 754 semantics. A floating
point number is represented as a sign, mantissa and exponent. The
special values @code{NaN}, @code{+/-Infinity}, @code{+0} and @code{-0}
are supported. The mantissa and exponent can have any bit length with
an implementation specific minimum and maximum.
@section Floating point rounding
Each floating point operation operates with infinite precision and
then rounds the result according to the specified floating point
environment (@code{BigFloatEnv} object). The status flags of the
environment are also set according to the result of the operation.
If no floating point environment is provided, the global floating
point environment is used.
The rounding mode of the global floating point environment is always
@code{RNDN} (``round to nearest with ties to even'')@footnote{The
rationale is that the rounding mode changes must always be
explicit.}. The status flags of the global environment cannot be
read@footnote{The rationale is to avoid side effects for the built-in
operators.}. The precision of the global environment is
@code{BigFloatEnv.prec}. The number of exponent bits of the global
environment is @code{BigFloatEnv.expBits}. The global environment
subnormal flag is set to @code{true}.
For example, @code{prec = 53} and @code{ expBits = 11} exactly give
the same precision as the IEEE 754 64 bit floating point format. The
default precision is @code{prec = 113} and @code{ expBits = 15} (IEEE
754 128 bit floating point format).
The global floating point environment can only be modified temporarily
when calling a function (see @code{BigFloatEnv.setPrec}). Hence a
function can change the global floating point environment for its
callees but not for its caller.
@section Operators
The builtin operators are extended so that a BigFloat is returned if
at least one operand is a BigFloat. The computations are always done
with infinite precision and rounded according to the global floating
point environment.
@code{typeof} applied on a @code{BigFloat} returns @code{bigfloat}.
BigFloat can be compared with all the other numeric types and the
result follows the expected mathematical relations.
However, since BigFloat and Number are different types they are never
equal when using the strict comparison operators (e.g. @code{0.0 ===
0.0l} is false).
@section BigFloat literals
BigFloat literals are floating point numbers with a trailing @code{l}
suffix. BigFloat literals have an infinite precision. They are rounded
according to the global floating point environment when they are
evaluated.@footnote{Base 10 floating point literals cannot usually be
exactly represented as base 2 floating point number. In order to
ensure that the literal is represented accurately with the current
precision, it must be evaluated at runtime.}
@section Builtin Object changes
@subsection @code{BigFloat} function
The @code{BigFloat} function cannot be invoked as a constructor. When
invoked as a function: the parameter is converted to a primitive
type. If the result is a numeric type, it is converted to BigFloat
without rounding. If the result is a string, it is converted to
BigFloat using the precision of the global floating point environment.
@code{BigFloat} properties:
@table @code
@item LN2
@item PI
Getter. Return the value of the corresponding mathematical constant
rounded to nearest, ties to even with the current global
precision. The constant values are cached for small precisions.
@item MIN_VALUE
@item MAX_VALUE
@item EPSILON
Getter. Return the minimum, maximum and epsilon @code{BigFloat} values
(same definition as the corresponding @code{Number} constants).
@item fpRound(a[, e])
Round the floating point number @code{a} according to the floating
point environment @code{e} or the global environment if @code{e} is
undefined.
@item parseFloat(a[, radix[, e]])
Parse the string @code{a} as a floating point number in radix
@code{radix}. The radix is 0 (default) or from 2 to 36. The radix 0
means radix 10 unless there is a hexadecimal or binary prefix. The
result is rounded according to the floating point environment @code{e}
or the global environment if @code{e} is undefined.
@item isFinite(a)
Return true if @code{a} is a finite bigfloat.
@item isNaN(a)
Return true if @code{a} is a NaN bigfloat.
@item add(a, b[, e])
@item sub(a, b[, e])
@item mul(a, b[, e])
@item div(a, b[, e])
Perform the specified floating point operation and round the floating
point number @code{a} according to the floating point environment
@code{e} or the global environment if @code{e} is undefined. If
@code{e} is specified, the floating point status flags are updated.
@item floor(x)
@item ceil(x)
@item round(x)
@item trunc(x)
Round to an integer. No additional rounding is performed.
@item abs(x)
Return the absolute value of x. No additional rounding is performed.
@item fmod(x, y[, e])
@item remainder(x, y[, e])
Floating point remainder. The quotient is truncated to zero (fmod) or
to the nearest integer with ties to even (remainder). @code{e} is an
optional floating point environment.
@item sqrt(x[, e])
Square root. Return a rounded floating point number. @code{e} is an
optional floating point environment.
@item sin(x[, e])
@item cos(x[, e])
@item tan(x[, e])
@item asin(x[, e])
@item acos(x[, e])
@item atan(x[, e])
@item atan2(x, y[, e])
@item exp(x[, e])
@item log(x[, e])
@item pow(x, y[, e])
Transcendental operations. Return a rounded floating point
number. @code{e} is an optional floating point environment.
@end table
@subsection @code{BigFloat.prototype}
The following properties are modified:
@table @code
@item valueOf()
Return the bigfloat primitive value corresponding to @code{this}.
@item toString(radix)
For floating point numbers:
@itemize
@item
If the radix is a power of two, the conversion is done with infinite
precision.
@item
Otherwise, the number is rounded to nearest with ties to even using
the global precision. It is then converted to string using the minimum
number of digits so that its conversion back to a floating point using
the global precision and round to nearest gives the same number.
@end itemize
The exponent letter is @code{e} for base 10, @code{p} for bases 2, 8,
16 with a binary exponent and @code{@@} for the other bases.
@item toPrecision(p, rnd_mode = BigFloatEnv.RNDNA, radix = 10)
@item toFixed(p, rnd_mode = BigFloatEnv.RNDNA, radix = 10)
@item toExponential(p, rnd_mode = BigFloatEnv.RNDNA, radix = 10)
Same semantics as the corresponding @code{Number} functions with
BigFloats. There is no limit on the accepted precision @code{p}. The
rounding mode and radix can be optionally specified. The radix must be
between 2 and 36.
@end table
@subsection @code{BigFloatEnv} constructor
The @code{BigFloatEnv([p, [,rndMode]]} constructor cannot be invoked as a
function. The floating point environment contains:
@itemize
@item the mantissa precision in bits
@item the exponent size in bits assuming an IEEE 754 representation;
@item the subnormal flag (if true, subnormal floating point numbers can
be generated by the floating point operations).
@item the rounding mode
@item the floating point status. The status flags can only be set by the floating point operations. They can be reset with @code{BigFloatEnv.prototype.clearStatus()} or with the various status flag setters.
@end itemize
@code{new BigFloatEnv([p, [,rndMode]]} creates a new floating point
environment. The status flags are reset. If no parameter is given the
precision, exponent bits and subnormal flags are copied from the
global floating point environment. Otherwise, the precision is set to
@code{p}, the number of exponent bits is set to @code{expBitsMax} and the
subnormal flags is set to @code{false}. If @code{rndMode} is
@code{undefined}, the rounding mode is set to @code{RNDN}.
@code{BigFloatEnv} properties:
@table @code
@item prec
Getter. Return the precision in bits of the global floating point
environment. The initial value is @code{113}.
@item expBits
Getter. Return the exponent size in bits of the global floating point
environment assuming an IEEE 754 representation. The initial value is
@code{15}.
@item setPrec(f, p[, e])
Set the precision of the global floating point environment to @code{p}
and the exponent size to @code{e} then call the function
@code{f}. Then the Float precision and exponent size are reset to
their precious value and the return value of @code{f} is returned (or
an exception is raised if @code{f} raised an exception). If @code{e}
is @code{undefined} it is set to @code{BigFloatEnv.expBitsMax}.
@item precMin
Read-only integer. Return the minimum allowed precision. Must be at least 2.
@item precMax
Read-only integer. Return the maximum allowed precision. Must be at least 113.
@item expBitsMin
Read-only integer. Return the minimum allowed exponent size in
bits. Must be at least 3.
@item expBitsMax
Read-only integer. Return the maximum allowed exponent size in
bits. Must be at least 15.
@item RNDN
Read-only integer. Round to nearest, with ties to even rounding mode.
@item RNDZ
Read-only integer. Round to zero rounding mode.
@item RNDD
Read-only integer. Round to -Infinity rounding mode.
@item RNDU
Read-only integer. Round to +Infinity rounding mode.
@item RNDNA
Read-only integer. Round to nearest, with ties away from zero rounding mode.
@item RNDA
Read-only integer. Round away from zero rounding mode.
@item RNDF@footnote{Could be removed in case a deterministic behavior for floating point operations is required.}
Read-only integer. Faithful rounding mode. The result is
non-deterministically rounded to -Infinity or +Infinity. This rounding
mode usually gives a faster and deterministic running time for the
floating point operations.
@end table
@code{BigFloatEnv.prototype} properties:
@table @code
@item prec
Getter and setter (Integer). Return or set the precision in bits.
@item expBits
Getter and setter (Integer). Return or set the exponent size in bits
assuming an IEEE 754 representation.
@item rndMode
Getter and setter (Integer). Return or set the rounding mode.
@item subnormal
Getter and setter (Boolean). subnormal flag. It is false when
@code{expBits = expBitsMax}.
@item clearStatus()
Clear the status flags.
@item invalidOperation
@item divideByZero
@item overflow
@item underflow
@item inexact
Getter and setter (Boolean). Status flags.
@end table
@chapter BigDecimal
This extension adds the @code{BigDecimal} primitive type. The
@code{BigDecimal} type represents floating point numbers in base
10. It is inspired from the proposal available at
@url{https://github.com/littledan/proposal-bigdecimal}.
The @code{BigDecimal} floating point numbers are always normalized and
finite. There is no concept of @code{-0}, @code{Infinity} or
@code{NaN}. By default, all the computations are done with infinite
precision.
@section Operators
The following builtin operators support BigDecimal:
@table @code
@item +
@item -
@item *
Both operands must be BigDecimal. The result is computed with infinite
precision.
@item %
Both operands must be BigDecimal. The result is computed with infinite
precision. A range error is throws in case of division by zero.
@item /
Both operands must be BigDecimal. A range error is throws in case of
division by zero or if the result cannot be represented with infinite
precision (use @code{BigDecimal.div} to specify the rounding).
@item **
Both operands must be BigDecimal. The exponent must be a positive
integer. The result is computed with infinite precision.
@item ===
When one of the operand is a BigDecimal, return true if both operands
are a BigDecimal and if they are equal.
@item ==
@item !=
@item <=
@item >=
@item <
@item >
Numerical comparison. When one of the operand is not a BigDecimal, it is
converted to BigDecimal by using ToString(). Hence comparisons between
Number and BigDecimal do not use the exact mathematical value of the
Number value.
@end table
@section BigDecimal literals
BigDecimal literals are decimal floating point numbers with a trailing
@code{m} suffix.
@section Builtin Object changes
@subsection The @code{BigDecimal} function.
It returns @code{0m} if no parameter is provided. Otherwise the first
parameter is converted to a bigdecimal by using ToString(). Hence
Number values are not converted to their exact numerical value as
BigDecimal.
@subsection Properties of the @code{BigDecimal} object
@table @code
@item add(a, b[, e])
@item sub(a, b[, e])
@item mul(a, b[, e])
@item div(a, b[, e])
@item mod(a, b[, e])
@item sqrt(a, e)
@item round(a, e)
Perform the specified floating point operation and round the floating
point result according to the rounding object @code{e}. If the
rounding object is not present, the operation is executed with
infinite precision.
For @code{div}, a @code{RangeError} exception is thrown in case of
division by zero or if the result cannot be represented with infinite
precision if no rounding object is present.
For @code{sqrt}, a range error is thrown if @code{a} is less than
zero.
The rounding object must contain the following properties:
@code{roundingMode} is a string specifying the rounding mode
(@code{"floor"}, @code{"ceiling"}, @code{"down"}, @code{"up"},
@code{"half-even"}, @code{"half-up"}). Either
@code{maximumSignificantDigits} or @code{maximumFractionDigits} must
be present to specify respectively the number of significant digits
(must be >= 1) or the number of digits after the decimal point (must
be >= 0).
@end table
@subsection Properties of the @code{BigDecimal.prototype} object
@table @code
@item valueOf()
Return the bigdecimal primitive value corresponding to @code{this}.
@item toString()
Convert @code{this} to a string with infinite precision in base 10.
@item toPrecision(p, rnd_mode = "half-up")
@item toFixed(p, rnd_mode = "half-up")
@item toExponential(p, rnd_mode = "half-up")
Convert the BigDecimal @code{this} to string with the specified
precision @code{p}. There is no limit on the accepted precision
@code{p}. The rounding mode can be optionally
specified. @code{toPrecision} outputs either in decimal fixed notation
or in decimal exponential notation with a @code{p} digits of
precision. @code{toExponential} outputs in decimal exponential
notation with @code{p} digits after the decimal point. @code{toFixed}
outputs in decimal notation with @code{p} digits after the decimal
point.
@end table
@chapter Math mode
A new @emph{math mode} is enabled with the @code{"use math"}
directive. It propagates the same way as the @emph{strict mode}. It is
designed so that arbitrarily large integers and floating point numbers
are available by default. In order to minimize the number of changes
in the Javascript semantics, integers are represented either as Number
or BigInt depending on their magnitude. Floating point numbers are
always represented as BigFloat.
The following changes are made to the Javascript semantics:
@itemize
@item Floating point literals (i.e. number with a decimal point or an exponent) are @code{BigFloat} by default (i.e. a @code{l} suffix is implied). Hence @code{typeof 1.0 === "bigfloat"}.
@item Integer literals (i.e. numbers without a decimal point or an exponent) with or without the @code{n} suffix are @code{BigInt} if their value cannot be represented as a safe integer. A safe integer is defined as a integer whose absolute value is smaller or equal to @code{2**53-1}. Hence @code{typeof 1 === "number "}, @code{typeof 1n === "number"} but @code{typeof 9007199254740992 === "bigint" }.
@item All the bigint builtin operators and functions are modified so that their result is returned as a Number if it is a safe integer. Otherwise the result stays a BigInt.
@item The builtin operators are modified so that they return an exact result (which can be a BigInt) if their operands are safe integers. Operands between Number and BigInt are accepted provided the Number operand is a safe integer. The integer power with a negative exponent returns a BigFloat as result. The integer division returns a BigFloat as result.
@item The @code{^} operator is an alias to the power operator (@code{**}).
@item The power operator (both @code{^} and @code{**}) grammar is modified so that @code{-2^2} is allowed and yields @code{-4}.
@item The logical xor operator is still available with the @code{^^} operator.
@item The modulo operator (@code{%}) returns the Euclidian remainder (always positive) instead of the truncated remainder.
@item The integer division operator can be overloaded with @code{Operators.updateBigIntOperators(dictionary)}.
@item The integer power operator with a non zero negative exponent can be overloaded with @code{Operators.updateBigIntOperators(dictionary)}.
@end itemize
@bye

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,535 +0,0 @@
/*
* Tiny arbitrary precision floating point library
*
* Copyright (c) 2017-2021 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef LIBBF_H
#define LIBBF_H
#include <stddef.h>
#include <stdint.h>
#if defined(__SIZEOF_INT128__) && (INTPTR_MAX >= INT64_MAX)
#define LIMB_LOG2_BITS 6
#else
#define LIMB_LOG2_BITS 5
#endif
#define LIMB_BITS (1 << LIMB_LOG2_BITS)
#if LIMB_BITS == 64
typedef __int128 int128_t;
typedef unsigned __int128 uint128_t;
typedef int64_t slimb_t;
typedef uint64_t limb_t;
typedef uint128_t dlimb_t;
#define BF_RAW_EXP_MIN INT64_MIN
#define BF_RAW_EXP_MAX INT64_MAX
#define LIMB_DIGITS 19
#define BF_DEC_BASE UINT64_C(10000000000000000000)
#else
typedef int32_t slimb_t;
typedef uint32_t limb_t;
typedef uint64_t dlimb_t;
#define BF_RAW_EXP_MIN INT32_MIN
#define BF_RAW_EXP_MAX INT32_MAX
#define LIMB_DIGITS 9
#define BF_DEC_BASE 1000000000U
#endif
/* in bits */
/* minimum number of bits for the exponent */
#define BF_EXP_BITS_MIN 3
/* maximum number of bits for the exponent */
#define BF_EXP_BITS_MAX (LIMB_BITS - 3)
/* extended range for exponent, used internally */
#define BF_EXT_EXP_BITS_MAX (BF_EXP_BITS_MAX + 1)
/* minimum possible precision */
#define BF_PREC_MIN 2
/* minimum possible precision */
#define BF_PREC_MAX (((limb_t)1 << (LIMB_BITS - 2)) - 2)
/* some operations support infinite precision */
#define BF_PREC_INF (BF_PREC_MAX + 1) /* infinite precision */
#if LIMB_BITS == 64
#define BF_CHKSUM_MOD (UINT64_C(975620677) * UINT64_C(9795002197))
#else
#define BF_CHKSUM_MOD 975620677U
#endif
#define BF_EXP_ZERO BF_RAW_EXP_MIN
#define BF_EXP_INF (BF_RAW_EXP_MAX - 1)
#define BF_EXP_NAN BF_RAW_EXP_MAX
/* +/-zero is represented with expn = BF_EXP_ZERO and len = 0,
+/-infinity is represented with expn = BF_EXP_INF and len = 0,
NaN is represented with expn = BF_EXP_NAN and len = 0 (sign is ignored)
*/
typedef struct {
struct bf_context_t *ctx;
int sign;
slimb_t expn;
limb_t len;
limb_t *tab;
} bf_t;
typedef struct {
/* must be kept identical to bf_t */
struct bf_context_t *ctx;
int sign;
slimb_t expn;
limb_t len;
limb_t *tab;
} bfdec_t;
typedef enum {
BF_RNDN, /* round to nearest, ties to even */
BF_RNDZ, /* round to zero */
BF_RNDD, /* round to -inf (the code relies on (BF_RNDD xor BF_RNDU) = 1) */
BF_RNDU, /* round to +inf */
BF_RNDNA, /* round to nearest, ties away from zero */
BF_RNDA, /* round away from zero */
BF_RNDF, /* faithful rounding (nondeterministic, either RNDD or RNDU,
inexact flag is always set) */
} bf_rnd_t;
/* allow subnormal numbers. Only available if the number of exponent
bits is <= BF_EXP_BITS_USER_MAX and prec != BF_PREC_INF. */
#define BF_FLAG_SUBNORMAL (1 << 3)
/* 'prec' is the precision after the radix point instead of the whole
mantissa. Can only be used with bf_round() and
bfdec_[add|sub|mul|div|sqrt|round](). */
#define BF_FLAG_RADPNT_PREC (1 << 4)
#define BF_RND_MASK 0x7
#define BF_EXP_BITS_SHIFT 5
#define BF_EXP_BITS_MASK 0x3f
/* shortcut for bf_set_exp_bits(BF_EXT_EXP_BITS_MAX) */
#define BF_FLAG_EXT_EXP (BF_EXP_BITS_MASK << BF_EXP_BITS_SHIFT)
/* contains the rounding mode and number of exponents bits */
typedef uint32_t bf_flags_t;
typedef void *bf_realloc_func_t(void *opaque, void *ptr, size_t size);
typedef struct {
bf_t val;
limb_t prec;
} BFConstCache;
typedef struct bf_context_t {
void *realloc_opaque;
bf_realloc_func_t *realloc_func;
BFConstCache log2_cache;
BFConstCache pi_cache;
struct BFNTTState *ntt_state;
} bf_context_t;
static inline int bf_get_exp_bits(bf_flags_t flags)
{
int e;
e = (flags >> BF_EXP_BITS_SHIFT) & BF_EXP_BITS_MASK;
if (e == BF_EXP_BITS_MASK)
return BF_EXP_BITS_MAX + 1;
else
return BF_EXP_BITS_MAX - e;
}
static inline bf_flags_t bf_set_exp_bits(int n)
{
return ((BF_EXP_BITS_MAX - n) & BF_EXP_BITS_MASK) << BF_EXP_BITS_SHIFT;
}
/* returned status */
#define BF_ST_INVALID_OP (1 << 0)
#define BF_ST_DIVIDE_ZERO (1 << 1)
#define BF_ST_OVERFLOW (1 << 2)
#define BF_ST_UNDERFLOW (1 << 3)
#define BF_ST_INEXACT (1 << 4)
/* indicate that a memory allocation error occured. NaN is returned */
#define BF_ST_MEM_ERROR (1 << 5)
#define BF_RADIX_MAX 36 /* maximum radix for bf_atof() and bf_ftoa() */
static inline slimb_t bf_max(slimb_t a, slimb_t b)
{
if (a > b)
return a;
else
return b;
}
static inline slimb_t bf_min(slimb_t a, slimb_t b)
{
if (a < b)
return a;
else
return b;
}
void bf_context_init(bf_context_t *s, bf_realloc_func_t *realloc_func,
void *realloc_opaque);
void bf_context_end(bf_context_t *s);
/* free memory allocated for the bf cache data */
void bf_clear_cache(bf_context_t *s);
static inline void *bf_realloc(bf_context_t *s, void *ptr, size_t size)
{
return s->realloc_func(s->realloc_opaque, ptr, size);
}
/* 'size' must be != 0 */
static inline void *bf_malloc(bf_context_t *s, size_t size)
{
return bf_realloc(s, NULL, size);
}
static inline void bf_free(bf_context_t *s, void *ptr)
{
/* must test ptr otherwise equivalent to malloc(0) */
if (ptr)
bf_realloc(s, ptr, 0);
}
void bf_init(bf_context_t *s, bf_t *r);
static inline void bf_delete(bf_t *r)
{
bf_context_t *s = r->ctx;
/* we accept to delete a zeroed bf_t structure */
if (s && r->tab) {
bf_realloc(s, r->tab, 0);
}
}
static inline void bf_neg(bf_t *r)
{
r->sign ^= 1;
}
static inline int bf_is_finite(const bf_t *a)
{
return (a->expn < BF_EXP_INF);
}
static inline int bf_is_nan(const bf_t *a)
{
return (a->expn == BF_EXP_NAN);
}
static inline int bf_is_zero(const bf_t *a)
{
return (a->expn == BF_EXP_ZERO);
}
static inline void bf_memcpy(bf_t *r, const bf_t *a)
{
*r = *a;
}
int bf_set_ui(bf_t *r, uint64_t a);
int bf_set_si(bf_t *r, int64_t a);
void bf_set_nan(bf_t *r);
void bf_set_zero(bf_t *r, int is_neg);
void bf_set_inf(bf_t *r, int is_neg);
int bf_set(bf_t *r, const bf_t *a);
void bf_move(bf_t *r, bf_t *a);
int bf_get_float64(const bf_t *a, double *pres, bf_rnd_t rnd_mode);
int bf_set_float64(bf_t *a, double d);
int bf_cmpu(const bf_t *a, const bf_t *b);
int bf_cmp_full(const bf_t *a, const bf_t *b);
int bf_cmp(const bf_t *a, const bf_t *b);
static inline int bf_cmp_eq(const bf_t *a, const bf_t *b)
{
return bf_cmp(a, b) == 0;
}
static inline int bf_cmp_le(const bf_t *a, const bf_t *b)
{
return bf_cmp(a, b) <= 0;
}
static inline int bf_cmp_lt(const bf_t *a, const bf_t *b)
{
return bf_cmp(a, b) < 0;
}
int bf_add(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags);
int bf_sub(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags);
int bf_add_si(bf_t *r, const bf_t *a, int64_t b1, limb_t prec, bf_flags_t flags);
int bf_mul(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags);
int bf_mul_ui(bf_t *r, const bf_t *a, uint64_t b1, limb_t prec, bf_flags_t flags);
int bf_mul_si(bf_t *r, const bf_t *a, int64_t b1, limb_t prec,
bf_flags_t flags);
int bf_mul_2exp(bf_t *r, slimb_t e, limb_t prec, bf_flags_t flags);
int bf_div(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec, bf_flags_t flags);
#define BF_DIVREM_EUCLIDIAN BF_RNDF
int bf_divrem(bf_t *q, bf_t *r, const bf_t *a, const bf_t *b,
limb_t prec, bf_flags_t flags, int rnd_mode);
int bf_rem(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
bf_flags_t flags, int rnd_mode);
int bf_remquo(slimb_t *pq, bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
bf_flags_t flags, int rnd_mode);
/* round to integer with infinite precision */
int bf_rint(bf_t *r, int rnd_mode);
int bf_round(bf_t *r, limb_t prec, bf_flags_t flags);
int bf_sqrtrem(bf_t *r, bf_t *rem1, const bf_t *a);
int bf_sqrt(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
slimb_t bf_get_exp_min(const bf_t *a);
int bf_logic_or(bf_t *r, const bf_t *a, const bf_t *b);
int bf_logic_xor(bf_t *r, const bf_t *a, const bf_t *b);
int bf_logic_and(bf_t *r, const bf_t *a, const bf_t *b);
/* additional flags for bf_atof */
/* do not accept hex radix prefix (0x or 0X) if radix = 0 or radix = 16 */
#define BF_ATOF_NO_HEX (1 << 16)
/* accept binary (0b or 0B) or octal (0o or 0O) radix prefix if radix = 0 */
#define BF_ATOF_BIN_OCT (1 << 17)
/* Do not parse NaN or Inf */
#define BF_ATOF_NO_NAN_INF (1 << 18)
/* return the exponent separately */
#define BF_ATOF_EXPONENT (1 << 19)
int bf_atof(bf_t *a, const char *str, const char **pnext, int radix,
limb_t prec, bf_flags_t flags);
/* this version accepts prec = BF_PREC_INF and returns the radix
exponent */
int bf_atof2(bf_t *r, slimb_t *pexponent,
const char *str, const char **pnext, int radix,
limb_t prec, bf_flags_t flags);
int bf_mul_pow_radix(bf_t *r, const bf_t *T, limb_t radix,
slimb_t expn, limb_t prec, bf_flags_t flags);
/* Conversion of floating point number to string. Return a null
terminated string or NULL if memory error. *plen contains its
length if plen != NULL. The exponent letter is "e" for base 10,
"p" for bases 2, 8, 16 with a binary exponent and "@" for the other
bases. */
#define BF_FTOA_FORMAT_MASK (3 << 16)
/* fixed format: prec significant digits rounded with (flags &
BF_RND_MASK). Exponential notation is used if too many zeros are
needed.*/
#define BF_FTOA_FORMAT_FIXED (0 << 16)
/* fractional format: prec digits after the decimal point rounded with
(flags & BF_RND_MASK) */
#define BF_FTOA_FORMAT_FRAC (1 << 16)
/* free format:
For binary radices with bf_ftoa() and for bfdec_ftoa(): use the minimum
number of digits to represent 'a'. The precision and the rounding
mode are ignored.
For the non binary radices with bf_ftoa(): use as many digits as
necessary so that bf_atof() return the same number when using
precision 'prec', rounding to nearest and the subnormal
configuration of 'flags'. The result is meaningful only if 'a' is
already rounded to 'prec' bits. If the subnormal flag is set, the
exponent in 'flags' must also be set to the desired exponent range.
*/
#define BF_FTOA_FORMAT_FREE (2 << 16)
/* same as BF_FTOA_FORMAT_FREE but uses the minimum number of digits
(takes more computation time). Identical to BF_FTOA_FORMAT_FREE for
binary radices with bf_ftoa() and for bfdec_ftoa(). */
#define BF_FTOA_FORMAT_FREE_MIN (3 << 16)
/* force exponential notation for fixed or free format */
#define BF_FTOA_FORCE_EXP (1 << 20)
/* add 0x prefix for base 16, 0o prefix for base 8 or 0b prefix for
base 2 if non zero value */
#define BF_FTOA_ADD_PREFIX (1 << 21)
/* return "Infinity" instead of "Inf" and add a "+" for positive
exponents */
#define BF_FTOA_JS_QUIRKS (1 << 22)
char *bf_ftoa(size_t *plen, const bf_t *a, int radix, limb_t prec,
bf_flags_t flags);
/* modulo 2^n instead of saturation. NaN and infinity return 0 */
#define BF_GET_INT_MOD (1 << 0)
int bf_get_int32(int *pres, const bf_t *a, int flags);
int bf_get_int64(int64_t *pres, const bf_t *a, int flags);
int bf_get_uint64(uint64_t *pres, const bf_t *a);
/* the following functions are exported for testing only. */
void mp_print_str(const char *str, const limb_t *tab, limb_t n);
void bf_print_str(const char *str, const bf_t *a);
int bf_resize(bf_t *r, limb_t len);
int bf_get_fft_size(int *pdpl, int *pnb_mods, limb_t len);
int bf_normalize_and_round(bf_t *r, limb_t prec1, bf_flags_t flags);
int bf_can_round(const bf_t *a, slimb_t prec, bf_rnd_t rnd_mode, slimb_t k);
slimb_t bf_mul_log2_radix(slimb_t a1, unsigned int radix, int is_inv,
int is_ceil1);
int mp_mul(bf_context_t *s, limb_t *result,
const limb_t *op1, limb_t op1_size,
const limb_t *op2, limb_t op2_size);
limb_t mp_add(limb_t *res, const limb_t *op1, const limb_t *op2,
limb_t n, limb_t carry);
limb_t mp_add_ui(limb_t *tab, limb_t b, size_t n);
int mp_sqrtrem(bf_context_t *s, limb_t *tabs, limb_t *taba, limb_t n);
int mp_recip(bf_context_t *s, limb_t *tabr, const limb_t *taba, limb_t n);
limb_t bf_isqrt(limb_t a);
/* transcendental functions */
int bf_const_log2(bf_t *T, limb_t prec, bf_flags_t flags);
int bf_const_pi(bf_t *T, limb_t prec, bf_flags_t flags);
int bf_exp(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
int bf_log(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
#define BF_POW_JS_QUIRKS (1 << 16) /* (+/-1)^(+/-Inf) = NaN, 1^NaN = NaN */
int bf_pow(bf_t *r, const bf_t *x, const bf_t *y, limb_t prec, bf_flags_t flags);
int bf_cos(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
int bf_sin(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
int bf_tan(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
int bf_atan(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
int bf_atan2(bf_t *r, const bf_t *y, const bf_t *x,
limb_t prec, bf_flags_t flags);
int bf_asin(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
int bf_acos(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags);
/* decimal floating point */
static inline void bfdec_init(bf_context_t *s, bfdec_t *r)
{
bf_init(s, (bf_t *)r);
}
static inline void bfdec_delete(bfdec_t *r)
{
bf_delete((bf_t *)r);
}
static inline void bfdec_neg(bfdec_t *r)
{
r->sign ^= 1;
}
static inline int bfdec_is_finite(const bfdec_t *a)
{
return (a->expn < BF_EXP_INF);
}
static inline int bfdec_is_nan(const bfdec_t *a)
{
return (a->expn == BF_EXP_NAN);
}
static inline int bfdec_is_zero(const bfdec_t *a)
{
return (a->expn == BF_EXP_ZERO);
}
static inline void bfdec_memcpy(bfdec_t *r, const bfdec_t *a)
{
bf_memcpy((bf_t *)r, (const bf_t *)a);
}
int bfdec_set_ui(bfdec_t *r, uint64_t a);
int bfdec_set_si(bfdec_t *r, int64_t a);
static inline void bfdec_set_nan(bfdec_t *r)
{
bf_set_nan((bf_t *)r);
}
static inline void bfdec_set_zero(bfdec_t *r, int is_neg)
{
bf_set_zero((bf_t *)r, is_neg);
}
static inline void bfdec_set_inf(bfdec_t *r, int is_neg)
{
bf_set_inf((bf_t *)r, is_neg);
}
static inline int bfdec_set(bfdec_t *r, const bfdec_t *a)
{
return bf_set((bf_t *)r, (bf_t *)a);
}
static inline void bfdec_move(bfdec_t *r, bfdec_t *a)
{
bf_move((bf_t *)r, (bf_t *)a);
}
static inline int bfdec_cmpu(const bfdec_t *a, const bfdec_t *b)
{
return bf_cmpu((const bf_t *)a, (const bf_t *)b);
}
static inline int bfdec_cmp_full(const bfdec_t *a, const bfdec_t *b)
{
return bf_cmp_full((const bf_t *)a, (const bf_t *)b);
}
static inline int bfdec_cmp(const bfdec_t *a, const bfdec_t *b)
{
return bf_cmp((const bf_t *)a, (const bf_t *)b);
}
static inline int bfdec_cmp_eq(const bfdec_t *a, const bfdec_t *b)
{
return bfdec_cmp(a, b) == 0;
}
static inline int bfdec_cmp_le(const bfdec_t *a, const bfdec_t *b)
{
return bfdec_cmp(a, b) <= 0;
}
static inline int bfdec_cmp_lt(const bfdec_t *a, const bfdec_t *b)
{
return bfdec_cmp(a, b) < 0;
}
int bfdec_add(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
bf_flags_t flags);
int bfdec_sub(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
bf_flags_t flags);
int bfdec_add_si(bfdec_t *r, const bfdec_t *a, int64_t b1, limb_t prec,
bf_flags_t flags);
int bfdec_mul(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
bf_flags_t flags);
int bfdec_mul_si(bfdec_t *r, const bfdec_t *a, int64_t b1, limb_t prec,
bf_flags_t flags);
int bfdec_div(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
bf_flags_t flags);
int bfdec_divrem(bfdec_t *q, bfdec_t *r, const bfdec_t *a, const bfdec_t *b,
limb_t prec, bf_flags_t flags, int rnd_mode);
int bfdec_rem(bfdec_t *r, const bfdec_t *a, const bfdec_t *b, limb_t prec,
bf_flags_t flags, int rnd_mode);
int bfdec_rint(bfdec_t *r, int rnd_mode);
int bfdec_sqrt(bfdec_t *r, const bfdec_t *a, limb_t prec, bf_flags_t flags);
int bfdec_round(bfdec_t *r, limb_t prec, bf_flags_t flags);
int bfdec_get_int32(int *pres, const bfdec_t *a);
int bfdec_pow_ui(bfdec_t *r, const bfdec_t *a, limb_t b);
char *bfdec_ftoa(size_t *plen, const bfdec_t *a, limb_t prec, bf_flags_t flags);
int bfdec_atof(bfdec_t *r, const char *str, const char **pnext,
limb_t prec, bf_flags_t flags);
/* the following functions are exported for testing only. */
extern const limb_t mp_pow_dec[LIMB_DIGITS + 1];
void bfdec_print_str(const char *str, const bfdec_t *a);
static inline int bfdec_resize(bfdec_t *r, limb_t len)
{
return bf_resize((bf_t *)r, len);
}
int bfdec_normalize_and_round(bfdec_t *r, limb_t prec1, bf_flags_t flags);
#endif /* LIBBF_H */

View file

@ -1,57 +0,0 @@
/*
* Regular Expression Engine
*
* Copyright (c) 2017-2018 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifdef DEF
DEF(invalid, 1) /* never used */
DEF(char, 3)
DEF(char32, 5)
DEF(dot, 1)
DEF(any, 1) /* same as dot but match any character including line terminator */
DEF(line_start, 1)
DEF(line_end, 1)
DEF(goto, 5)
DEF(split_goto_first, 5)
DEF(split_next_first, 5)
DEF(match, 1)
DEF(save_start, 2) /* save start position */
DEF(save_end, 2) /* save end position, must come after saved_start */
DEF(save_reset, 3) /* reset save positions */
DEF(loop, 5) /* decrement the top the stack and goto if != 0 */
DEF(push_i32, 5) /* push integer on the stack */
DEF(drop, 1)
DEF(word_boundary, 1)
DEF(not_word_boundary, 1)
DEF(back_reference, 2)
DEF(backward_back_reference, 2) /* must come after back_reference */
DEF(range, 3) /* variable length */
DEF(range32, 3) /* variable length */
DEF(lookahead, 5)
DEF(negative_lookahead, 5)
DEF(push_char_pos, 1) /* push the character position on the stack */
DEF(check_advance, 1) /* pop one stack element and check that it is different from the character position */
DEF(prev, 1) /* go to the previous char */
DEF(simple_greedy_quant, 17)
#endif /* DEF */

File diff suppressed because it is too large Load diff

View file

@ -1,93 +0,0 @@
/*
* Regular Expression Engine
*
* Copyright (c) 2017-2018 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef LIBREGEXP_H
#define LIBREGEXP_H
#include <stddef.h>
#include "libunicode.h"
#define LRE_BOOL int /* for documentation purposes */
#define LRE_FLAG_GLOBAL (1 << 0)
#define LRE_FLAG_IGNORECASE (1 << 1)
#define LRE_FLAG_MULTILINE (1 << 2)
#define LRE_FLAG_DOTALL (1 << 3)
#define LRE_FLAG_UTF16 (1 << 4)
#define LRE_FLAG_STICKY (1 << 5)
#define LRE_FLAG_INDICES (1 << 6) /* Unused by libregexp, just recorded. */
#define LRE_FLAG_NAMED_GROUPS (1 << 7) /* named groups are present in the regexp */
uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size,
const char *buf, size_t buf_len, int re_flags,
void *opaque);
int lre_get_capture_count(const uint8_t *bc_buf);
int lre_get_flags(const uint8_t *bc_buf);
const char *lre_get_groupnames(const uint8_t *bc_buf);
int lre_exec(uint8_t **capture,
const uint8_t *bc_buf, const uint8_t *cbuf, int cindex, int clen,
int cbuf_type, void *opaque);
int lre_parse_escape(const uint8_t **pp, int allow_utf16);
LRE_BOOL lre_is_space(int c);
/* must be provided by the user */
LRE_BOOL lre_check_stack_overflow(void *opaque, size_t alloca_size);
void *lre_realloc(void *opaque, void *ptr, size_t size);
/* JS identifier test */
extern uint32_t const lre_id_start_table_ascii[4];
extern uint32_t const lre_id_continue_table_ascii[4];
static inline int lre_js_is_ident_first(int c)
{
if ((uint32_t)c < 128) {
return (lre_id_start_table_ascii[c >> 5] >> (c & 31)) & 1;
} else {
#ifdef CONFIG_ALL_UNICODE
return lre_is_id_start(c);
#else
return !lre_is_space(c);
#endif
}
}
static inline int lre_js_is_ident_next(int c)
{
if ((uint32_t)c < 128) {
return (lre_id_continue_table_ascii[c >> 5] >> (c & 31)) & 1;
} else {
/* ZWNJ and ZWJ are accepted in identifiers */
#ifdef CONFIG_ALL_UNICODE
return lre_is_id_continue(c) || c == 0x200C || c == 0x200D;
#else
return !lre_is_space(c) || c == 0x200C || c == 0x200D;
#endif
}
}
#undef LRE_BOOL
#endif /* LIBREGEXP_H */

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,127 +0,0 @@
/*
* Unicode utilities
*
* Copyright (c) 2017-2018 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef LIBUNICODE_H
#define LIBUNICODE_H
#include <inttypes.h>
#define LRE_BOOL int /* for documentation purposes */
/* define it to include all the unicode tables (40KB larger) */
#define CONFIG_ALL_UNICODE
#define LRE_CC_RES_LEN_MAX 3
typedef enum {
UNICODE_NFC,
UNICODE_NFD,
UNICODE_NFKC,
UNICODE_NFKD,
} UnicodeNormalizationEnum;
int lre_case_conv(uint32_t *res, uint32_t c, int conv_type);
int lre_canonicalize(uint32_t c, BOOL is_unicode);
LRE_BOOL lre_is_cased(uint32_t c);
LRE_BOOL lre_is_case_ignorable(uint32_t c);
/* char ranges */
typedef struct {
int len; /* in points, always even */
int size;
uint32_t *points; /* points sorted by increasing value */
void *mem_opaque;
void *(*realloc_func)(void *opaque, void *ptr, size_t size);
} CharRange;
typedef enum {
CR_OP_UNION,
CR_OP_INTER,
CR_OP_XOR,
} CharRangeOpEnum;
void cr_init(CharRange *cr, void *mem_opaque, void *(*realloc_func)(void *opaque, void *ptr, size_t size));
void cr_free(CharRange *cr);
int cr_realloc(CharRange *cr, int size);
int cr_copy(CharRange *cr, const CharRange *cr1);
static inline int cr_add_point(CharRange *cr, uint32_t v)
{
if (cr->len >= cr->size) {
if (cr_realloc(cr, cr->len + 1))
return -1;
}
cr->points[cr->len++] = v;
return 0;
}
static inline int cr_add_interval(CharRange *cr, uint32_t c1, uint32_t c2)
{
if ((cr->len + 2) > cr->size) {
if (cr_realloc(cr, cr->len + 2))
return -1;
}
cr->points[cr->len++] = c1;
cr->points[cr->len++] = c2;
return 0;
}
int cr_union1(CharRange *cr, const uint32_t *b_pt, int b_len);
static inline int cr_union_interval(CharRange *cr, uint32_t c1, uint32_t c2)
{
uint32_t b_pt[2];
b_pt[0] = c1;
b_pt[1] = c2 + 1;
return cr_union1(cr, b_pt, 2);
}
int cr_op(CharRange *cr, const uint32_t *a_pt, int a_len,
const uint32_t *b_pt, int b_len, int op);
int cr_invert(CharRange *cr);
int cr_regexp_canonicalize(CharRange *cr, BOOL is_unicode);
#ifdef CONFIG_ALL_UNICODE
LRE_BOOL lre_is_id_start(uint32_t c);
LRE_BOOL lre_is_id_continue(uint32_t c);
int unicode_normalize(uint32_t **pdst, const uint32_t *src, int src_len,
UnicodeNormalizationEnum n_type,
void *opaque, void *(*realloc_func)(void *opaque, void *ptr, size_t size));
/* Unicode character range functions */
int unicode_script(CharRange *cr,
const char *script_name, LRE_BOOL is_ext);
int unicode_general_category(CharRange *cr, const char *gc_name);
int unicode_prop(CharRange *cr, const char *prop_name);
#endif /* CONFIG_ALL_UNICODE */
#undef LRE_BOOL
#endif /* LIBUNICODE_H */

View file

@ -1,99 +0,0 @@
/*
* Linux klist like system
*
* Copyright (c) 2016-2017 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef LIST_H
#define LIST_H
#ifndef NULL
#include <stddef.h>
#endif
struct list_head {
struct list_head *prev;
struct list_head *next;
};
#define LIST_HEAD_INIT(el) { &(el), &(el) }
/* return the pointer of type 'type *' containing 'el' as field 'member' */
#define list_entry(el, type, member) container_of(el, type, member)
static inline void init_list_head(struct list_head *head)
{
head->prev = head;
head->next = head;
}
/* insert 'el' between 'prev' and 'next' */
static inline void __list_add(struct list_head *el,
struct list_head *prev, struct list_head *next)
{
prev->next = el;
el->prev = prev;
el->next = next;
next->prev = el;
}
/* add 'el' at the head of the list 'head' (= after element head) */
static inline void list_add(struct list_head *el, struct list_head *head)
{
__list_add(el, head, head->next);
}
/* add 'el' at the end of the list 'head' (= before element head) */
static inline void list_add_tail(struct list_head *el, struct list_head *head)
{
__list_add(el, head->prev, head);
}
static inline void list_del(struct list_head *el)
{
struct list_head *prev, *next;
prev = el->prev;
next = el->next;
prev->next = next;
next->prev = prev;
el->prev = NULL; /* fail safe */
el->next = NULL; /* fail safe */
}
static inline int list_empty(struct list_head *el)
{
return el->next == el;
}
#define list_for_each(el, head) \
for(el = (head)->next; el != (head); el = el->next)
#define list_for_each_safe(el, el1, head) \
for(el = (head)->next, el1 = el->next; el != (head); \
el = el1, el1 = el->next)
#define list_for_each_prev(el, head) \
for(el = (head)->prev; el != (head); el = el->prev)
#define list_for_each_prev_safe(el, el1, head) \
for(el = (head)->prev, el1 = el->prev; el != (head); \
el = el1, el1 = el->prev)
#endif /* LIST_H */

View file

@ -1,273 +0,0 @@
/*
* QuickJS atom definitions
*
* Copyright (c) 2017-2018 Fabrice Bellard
* Copyright (c) 2017-2018 Charlie Gordon
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifdef DEF
/* Note: first atoms are considered as keywords in the parser */
DEF(null, "null") /* must be first */
DEF(false, "false")
DEF(true, "true")
DEF(if, "if")
DEF(else, "else")
DEF(return, "return")
DEF(var, "var")
DEF(this, "this")
DEF(delete, "delete")
DEF(void, "void")
DEF(typeof, "typeof")
DEF(new, "new")
DEF(in, "in")
DEF(instanceof, "instanceof")
DEF(do, "do")
DEF(while, "while")
DEF(for, "for")
DEF(break, "break")
DEF(continue, "continue")
DEF(switch, "switch")
DEF(case, "case")
DEF(default, "default")
DEF(throw, "throw")
DEF(try, "try")
DEF(catch, "catch")
DEF(finally, "finally")
DEF(function, "function")
DEF(debugger, "debugger")
DEF(with, "with")
/* FutureReservedWord */
DEF(class, "class")
DEF(const, "const")
DEF(enum, "enum")
DEF(export, "export")
DEF(extends, "extends")
DEF(import, "import")
DEF(super, "super")
/* FutureReservedWords when parsing strict mode code */
DEF(implements, "implements")
DEF(interface, "interface")
DEF(let, "let")
DEF(package, "package")
DEF(private, "private")
DEF(protected, "protected")
DEF(public, "public")
DEF(static, "static")
DEF(yield, "yield")
DEF(await, "await")
/* empty string */
DEF(empty_string, "")
/* identifiers */
DEF(length, "length")
DEF(fileName, "fileName")
DEF(lineNumber, "lineNumber")
DEF(message, "message")
DEF(cause, "cause")
DEF(errors, "errors")
DEF(stack, "stack")
DEF(name, "name")
DEF(toString, "toString")
DEF(toLocaleString, "toLocaleString")
DEF(valueOf, "valueOf")
DEF(eval, "eval")
DEF(prototype, "prototype")
DEF(constructor, "constructor")
DEF(configurable, "configurable")
DEF(writable, "writable")
DEF(enumerable, "enumerable")
DEF(value, "value")
DEF(get, "get")
DEF(set, "set")
DEF(of, "of")
DEF(__proto__, "__proto__")
DEF(undefined, "undefined")
DEF(number, "number")
DEF(boolean, "boolean")
DEF(string, "string")
DEF(object, "object")
DEF(symbol, "symbol")
DEF(integer, "integer")
DEF(unknown, "unknown")
DEF(arguments, "arguments")
DEF(callee, "callee")
DEF(caller, "caller")
DEF(_eval_, "<eval>")
DEF(_ret_, "<ret>")
DEF(_var_, "<var>")
DEF(_arg_var_, "<arg_var>")
DEF(_with_, "<with>")
DEF(lastIndex, "lastIndex")
DEF(target, "target")
DEF(index, "index")
DEF(input, "input")
DEF(defineProperties, "defineProperties")
DEF(apply, "apply")
DEF(join, "join")
DEF(concat, "concat")
DEF(split, "split")
DEF(construct, "construct")
DEF(getPrototypeOf, "getPrototypeOf")
DEF(setPrototypeOf, "setPrototypeOf")
DEF(isExtensible, "isExtensible")
DEF(preventExtensions, "preventExtensions")
DEF(has, "has")
DEF(deleteProperty, "deleteProperty")
DEF(defineProperty, "defineProperty")
DEF(getOwnPropertyDescriptor, "getOwnPropertyDescriptor")
DEF(ownKeys, "ownKeys")
DEF(add, "add")
DEF(done, "done")
DEF(next, "next")
DEF(values, "values")
DEF(source, "source")
DEF(flags, "flags")
DEF(global, "global")
DEF(unicode, "unicode")
DEF(raw, "raw")
DEF(new_target, "new.target")
DEF(this_active_func, "this.active_func")
DEF(home_object, "<home_object>")
DEF(computed_field, "<computed_field>")
DEF(static_computed_field, "<static_computed_field>") /* must come after computed_fields */
DEF(class_fields_init, "<class_fields_init>")
DEF(brand, "<brand>")
DEF(hash_constructor, "#constructor")
DEF(as, "as")
DEF(from, "from")
DEF(meta, "meta")
DEF(_default_, "*default*")
DEF(_star_, "*")
DEF(Module, "Module")
DEF(then, "then")
DEF(resolve, "resolve")
DEF(reject, "reject")
DEF(promise, "promise")
DEF(proxy, "proxy")
DEF(revoke, "revoke")
DEF(async, "async")
DEF(exec, "exec")
DEF(groups, "groups")
DEF(indices, "indices")
DEF(status, "status")
DEF(reason, "reason")
DEF(globalThis, "globalThis")
DEF(bigint, "bigint")
#ifdef CONFIG_BIGNUM
DEF(bigfloat, "bigfloat")
DEF(bigdecimal, "bigdecimal")
DEF(roundingMode, "roundingMode")
DEF(maximumSignificantDigits, "maximumSignificantDigits")
DEF(maximumFractionDigits, "maximumFractionDigits")
#endif
/* the following 3 atoms are only used with CONFIG_ATOMICS */
DEF(not_equal, "not-equal")
DEF(timed_out, "timed-out")
DEF(ok, "ok")
/* */
DEF(toJSON, "toJSON")
/* class names */
DEF(Object, "Object")
DEF(Array, "Array")
DEF(Error, "Error")
DEF(Number, "Number")
DEF(String, "String")
DEF(Boolean, "Boolean")
DEF(Symbol, "Symbol")
DEF(Arguments, "Arguments")
DEF(Math, "Math")
DEF(JSON, "JSON")
DEF(Date, "Date")
DEF(Function, "Function")
DEF(GeneratorFunction, "GeneratorFunction")
DEF(ForInIterator, "ForInIterator")
DEF(RegExp, "RegExp")
DEF(ArrayBuffer, "ArrayBuffer")
DEF(SharedArrayBuffer, "SharedArrayBuffer")
/* must keep same order as class IDs for typed arrays */
DEF(Uint8ClampedArray, "Uint8ClampedArray")
DEF(Int8Array, "Int8Array")
DEF(Uint8Array, "Uint8Array")
DEF(Int16Array, "Int16Array")
DEF(Uint16Array, "Uint16Array")
DEF(Int32Array, "Int32Array")
DEF(Uint32Array, "Uint32Array")
DEF(BigInt64Array, "BigInt64Array")
DEF(BigUint64Array, "BigUint64Array")
DEF(Float32Array, "Float32Array")
DEF(Float64Array, "Float64Array")
DEF(DataView, "DataView")
DEF(BigInt, "BigInt")
#ifdef CONFIG_BIGNUM
DEF(BigFloat, "BigFloat")
DEF(BigFloatEnv, "BigFloatEnv")
DEF(BigDecimal, "BigDecimal")
DEF(OperatorSet, "OperatorSet")
DEF(Operators, "Operators")
#endif
DEF(Map, "Map")
DEF(Set, "Set") /* Map + 1 */
DEF(WeakMap, "WeakMap") /* Map + 2 */
DEF(WeakSet, "WeakSet") /* Map + 3 */
DEF(Map_Iterator, "Map Iterator")
DEF(Set_Iterator, "Set Iterator")
DEF(Array_Iterator, "Array Iterator")
DEF(String_Iterator, "String Iterator")
DEF(RegExp_String_Iterator, "RegExp String Iterator")
DEF(Generator, "Generator")
DEF(Proxy, "Proxy")
DEF(Promise, "Promise")
DEF(PromiseResolveFunction, "PromiseResolveFunction")
DEF(PromiseRejectFunction, "PromiseRejectFunction")
DEF(AsyncFunction, "AsyncFunction")
DEF(AsyncFunctionResolve, "AsyncFunctionResolve")
DEF(AsyncFunctionReject, "AsyncFunctionReject")
DEF(AsyncGeneratorFunction, "AsyncGeneratorFunction")
DEF(AsyncGenerator, "AsyncGenerator")
DEF(EvalError, "EvalError")
DEF(RangeError, "RangeError")
DEF(ReferenceError, "ReferenceError")
DEF(SyntaxError, "SyntaxError")
DEF(TypeError, "TypeError")
DEF(URIError, "URIError")
DEF(InternalError, "InternalError")
/* private symbols */
DEF(Private_brand, "<brand>")
/* symbols */
DEF(Symbol_toPrimitive, "Symbol.toPrimitive")
DEF(Symbol_iterator, "Symbol.iterator")
DEF(Symbol_match, "Symbol.match")
DEF(Symbol_matchAll, "Symbol.matchAll")
DEF(Symbol_replace, "Symbol.replace")
DEF(Symbol_search, "Symbol.search")
DEF(Symbol_split, "Symbol.split")
DEF(Symbol_toStringTag, "Symbol.toStringTag")
DEF(Symbol_isConcatSpreadable, "Symbol.isConcatSpreadable")
DEF(Symbol_hasInstance, "Symbol.hasInstance")
DEF(Symbol_species, "Symbol.species")
DEF(Symbol_unscopables, "Symbol.unscopables")
DEF(Symbol_asyncIterator, "Symbol.asyncIterator")
#ifdef CONFIG_BIGNUM
DEF(Symbol_operatorSet, "Symbol.operatorSet")
#endif
#endif /* DEF */

File diff suppressed because it is too large Load diff

View file

@ -1,59 +0,0 @@
/*
* QuickJS C library
*
* Copyright (c) 2017-2018 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef QUICKJS_LIBC_H
#define QUICKJS_LIBC_H
#include <stdio.h>
#include <stdlib.h>
#include "quickjs.h"
#ifdef __cplusplus
extern "C" {
#endif
JSModuleDef *js_init_module_std(JSContext *ctx, const char *module_name);
JSModuleDef *js_init_module_os(JSContext *ctx, const char *module_name);
void js_std_add_helpers(JSContext *ctx, int argc, char **argv);
void js_std_loop(JSContext *ctx);
void js_std_init_handlers(JSRuntime *rt);
void js_std_free_handlers(JSRuntime *rt);
void js_std_dump_error(JSContext *ctx);
uint8_t *js_load_file(JSContext *ctx, size_t *pbuf_len, const char *filename);
int js_module_set_import_meta(JSContext *ctx, JSValueConst func_val,
JS_BOOL use_realpath, JS_BOOL is_main);
JSModuleDef *js_module_loader(JSContext *ctx,
const char *module_name, void *opaque);
void js_std_eval_binary(JSContext *ctx, const uint8_t *buf, size_t buf_len,
int flags);
void js_std_promise_rejection_tracker(JSContext *ctx, JSValueConst promise,
JSValueConst reason,
JS_BOOL is_handled, void *opaque);
void js_std_set_worker_new_context_func(JSContext *(*func)(JSRuntime *rt));
#ifdef __cplusplus
} /* extern "C" { */
#endif
#endif /* QUICKJS_LIBC_H */

View file

@ -1,372 +0,0 @@
/*
* QuickJS opcode definitions
*
* Copyright (c) 2017-2018 Fabrice Bellard
* Copyright (c) 2017-2018 Charlie Gordon
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifdef FMT
FMT(none)
FMT(none_int)
FMT(none_loc)
FMT(none_arg)
FMT(none_var_ref)
FMT(u8)
FMT(i8)
FMT(loc8)
FMT(const8)
FMT(label8)
FMT(u16)
FMT(i16)
FMT(label16)
FMT(npop)
FMT(npopx)
FMT(npop_u16)
FMT(loc)
FMT(arg)
FMT(var_ref)
FMT(u32)
FMT(i32)
FMT(const)
FMT(label)
FMT(atom)
FMT(atom_u8)
FMT(atom_u16)
FMT(atom_label_u8)
FMT(atom_label_u16)
FMT(label_u16)
#undef FMT
#endif /* FMT */
#ifdef DEF
#ifndef def
#define def(id, size, n_pop, n_push, f) DEF(id, size, n_pop, n_push, f)
#endif
DEF(invalid, 1, 0, 0, none) /* never emitted */
/* push values */
DEF( push_i32, 5, 0, 1, i32)
DEF( push_const, 5, 0, 1, const)
DEF( fclosure, 5, 0, 1, const) /* must follow push_const */
DEF(push_atom_value, 5, 0, 1, atom)
DEF( private_symbol, 5, 0, 1, atom)
DEF( undefined, 1, 0, 1, none)
DEF( null, 1, 0, 1, none)
DEF( push_this, 1, 0, 1, none) /* only used at the start of a function */
DEF( push_false, 1, 0, 1, none)
DEF( push_true, 1, 0, 1, none)
DEF( object, 1, 0, 1, none)
DEF( special_object, 2, 0, 1, u8) /* only used at the start of a function */
DEF( rest, 3, 0, 1, u16) /* only used at the start of a function */
DEF( drop, 1, 1, 0, none) /* a -> */
DEF( nip, 1, 2, 1, none) /* a b -> b */
DEF( nip1, 1, 3, 2, none) /* a b c -> b c */
DEF( dup, 1, 1, 2, none) /* a -> a a */
DEF( dup1, 1, 2, 3, none) /* a b -> a a b */
DEF( dup2, 1, 2, 4, none) /* a b -> a b a b */
DEF( dup3, 1, 3, 6, none) /* a b c -> a b c a b c */
DEF( insert2, 1, 2, 3, none) /* obj a -> a obj a (dup_x1) */
DEF( insert3, 1, 3, 4, none) /* obj prop a -> a obj prop a (dup_x2) */
DEF( insert4, 1, 4, 5, none) /* this obj prop a -> a this obj prop a */
DEF( perm3, 1, 3, 3, none) /* obj a b -> a obj b */
DEF( perm4, 1, 4, 4, none) /* obj prop a b -> a obj prop b */
DEF( perm5, 1, 5, 5, none) /* this obj prop a b -> a this obj prop b */
DEF( swap, 1, 2, 2, none) /* a b -> b a */
DEF( swap2, 1, 4, 4, none) /* a b c d -> c d a b */
DEF( rot3l, 1, 3, 3, none) /* x a b -> a b x */
DEF( rot3r, 1, 3, 3, none) /* a b x -> x a b */
DEF( rot4l, 1, 4, 4, none) /* x a b c -> a b c x */
DEF( rot5l, 1, 5, 5, none) /* x a b c d -> a b c d x */
DEF(call_constructor, 3, 2, 1, npop) /* func new.target args -> ret. arguments are not counted in n_pop */
DEF( call, 3, 1, 1, npop) /* arguments are not counted in n_pop */
DEF( tail_call, 3, 1, 0, npop) /* arguments are not counted in n_pop */
DEF( call_method, 3, 2, 1, npop) /* arguments are not counted in n_pop */
DEF(tail_call_method, 3, 2, 0, npop) /* arguments are not counted in n_pop */
DEF( array_from, 3, 0, 1, npop) /* arguments are not counted in n_pop */
DEF( apply, 3, 3, 1, u16)
DEF( return, 1, 1, 0, none)
DEF( return_undef, 1, 0, 0, none)
DEF(check_ctor_return, 1, 1, 2, none)
DEF( check_ctor, 1, 0, 0, none)
DEF( check_brand, 1, 2, 2, none) /* this_obj func -> this_obj func */
DEF( add_brand, 1, 2, 0, none) /* this_obj home_obj -> */
DEF( return_async, 1, 1, 0, none)
DEF( throw, 1, 1, 0, none)
DEF( throw_error, 6, 0, 0, atom_u8)
DEF( eval, 5, 1, 1, npop_u16) /* func args... -> ret_val */
DEF( apply_eval, 3, 2, 1, u16) /* func array -> ret_eval */
DEF( regexp, 1, 2, 1, none) /* create a RegExp object from the pattern and a
bytecode string */
DEF( get_super, 1, 1, 1, none)
DEF( import, 1, 1, 1, none) /* dynamic module import */
DEF( check_var, 5, 0, 1, atom) /* check if a variable exists */
DEF( get_var_undef, 5, 0, 1, atom) /* push undefined if the variable does not exist */
DEF( get_var, 5, 0, 1, atom) /* throw an exception if the variable does not exist */
DEF( put_var, 5, 1, 0, atom) /* must come after get_var */
DEF( put_var_init, 5, 1, 0, atom) /* must come after put_var. Used to initialize a global lexical variable */
DEF( put_var_strict, 5, 2, 0, atom) /* for strict mode variable write */
DEF( get_ref_value, 1, 2, 3, none)
DEF( put_ref_value, 1, 3, 0, none)
DEF( define_var, 6, 0, 0, atom_u8)
DEF(check_define_var, 6, 0, 0, atom_u8)
DEF( define_func, 6, 1, 0, atom_u8)
DEF( get_field, 5, 1, 1, atom)
DEF( get_field2, 5, 1, 2, atom)
DEF( put_field, 5, 2, 0, atom)
DEF( get_private_field, 1, 2, 1, none) /* obj prop -> value */
DEF( put_private_field, 1, 3, 0, none) /* obj value prop -> */
DEF(define_private_field, 1, 3, 1, none) /* obj prop value -> obj */
DEF( get_array_el, 1, 2, 1, none)
DEF( get_array_el2, 1, 2, 2, none) /* obj prop -> obj value */
DEF( put_array_el, 1, 3, 0, none)
DEF(get_super_value, 1, 3, 1, none) /* this obj prop -> value */
DEF(put_super_value, 1, 4, 0, none) /* this obj prop value -> */
DEF( define_field, 5, 2, 1, atom)
DEF( set_name, 5, 1, 1, atom)
DEF(set_name_computed, 1, 2, 2, none)
DEF( set_proto, 1, 2, 1, none)
DEF(set_home_object, 1, 2, 2, none)
DEF(define_array_el, 1, 3, 2, none)
DEF( append, 1, 3, 2, none) /* append enumerated object, update length */
DEF(copy_data_properties, 2, 3, 3, u8)
DEF( define_method, 6, 2, 1, atom_u8)
DEF(define_method_computed, 2, 3, 1, u8) /* must come after define_method */
DEF( define_class, 6, 2, 2, atom_u8) /* parent ctor -> ctor proto */
DEF( define_class_computed, 6, 3, 3, atom_u8) /* field_name parent ctor -> field_name ctor proto (class with computed name) */
DEF( get_loc, 3, 0, 1, loc)
DEF( put_loc, 3, 1, 0, loc) /* must come after get_loc */
DEF( set_loc, 3, 1, 1, loc) /* must come after put_loc */
DEF( get_arg, 3, 0, 1, arg)
DEF( put_arg, 3, 1, 0, arg) /* must come after get_arg */
DEF( set_arg, 3, 1, 1, arg) /* must come after put_arg */
DEF( get_var_ref, 3, 0, 1, var_ref)
DEF( put_var_ref, 3, 1, 0, var_ref) /* must come after get_var_ref */
DEF( set_var_ref, 3, 1, 1, var_ref) /* must come after put_var_ref */
DEF(set_loc_uninitialized, 3, 0, 0, loc)
DEF( get_loc_check, 3, 0, 1, loc)
DEF( put_loc_check, 3, 1, 0, loc) /* must come after get_loc_check */
DEF( put_loc_check_init, 3, 1, 0, loc)
DEF(get_loc_checkthis, 3, 0, 1, loc)
DEF(get_var_ref_check, 3, 0, 1, var_ref)
DEF(put_var_ref_check, 3, 1, 0, var_ref) /* must come after get_var_ref_check */
DEF(put_var_ref_check_init, 3, 1, 0, var_ref)
DEF( close_loc, 3, 0, 0, loc)
DEF( if_false, 5, 1, 0, label)
DEF( if_true, 5, 1, 0, label) /* must come after if_false */
DEF( goto, 5, 0, 0, label) /* must come after if_true */
DEF( catch, 5, 0, 1, label)
DEF( gosub, 5, 0, 0, label) /* used to execute the finally block */
DEF( ret, 1, 1, 0, none) /* used to return from the finally block */
DEF( nip_catch, 1, 2, 1, none) /* catch ... a -> a */
DEF( to_object, 1, 1, 1, none)
//DEF( to_string, 1, 1, 1, none)
DEF( to_propkey, 1, 1, 1, none)
DEF( to_propkey2, 1, 2, 2, none)
DEF( with_get_var, 10, 1, 0, atom_label_u8) /* must be in the same order as scope_xxx */
DEF( with_put_var, 10, 2, 1, atom_label_u8) /* must be in the same order as scope_xxx */
DEF(with_delete_var, 10, 1, 0, atom_label_u8) /* must be in the same order as scope_xxx */
DEF( with_make_ref, 10, 1, 0, atom_label_u8) /* must be in the same order as scope_xxx */
DEF( with_get_ref, 10, 1, 0, atom_label_u8) /* must be in the same order as scope_xxx */
DEF(with_get_ref_undef, 10, 1, 0, atom_label_u8)
DEF( make_loc_ref, 7, 0, 2, atom_u16)
DEF( make_arg_ref, 7, 0, 2, atom_u16)
DEF(make_var_ref_ref, 7, 0, 2, atom_u16)
DEF( make_var_ref, 5, 0, 2, atom)
DEF( for_in_start, 1, 1, 1, none)
DEF( for_of_start, 1, 1, 3, none)
DEF(for_await_of_start, 1, 1, 3, none)
DEF( for_in_next, 1, 1, 3, none)
DEF( for_of_next, 2, 3, 5, u8)
DEF(iterator_check_object, 1, 1, 1, none)
DEF(iterator_get_value_done, 1, 1, 2, none)
DEF( iterator_close, 1, 3, 0, none)
DEF( iterator_next, 1, 4, 4, none)
DEF( iterator_call, 2, 4, 5, u8)
DEF( initial_yield, 1, 0, 0, none)
DEF( yield, 1, 1, 2, none)
DEF( yield_star, 1, 1, 2, none)
DEF(async_yield_star, 1, 1, 2, none)
DEF( await, 1, 1, 1, none)
/* arithmetic/logic operations */
DEF( neg, 1, 1, 1, none)
DEF( plus, 1, 1, 1, none)
DEF( dec, 1, 1, 1, none)
DEF( inc, 1, 1, 1, none)
DEF( post_dec, 1, 1, 2, none)
DEF( post_inc, 1, 1, 2, none)
DEF( dec_loc, 2, 0, 0, loc8)
DEF( inc_loc, 2, 0, 0, loc8)
DEF( add_loc, 2, 1, 0, loc8)
DEF( not, 1, 1, 1, none)
DEF( lnot, 1, 1, 1, none)
DEF( typeof, 1, 1, 1, none)
DEF( delete, 1, 2, 1, none)
DEF( delete_var, 5, 0, 1, atom)
DEF( mul, 1, 2, 1, none)
DEF( div, 1, 2, 1, none)
DEF( mod, 1, 2, 1, none)
DEF( add, 1, 2, 1, none)
DEF( sub, 1, 2, 1, none)
DEF( pow, 1, 2, 1, none)
DEF( shl, 1, 2, 1, none)
DEF( sar, 1, 2, 1, none)
DEF( shr, 1, 2, 1, none)
DEF( lt, 1, 2, 1, none)
DEF( lte, 1, 2, 1, none)
DEF( gt, 1, 2, 1, none)
DEF( gte, 1, 2, 1, none)
DEF( instanceof, 1, 2, 1, none)
DEF( in, 1, 2, 1, none)
DEF( eq, 1, 2, 1, none)
DEF( neq, 1, 2, 1, none)
DEF( strict_eq, 1, 2, 1, none)
DEF( strict_neq, 1, 2, 1, none)
DEF( and, 1, 2, 1, none)
DEF( xor, 1, 2, 1, none)
DEF( or, 1, 2, 1, none)
DEF(is_undefined_or_null, 1, 1, 1, none)
DEF( private_in, 1, 2, 1, none)
#ifdef CONFIG_BIGNUM
DEF( mul_pow10, 1, 2, 1, none)
DEF( math_mod, 1, 2, 1, none)
#endif
/* must be the last non short and non temporary opcode */
DEF( nop, 1, 0, 0, none)
/* temporary opcodes: never emitted in the final bytecode */
def( enter_scope, 3, 0, 0, u16) /* emitted in phase 1, removed in phase 2 */
def( leave_scope, 3, 0, 0, u16) /* emitted in phase 1, removed in phase 2 */
def( label, 5, 0, 0, label) /* emitted in phase 1, removed in phase 3 */
/* the following opcodes must be in the same order as the 'with_x' and
get_var_undef, get_var and put_var opcodes */
def(scope_get_var_undef, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase 2 */
def( scope_get_var, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase 2 */
def( scope_put_var, 7, 1, 0, atom_u16) /* emitted in phase 1, removed in phase 2 */
def(scope_delete_var, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase 2 */
def( scope_make_ref, 11, 0, 2, atom_label_u16) /* emitted in phase 1, removed in phase 2 */
def( scope_get_ref, 7, 0, 2, atom_u16) /* emitted in phase 1, removed in phase 2 */
def(scope_put_var_init, 7, 0, 2, atom_u16) /* emitted in phase 1, removed in phase 2 */
def(scope_get_var_checkthis, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase 2, only used to return 'this' in derived class constructors */
def(scope_get_private_field, 7, 1, 1, atom_u16) /* obj -> value, emitted in phase 1, removed in phase 2 */
def(scope_get_private_field2, 7, 1, 2, atom_u16) /* obj -> obj value, emitted in phase 1, removed in phase 2 */
def(scope_put_private_field, 7, 2, 0, atom_u16) /* obj value ->, emitted in phase 1, removed in phase 2 */
def(scope_in_private_field, 7, 1, 1, atom_u16) /* obj -> res emitted in phase 1, removed in phase 2 */
def(get_field_opt_chain, 5, 1, 1, atom) /* emitted in phase 1, removed in phase 2 */
def(get_array_el_opt_chain, 1, 2, 1, none) /* emitted in phase 1, removed in phase 2 */
def( set_class_name, 5, 1, 1, u32) /* emitted in phase 1, removed in phase 2 */
def( line_num, 5, 0, 0, u32) /* emitted in phase 1, removed in phase 3 */
#if SHORT_OPCODES
DEF( push_minus1, 1, 0, 1, none_int)
DEF( push_0, 1, 0, 1, none_int)
DEF( push_1, 1, 0, 1, none_int)
DEF( push_2, 1, 0, 1, none_int)
DEF( push_3, 1, 0, 1, none_int)
DEF( push_4, 1, 0, 1, none_int)
DEF( push_5, 1, 0, 1, none_int)
DEF( push_6, 1, 0, 1, none_int)
DEF( push_7, 1, 0, 1, none_int)
DEF( push_i8, 2, 0, 1, i8)
DEF( push_i16, 3, 0, 1, i16)
DEF( push_const8, 2, 0, 1, const8)
DEF( fclosure8, 2, 0, 1, const8) /* must follow push_const8 */
DEF(push_empty_string, 1, 0, 1, none)
DEF( get_loc8, 2, 0, 1, loc8)
DEF( put_loc8, 2, 1, 0, loc8)
DEF( set_loc8, 2, 1, 1, loc8)
DEF( get_loc0, 1, 0, 1, none_loc)
DEF( get_loc1, 1, 0, 1, none_loc)
DEF( get_loc2, 1, 0, 1, none_loc)
DEF( get_loc3, 1, 0, 1, none_loc)
DEF( put_loc0, 1, 1, 0, none_loc)
DEF( put_loc1, 1, 1, 0, none_loc)
DEF( put_loc2, 1, 1, 0, none_loc)
DEF( put_loc3, 1, 1, 0, none_loc)
DEF( set_loc0, 1, 1, 1, none_loc)
DEF( set_loc1, 1, 1, 1, none_loc)
DEF( set_loc2, 1, 1, 1, none_loc)
DEF( set_loc3, 1, 1, 1, none_loc)
DEF( get_arg0, 1, 0, 1, none_arg)
DEF( get_arg1, 1, 0, 1, none_arg)
DEF( get_arg2, 1, 0, 1, none_arg)
DEF( get_arg3, 1, 0, 1, none_arg)
DEF( put_arg0, 1, 1, 0, none_arg)
DEF( put_arg1, 1, 1, 0, none_arg)
DEF( put_arg2, 1, 1, 0, none_arg)
DEF( put_arg3, 1, 1, 0, none_arg)
DEF( set_arg0, 1, 1, 1, none_arg)
DEF( set_arg1, 1, 1, 1, none_arg)
DEF( set_arg2, 1, 1, 1, none_arg)
DEF( set_arg3, 1, 1, 1, none_arg)
DEF( get_var_ref0, 1, 0, 1, none_var_ref)
DEF( get_var_ref1, 1, 0, 1, none_var_ref)
DEF( get_var_ref2, 1, 0, 1, none_var_ref)
DEF( get_var_ref3, 1, 0, 1, none_var_ref)
DEF( put_var_ref0, 1, 1, 0, none_var_ref)
DEF( put_var_ref1, 1, 1, 0, none_var_ref)
DEF( put_var_ref2, 1, 1, 0, none_var_ref)
DEF( put_var_ref3, 1, 1, 0, none_var_ref)
DEF( set_var_ref0, 1, 1, 1, none_var_ref)
DEF( set_var_ref1, 1, 1, 1, none_var_ref)
DEF( set_var_ref2, 1, 1, 1, none_var_ref)
DEF( set_var_ref3, 1, 1, 1, none_var_ref)
DEF( get_length, 1, 1, 1, none)
DEF( if_false8, 2, 1, 0, label8)
DEF( if_true8, 2, 1, 0, label8) /* must come after if_false8 */
DEF( goto8, 2, 0, 0, label8) /* must come after if_true8 */
DEF( goto16, 3, 0, 0, label16)
DEF( call0, 1, 1, 1, npopx)
DEF( call1, 1, 1, 1, npopx)
DEF( call2, 1, 1, 1, npopx)
DEF( call3, 1, 1, 1, npopx)
DEF( is_undefined, 1, 1, 1, none)
DEF( is_null, 1, 1, 1, none)
DEF(typeof_is_undefined, 1, 1, 1, none)
DEF( typeof_is_function, 1, 1, 1, none)
#endif
#undef DEF
#undef def
#endif /* DEF */

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1 +0,0 @@
The main documentation is in doc/quickjs.pdf or doc/quickjs.html.

View file

@ -1,158 +0,0 @@
#!/bin/sh
# Release the QuickJS source code
set -e
version=`cat VERSION`
if [ "$1" = "-h" ] ; then
echo "release.sh [release_list]"
echo ""
echo "release_list: extras binary win_binary quickjs"
exit 1
fi
release_list="extras binary win_binary quickjs"
if [ "$1" != "" ] ; then
release_list="$1"
fi
#################################################"
# extras
if echo $release_list | grep -w -q extras ; then
d="quickjs-${version}"
name="quickjs-extras-${version}"
outdir="/tmp/${d}"
rm -rf $outdir
mkdir -p $outdir $outdir/unicode $outdir/tests
cp unicode/* $outdir/unicode
cp -a tests/bench-v8 $outdir/tests
( cd /tmp && tar Jcvf /tmp/${name}.tar.xz ${d} )
fi
#################################################"
# Windows binary release
if echo $release_list | grep -w -q win_binary ; then
# win64
dlldir=/usr/x86_64-w64-mingw32/sys-root/mingw/bin
cross_prefix="x86_64-w64-mingw32-"
d="quickjs-win-x86_64-${version}"
outdir="/tmp/${d}"
rm -rf $outdir
mkdir -p $outdir
make CONFIG_WIN32=y qjs.exe
cp qjs.exe $outdir
${cross_prefix}strip $outdir/qjs.exe
cp $dlldir/libwinpthread-1.dll $outdir
( cd /tmp/$d && rm -f ../${d}.zip && zip -r ../${d}.zip . )
make CONFIG_WIN32=y clean
# win32
dlldir=/usr/i686-w64-mingw32/sys-root/mingw/bin
cross_prefix="i686-w64-mingw32-"
d="quickjs-win-i686-${version}"
outdir="/tmp/${d}"
rm -rf $outdir
mkdir -p $outdir
make clean
make CONFIG_WIN32=y clean
make CONFIG_WIN32=y CONFIG_M32=y qjs.exe
cp qjs.exe $outdir
${cross_prefix}strip $outdir/qjs.exe
cp $dlldir/libwinpthread-1.dll $outdir
( cd /tmp/$d && rm -f ../${d}.zip && zip -r ../${d}.zip . )
fi
#################################################"
# Linux binary release
if echo $release_list | grep -w -q binary ; then
make clean
make CONFIG_WIN32=y clean
make -j4 qjs run-test262
make -j4 CONFIG_M32=y qjs32 run-test262-32
strip qjs run-test262 qjs32 run-test262-32
d="quickjs-linux-x86_64-${version}"
outdir="/tmp/${d}"
rm -rf $outdir
mkdir -p $outdir
cp qjs run-test262 $outdir
( cd /tmp/$d && rm -f ../${d}.zip && zip -r ../${d}.zip . )
d="quickjs-linux-i686-${version}"
outdir="/tmp/${d}"
rm -rf $outdir
mkdir -p $outdir
cp qjs32 $outdir/qjs
cp run-test262-32 $outdir/run-test262
( cd /tmp/$d && rm -f ../${d}.zip && zip -r ../${d}.zip . )
fi
#################################################"
# quickjs
if echo $release_list | grep -w -q quickjs ; then
make build_doc
d="quickjs-${version}"
outdir="/tmp/${d}"
rm -rf $outdir
mkdir -p $outdir $outdir/doc $outdir/tests $outdir/examples
cp Makefile VERSION TODO Changelog readme.txt LICENSE \
release.sh unicode_download.sh \
qjs.c qjsc.c qjscalc.js repl.js \
quickjs.c quickjs.h quickjs-atom.h \
quickjs-libc.c quickjs-libc.h quickjs-opcode.h \
cutils.c cutils.h list.h \
libregexp.c libregexp.h libregexp-opcode.h \
libunicode.c libunicode.h libunicode-table.h \
libbf.c libbf.h \
unicode_gen.c unicode_gen_def.h \
run-test262.c test262o.conf test262.conf \
test262o_errors.txt test262_errors.txt \
$outdir
cp tests/*.js tests/*.patch tests/bjson.c $outdir/tests
cp examples/*.js examples/*.c $outdir/examples
cp doc/quickjs.texi doc/quickjs.pdf doc/quickjs.html \
doc/jsbignum.texi doc/jsbignum.html doc/jsbignum.pdf \
$outdir/doc
( cd /tmp && tar Jcvf /tmp/${d}.tar.xz ${d} )
fi

View file

@ -1,19 +0,0 @@
#!/bin/sh
set -e
url="ftp://ftp.unicode.org/Public/14.0.0/ucd"
emoji_url="${url}/emoji/emoji-data.txt"
files="CaseFolding.txt DerivedNormalizationProps.txt PropList.txt \
SpecialCasing.txt CompositionExclusions.txt ScriptExtensions.txt \
UnicodeData.txt DerivedCoreProperties.txt NormalizationTest.txt Scripts.txt \
PropertyValueAliases.txt"
mkdir -p unicode
for f in $files; do
g="${url}/${f}"
wget $g -O unicode/$f
done
wget $emoji_url -O unicode/emoji-data.txt

File diff suppressed because it is too large Load diff

View file

@ -1,291 +0,0 @@
#ifdef UNICODE_GENERAL_CATEGORY
DEF(Cn, "Unassigned") /* must be zero */
DEF(Lu, "Uppercase_Letter")
DEF(Ll, "Lowercase_Letter")
DEF(Lt, "Titlecase_Letter")
DEF(Lm, "Modifier_Letter")
DEF(Lo, "Other_Letter")
DEF(Mn, "Nonspacing_Mark")
DEF(Mc, "Spacing_Mark")
DEF(Me, "Enclosing_Mark")
DEF(Nd, "Decimal_Number,digit")
DEF(Nl, "Letter_Number")
DEF(No, "Other_Number")
DEF(Sm, "Math_Symbol")
DEF(Sc, "Currency_Symbol")
DEF(Sk, "Modifier_Symbol")
DEF(So, "Other_Symbol")
DEF(Pc, "Connector_Punctuation")
DEF(Pd, "Dash_Punctuation")
DEF(Ps, "Open_Punctuation")
DEF(Pe, "Close_Punctuation")
DEF(Pi, "Initial_Punctuation")
DEF(Pf, "Final_Punctuation")
DEF(Po, "Other_Punctuation")
DEF(Zs, "Space_Separator")
DEF(Zl, "Line_Separator")
DEF(Zp, "Paragraph_Separator")
DEF(Cc, "Control,cntrl")
DEF(Cf, "Format")
DEF(Cs, "Surrogate")
DEF(Co, "Private_Use")
/* synthetic properties */
DEF(LC, "Cased_Letter")
DEF(L, "Letter")
DEF(M, "Mark,Combining_Mark")
DEF(N, "Number")
DEF(S, "Symbol")
DEF(P, "Punctuation,punct")
DEF(Z, "Separator")
DEF(C, "Other")
#endif
#ifdef UNICODE_SCRIPT
/* scripts aliases names in PropertyValueAliases.txt */
DEF(Unknown, "Zzzz")
DEF(Adlam, "Adlm")
DEF(Ahom, "Ahom")
DEF(Anatolian_Hieroglyphs, "Hluw")
DEF(Arabic, "Arab")
DEF(Armenian, "Armn")
DEF(Avestan, "Avst")
DEF(Balinese, "Bali")
DEF(Bamum, "Bamu")
DEF(Bassa_Vah, "Bass")
DEF(Batak, "Batk")
DEF(Bengali, "Beng")
DEF(Bhaiksuki, "Bhks")
DEF(Bopomofo, "Bopo")
DEF(Brahmi, "Brah")
DEF(Braille, "Brai")
DEF(Buginese, "Bugi")
DEF(Buhid, "Buhd")
DEF(Canadian_Aboriginal, "Cans")
DEF(Carian, "Cari")
DEF(Caucasian_Albanian, "Aghb")
DEF(Chakma, "Cakm")
DEF(Cham, "Cham")
DEF(Cherokee, "Cher")
DEF(Chorasmian, "Chrs")
DEF(Common, "Zyyy")
DEF(Coptic, "Copt,Qaac")
DEF(Cuneiform, "Xsux")
DEF(Cypriot, "Cprt")
DEF(Cyrillic, "Cyrl")
DEF(Cypro_Minoan, "Cpmn")
DEF(Deseret, "Dsrt")
DEF(Devanagari, "Deva")
DEF(Dives_Akuru, "Diak")
DEF(Dogra, "Dogr")
DEF(Duployan, "Dupl")
DEF(Egyptian_Hieroglyphs, "Egyp")
DEF(Elbasan, "Elba")
DEF(Elymaic, "Elym")
DEF(Ethiopic, "Ethi")
DEF(Georgian, "Geor")
DEF(Glagolitic, "Glag")
DEF(Gothic, "Goth")
DEF(Grantha, "Gran")
DEF(Greek, "Grek")
DEF(Gujarati, "Gujr")
DEF(Gunjala_Gondi, "Gong")
DEF(Gurmukhi, "Guru")
DEF(Han, "Hani")
DEF(Hangul, "Hang")
DEF(Hanifi_Rohingya, "Rohg")
DEF(Hanunoo, "Hano")
DEF(Hatran, "Hatr")
DEF(Hebrew, "Hebr")
DEF(Hiragana, "Hira")
DEF(Imperial_Aramaic, "Armi")
DEF(Inherited, "Zinh,Qaai")
DEF(Inscriptional_Pahlavi, "Phli")
DEF(Inscriptional_Parthian, "Prti")
DEF(Javanese, "Java")
DEF(Kaithi, "Kthi")
DEF(Kannada, "Knda")
DEF(Katakana, "Kana")
DEF(Kawi, "Kawi")
DEF(Kayah_Li, "Kali")
DEF(Kharoshthi, "Khar")
DEF(Khmer, "Khmr")
DEF(Khojki, "Khoj")
DEF(Khitan_Small_Script, "Kits")
DEF(Khudawadi, "Sind")
DEF(Lao, "Laoo")
DEF(Latin, "Latn")
DEF(Lepcha, "Lepc")
DEF(Limbu, "Limb")
DEF(Linear_A, "Lina")
DEF(Linear_B, "Linb")
DEF(Lisu, "Lisu")
DEF(Lycian, "Lyci")
DEF(Lydian, "Lydi")
DEF(Makasar, "Maka")
DEF(Mahajani, "Mahj")
DEF(Malayalam, "Mlym")
DEF(Mandaic, "Mand")
DEF(Manichaean, "Mani")
DEF(Marchen, "Marc")
DEF(Masaram_Gondi, "Gonm")
DEF(Medefaidrin, "Medf")
DEF(Meetei_Mayek, "Mtei")
DEF(Mende_Kikakui, "Mend")
DEF(Meroitic_Cursive, "Merc")
DEF(Meroitic_Hieroglyphs, "Mero")
DEF(Miao, "Plrd")
DEF(Modi, "Modi")
DEF(Mongolian, "Mong")
DEF(Mro, "Mroo")
DEF(Multani, "Mult")
DEF(Myanmar, "Mymr")
DEF(Nabataean, "Nbat")
DEF(Nag_Mundari, "Nagm")
DEF(Nandinagari, "Nand")
DEF(New_Tai_Lue, "Talu")
DEF(Newa, "Newa")
DEF(Nko, "Nkoo")
DEF(Nushu, "Nshu")
DEF(Nyiakeng_Puachue_Hmong, "Hmnp")
DEF(Ogham, "Ogam")
DEF(Ol_Chiki, "Olck")
DEF(Old_Hungarian, "Hung")
DEF(Old_Italic, "Ital")
DEF(Old_North_Arabian, "Narb")
DEF(Old_Permic, "Perm")
DEF(Old_Persian, "Xpeo")
DEF(Old_Sogdian, "Sogo")
DEF(Old_South_Arabian, "Sarb")
DEF(Old_Turkic, "Orkh")
DEF(Old_Uyghur, "Ougr")
DEF(Oriya, "Orya")
DEF(Osage, "Osge")
DEF(Osmanya, "Osma")
DEF(Pahawh_Hmong, "Hmng")
DEF(Palmyrene, "Palm")
DEF(Pau_Cin_Hau, "Pauc")
DEF(Phags_Pa, "Phag")
DEF(Phoenician, "Phnx")
DEF(Psalter_Pahlavi, "Phlp")
DEF(Rejang, "Rjng")
DEF(Runic, "Runr")
DEF(Samaritan, "Samr")
DEF(Saurashtra, "Saur")
DEF(Sharada, "Shrd")
DEF(Shavian, "Shaw")
DEF(Siddham, "Sidd")
DEF(SignWriting, "Sgnw")
DEF(Sinhala, "Sinh")
DEF(Sogdian, "Sogd")
DEF(Sora_Sompeng, "Sora")
DEF(Soyombo, "Soyo")
DEF(Sundanese, "Sund")
DEF(Syloti_Nagri, "Sylo")
DEF(Syriac, "Syrc")
DEF(Tagalog, "Tglg")
DEF(Tagbanwa, "Tagb")
DEF(Tai_Le, "Tale")
DEF(Tai_Tham, "Lana")
DEF(Tai_Viet, "Tavt")
DEF(Takri, "Takr")
DEF(Tamil, "Taml")
DEF(Tangut, "Tang")
DEF(Telugu, "Telu")
DEF(Thaana, "Thaa")
DEF(Thai, "Thai")
DEF(Tibetan, "Tibt")
DEF(Tifinagh, "Tfng")
DEF(Tirhuta, "Tirh")
DEF(Tangsa, "Tnsa")
DEF(Toto, "Toto")
DEF(Ugaritic, "Ugar")
DEF(Vai, "Vaii")
DEF(Vithkuqi, "Vith")
DEF(Wancho, "Wcho")
DEF(Warang_Citi, "Wara")
DEF(Yezidi, "Yezi")
DEF(Yi, "Yiii")
DEF(Zanabazar_Square, "Zanb")
#endif
#ifdef UNICODE_PROP_LIST
/* Prop list not exported to regexp */
DEF(Hyphen, "")
DEF(Other_Math, "")
DEF(Other_Alphabetic, "")
DEF(Other_Lowercase, "")
DEF(Other_Uppercase, "")
DEF(Other_Grapheme_Extend, "")
DEF(Other_Default_Ignorable_Code_Point, "")
DEF(Other_ID_Start, "")
DEF(Other_ID_Continue, "")
DEF(Prepended_Concatenation_Mark, "")
/* additional computed properties for smaller tables */
DEF(ID_Continue1, "")
DEF(XID_Start1, "")
DEF(XID_Continue1, "")
DEF(Changes_When_Titlecased1, "")
DEF(Changes_When_Casefolded1, "")
DEF(Changes_When_NFKC_Casefolded1, "")
/* Prop list exported to JS */
DEF(ASCII_Hex_Digit, "AHex")
DEF(Bidi_Control, "Bidi_C")
DEF(Dash, "")
DEF(Deprecated, "Dep")
DEF(Diacritic, "Dia")
DEF(Extender, "Ext")
DEF(Hex_Digit, "Hex")
DEF(IDS_Binary_Operator, "IDSB")
DEF(IDS_Trinary_Operator, "IDST")
DEF(Ideographic, "Ideo")
DEF(Join_Control, "Join_C")
DEF(Logical_Order_Exception, "LOE")
DEF(Noncharacter_Code_Point, "NChar")
DEF(Pattern_Syntax, "Pat_Syn")
DEF(Pattern_White_Space, "Pat_WS")
DEF(Quotation_Mark, "QMark")
DEF(Radical, "")
DEF(Regional_Indicator, "RI")
DEF(Sentence_Terminal, "STerm")
DEF(Soft_Dotted, "SD")
DEF(Terminal_Punctuation, "Term")
DEF(Unified_Ideograph, "UIdeo")
DEF(Variation_Selector, "VS")
DEF(White_Space, "space")
DEF(Bidi_Mirrored, "Bidi_M")
DEF(Emoji, "")
DEF(Emoji_Component, "EComp")
DEF(Emoji_Modifier, "EMod")
DEF(Emoji_Modifier_Base, "EBase")
DEF(Emoji_Presentation, "EPres")
DEF(Extended_Pictographic, "ExtPict")
DEF(Default_Ignorable_Code_Point, "DI")
DEF(ID_Start, "IDS")
DEF(Case_Ignorable, "CI")
/* other binary properties */
DEF(ASCII,"")
DEF(Alphabetic, "Alpha")
DEF(Any, "")
DEF(Assigned,"")
DEF(Cased, "")
DEF(Changes_When_Casefolded, "CWCF")
DEF(Changes_When_Casemapped, "CWCM")
DEF(Changes_When_Lowercased, "CWL")
DEF(Changes_When_NFKC_Casefolded, "CWKCF")
DEF(Changes_When_Titlecased, "CWT")
DEF(Changes_When_Uppercased, "CWU")
DEF(Grapheme_Base, "Gr_Base")
DEF(Grapheme_Extend, "Gr_Ext")
DEF(ID_Continue, "IDC")
DEF(Lowercase, "Lower")
DEF(Math, "")
DEF(Uppercase, "Upper")
DEF(XID_Continue, "XIDC")
DEF(XID_Start, "XIDS")
/* internal tables with index */
DEF(Cased1, "")
#endif

View file

@ -1,4 +0,0 @@
# Prosperon Engine
The easily extendable, developer minded, 2D-first game engine.
See the documentation [here](https://prosperon.dev/doc).

View file

@ -5,7 +5,7 @@ actor.spawn = function(script, config){
if (typeof script !== 'string') return undefined; if (typeof script !== 'string') return undefined;
if (!a_db[script]) a_db[script] = io.slurp(script); if (!a_db[script]) a_db[script] = io.slurp(script);
var padawan = Object.create(actor); var padawan = Object.create(actor);
eval_env(a_db[script], padawan); eval_env(a_db[script], padawan, script);
if (typeof config === 'object') if (typeof config === 'object')
Object.merge(padawan,config); Object.merge(padawan,config);
@ -14,18 +14,25 @@ actor.spawn = function(script, config){
padawan.timers = []; padawan.timers = [];
padawan.master = this; padawan.master = this;
Object.hide(padawan, "master","timers", "padawans"); Object.hide(padawan, "master","timers", "padawans");
check_registers(padawan);
this.padawans.push(padawan); this.padawans.push(padawan);
return padawan; return padawan;
}; };
actor.spawn.doc = `Create a new actor, using this actor as the master, initializing it with 'script' and with data (as a JSON or Nota file) from 'config'.`; actor.spawn.doc = `Create a new actor, using this actor as the master, initializing it with 'script' and with data (as a JSON or Nota file) from 'config'.`;
actor.rm_pawn = function(pawn)
{
this.padawans.remove(pawn);
}
actor.timers = []; actor.timers = [];
actor.kill = function(){ actor.kill = function(){
if (this.__dead__) return; if (this.__dead__) return;
this.timers.forEach(t => t.kill()); this.timers.forEach(t => t());
if (this.master) Player.do_uncontrol(this);
delete this.master[this.toString()]; Event.rm_obj(this);
if (this.master) this.master.rm_pawn(this);
this.padawans.forEach(p => p.kill()); this.padawans.forEach(p => p.kill());
this.padawans = []; this.padawans = [];
this.__dead__ = true; this.__dead__ = true;
@ -36,32 +43,15 @@ actor.kill = function(){
actor.kill.doc = `Remove this actor and all its padawans from existence.`; actor.kill.doc = `Remove this actor and all its padawans from existence.`;
actor.delay = function(fn, seconds) { actor.delay = function(fn, seconds) {
var t = Object.create(timer); var t = timer.delay(fn.bind(this), seconds);
t.remain = seconds;
t.kill = () => {
timer.kill.call(t);
delete this.timers[t.toString()];
}
t.fire = () => {
if (this.__dead__) return;
fn();
t.kill();
};
Register.appupdate.register(t.update, t);
this.timers.push(t); this.timers.push(t);
return function() { t.kill(); }; return t;
}; };
actor.delay.doc = `Call 'fn' after 'seconds' with 'this' set to the actor.`; actor.delay.doc = `Call 'fn' after 'seconds' with 'this' set to the actor.`;
actor.padawans = []; actor.padawans = [];
actor.remaster = function(to){
delete this.master.padawans[this.toString()];
this.master = to;
to.padawans.push(this);
};
global.app = Object.create(actor); global.app = Object.create(actor);
app.die = function() app.die = function()

View file

@ -6,24 +6,24 @@ this.realzoom = function() { return cmd(135); };
this.right = function() this.right = function()
{ {
return this.pos.x + (Window.width/2); return this.pos.x + (Game.width/2);
} }
this.left = function() this.left = function()
{ {
return this.pos.x - (Window.width/2); return this.pos.x - (Game.width/2);
} }
this.mixin({ this.mixin({
get zoom() { get zoom() {
var z = Game.native.y / Window.dimensions.y; // var z = Game.native.y / Window.dimensions.y;
return cmd(135)/z; return cmd(135);///z;
}, },
set zoom(x) { set zoom(x) {
x = Math.clamp(x,0.1,10); x = Math.clamp(x,0.1,10);
var z = Game.native.y / Window.dimensions.y; // var z = Game.native.y / Window.dimensions.y;
z *= x; // z *= x;
cmd(62,z); cmd(62,x);
}, },
}); });

View file

@ -160,6 +160,10 @@ component.sprite.impl = {
set angle(x) { cmd(218,this.id,x); }, set angle(x) { cmd(218,this.id,x); },
get scale() { return cmd(215, this.id); }, get scale() { return cmd(215, this.id); },
set scale(x) { cmd(216, this.id, x); }, set scale(x) { cmd(216, this.id, x); },
grow(x) {
this.scale = this.scale.scale(x);
this.pos = this.pos.scale(x);
},
get drawmode() { return cmd(220,this.id); }, get drawmode() { return cmd(220,this.id); },
set drawmode(x) { cmd(219,this.id,x); }, set drawmode(x) { cmd(219,this.id,x); },
emissive(x) { cmd(170, this.id, x); }, emissive(x) { cmd(170, this.id, x); },
@ -417,9 +421,15 @@ component.polygon2d = Object.copy(collider2d, {
}, },
}); });
function pointscaler(x) {
if (typeof x === 'number') return;
this.points = this.points.map(p => p.mult(x));
}
component.polygon2d.impl = Object.mix(collider2d.impl, { component.polygon2d.impl = Object.mix(collider2d.impl, {
sync() { cmd_poly2d(0, this.id, this.spoints());}, sync() { cmd_poly2d(0, this.id, this.spoints());},
query() { return cmd(80, this.shape); }, query() { return cmd(80, this.shape); },
grow: pointscaler,
}); });
var polygon2d = component.polygon2d; var polygon2d = component.polygon2d;
@ -463,15 +473,15 @@ component.edge2d = Object.copy(collider2d, {
flipx: false, flipx: false,
flipy: false, flipy: false,
cpoints:[], points:[],
toString() { return "edge2d"; }, toString() { return "edge2d"; },
hollow: false, hollow: false,
hollowt: 0, hollowt: 0,
spoints() { spoints() {
if (!this.cpoints) return []; if (!this.points) return [];
var spoints = this.cpoints.slice(); var spoints = this.points.slice();
if (this.flipx) { if (this.flipx) {
if (Spline.is_bezier(this.type)) if (Spline.is_bezier(this.type))
@ -507,12 +517,12 @@ component.edge2d = Object.copy(collider2d, {
}, },
setpoints(points) { setpoints(points) {
this.cpoints = points; this.points = points;
// this.sync(); // this.sync();
}, },
post() { post() {
this.cpoints = []; this.points = [];
}, },
sample() { sample() {
@ -546,25 +556,25 @@ component.edge2d = Object.copy(collider2d, {
gizmo() { gizmo() {
if (this.type === Spline.type.catmull || this.type === -1) { if (this.type === Spline.type.catmull || this.type === -1) {
this.spoints().forEach(x => render.point(this.gameobject.this2screen(x), 3, Color.teal)); this.spoints().forEach(x => render.point(this.gameobject.this2screen(x), 3, Color.teal));
this.cpoints.forEach((x,i) => Debug.numbered_point(this.gameobject.this2screen(x), i)); this.points.forEach((x,i) => Debug.numbered_point(this.gameobject.this2screen(x), i));
} else { } else {
for (var i = 0; i < this.cpoints.length; i += 3) for (var i = 0; i < this.points.length; i += 3)
Debug.numbered_point(this.gameobject.this2screen(this.cpoints[i]), i, Color.teal); Debug.numbered_point(this.gameobject.this2screen(this.points[i]), i, Color.teal);
for (var i = 1; i < this.cpoints.length; i+=3) { for (var i = 1; i < this.points.length; i+=3) {
Debug.numbered_point(this.gameobject.this2screen(this.cpoints[i]), i, Color.green); Debug.numbered_point(this.gameobject.this2screen(this.points[i]), i, Color.green);
Debug.numbered_point(this.gameobject.this2screen(this.cpoints[i+1]), i+1, Color.green); Debug.numbered_point(this.gameobject.this2screen(this.points[i+1]), i+1, Color.green);
render.line([this.gameobject.this2screen(this.cpoints[i-1]), this.gameobject.this2screen(this.cpoints[i])], Color.yellow); render.line([this.gameobject.this2screen(this.points[i-1]), this.gameobject.this2screen(this.points[i])], Color.yellow);
render.line([this.gameobject.this2screen(this.cpoints[i+1]), this.gameobject.this2screen(this.cpoints[i+2])], Color.yellow); render.line([this.gameobject.this2screen(this.points[i+1]), this.gameobject.this2screen(this.points[i+2])], Color.yellow);
} }
} }
}, },
finish_center(change) { this.cpoints = this.cpoints.map(function(x) { return x.sub(change); }); }, finish_center(change) { this.points = this.points.map(function(x) { return x.sub(change); }); },
pick(pos) { pick(pos) {
var i = Gizmos.pick_gameobject_points(pos, this.gameobject, this.cpoints); var i = Gizmos.pick_gameobject_points(pos, this.gameobject, this.points);
var p = this.cpoints[i]; var p = this.points[i];
if (!p) return undefined; if (!p) return undefined;
if (Spline.is_catmull(this.type) || this.type === -1) if (Spline.is_catmull(this.type) || this.type === -1)
@ -577,38 +587,38 @@ component.edge2d = Object.copy(collider2d, {
pos: p, pos: p,
sync: me.sync.bind(me) sync: me.sync.bind(me)
}; };
if (Spline.bezier_is_handle(this.cpoints,i)) if (Spline.bezier_is_handle(this.points,i))
o.move = function(d) { o.move = function(d) {
d = that.dir_world2this(d); d = that.dir_world2this(d);
p.x += d.x; p.x += d.x;
p.y += d.y; p.y += d.y;
Spline.bezier_cp_mirror(me.cpoints,i); Spline.bezier_cp_mirror(me.points,i);
}; };
else else
o.move = function(d) { o.move = function(d) {
d = that.dir_world2this(d); d = that.dir_world2this(d);
p.x += d.x; p.x += d.x;
p.y += d.y; p.y += d.y;
var pp = Spline.bezier_point_handles(me.cpoints,i); var pp = Spline.bezier_point_handles(me.points,i);
pp.forEach(ph => me.cpoints[ph] = me.cpoints[ph].add(d)); pp.forEach(ph => me.points[ph] = me.points[ph].add(d));
} }
return o; return o;
} }
}, },
rm_node(idx) { rm_node(idx) {
if (idx < 0 || idx >= this.cpoints.length) return; if (idx < 0 || idx >= this.points.length) return;
if (Spline.is_catmull(this.type)) if (Spline.is_catmull(this.type))
this.cpoints.splice(idx,1); this.points.splice(idx,1);
if (Spline.is_bezier(this.type)) { if (Spline.is_bezier(this.type)) {
Debug.assert(Spline.bezier_is_node(this.cpoints, idx), 'Attempted to delete a bezier handle.'); Debug.assert(Spline.bezier_is_node(this.points, idx), 'Attempted to delete a bezier handle.');
if (idx === 0) if (idx === 0)
this.cpoints.splice(idx,2); this.points.splice(idx,2);
else if (idx === this.cpoints.length-1) else if (idx === this.points.length-1)
this.cpoints.splice(this.cpoints.length-2,2); this.points.splice(this.points.length-2,2);
else else
this.cpoints.splice(idx-1,3); this.points.splice(idx-1,3);
} }
}, },
@ -616,46 +626,47 @@ component.edge2d = Object.copy(collider2d, {
pos = this.gameobject.world2this(pos); pos = this.gameobject.world2this(pos);
var idx = 0; var idx = 0;
if (Spline.is_catmull(this.type) || this.type === -1) { if (Spline.is_catmull(this.type) || this.type === -1) {
if (this.cpoints.length >= 2) if (this.points.length >= 2)
idx = cmd(59, pos, this.cpoints, 400); idx = cmd(59, pos, this.points, 400);
if (idx === this.cpoints.length) if (idx === this.points.length)
this.cpoints.push(pos); this.points.push(pos);
else else
this.cpoints.splice(idx, 0, pos); this.points.splice(idx, 0, pos);
} }
if (Spline.is_bezier(this.type)) { if (Spline.is_bezier(this.type)) {
idx = cmd(59, pos, Spline.bezier_nodes(this.cpoints),400); idx = cmd(59, pos, Spline.bezier_nodes(this.points),400);
if (idx < 0) return; if (idx < 0) return;
if (idx === 0) { if (idx === 0) {
this.cpoints.unshift(pos.slice(), pos.add([-100,0]), Vector.reflect_point(this.cpoints[1], this.cpoints[0])); this.points.unshift(pos.slice(), pos.add([-100,0]), Vector.reflect_point(this.points[1], this.points[0]));
return; return;
} }
if (idx === Spline.bezier_node_count(this.cpoints)) { if (idx === Spline.bezier_node_count(this.points)) {
this.cpoints.push(Vector.reflect_point(this.cpoints.at(-2), this.cpoints.at(-1)), pos.add([-100,0]), pos.slice()); this.points.push(Vector.reflect_point(this.points.at(-2), this.points.at(-1)), pos.add([-100,0]), pos.slice());
return; return;
} }
idx = 2 + (idx-1)*3; idx = 2 + (idx-1)*3;
var adds = [pos.add([100,0]), pos.slice(), pos.add([-100,0])]; var adds = [pos.add([100,0]), pos.slice(), pos.add([-100,0])];
this.cpoints.splice(idx, 0, ...adds); this.points.splice(idx, 0, ...adds);
} }
}, },
pick_all() { pick_all() {
var picks = []; var picks = [];
this.cpoints.forEach(x =>picks.push(make_point_obj(this,x))); this.points.forEach(x =>picks.push(make_point_obj(this,x)));
return picks; return picks;
}, },
}); });
component.edge2d.impl = Object.mix({ component.edge2d.impl = Object.mix(collider2d.impl, {
set thickness(x) { set thickness(x) {
cmd_edge2d(1,this.id,x); cmd_edge2d(1,this.id,x);
}, },
get thickness() { return cmd(112,this.id); }, get thickness() { return cmd(112,this.id); },
grow: pointscaler,
sync() { sync() {
var sensor = this.sensor; var sensor = this.sensor;
var points = this.sample(); var points = this.sample();
@ -663,7 +674,7 @@ component.edge2d.impl = Object.mix({
cmd_edge2d(0,this.id,points); cmd_edge2d(0,this.id,points);
this.sensor = sensor; this.sensor = sensor;
}, },
}, component.edge2d.impl); });
var bucket = component.edge2d; var bucket = component.edge2d;
bucket.spoints.doc = "Returns the controls points after modifiers are applied, such as it being hollow or mirrored on its axises."; bucket.spoints.doc = "Returns the controls points after modifiers are applied, such as it being hollow or mirrored on its axises.";
@ -685,7 +696,7 @@ bucket.inputs['M-v'].doc = "Decrease spline thickness.";
bucket.inputs['M-v'].rep = true; bucket.inputs['M-v'].rep = true;
bucket.inputs['C-y'] = function() { bucket.inputs['C-y'] = function() {
this.cpoints = this.spoints(); this.points = this.spoints();
this.flipx = false; this.flipx = false;
this.flipy = false; this.flipy = false;
this.hollow = false; this.hollow = false;
@ -709,7 +720,7 @@ bucket.inputs.minus = function() { this.angle *= 1.1; };
bucket.inputs.minus.doc = "Decrease the number of samples on this spline."; bucket.inputs.minus.doc = "Decrease the number of samples on this spline.";
bucket.inputs.minus.rep = true; bucket.inputs.minus.rep = true;
bucket.inputs['C-r'] = function() { this.cpoints = this.cpoints.reverse(); }; bucket.inputs['C-r'] = function() { this.points = this.points.reverse(); };
bucket.inputs['C-r'].doc = "Reverse the order of the spline's points."; bucket.inputs['C-r'].doc = "Reverse the order of the spline's points.";
bucket.inputs['C-l'] = function() { this.looped = !this.looped}; bucket.inputs['C-l'] = function() { this.looped = !this.looped};
@ -718,7 +729,7 @@ bucket.inputs['C-l'].doc = "Toggle spline being looped.";
bucket.inputs['C-c'] = function() { bucket.inputs['C-c'] = function() {
switch(this.type) { switch(this.type) {
case Spline.type.bezier: case Spline.type.bezier:
this.cpoints = Spline.bezier2catmull(this.cpoints); this.points = Spline.bezier2catmull(this.points);
break; break;
} }
this.type = Spline.type.catmull; this.type = Spline.type.catmull;
@ -729,7 +740,7 @@ bucket.inputs['C-c'].doc = "Set type of spline to catmull-rom.";
bucket.inputs['C-b'] = function() { bucket.inputs['C-b'] = function() {
switch(this.type) { switch(this.type) {
case Spline.type.catmull: case Spline.type.catmull:
this.cpoints = Spline.catmull2bezier(Spline.catmull_caps(this.cpoints)); this.points = Spline.catmull2bezier(Spline.catmull_caps(this.points));
break; break;
} }
this.type = Spline.type.bezier; this.type = Spline.type.bezier;
@ -740,13 +751,13 @@ bucket.inputs['C-o'].doc = "Set spline to linear.";
bucket.inputs['C-M-lm'] = function() { bucket.inputs['C-M-lm'] = function() {
if (Spline.is_catmull(this.type)) { if (Spline.is_catmull(this.type)) {
var idx = Math.grab_from_points(Mouse.worldpos, this.cpoints.map(p => this.gameobject.this2world(p)), 25); var idx = Math.grab_from_points(Mouse.worldpos, this.points.map(p => this.gameobject.this2world(p)), 25);
if (idx === -1) return; if (idx === -1) return;
} else { } else {
} }
this.cpoints = this.cpoints.newfirst(idx); this.points = this.points.newfirst(idx);
}; };
bucket.inputs['C-M-lm'].doc = "Select the given point as the '0' of this spline."; bucket.inputs['C-M-lm'].doc = "Select the given point as the '0' of this spline.";
@ -756,9 +767,9 @@ bucket.inputs['C-lm'].doc = "Add a point to the spline at the mouse position.";
bucket.inputs['C-M-lm'] = function() { bucket.inputs['C-M-lm'] = function() {
var idx = -1; var idx = -1;
if (Spline.is_catmull(this.type)) if (Spline.is_catmull(this.type))
idx = Math.grab_from_points(Mouse.worldpos, this.cpoints.map(p => this.gameobject.this2world(p)), 25); idx = Math.grab_from_points(Mouse.worldpos, this.points.map(p => this.gameobject.this2world(p)), 25);
else { else {
var nodes = Spline.bezier_nodes(this.cpoints); var nodes = Spline.bezier_nodes(this.points);
idx = Math.grab_from_points(Mouse.worldpos, nodes.map(p => this.gameobject.this2world(p)), 25); idx = Math.grab_from_points(Mouse.worldpos, nodes.map(p => this.gameobject.this2world(p)), 25);
idx *= 3; idx *= 3;
} }
@ -773,11 +784,11 @@ bucket.inputs.lm.released = function(){};
bucket.inputs.lb = function() { bucket.inputs.lb = function() {
var np = []; var np = [];
this.cpoints.forEach(function(c) { this.points.forEach(function(c) {
np.push(Vector.rotate(c, Math.deg2rad(-1))); np.push(Vector.rotate(c, Math.deg2rad(-1)));
}); });
this.cpoints = np; this.points = np;
}; };
bucket.inputs.lb.doc = "Rotate the points CCW."; bucket.inputs.lb.doc = "Rotate the points CCW.";
bucket.inputs.lb.rep = true; bucket.inputs.lb.rep = true;
@ -785,11 +796,11 @@ bucket.inputs.lb.rep = true;
bucket.inputs.rb = function() { bucket.inputs.rb = function() {
var np = []; var np = [];
this.cpoints.forEach(function(c) { this.points.forEach(function(c) {
np.push(Vector.rotate(c, Math.deg2rad(1))); np.push(Vector.rotate(c, Math.deg2rad(1)));
}); });
this.cpoints = np; this.points = np;
}; };
bucket.inputs.rb.doc = "Rotate the points CW."; bucket.inputs.rb.doc = "Rotate the points CW.";
bucket.inputs.rb.rep = true; bucket.inputs.rb.rep = true;
@ -820,6 +831,11 @@ component.circle2d.impl = Object.mix({
get pos() { return cmd_circle2d(3,this.id); }, get pos() { return cmd_circle2d(3,this.id); },
set pos(x) { cmd_circle2d(1,this.id,x); }, set pos(x) { cmd_circle2d(1,this.id,x); },
grow(x) {
if (typeof x === 'number') this.scale *= x;
else if (typeof x === 'object') this.scale *= x[0];
},
}, collider2d.impl); }, collider2d.impl);
return {component}; return {component};

View file

@ -164,18 +164,16 @@ performance.test.call_fn_n.doc = "Calls fn1 n times, and then fn2.";
performance.cpu.doc = `Output the time it takes to do a given function n number of times. Provide 'q' as "ns", "us", or "ms" to output the time taken in the requested resolution.`; performance.cpu.doc = `Output the time it takes to do a given function n number of times. Provide 'q' as "ns", "us", or "ms" to output the time taken in the requested resolution.`;
/* These controls are available during editing, and during play of debug builds */ /* These controls are available during editing, and during play of debug builds */
var DebugControls = {}; Debug.inputs = {};
DebugControls.toString = function() { return "Debug"; }; Debug.inputs.f1 = function () { Debug.draw_phys(!Debug.phys_drawing); };
DebugControls.inputs = {}; Debug.inputs.f1.doc = "Draw physics debugging aids.";
DebugControls.inputs.f1 = function () { Debug.draw_phys(!Debug.phys_drawing); }; //Debug.inputs.f3 = function() { Debug.draw_bb = !Debug.draw_bb; };
DebugControls.inputs.f1.doc = "Draw physics debugging aids."; //Debug.inputs.f3.doc = "Toggle drawing bounding boxes.";
//DebugControls.inputs.f3 = function() { Debug.draw_bb = !Debug.draw_bb; }; Debug.inputs.f4 = function() {
//DebugControls.inputs.f3.doc = "Toggle drawing bounding boxes."; Debug.draw_names = !Debug.draw_names;
DebugControls.inputs.f4 = function() { Debug.draw_gizmos = !Debug.draw_gizmos;
// Debug.draw_names = !Debug.draw_names;
// Debug.draw_gizmos = !Debug.draw_gizmos;
}; };
DebugControls.inputs.f4.doc = "Toggle drawing gizmos and names of objects."; Debug.inputs.f4.doc = "Toggle drawing gizmos and names of objects.";
Debug.Options.gif = { Debug.Options.gif = {
w: 640, /* Max width */ w: 640, /* Max width */
@ -215,26 +213,26 @@ Debug.Options.gif = {
}, },
}; };
DebugControls.inputs.f8 = function() { Debug.inputs.f8 = function() {
var now = new Date(); var now = new Date();
Debug.Options.gif.file = now.toISOString() + ".gif"; Debug.Options.gif.file = now.toISOString() + ".gif";
Debug.Options.gif.start(); Debug.Options.gif.start();
}; };
DebugControls.inputs.f9 = function() { Debug.inputs.f9 = function() {
Debug.Options.gif.stop(); Debug.Options.gif.stop();
} }
DebugControls.inputs.f10 = function() { Time.timescale = 0.1; }; Debug.inputs.f10 = function() { Time.timescale = 0.1; };
DebugControls.inputs.f10.doc = "Toggle timescale to 1/10."; Debug.inputs.f10.doc = "Toggle timescale to 1/10.";
DebugControls.inputs.f10.released = function () { Time.timescale = 1.0; }; Debug.inputs.f10.released = function () { Time.timescale = 1.0; };
DebugControls.inputs.f12 = function() { GUI.defaults.debug = !GUI.defaults.debug; console.warn("GUI toggle debug");}; Debug.inputs.f12 = function() { GUI.defaults.debug = !GUI.defaults.debug; console.warn("GUI toggle debug");};
DebugControls.inputs.f12.doc = "Toggle drawing GUI debugging aids."; Debug.inputs.f12.doc = "Toggle drawing GUI debugging aids.";
DebugControls.inputs['M-1'] = render.normal; Debug.inputs['M-1'] = render.normal;
DebugControls.inputs['M-2'] = render.wireframe; Debug.inputs['M-2'] = render.wireframe;
DebugControls.inputs['C-M-f'] = function() {}; Debug.inputs['C-M-f'] = function() {};
DebugControls.inputs['C-M-f'].doc = "Enter camera fly mode."; Debug.inputs['C-M-f'].doc = "Enter camera fly mode.";
var Time = { var Time = {
set timescale(x) { cmd(3, x); }, set timescale(x) { cmd(3, x); },
@ -276,9 +274,6 @@ Time.doc.time = "Seconds elapsed since the game started.";
Time.doc.pause = "Pause the game by setting the timescale to 0; remembers the current timescale on play."; Time.doc.pause = "Pause the game by setting the timescale to 0; remembers the current timescale on play.";
Time.doc.play = "Resume the game after using Time.pause."; Time.doc.play = "Resume the game after using Time.pause.";
player[0].control(DebugControls);
Register.gui.register(Debug.draw, Debug);
Debug.api = {}; Debug.api = {};
Debug.api.doc_entry = function(obj, key) Debug.api.doc_entry = function(obj, key)
{ {

View file

@ -3,6 +3,13 @@
selectable selectable
*/ */
global.mixin("config.js");
Window.aspect(Window.mode.full);
Game.loadurs();
player[0].control(Debug);
Register.gui.register(Debug.draw, Debug);
var editor = { var editor = {
toString() { return "editor"; }, toString() { return "editor"; },
grid_size: 100, grid_size: 100,
@ -205,7 +212,7 @@ var editor = {
player[0].control(limited_editor); player[0].control(limited_editor);
editor.cbs.forEach(cb=>cb()); editor.cbs.forEach(cb=>cb());
editor.cbs = []; editor.cbs = [];
global.mixin("game.js"); actor.spawn("game.js");
}, },
cbs: [], cbs: [],
@ -371,7 +378,7 @@ var editor = {
x.gizmo(); x.gizmo();
}); });
render.line(bbox.topoints(bbox.fromcwh([0,0],[Game.native.x,Game.native.y])).wrapped(1), Color.yellow); render.line(bbox.topoints(bbox.fromcwh([0,0],[Game.width,Game.height])).wrapped(1), Color.green);
/* Draw selection box */ /* Draw selection box */
if (this.sel_start) { if (this.sel_start) {
@ -393,7 +400,7 @@ var editor = {
gui() { gui() {
/* Clean out killed objects */ /* Clean out killed objects */
this.selectlist = this.selectlist.filter(function(x) { return x.alive; }); this.selectlist = this.selectlist.filter(function(x) { return x.alive; });
Debug.coordinate(Window.world2screen([0,0])); GUI.text([0,0], Window.world2screen([0,0]));
GUI.text("WORKING LAYER: " + this.working_layer, [0,520]); GUI.text("WORKING LAYER: " + this.working_layer, [0,520]);
GUI.text("MODE: " + this.edit_mode, [0,500]); GUI.text("MODE: " + this.edit_mode, [0,500]);
@ -480,7 +487,7 @@ var editor = {
editor.edit_level.objects.forEach(function(obj) { editor.edit_level.objects.forEach(function(obj) {
if (!obj._ed.selectable) if (!obj._ed.selectable)
GUI.image("icons/icons8-lock-16.png", obj.screenpos()); GUI.text("lock", obj,screenpos());
}); });
Debug.draw_grid(1, editor.grid_size, Color.Editor.grid.alpha(0.3)); Debug.draw_grid(1, editor.grid_size, Color.Editor.grid.alpha(0.3));
@ -618,6 +625,23 @@ editor.new_from_img = function(path)
} }
editor.inputs = {}; editor.inputs = {};
editor.inputs['C-b'] = function() {
if (this.selectlist.length !== 1) {
console.warn(`Can only bake a single object at a time.`);
return;
}
var obj = this.selectlist[0];
obj.components.forEach(function(c) {
if (typeof c.grow !== 'function') return;
c.grow(obj.scale);
c.sync?.();
});
obj.scale = [1,1,1];
}
editor.inputs.drop = function(str) { editor.inputs.drop = function(str) {
str = str.slice(os.cwd().length+1); str = str.slice(os.cwd().length+1);
if (!Resources.is_image(str)) { if (!Resources.is_image(str)) {

View file

@ -29,6 +29,38 @@ function eval_env(script, env, file)
return cmd(123,script,env,file); return cmd(123,script,env,file);
} }
global.check_registers = function(obj)
{
if (typeof obj.update === 'function')
obj.timers.push(Register.update.register(obj.update.bind(obj)));
if (typeof obj.physupdate === 'function')
obj.timers.push(Register.physupdate.register(obj.physupdate.bind(obj)));
if (typeof obj.collide === 'function')
register_collide(0, obj.collide.bind(obj), obj.body);
if (typeof obj.separate === 'function')
register_collide(3,obj.separate.bind(obj), obj.body);
if (typeof obj.draw === 'function')
obj.timers.push(Register.draw.register(obj.draw.bind(obj), obj));
if (typeof obj.debug === 'function')
obj.timers.push(Register.debug.register(obj.debug.bind(obj)));
if (typeof obj.gui === 'function')
obj.timers.push(Register.gui.register(obj.gui.bind(obj)));
for (var k in obj) {
if (!k.startswith("on_")) continue;
var signal = k.fromfirst("on_");
Event.observe(signal, obj, obj[k]);
};
}
eval_env.dov = `Counterpart to /load_env/, but with a string.`; eval_env.dov = `Counterpart to /load_env/, but with a string.`;
function feval_env(file, env) function feval_env(file, env)
@ -59,8 +91,6 @@ global.Game = {
cmd(257, fn); cmd(257, fn);
}, },
native: render.device.pc,
object_count() { object_count() {
return cmd(214); return cmd(214);
}, },
@ -112,6 +142,12 @@ global.Game = {
this.wait_fns = []; this.wait_fns = [];
}, },
set width(w) { cmd(125, w); },
set height(h) { cmd(126, h); },
get width() { return cmd(48); },
get height() { return cmd(49); },
dimensions() { return [this.width,this.height]; },
}; };
Game.gc = function() { cmd(259); } Game.gc = function() { cmd(259); }
@ -340,13 +376,22 @@ var Event = {
}, },
}; };
// Window
var Window = { var Window = {
fullscreen(f) { cmd(145, f); }, fullscreen(f) { cmd(145, f); },
set width(w) { cmd(125, w); }, dimensions() { return cmd(265); },
set height(h) { cmd(126, h); }, get width() { return this.dimensions().x; },
get width() { return cmd(48); }, get height() { return this.dimensions().y; },
get height() { return cmd(49); }, mode: {
get dimensions() { return [this.width, this.height]; }, stretch: 0,
keep: 1,
width: 2,
height: 3,
expand: 4,
full: 5
},
aspect(x) { cmd(264, x); },
title(str) { cmd(134, str); }, title(str) { cmd(134, str); },
boundingbox() { boundingbox() {
return { return {
@ -358,12 +403,16 @@ var Window = {
}, },
}; };
Game.width = 1920;
Game.height = 1080;
Window.screen2world = function(screenpos) { Window.screen2world = function(screenpos) {
if (Game.camera) if (Game.camera)
return Game.camera.view2world(screenpos); return Game.camera.view2world(screenpos);
return screenpos; return screenpos;
} }
Window.world2screen = function(worldpos) { Window.world2screen = function(worldpos) {
return Game.camera.world2view(worldpos); return Game.camera.world2view(worldpos);
} }
@ -375,7 +424,6 @@ global.mixin("scripts/debug.js");
global.mixin("scripts/spline.js"); global.mixin("scripts/spline.js");
global.mixin("scripts/components.js"); global.mixin("scripts/components.js");
Window.doc = {}; Window.doc = {};
Window.doc.width = "Width of the game window."; Window.doc.width = "Width of the game window.";
Window.doc.height = "Height of the game window."; Window.doc.height = "Height of the game window.";
@ -420,5 +468,3 @@ Game.view_camera = function(cam)
} }
Window.title(`Prosperon v${prosperon.version}`); Window.title(`Prosperon v${prosperon.version}`);
Window.width = 1280;
Window.height = 720;

View file

@ -11,40 +11,6 @@ function obj_unique_name(name, obj)
return n; return n;
} }
function check_registers(obj)
{
if (typeof obj.update === 'function')
obj.timers.push(Register.update.register(obj.update.bind(obj)));
if (typeof obj.physupdate === 'function')
obj.timers.push(Register.physupdate.register(obj.physupdate.bind(obj)));
if (typeof obj.collide === 'function')
register_collide(0, obj.collide.bind(obj), obj.body);
if (typeof obj.separate === 'function')
register_collide(3,obj.separate.bind(obj), obj.body);
if (typeof obj.draw === 'function')
obj.timers.push(Register.draw.register(obj.draw.bind(obj), obj));
if (typeof obj.debug === 'function')
obj.timers.push(Register.debug.register(obj.debug.bind(obj)));
if (typeof obj.gui === 'function')
obj.timers.push(Register.gui.register(obj.gui.bind(obj)));
for (var k in obj) {
if (!k.startswith("on_")) continue;
var signal = k.fromfirst("on_");
Event.observe(signal, obj, obj[k]);
};
obj.components.forEach(function(x) {
if (typeof x.collide === 'function')
register_collide(1, x.collide.bind(x), obj.body, x.shape);
});
}
var gameobject_impl = { var gameobject_impl = {
get pos() { get pos() {
@ -76,11 +42,6 @@ var gameobject_impl = {
get scale() { get scale() {
Debug.assert(this.master, `No master set on ${this.toString()}`); Debug.assert(this.master, `No master set on ${this.toString()}`);
var pscale = [1,1,1]; var pscale = [1,1,1];
/* if (typeof this.master.scale === 'object')
pscale = this.master.scale;
else
pscale = [1,1,1];
*/
return this.gscale().map((x,i) => x/(this.master.gscale()[i]*pscale[i])); return this.gscale().map((x,i) => x/(this.master.gscale()[i]*pscale[i]));
}, },
@ -89,11 +50,11 @@ var gameobject_impl = {
x = [x,x]; x = [x,x];
var pct = this.scale.map((s,i) => x[i]/s); var pct = this.scale.map((s,i) => x[i]/s);
this.spread(pct); this.grow(pct);
/* TRANSLATE ALL SUB OBJECTS */ /* TRANSLATE ALL SUB OBJECTS */
this.objects.forEach(obj => { this.objects.forEach(obj => {
obj.spread(pct); obj.grow(pct);
obj.pos = obj.pos.map((x,i)=>x*pct[i]); obj.pos = obj.pos.map((x,i)=>x*pct[i]);
}); });
}, },
@ -378,6 +339,11 @@ var gameobject = {
}; };
check_registers(ent); check_registers(ent);
ent.components.forEach(function(x) {
if (typeof x.collide === 'function')
register_collide(1, x.collide.bind(x), ent.body, x.shape);
});
if (typeof ent.load === 'function') ent.load(); if (typeof ent.load === 'function') ent.load();
if (Game.playing()) if (Game.playing())
@ -477,7 +443,7 @@ var gameobject = {
/* Moving, rotating, scaling functions, world relative */ /* Moving, rotating, scaling functions, world relative */
move(vec) { this.set_worldpos(this.worldpos().add(vec)); }, move(vec) { this.set_worldpos(this.worldpos().add(vec)); },
rotate(x) { this.sworldangle(this.worldangle()+x); }, rotate(x) { this.sworldangle(this.worldangle()+x); },
spread(vec) { this.sgscale(this.gscale().map((x,i)=>x*vec[i])); }, grow(vec) { this.sgscale(this.gscale().map((x,i)=>x*vec[i])); },
/* Make a unique object the same as its prototype */ /* Make a unique object the same as its prototype */
revert() { revert() {
@ -509,8 +475,8 @@ var gameobject = {
disable() { this.components.forEach(function(x) { x.disable(); });}, disable() { this.components.forEach(function(x) { x.disable(); });},
enable() { this.components.forEach(function(x) { x.enable(); });}, enable() { this.components.forEach(function(x) { x.enable(); });},
sync() { sync() {
this.components.forEach(function(x) { x.sync(); }); this.components.forEach(function(x) { x.sync?.(); });
this.objects.forEach(function(x) { x.sync(); }); this.objects.forEach(function(x) { x.sync?.(); });
}, },
/* Bounding box of the object in world dimensions */ /* Bounding box of the object in world dimensions */
@ -749,38 +715,7 @@ gameobject.doc = {
warp_layer: 'Bitmask for selecting what warps should affect this entity.', warp_layer: 'Bitmask for selecting what warps should affect this entity.',
}; };
var resavi = function(ur, path) global.ur = {};
{
if (!ur) return path;
if (path[0] === '/') return path;
var res = ur.replaceAll('.', '/');
var dir = path.dir();
if (res.startsWith(dir))
return path.base();
return path;
}
var resani = function(ur, path)
{
if (!path) return "";
if (!ur) return path;
if (path[0] === '/') return path.slice(1);
var res = ur.replaceAll('.', '/');
var restry = res + "/" + path;
while (!io.exists(restry)) {
res = res.updir() + "/";
if (res === "/")
return path;
restry = res + path;
}
return restry;
}
var ur;
if (io.exists(".prosperon/ur.json")) if (io.exists(".prosperon/ur.json"))
ur = json.decode(io.slurp(".prosperon/ur.json")); ur = json.decode(io.slurp(".prosperon/ur.json"));
@ -860,26 +795,27 @@ function file2fqn(file)
return ur[fqn]; return ur[fqn];
} }
/* FIND ALL URS IN A PROJECT */ Game.loadurs = function() {
for (var file of io.glob("**.jso")) { ur = {};
if (file[0] === '.' || file[0] === '_') continue; ur._list = [];
var topur = file2fqn(file); /* FIND ALL URS IN A PROJECT */
topur.text = file; for (var file of io.glob("**.jso")) {
} if (file[0] === '.' || file[0] === '_') continue;
var topur = file2fqn(file);
topur.text = file;
}
for (var file of io.glob("**.json")) { for (var file of io.glob("**.json")) {
if (file[0] === '.' || file[0] === '_') continue; if (file[0] === '.' || file[0] === '_') continue;
var topur = file2fqn(file); var topur = file2fqn(file);
topur.data = file; topur.data = file;
} }
io.slurpwrite(".prosperon/ur.json", json.encode(ur)); ur.empty = {
name: "empty"
ur.empty = { };
name: "empty"
}; };
return { return {
gameobject, gameobject
ur
} }

View file

@ -65,3 +65,5 @@ shape.circle.points = function(radius, n) {
if (n <= 1) return []; if (n <= 1) return [];
return shape.arc(radius, 360, n); return shape.arc(radius, 360, n);
}; };
return {shape};

View file

@ -37,7 +37,7 @@ var GUI = {
image(path,pos,color) { image(path,pos,color) {
color ??= Color.black; color ??= Color.black;
var wh = cmd(64,path); var wh = cmd(64,path);
gui_img(path,pos, [1.0,1.0], 0.0, 0.0, [0.0,0.0], 0.0, Color.black); gui_img(path,pos, [1.0,1.0], 0.0, false, [0.0,0.0], Color.white);
return bbox.fromcwh([0,0], wh); return bbox.fromcwh([0,0], wh);
}, },
@ -105,7 +105,7 @@ GUI.controls.check_submit = function() {
var Mum = { var Mum = {
padding:[0,0], /* Each element inset with this padding on all sides */ padding:[0,0], /* Each element inset with this padding on all sides */
offset:[0,0], offset:[0,0],
font: "fonts/LessPerfectDOSVGA.ttf", font: "fonts/c64.ttf",
selectable: false, selectable: false,
selected: false, selected: false,
font_size: 1, font_size: 1,

View file

@ -1,14 +0,0 @@
function nogamegui()
{
GUI.column({
items: [
GUI.text_fn("NO GAME LOADED", {font_size: 6}),
GUI.text_fn("No game.js available.")
],
anchor: [0.5,0.5],
}).draw(Window.dimensions.scale(0.5));
}
Register.gui.register(nogamegui);

View file

@ -1,6 +0,0 @@
Game.play();
if (!io.exists("game.js"))
load("scripts/nogame.js");
else
load("game.js");

View file

@ -77,7 +77,7 @@ Resources.replpath = function(str, path)
while (stem) { while (stem) {
var tr = stem + "/" +str; var tr = stem + "/" +str;
if (io.exists(tr)) return tr; if (io.exists(tr)) return tr;
stem = steam.updir(); stem = stem.updir();
} }
return str; return str;
@ -219,6 +219,7 @@ io.slurpbytes = function(path)
io.mkpath = function(dir) io.mkpath = function(dir)
{ {
if (!dir) return;
var mkstack = []; var mkstack = [];
while (!io.exists(dir)) { while (!io.exists(dir)) {
mkstack.push(dir.fromlast('/')); mkstack.push(dir.fromlast('/'));
@ -266,14 +267,15 @@ io.mixin({
}, },
glob(pat) { glob(pat) {
var paths = io.ls(); var paths = io.ls('.');
pat = pat.replaceAll(/([\[\]\(\)\^\$\.\|\+])/g, "\\$1"); pat = pat.replaceAll(/([\[\]\(\)\^\$\.\|\+])/g, "\\$1");
pat = pat.replaceAll('**', '.*'); pat = pat.replaceAll('**', '.*');
pat = pat.replaceAll(/[^\.]\*/g, '[^\\/]*'); pat = pat.replaceAll(/[^\.]\*/g, '[^\\/]*');
pat = pat.replaceAll('?', '.'); pat = pat.replaceAll('?', '.');
var regex = new RegExp("^"+pat+"$", ""); var regex = new RegExp("^"+pat+"$", "");
return paths.filter(str => str.match(regex)); paths = paths.filter(str => str.match(regex)).sort();
return paths;
}, },
}); });
@ -343,10 +345,15 @@ Cmdline.register_order("init", function() {
}, "Turn the directory into a Prosperon game."); }, "Turn the directory into a Prosperon game.");
Cmdline.register_order("debug", function() { Cmdline.register_order("debug", function() {
Cmdline.orders.play(); Cmdline.orders.play([]);
}, "Play the game with debugging enabled."); }, "Play the game with debugging enabled.");
Cmdline.register_order("play", function() { Cmdline.register_order("play", function(argv) {
if (argv[0])
io.chdir(argv[0]);
Game.loadurs();
if (!io.exists(projectfile)) { if (!io.exists(projectfile)) {
say("No game to play. Try making one with 'prosperon init'."); say("No game to play. Try making one with 'prosperon init'.");
return; return;
@ -354,12 +361,13 @@ Cmdline.register_order("play", function() {
var project = json.decode(io.slurp(projectfile)); var project = json.decode(io.slurp(projectfile));
Game.title = project.title; Game.title = project.title;
Window.aspect(Window.mode.expand);
global.mixin("config.js"); global.mixin("config.js");
if (project.title) Window.title(project.title); if (project.title) Window.title(project.title);
Game.engine_start(function() { Game.engine_start(function() {
global.mixin("scripts/sound.js"); global.mixin("scripts/sound.js");
global.mixin("game.js"); global.game = actor.spawn("game.js");
if (project.icon) Window.icon(project.icon); if (project.icon) Window.icon(project.icon);
}); });
}, "Play the game present in this folder."); }, "Play the game present in this folder.");
@ -416,6 +424,7 @@ Cmdline.register_order("about", function(argv) {
}, "Get information about this game."); }, "Get information about this game.");
Cmdline.register_order("ur", function(argv) { Cmdline.register_order("ur", function(argv) {
Game.loadurs();
for (var i of ur._list.sort()) say(i); for (var i of ur._list.sort()) say(i);
}, "Get information about the ur types in your game."); }, "Get information about the ur types in your game.");

View file

@ -553,8 +553,8 @@ void draw_grid(float width, float span, struct rgba color)
float ubo[4]; float ubo[4];
ubo[0] = offset.x; ubo[0] = offset.x;
ubo[1] = offset.y; ubo[1] = offset.y;
ubo[2] = mainwin.rwidth; ubo[2] = mainwin.width;
ubo[3] = mainwin.rheight; ubo[3] = mainwin.height;
sg_apply_pipeline(grid_pipe); sg_apply_pipeline(grid_pipe);
sg_apply_bindings(&grid_bind); sg_apply_bindings(&grid_bind);

View file

@ -84,7 +84,7 @@ void font_init() {
.label = "text buffer" .label = "text buffer"
}); });
font_set("fonts/LessPerfectDOSVGA.ttf"); font_set("fonts/c64.ttf");
bind_text.fs.images[0] = font->texID; bind_text.fs.images[0] = font->texID;
bind_text.fs.samplers[0] = sg_make_sampler(&(sg_sampler_desc){}); bind_text.fs.samplers[0] = sg_make_sampler(&(sg_sampler_desc){});
} }
@ -100,7 +100,7 @@ void font_set(const char *path)
return; return;
} }
struct sFont *newfont = MakeFont(path, 16); struct sFont *newfont = MakeFont(path, 8);
if (!newfont) { if (!newfont) {
YughError("Could not make font from %s.", path); YughError("Could not make font from %s.", path);
return; return;
@ -253,22 +253,19 @@ void sdrawCharacter(struct Character c, HMM_Vec2 cursor, float scale, struct rgb
float lsize = 1.0 / 1024.0; float lsize = 1.0 / 1024.0;
float oline = 1.0; vert.pos.x = cursor.X + c.Bearing[0] * scale;
vert.pos.y = cursor.Y - c.Bearing[1] * scale;
vert.pos.x = cursor.X + c.Bearing[0] * scale + oline; vert.wh.x = c.Size[0] * scale;
vert.pos.y = cursor.Y - c.Bearing[1] * scale - oline; vert.wh.y = c.Size[1] * scale;
vert.wh.x = c.Size[0] * scale + (oline*2);
vert.wh.y = c.Size[1] * scale + (oline*2);
// if (vert.pos.x > frame.l || vert.pos.y > frame.t || (vert.pos.y + vert.wh.y) < frame.b || (vert.pos.x + vert.wh.x) < frame.l) return; // if (vert.pos.x > frame.l || vert.pos.y > frame.t || (vert.pos.y + vert.wh.y) < frame.b || (vert.pos.x + vert.wh.x) < frame.l) return;
vert.uv.u = (c.rect.s0 - oline*lsize)*USHRT_MAX; vert.uv.u = c.rect.s0*USHRT_MAX;
vert.uv.v = (c.rect.t0 - oline*lsize)*USHRT_MAX; vert.uv.v = c.rect.t0*USHRT_MAX;
vert.st.u = (c.rect.s1-c.rect.s0+oline*lsize*2.0)*USHRT_MAX; vert.st.u = (c.rect.s1-c.rect.s0)*USHRT_MAX;
vert.st.v = (c.rect.t1-c.rect.t0+oline*lsize*2.0)*USHRT_MAX; vert.st.v = (c.rect.t1-c.rect.t0)*USHRT_MAX;
vert.color = color; vert.color = color;
// sg_append_buffer(bind_text.vertex_buffers[0], &vert, sizeof(struct text_vert));
memcpy(text_buffer + curchar, &vert, sizeof(struct text_vert)); memcpy(text_buffer + curchar, &vert, sizeof(struct text_vert));
curchar++; curchar++;
} }
@ -401,7 +398,9 @@ int renderText(const char *text, HMM_Vec2 pos, float scale, struct rgba color, f
if (*wordstart == '\e') if (*wordstart == '\e')
wordstart = esc_color(wordstart, &usecolor, color); wordstart = esc_color(wordstart, &usecolor, color);
sdrawCharacter(font->Characters[*wordstart], HMM_AddV2(cursor, HMM_MulV2F((HMM_Vec2){1,-1},scale)), scale, (rgba){0,0,0,255});
sdrawCharacter(font->Characters[*wordstart], cursor, scale, usecolor); sdrawCharacter(font->Characters[*wordstart], cursor, scale, usecolor);
cursor.X += font->Characters[*wordstart].Advance * tracking * scale; cursor.X += font->Characters[*wordstart].Advance * tracking * scale;
wordstart++; wordstart++;
check_caret(caret, wordstart-drawstart, cursor, scale, usecolor); check_caret(caret, wordstart-drawstart, cursor, scale, usecolor);

View file

@ -865,11 +865,11 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
break; break;
case 48: case 48:
ret = JS_NewInt64(js, mainwin.width); ret = JS_NewInt64(js, mainwin.rwidth);
break; break;
case 49: case 49:
ret = JS_NewInt64(js, mainwin.height); ret = JS_NewInt64(js, mainwin.rheight);
break; break;
case 50: case 50:
@ -1103,11 +1103,11 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
break; break;
case 125: case 125:
mainwin.width = js2int(argv[1]); mainwin.rwidth = js2int(argv[1]);
break; break;
case 126: case 126:
mainwin.height = js2int(argv[1]); mainwin.rheight = js2int(argv[1]);
break; break;
case 127: case 127:
@ -1456,6 +1456,12 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
str = js2str(argv[1]); str = js2str(argv[1]);
font_set(str); font_set(str);
break; break;
case 264:
aspect_mode = js2int(argv[1]);
break;
case 265:
ret = vec2js((HMM_Vec2){mainwin.width, mainwin.height});
break;
} }
if (str) JS_FreeCString(js, str); if (str) JS_FreeCString(js, str);
@ -1872,14 +1878,14 @@ GETSET_PAIR(emitter, persist, number)
GETSET_PAIR(emitter, persist_var, number) GETSET_PAIR(emitter, persist_var, number)
GETSET_PAIR(emitter, warp_mask, bitmask) GETSET_PAIR(emitter, warp_mask, bitmask)
JSValue js_emitter_start (JSContext *js, JSValue this) JSValue js_emitter_start (JSContext *js, JSValue this, int argc, JSValue *argv)
{ {
emitter *n = js2emitter(this); emitter *n = js2emitter(this);
start_emitter(n); start_emitter(n);
return JS_UNDEFINED; return JS_UNDEFINED;
} }
JSValue js_emitter_stop(JSContext *js, JSValue this) JSValue js_emitter_stop(JSContext *js, JSValue this, int argc, JSValue *argv)
{ {
emitter *n = js2emitter(this); emitter *n = js2emitter(this);
stop_emitter(n); stop_emitter(n);
@ -1893,10 +1899,15 @@ JSValue js_emitter_emit(JSContext *js, JSValueConst this, int argc, JSValue *arg
return JS_UNDEFINED; return JS_UNDEFINED;
} }
JSValue js_os_cwd(JSContext *js, JSValueConst this) JSValue js_os_cwd(JSContext *js, JSValueConst this, int argc, JSValue *argv)
{ {
char cwd[PATH_MAX]; char cwd[PATH_MAX];
#ifndef __EMSCRIPTEN__
getcwd(cwd, sizeof(cwd)); getcwd(cwd, sizeof(cwd));
#else
cwd[0] = '.';
cwd[1] = 0;
#endif
return str2js(cwd); return str2js(cwd);
} }
@ -1909,7 +1920,7 @@ JSValue js_os_env(JSContext *js, JSValueConst this, int argc, JSValue *argv)
return ret; return ret;
} }
JSValue js_os_sys(JSContext *js, JSValueConst this) JSValue js_os_sys(JSContext *js, JSValueConst this, int argc, JSValue *argv)
{ {
#ifdef __linux__ #ifdef __linux__
return str2js("linux"); return str2js("linux");
@ -1935,14 +1946,14 @@ JSValue js_io_exists(JSContext *js, JSValueConst this, int argc, JSValue *argv)
return ret; return ret;
} }
JSValue js_io_ls(JSContext *js, JSValueConst this) JSValue js_io_ls(JSContext *js, JSValueConst this, int argc, JSValue *argv)
{ {
return strarr2js(ls(",")); return strarr2js(ls("."));
} }
JSValue js_io_cp(JSContext *js, JSValueConst this, int argc, JSValue *argv) JSValue js_io_cp(JSContext *js, JSValueConst this, int argc, JSValue *argv)
{ {
char *f1, f2; char *f1, *f2;
f1 = JS_ToCString(js, argv[0]); f1 = JS_ToCString(js, argv[0]);
f2 = JS_ToCString(js, argv[1]); f2 = JS_ToCString(js, argv[1]);
JSValue ret = int2js(cp(f1,f2)); JSValue ret = int2js(cp(f1,f2));
@ -1953,7 +1964,7 @@ JSValue js_io_cp(JSContext *js, JSValueConst this, int argc, JSValue *argv)
JSValue js_io_mv(JSContext *js, JSValueConst this, int argc, JSValue *argv) JSValue js_io_mv(JSContext *js, JSValueConst this, int argc, JSValue *argv)
{ {
char *f1, f2; char *f1, *f2;
f1 = JS_ToCString(js, argv[0]); f1 = JS_ToCString(js, argv[0]);
f2 = JS_ToCString(js, argv[1]); f2 = JS_ToCString(js, argv[1]);
JSValue ret = int2js(rename(f1,f2)); JSValue ret = int2js(rename(f1,f2));
@ -1962,6 +1973,14 @@ JSValue js_io_mv(JSContext *js, JSValueConst this, int argc, JSValue *argv)
return ret; return ret;
} }
JSValue js_io_chdir(JSContext *js, JSValueConst this, int argc, JSValue *argv)
{
char *path = JS_ToCString(js, argv[0]);
JSValue ret = int2js(chdir(path));
JS_FreeCString(js,path);
return ret;
}
JSValue js_io_rm(JSContext *js, JSValueConst this, int argc, JSValue *argv) JSValue js_io_rm(JSContext *js, JSValueConst this, int argc, JSValue *argv)
{ {
char *file = JS_ToCString(js, argv[0]); char *file = JS_ToCString(js, argv[0]);
@ -2036,6 +2055,7 @@ static const JSCFunctionListEntry js_io_funcs[] = {
MIST_CFUNC_DEF("cp", 2, js_io_cp), MIST_CFUNC_DEF("cp", 2, js_io_cp),
MIST_CFUNC_DEF("mv", 2, js_io_mv), MIST_CFUNC_DEF("mv", 2, js_io_mv),
MIST_CFUNC_DEF("rm", 1, js_io_rm), MIST_CFUNC_DEF("rm", 1, js_io_rm),
MIST_CFUNC_DEF("chdir", 1, js_io_chdir),
MIST_CFUNC_DEF("mkdir", 1, js_io_mkdir), MIST_CFUNC_DEF("mkdir", 1, js_io_mkdir),
MIST_CFUNC_DEF("chmod", 2, js_io_chmod), MIST_CFUNC_DEF("chmod", 2, js_io_chmod),
MIST_CFUNC_DEF("slurp", 1, js_io_slurp), MIST_CFUNC_DEF("slurp", 1, js_io_slurp),
@ -2078,7 +2098,7 @@ JSValue js_dsp_node_plugin(JSContext *js, JSValueConst this, int argc, JSValue *
return JS_UNDEFINED; return JS_UNDEFINED;
} }
JSValue js_dsp_node_unplug(JSContext *js, JSValueConst this) JSValue js_dsp_node_unplug(JSContext *js, JSValueConst this, int argc, JSValue *argv)
{ {
unplug_node(js2dsp_node(this)); unplug_node(js2dsp_node(this));
return JS_UNDEFINED; return JS_UNDEFINED;

View file

@ -75,7 +75,6 @@ void gif_rec_start(int w, int h, int cpf, int bitdepth)
.render_target = true, .render_target = true,
.width = gif.w, .width = gif.w,
.height = gif.h, .height = gif.h,
// .pixel_format = SG_PIXELFORMAT_DEPTH,
.label = "gif depth", .label = "gif depth",
}); });
@ -255,7 +254,6 @@ void render_init() {
mainwin.height = sapp_height(); mainwin.height = sapp_height();
sg_setup(&(sg_desc){ sg_setup(&(sg_desc){
.environment = sglue_environment(), .environment = sglue_environment(),
// .mtl_force_managed_storage_mode = 1,
.logger = { .func = sg_logging }, .logger = { .func = sg_logging },
.buffer_pool_size = 1024 .buffer_pool_size = 1024
}); });
@ -320,7 +318,6 @@ void render_init() {
.size = sizeof(gif_quad), .size = sizeof(gif_quad),
.data = gif_quad, .data = gif_quad,
}); });
// sg_gif.bind.fs.images[0] = crt_post.img;
sg_gif.bind.fs.samplers[0] = sg_make_sampler(&(sg_sampler_desc){}); sg_gif.bind.fs.samplers[0] = sg_make_sampler(&(sg_sampler_desc){});
/* /*
@ -365,11 +362,6 @@ void render_init() {
} }
void render_winsize()
{
// sg_gif.bind.fs.images[0] = crt_post.img;
}
static cpBody *camera = NULL; static cpBody *camera = NULL;
void set_cam_body(cpBody *body) { camera = body; } void set_cam_body(cpBody *body) { camera = body; }
cpVect cam_pos() { return camera ? cpBodyGetPosition(camera) : cpvzero; } cpVect cam_pos() { return camera ? cpBodyGetPosition(camera) : cpvzero; }
@ -382,14 +374,14 @@ HMM_Vec2 world2screen(HMM_Vec2 pos)
{ {
pos = HMM_SubV2(pos, HMM_V2(cam_pos().x, cam_pos().y)); pos = HMM_SubV2(pos, HMM_V2(cam_pos().x, cam_pos().y));
pos = HMM_ScaleV2(pos, 1.0/zoom); pos = HMM_ScaleV2(pos, 1.0/zoom);
pos = HMM_AddV2(pos, HMM_V2(mainwin.rwidth/2.0, mainwin.rheight/2.0)); pos = HMM_AddV2(pos, HMM_V2(mainwin.width/2.0, mainwin.height/2.0));
return pos; return pos;
} }
HMM_Vec2 screen2world(HMM_Vec2 pos) HMM_Vec2 screen2world(HMM_Vec2 pos)
{ {
pos = HMM_ScaleV2(pos, 1/mainwin.dpi); pos = HMM_ScaleV2(pos, 1/mainwin.dpi);
pos = HMM_SubV2(pos, HMM_V2(mainwin.rwidth/2.0, mainwin.rheight/2.0)); pos = HMM_SubV2(pos, HMM_V2(mainwin.width/2.0, mainwin.height/2.0));
pos = HMM_ScaleV2(pos, zoom); pos = HMM_ScaleV2(pos, zoom);
pos = HMM_AddV2(pos, HMM_V2(cam_pos().x, cam_pos().y)); pos = HMM_AddV2(pos, HMM_V2(cam_pos().x, cam_pos().y));
return pos; return pos;
@ -400,18 +392,64 @@ HMM_Mat4 hudproj = {0.f};
HMM_Vec3 dirl_pos = {4, 100, 20}; HMM_Vec3 dirl_pos = {4, 100, 20};
#define MODE_STRETCH 0
#define MODE_KEEP 1
#define MODE_WIDTH 2
#define MODE_HEIGHT 3
#define MODE_EXPAND 4
#define MODE_FULL 5
int aspect_mode = MODE_FULL;
void full_2d_pass(struct window *window) void full_2d_pass(struct window *window)
{ {
//////////// 2D projection float aspect = mainwin.width/mainwin.height;
float raspect = mainwin.rwidth/mainwin.rheight;
float pwidth = window->width*raspect/aspect;
float left = (window->width-pwidth)/2;
float pheight = window->height*aspect/raspect;
float top = (window->height-pheight)/2;
float usewidth, useheight;
usewidth = window->rwidth;
useheight = window->rheight;
switch(aspect_mode) {
case MODE_STRETCH:
sg_apply_viewportf(0,0,window->width,window->height,1);
break;
case MODE_WIDTH:
sg_apply_viewportf(0, top, window->width, pheight,1); // keep width
break;
case MODE_HEIGHT:
sg_apply_viewportf(left,0,pwidth, window->height,1); // keep height
break;
case MODE_KEEP:
sg_apply_viewportf(0,0,window->rwidth, window->rheight, 1); // no scaling
break;
case MODE_EXPAND:
if (aspect < raspect)
sg_apply_viewportf(0, top, window->width, pheight,1); // keep width
else
sg_apply_viewportf(left,0,pwidth, window->height,1); // keep height
break;
case MODE_FULL:
usewidth = window->width;
useheight = window->height;
break;
}
// 2D projection
cpVect pos = cam_pos(); cpVect pos = cam_pos();
projection = HMM_Orthographic_LH_NO( projection = HMM_Orthographic_LH_NO(
pos.x - zoom * window->rwidth / 2, pos.x - zoom * usewidth / 2,
pos.x + zoom * window->rwidth / 2, pos.x + zoom * usewidth / 2,
pos.y - zoom * window->rheight / 2, pos.y - zoom * useheight / 2,
pos.y + zoom * window->rheight / 2, -10000.f, 10000.f); pos.y + zoom * useheight / 2, -10000.f, 10000.f);
hudproj = HMM_Orthographic_LH_ZO(0, usewidth, 0, useheight, -1.f, 1.f);
hudproj = HMM_Orthographic_LH_ZO(0, window->rwidth, 0, window->rheight, -1.f, 1.f);
sprite_draw_all(); sprite_draw_all();
model_draw_all(); model_draw_all();
call_draw(); call_draw();
@ -458,6 +496,7 @@ void full_3d_pass(struct window *window)
} }
void openglRender(struct window *window) { void openglRender(struct window *window) {
sg_swapchain sch = sglue_swapchain();
sg_begin_pass(&(sg_pass){ sg_begin_pass(&(sg_pass){
.action = pass_action, .action = pass_action,
.swapchain = sglue_swapchain(), .swapchain = sglue_swapchain(),

View file

@ -58,7 +58,7 @@ void openglInit3d(struct window *window);
void openglRender3d(struct window *window, camera3d *camera); void openglRender3d(struct window *window, camera3d *camera);
void capture_screen(int x, int y, int w, int h, const char *path); void capture_screen(int x, int y, int w, int h, const char *path);
void render_winsize(); extern int aspect_mode;
void debug_draw_phys(int draw); void debug_draw_phys(int draw);

View file

@ -21,10 +21,18 @@
#include <ftw.h> #include <ftw.h>
#endif #endif
#define SOKOL_FETCH_IMPL
#include "sokol/sokol_fetch.h"
#include "stb_ds.h" #include "stb_ds.h"
#include "core.cdb.h" #include "core.cdb.h"
#if defined(_WIN32)
#include <direct.h>
#define mkdir(x,y) _mkdir(x)
#endif
char **prefabs; char **prefabs;
static const char *cur_ext = NULL; static const char *cur_ext = NULL;
@ -35,9 +43,41 @@ char pathbuf[MAXPATH + 1];
static struct cdb corecdb; static struct cdb corecdb;
static struct cdb game_cdb; static struct cdb game_cdb;
extern int LOADED_GAME = 0;
uint8_t *gamebuf;
static void response_cb(const sfetch_response_t *r)
{
if (r->fetched) {
cdb_initf(&game_cdb, r->data.ptr, r->data.size);
LOADED_GAME = 1;
}
if (r->finished) {
LOADED_GAME = -1;
if (r->failed) {
LOADED_GAME = -1;
}
}
}
void resources_init() { void resources_init() {
int fd = open("game.cdb", O_RDONLY); sfetch_setup(&(sfetch_desc_t){
cdb_init(&game_cdb, fd); .max_requests = 1024,
.num_channels = 4,
.num_lanes = 8,
.logger = { .func = sg_logging },
});
gamebuf = malloc(64*1024*1024);
sfetch_handle_t h = sfetch_send(&(sfetch_request_t){
.path="game.cdb",
.callback = response_cb,
.buffer = {
.ptr = gamebuf,
.size = 64*1024*1024
}
});
cdb_initf(&corecdb, core_cdb, core_cdb_len); cdb_initf(&corecdb, core_cdb, core_cdb_len);
} }
@ -106,7 +146,8 @@ char **ls(const char *path)
arrfree(ls_paths); arrfree(ls_paths);
} }
ftw(".", ls_ftw, 10);
ftw(path, ls_ftw, 10);
return ls_paths; return ls_paths;
} }
@ -215,19 +256,43 @@ int cp(const char *p1, const char *p2)
return 0; return 0;
} }
int mkpath(char *dir, mode_t mode) int mkpath(char *path, mode_t mode)
{ {
if (!dir) { char tmp[256];
errno = EINVAL; char *p = NULL;
return 1; size_t len;
} struct stat sb;
if (strlen(dir) == 1 && dir[0] == '/') strncpy(tmp, path, sizeof(tmp));
return 0; len = strlen(tmp);
if (len > 0 && tmp[len - 1] == '/')
tmp[len - 1] = 0;
// mkpath(dirname(strdupa(dir)), mode); for (p = tmp + 1; *p; p++) {
if (*p == '/') {
*p = 0;
if (stat(tmp, &sb) != 0) {
if (errno != ENOENT || mkdir(tmp, mode) != 0) {
return -1;
}
} else if (!S_ISDIR(sb.st_mode)) {
errno = ENOTDIR;
return -1;
}
*p = '/';
}
}
return mkdir(dir, mode); if (stat(tmp, &sb) != 0) {
if (errno != ENOENT || mkdir(tmp, mode) != 0) {
return -1;
}
} else if (!S_ISDIR(sb.st_mode)) {
errno = ENOTDIR;
return -1;
}
return 0;
} }
int slurp_write(const char *txt, const char *filename, size_t len) { int slurp_write(const char *txt, const char *filename, size_t len) {
@ -292,5 +357,5 @@ void pack_engine(const char *fname){
YughError("Cannot pack engine on a web build."); YughError("Cannot pack engine on a web build.");
} }
char **ls(char *path) { return NULL; } char **ls(const char *path) { return NULL; }
#endif #endif

View file

@ -6,6 +6,7 @@
#include "string.h" #include "string.h"
extern char *DATA_PATH; extern char *DATA_PATH;
extern int LOADED_GAME;
void resources_init(); void resources_init();
char *get_filename_from_path(char *path, int extension); char *get_filename_from_path(char *path, int extension);

View file

@ -0,0 +1,306 @@
/*
sokol_gfx_ext.h - extensions for sokol_gfx
https://github.com/edubart/sokol_gp
*/
#if defined(SOKOL_IMPL) && !defined(SOKOL_GFX_EXT_IMPL)
#define SOKOL_GFX_EXT_IMPL
#endif
#ifndef SOKOL_GFX_EXT_INCLUDED
#define SOKOL_GFX_EXT_INCLUDED
#ifndef SOKOL_GFX_INCLUDED
#error "Please include sokol_gfx.h before sokol_gfx_ext.h"
#endif
#include <stdbool.h>
#include <stdint.h>
SOKOL_GFX_API_DECL void sg_query_image_pixels(sg_image img_id, sg_sampler smp_id, void* pixels, int size);
SOKOL_GFX_API_DECL void sg_query_pixels(int x, int y, int w, int h, bool origin_top_left, void *pixels, int size);
#endif // SOKOL_GFX_EXT_INCLUDED
#ifdef SOKOL_GFX_EXT_IMPL
#ifndef SOKOL_GFX_EXT_IMPL_INCLUDED
#define SOKOL_GFX_EXT_IMPL_INCLUDED
#ifndef SOKOL_GFX_IMPL_INCLUDED
#error "Please include sokol_gfx.h implementation before sokol_gp.h implementation"
#endif
#if defined(_SOKOL_ANY_GL)
static void _sg_gl_query_image_pixels(_sg_image_t* img, _sg_sampler_t *smp, void* pixels) {
SOKOL_ASSERT(img->gl.target == GL_TEXTURE_2D);
SOKOL_ASSERT(0 != img->gl.tex[img->cmn.active_slot]);
#if defined(SOKOL_GLCORE33)
_sg_gl_cache_store_texture_sampler_binding(0);
_sg_gl_cache_bind_texture_sampler(0, img->gl.target, img->gl.tex[img->cmn.active_slot], smp->gl.smp);
glGetTexImage(img->gl.target, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
_SG_GL_CHECK_ERROR();
_sg_gl_cache_restore_texture_sampler_binding(0);
#else
static GLuint newFbo = 0;
GLuint oldFbo = 0;
if(newFbo == 0) {
glGenFramebuffers(1, &newFbo);
}
glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*)&oldFbo);
glBindFramebuffer(GL_FRAMEBUFFER, newFbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, img->gl.tex[img->cmn.active_slot], 0);
glReadPixels(0, 0, img->cmn.width, img->cmn.height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
glBindFramebuffer(GL_FRAMEBUFFER, oldFbo);
//glDeleteFramebuffers(1, &newFbo);
_SG_GL_CHECK_ERROR();
#endif
}
static void _sg_gl_query_pixels(int x, int y, int w, int h, bool origin_top_left, void *pixels) {
SOKOL_ASSERT(pixels);
GLuint gl_fb;
GLint dims[4];
glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*)&gl_fb);
_SG_GL_CHECK_ERROR();
glGetIntegerv(GL_VIEWPORT, dims);
int cur_height = dims[3];
y = origin_top_left ? (cur_height - (y+h)) : y;
_SG_GL_CHECK_ERROR();
#if defined(SOKOL_GLES2) // use NV extension instead
glReadBufferNV(gl_fb == 0 ? GL_BACK : GL_COLOR_ATTACHMENT0);
#else
glReadBuffer(gl_fb == 0 ? GL_BACK : GL_COLOR_ATTACHMENT0);
#endif
_SG_GL_CHECK_ERROR();
glReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
_SG_GL_CHECK_ERROR();
}
#elif defined(SOKOL_D3D11)
static inline void _sgext_d3d11_Texture2D_GetDesc(ID3D11Texture2D* self, D3D11_TEXTURE2D_DESC* pDesc) {
self->lpVtbl->GetDesc(self, pDesc);
}
static inline void _sgext_d3d11_SamplerState_GetDesc(ID3D11SamplerState* self, D3D11_SAMPLER_DESC* pDesc) {
self->lpVtbl->GetDesc(self, pDesc);
}
static inline void _sgext_d3d11_CopySubresourceRegion(ID3D11DeviceContext* self, ID3D11Resource *pDstResource, UINT DstSubresource, UINT DstX, UINT DstY, UINT DstZ, ID3D11Resource *pSrcResource, UINT SrcSubresource, const D3D11_BOX *pSrcBox) {
self->lpVtbl->CopySubresourceRegion(self, pDstResource, DstSubresource, DstX, DstY, DstZ, pSrcResource, SrcSubresource, pSrcBox);
}
static inline void _sgext_d3d11_OMGetRenderTargets(ID3D11DeviceContext* self, UINT NumViews, ID3D11RenderTargetView **ppRenderTargetViews, ID3D11DepthStencilView **ppDepthStencilView) {
self->lpVtbl->OMGetRenderTargets(self, NumViews, ppRenderTargetViews, ppDepthStencilView);
}
static inline void _sgext_d3d11_RenderTargetView_GetResource(ID3D11RenderTargetView* self, ID3D11Resource** ppResource) {
self->lpVtbl->GetResource(self, ppResource);
}
static void _sg_d3d11_query_image_pixels(_sg_image_t* img, void* pixels) {
SOKOL_ASSERT(_sg.d3d11.ctx);
SOKOL_ASSERT(img->d3d11.tex2d);
HRESULT hr;
_SOKOL_UNUSED(hr);
// create staging texture
ID3D11Texture2D* staging_tex = NULL;
D3D11_TEXTURE2D_DESC staging_desc = {
.Width = (UINT)img->cmn.width,
.Height = (UINT)img->cmn.height,
.MipLevels = 1,
.ArraySize = 1,
.Format = img->d3d11.format,
.SampleDesc = {
.Count = 1,
.Quality = 0,
},
.Usage = D3D11_USAGE_STAGING,
.BindFlags = 0,
.CPUAccessFlags = D3D11_CPU_ACCESS_READ,
.MiscFlags = 0
};
hr = _sg_d3d11_CreateTexture2D(_sg.d3d11.dev, &staging_desc, NULL, &staging_tex);
SOKOL_ASSERT(SUCCEEDED(hr));
// copy pixels to staging texture
_sgext_d3d11_CopySubresourceRegion(_sg.d3d11.ctx,
(ID3D11Resource*)staging_tex,
0, 0, 0, 0,
(ID3D11Resource*)img->d3d11.tex2d,
0, NULL);
// map the staging texture's data to CPU-accessible memory
D3D11_MAPPED_SUBRESOURCE msr = {.pData = NULL};
hr = _sg_d3d11_Map(_sg.d3d11.ctx, (ID3D11Resource*)staging_tex, 0, D3D11_MAP_READ, 0, &msr);
SOKOL_ASSERT(SUCCEEDED(hr));
memcpy(pixels, msr.pData, img->cmn.width * img->cmn.height * 4);
// unmap the texture
_sg_d3d11_Unmap(_sg.d3d11.ctx, (ID3D11Resource*)staging_tex, 0);
if(staging_tex) _sg_d3d11_Release(staging_tex);
}
static void _sg_d3d11_query_pixels(int x, int y, int w, int h, bool origin_top_left, void *pixels) {
// get current render target
ID3D11RenderTargetView* render_target_view = NULL;
_sgext_d3d11_OMGetRenderTargets(_sg.d3d11.ctx, 1, &render_target_view, NULL);
// fallback to window render target
if(!render_target_view)
render_target_view = (ID3D11RenderTargetView*)_sg.d3d11.cur_pass.render_view;
SOKOL_ASSERT(render_target_view);
// get the back buffer texture
ID3D11Texture2D *back_buffer = NULL;
_sgext_d3d11_RenderTargetView_GetResource(render_target_view, (ID3D11Resource**)&back_buffer);
SOKOL_ASSERT(back_buffer);
// create a staging texture to copy the screen's data to
D3D11_TEXTURE2D_DESC staging_desc;
_sgext_d3d11_Texture2D_GetDesc(back_buffer, &staging_desc);
staging_desc.Width = w;
staging_desc.Height = h;
staging_desc.BindFlags = 0;
staging_desc.MiscFlags = 0;
staging_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
staging_desc.Usage = D3D11_USAGE_STAGING;
ID3D11Texture2D *staging_tex = NULL;
HRESULT hr = _sg_d3d11_CreateTexture2D(_sg.d3d11.dev, &staging_desc, NULL, &staging_tex);
SOKOL_ASSERT(SUCCEEDED(hr));
_SOKOL_UNUSED(hr);
// copy the desired portion of the back buffer to the staging texture
// y = (origin_top_left ? y : (_sg.d3d11.cur_height - (y + h)));
D3D11_BOX src_box = {
.left = (UINT)x,
.top = (UINT)y,
.front = 0,
.right = (UINT)(x + w),
.bottom = (UINT)(y + w),
.back = 1,
};
_sgext_d3d11_CopySubresourceRegion(_sg.d3d11.ctx,
(ID3D11Resource*)staging_tex,
0, 0, 0, 0,
(ID3D11Resource*)back_buffer,
0, &src_box);
// map the staging texture's data to CPU-accessible memory
D3D11_MAPPED_SUBRESOURCE msr = {.pData = NULL};
hr = _sg_d3d11_Map(_sg.d3d11.ctx, (ID3D11Resource*)staging_tex, 0, D3D11_MAP_READ, 0, &msr);
SOKOL_ASSERT(SUCCEEDED(hr));
memcpy(pixels, msr.pData, w * h * 4);
// unmap the texture
_sg_d3d11_Unmap(_sg.d3d11.ctx, (ID3D11Resource*)staging_tex, 0);
if(back_buffer) _sg_d3d11_Release(back_buffer);
if(staging_tex) _sg_d3d11_Release(staging_tex);
}
#elif defined(SOKOL_METAL)
#ifdef TARGET_OS_IPHONE
static void _sg_metal_commit_command_buffer(){};
static void _sg_metal_encode_texture_pixels(int x, int y, int w, int h, bool origin_top_left, id<MTLTexture> mtl_src_texture, void* pixels) {};
static void _sg_metal_query_image_pixels(_sg_image_t* img, void* pixels) {};
static void _sg_metal_query_pixels(int x, int y, int w, int h, bool origin_top_left, void *pixels) {};
#else
#import <Metal/Metal.h>
#import <QuartzCore/CAMetalLayer.h>
static void _sg_metal_commit_command_buffer() {
SOKOL_ASSERT(!_sg.mtl.in_pass);
if(_sg.mtl.cmd_buffer) {
#if defined(_SG_TARGET_MACOS)
[_sg.mtl.uniform_buffers[_sg.mtl.cur_frame_rotate_index] didModifyRange:NSMakeRange(0, _sg.mtl.cur_ub_offset)];
#endif
[_sg.mtl.cmd_buffer commit];
[_sg.mtl.cmd_buffer waitUntilCompleted];
_sg.mtl.cmd_buffer = [_sg.mtl.cmd_queue commandBufferWithUnretainedReferences];
}
}
static void _sg_metal_encode_texture_pixels(int x, int y, int w, int h, bool origin_top_left, id<MTLTexture> mtl_src_texture, void* pixels) {
SOKOL_ASSERT(!_sg.mtl.in_pass);
_sg_metal_commit_command_buffer();
MTLTextureDescriptor* mtl_dst_texture_desc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:mtl_src_texture.pixelFormat width:w height:h mipmapped:NO];
mtl_dst_texture_desc.storageMode = MTLStorageModeManaged;
mtl_dst_texture_desc.resourceOptions = MTLResourceStorageModeManaged;
mtl_dst_texture_desc.usage = MTLTextureUsageShaderRead + MTLTextureUsageShaderWrite;
id<MTLTexture> mtl_dst_texture = [mtl_src_texture.device newTextureWithDescriptor:mtl_dst_texture_desc];
id<MTLCommandBuffer> cmd_buffer = [_sg.mtl.cmd_queue commandBuffer];
id<MTLBlitCommandEncoder> blit_encoder = [cmd_buffer blitCommandEncoder];
[blit_encoder copyFromTexture:mtl_src_texture
sourceSlice:0
sourceLevel:0
sourceOrigin:MTLOriginMake(x,(origin_top_left ? y : (mtl_src_texture.height - (y + h))),0)
sourceSize:MTLSizeMake(w,h,1)
toTexture:mtl_dst_texture
destinationSlice:0
destinationLevel:0
destinationOrigin:MTLOriginMake(0,0,0)
];
[blit_encoder synchronizeTexture:mtl_dst_texture slice:0 level:0];
[blit_encoder endEncoding];
[cmd_buffer commit];
[cmd_buffer waitUntilCompleted];
MTLRegion mtl_region = MTLRegionMake2D(0, 0, w, h);
[mtl_dst_texture getBytes:pixels bytesPerRow:w * 4 fromRegion:mtl_region mipmapLevel:0];
}
static void _sg_metal_query_image_pixels(_sg_image_t* img, void* pixels) {
id<MTLTexture> mtl_src_texture = _sg.mtl.idpool.pool[img->mtl.tex[0]];
_sg_metal_encode_texture_pixels(0, 0, mtl_src_texture.width, mtl_src_texture.height, true, mtl_src_texture, pixels);
}
static void _sg_metal_query_pixels(int x, int y, int w, int h, bool origin_top_left, void *pixels) {
id<CAMetalDrawable> mtl_drawable = (__bridge id<CAMetalDrawable>)_sg.mtl.drawable_cb();
_sg_metal_encode_texture_pixels(x, y, w, h, origin_top_left, mtl_drawable.texture, pixels);
}
#endif
#endif
void sg_query_image_pixels(sg_image img_id, sg_sampler smp_id, void* pixels, int size) {
SOKOL_ASSERT(pixels);
SOKOL_ASSERT(img_id.id != SG_INVALID_ID);
_sg_image_t* img = _sg_lookup_image(&_sg.pools, img_id.id);
_sg_sampler_t *smp = _sg_lookup_sampler(&_sg.pools, smp_id.id);
SOKOL_ASSERT(img);
SOKOL_ASSERT(size >= (img->cmn.width * img->cmn.height * 4));
_SOKOL_UNUSED(size);
#if defined(_SOKOL_ANY_GL)
_sg_gl_query_image_pixels(img, smp, pixels);
#elif defined(SOKOL_D3D11)
_sg_d3d11_query_image_pixels(img, pixels);
#elif defined(SOKOL_METAL)
_sg_metal_query_image_pixels(img, pixels);
#endif
}
void sg_query_pixels(int x, int y, int w, int h, bool origin_top_left, void *pixels, int size) {
SOKOL_ASSERT(pixels);
SOKOL_ASSERT(size >= w*h);
_SOKOL_UNUSED(size);
#if defined(_SOKOL_ANY_GL)
_sg_gl_query_pixels(x, y, w, h, origin_top_left, pixels);
#elif defined(SOKOL_D3D11)
_sg_d3d11_query_pixels(x, y, w, h, origin_top_left, pixels);
#elif defined(SOKOL_METAL)
_sg_metal_query_pixels(x, y, w, h, origin_top_left, pixels);
#endif
}
#endif // SOKOL_GFX_EXT_IMPL_INCLUDED
#endif // SOKOL_GFX_EXT_IMPL

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -144,14 +144,9 @@ void sprite_initialize() {
[1].format = SG_VERTEXFORMAT_FLOAT2, [1].format = SG_VERTEXFORMAT_FLOAT2,
[2].format = SG_VERTEXFORMAT_UBYTE4N, [2].format = SG_VERTEXFORMAT_UBYTE4N,
[3].format = SG_VERTEXFORMAT_UBYTE4N}}, [3].format = SG_VERTEXFORMAT_UBYTE4N}},
// [4].format = SG_VERTEXFORMAT_FLOAT}},
.primitive_type = SG_PRIMITIVETYPE_TRIANGLE_STRIP, .primitive_type = SG_PRIMITIVETYPE_TRIANGLE_STRIP,
.label = "sprite pipeline", .label = "sprite pipeline",
.colors[0].blend = blend_trans, .colors[0].blend = blend_trans,
.depth = {
.write_enabled = true,
.compare = SG_COMPAREFUNC_LESS_EQUAL,
}
}); });
bind_sprite.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){ bind_sprite.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){
@ -240,7 +235,7 @@ void gui_draw_img(const char *img, transform2d t, int wrap, HMM_Vec2 wrapoffset,
sg_apply_pipeline(pip_sprite); sg_apply_pipeline(pip_sprite);
sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, SG_RANGE_REF(hudproj)); sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, SG_RANGE_REF(hudproj));
struct Texture *tex = texture_pullfromfile(img); struct Texture *tex = texture_pullfromfile(img);
tex_draw(tex, transform2d2mat(t), tex_get_rect(tex), color, wrap, wrapoffset, (HMM_Vec2){wrapscale,wrapscale}, (struct rgba){0,0,0,0}, 0); tex_draw(tex, transform2d2mat(t), ST_UNIT, color, wrap, wrapoffset, (HMM_Vec2){wrapscale,wrapscale}, (struct rgba){0,0,0,0}, 0);
} }
void slice9_draw(const char *img, HMM_Vec2 pos, HMM_Vec2 dimensions, struct rgba color) void slice9_draw(const char *img, HMM_Vec2 pos, HMM_Vec2 dimensions, struct rgba color)
@ -249,7 +244,7 @@ void slice9_draw(const char *img, HMM_Vec2 pos, HMM_Vec2 dimensions, struct rgba
sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, SG_RANGE_REF(hudproj)); sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, SG_RANGE_REF(hudproj));
struct Texture *tex = texture_pullfromfile(img); struct Texture *tex = texture_pullfromfile(img);
struct glrect r = tex_get_rect(tex); struct glrect r = ST_UNIT;
struct slice9_vert verts[4]; struct slice9_vert verts[4];

View file

@ -285,8 +285,6 @@ struct Texture *texture_fromdata(void *raw, long size)
struct Texture *texture_loadfromfile(const char *path) { return texture_pullfromfile(path); } struct Texture *texture_loadfromfile(const char *path) { return texture_pullfromfile(path); }
struct glrect tex_get_rect(struct Texture *tex) { return ST_UNIT; }
HMM_Vec2 tex_get_dimensions(struct Texture *tex) { HMM_Vec2 tex_get_dimensions(struct Texture *tex) {
if (!tex) return (HMM_Vec2){0,0}; if (!tex) return (HMM_Vec2){0,0};
HMM_Vec2 d; HMM_Vec2 d;

@ -0,0 +1 @@
Subproject commit 92a8f0e9fe3c98358be7d8564db21fc4b1142d04

1
source/engine/thirdparty/dr_libs vendored Submodule

@ -0,0 +1 @@
Subproject commit da35f9d6c7374a95353fd1df1d394d44ab66cf01

View file

@ -1,531 +0,0 @@
/* TinyMidiLoader - v0.7 - Minimalistic midi parsing library - https://github.com/schellingb/TinySoundFont
no warranty implied; use at your own risk
Do this:
#define TML_IMPLEMENTATION
before you include this file in *one* C or C++ file to create the implementation.
// i.e. it should look like this:
#include ...
#include ...
#define TML_IMPLEMENTATION
#include "tml.h"
[OPTIONAL] #define TML_NO_STDIO to remove stdio dependency
[OPTIONAL] #define TML_MALLOC, TML_REALLOC, and TML_FREE to avoid stdlib.h
[OPTIONAL] #define TML_MEMCPY to avoid string.h
LICENSE (ZLIB)
Copyright (C) 2017, 2018, 2020 Bernhard Schelling
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef TML_INCLUDE_TML_INL
#define TML_INCLUDE_TML_INL
#ifdef __cplusplus
extern "C" {
#endif
// Define this if you want the API functions to be static
#ifdef TML_STATIC
#define TMLDEF static
#else
#define TMLDEF extern
#endif
// Channel message type
enum TMLMessageType
{
TML_NOTE_OFF = 0x80, TML_NOTE_ON = 0x90, TML_KEY_PRESSURE = 0xA0, TML_CONTROL_CHANGE = 0xB0, TML_PROGRAM_CHANGE = 0xC0, TML_CHANNEL_PRESSURE = 0xD0, TML_PITCH_BEND = 0xE0, TML_SET_TEMPO = 0x51
};
// Midi controller numbers
enum TMLController
{
TML_BANK_SELECT_MSB, TML_MODULATIONWHEEL_MSB, TML_BREATH_MSB, TML_FOOT_MSB = 4, TML_PORTAMENTO_TIME_MSB, TML_DATA_ENTRY_MSB, TML_VOLUME_MSB,
TML_BALANCE_MSB, TML_PAN_MSB = 10, TML_EXPRESSION_MSB, TML_EFFECTS1_MSB, TML_EFFECTS2_MSB, TML_GPC1_MSB = 16, TML_GPC2_MSB, TML_GPC3_MSB, TML_GPC4_MSB,
TML_BANK_SELECT_LSB = 32, TML_MODULATIONWHEEL_LSB, TML_BREATH_LSB, TML_FOOT_LSB = 36, TML_PORTAMENTO_TIME_LSB, TML_DATA_ENTRY_LSB, TML_VOLUME_LSB,
TML_BALANCE_LSB, TML_PAN_LSB = 42, TML_EXPRESSION_LSB, TML_EFFECTS1_LSB, TML_EFFECTS2_LSB, TML_GPC1_LSB = 48, TML_GPC2_LSB, TML_GPC3_LSB, TML_GPC4_LSB,
TML_SUSTAIN_SWITCH = 64, TML_PORTAMENTO_SWITCH, TML_SOSTENUTO_SWITCH, TML_SOFT_PEDAL_SWITCH, TML_LEGATO_SWITCH, TML_HOLD2_SWITCH,
TML_SOUND_CTRL1, TML_SOUND_CTRL2, TML_SOUND_CTRL3, TML_SOUND_CTRL4, TML_SOUND_CTRL5, TML_SOUND_CTRL6,
TML_SOUND_CTRL7, TML_SOUND_CTRL8, TML_SOUND_CTRL9, TML_SOUND_CTRL10, TML_GPC5, TML_GPC6, TML_GPC7, TML_GPC8,
TML_PORTAMENTO_CTRL, TML_FX_REVERB = 91, TML_FX_TREMOLO, TML_FX_CHORUS, TML_FX_CELESTE_DETUNE, TML_FX_PHASER,
TML_DATA_ENTRY_INCR, TML_DATA_ENTRY_DECR, TML_NRPN_LSB, TML_NRPN_MSB, TML_RPN_LSB, TML_RPN_MSB,
TML_ALL_SOUND_OFF = 120, TML_ALL_CTRL_OFF, TML_LOCAL_CONTROL, TML_ALL_NOTES_OFF, TML_OMNI_OFF, TML_OMNI_ON, TML_POLY_OFF, TML_POLY_ON
};
// A single MIDI message linked to the next message in time
typedef struct tml_message
{
// Time of the message in milliseconds
unsigned int time;
// Type (see TMLMessageType) and channel number
unsigned char type, channel;
// 2 byte of parameter data based on the type:
// - key, velocity for TML_NOTE_ON and TML_NOTE_OFF messages
// - key, key_pressure for TML_KEY_PRESSURE messages
// - control, control_value for TML_CONTROL_CHANGE messages (see TMLController)
// - program for TML_PROGRAM_CHANGE messages
// - channel_pressure for TML_CHANNEL_PRESSURE messages
// - pitch_bend for TML_PITCH_BEND messages
union
{
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4201) //nonstandard extension used: nameless struct/union
#elif defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic" //ISO C++ prohibits anonymous structs
#endif
struct { union { char key, control, program, channel_pressure; }; union { char velocity, key_pressure, control_value; }; };
struct { unsigned short pitch_bend; };
#ifdef _MSC_VER
#pragma warning( pop )
#elif defined(__GNUC__)
#pragma GCC diagnostic pop
#endif
};
// The pointer to the next message in time following this event
struct tml_message* next;
} tml_message;
// The load functions will return a pointer to a struct tml_message.
// Normally the linked list gets traversed by following the next pointers.
// Make sure to keep the pointer to the first message to free the memory.
// On error the tml_load* functions will return NULL most likely due to an
// invalid MIDI stream (or if the file did not exist in tml_load_filename).
#ifndef TML_NO_STDIO
// Directly load a MIDI file from a .mid file path
TMLDEF tml_message* tml_load_filename(const char* filename);
#endif
// Load a MIDI file from a block of memory
TMLDEF tml_message* tml_load_memory(const void* buffer, int size);
// Get infos about this loaded MIDI file, returns the note count
// NULL can be passed for any output value pointer if not needed.
// used_channels: Will be set to how many channels play notes
// (i.e. 1 if channel 15 is used but no other)
// used_programs: Will be set to how many different programs are used
// total_notes: Will be set to the total number of note on messages
// time_first_note: Will be set to the time of the first note on message
// time_length: Will be set to the total time in milliseconds
TMLDEF int tml_get_info(tml_message* first_message, int* used_channels, int* used_programs, int* total_notes, unsigned int* time_first_note, unsigned int* time_length);
// Read the tempo (microseconds per quarter note) value from a message with the type TML_SET_TEMPO
TMLDEF int tml_get_tempo_value(tml_message* set_tempo_message);
// Free all the memory of the linked message list (can also call free() manually)
TMLDEF void tml_free(tml_message* f);
// Stream structure for the generic loading
struct tml_stream
{
// Custom data given to the functions as the first parameter
void* data;
// Function pointer will be called to read 'size' bytes into ptr (returns number of read bytes)
int (*read)(void* data, void* ptr, unsigned int size);
};
// Generic Midi loading method using the stream structure above
TMLDEF tml_message* tml_load(struct tml_stream* stream);
// If this library is used together with TinySoundFont, tsf_stream (equivalent to tml_stream) can also be used
struct tsf_stream;
TMLDEF tml_message* tml_load_tsf_stream(struct tsf_stream* stream);
#ifdef __cplusplus
}
#endif
// end header
// ---------------------------------------------------------------------------------------------------------
#endif //TML_INCLUDE_TML_INL
#ifdef TML_IMPLEMENTATION
#if !defined(TML_MALLOC) || !defined(TML_FREE) || !defined(TML_REALLOC)
# include <stdlib.h>
# define TML_MALLOC malloc
# define TML_FREE free
# define TML_REALLOC realloc
#endif
#if !defined(TML_MEMCPY)
# include <string.h>
# define TML_MEMCPY memcpy
#endif
#ifndef TML_NO_STDIO
# include <stdio.h>
#endif
#define TML_NULL 0
////crash on errors and warnings to find broken midi files while debugging
//#define TML_ERROR(msg) *(int*)0 = 0xbad;
//#define TML_WARN(msg) *(int*)0 = 0xf00d;
////print errors and warnings
//#define TML_ERROR(msg) printf("ERROR: %s\n", msg);
//#define TML_WARN(msg) printf("WARNING: %s\n", msg);
#ifndef TML_ERROR
#define TML_ERROR(msg)
#endif
#ifndef TML_WARN
#define TML_WARN(msg)
#endif
#ifdef __cplusplus
extern "C" {
#endif
#ifndef TML_NO_STDIO
static int tml_stream_stdio_read(FILE* f, void* ptr, unsigned int size) { return (int)fread(ptr, 1, size, f); }
TMLDEF tml_message* tml_load_filename(const char* filename)
{
struct tml_message* res;
struct tml_stream stream = { TML_NULL, (int(*)(void*,void*,unsigned int))&tml_stream_stdio_read };
#if __STDC_WANT_SECURE_LIB__
FILE* f = TML_NULL; fopen_s(&f, filename, "rb");
#else
FILE* f = fopen(filename, "rb");
#endif
if (!f) { TML_ERROR("File not found"); return 0; }
stream.data = f;
res = tml_load(&stream);
fclose(f);
return res;
}
#endif
struct tml_stream_memory { const char* buffer; unsigned int total, pos; };
static int tml_stream_memory_read(struct tml_stream_memory* m, void* ptr, unsigned int size) { if (size > m->total - m->pos) size = m->total - m->pos; TML_MEMCPY(ptr, m->buffer+m->pos, size); m->pos += size; return size; }
TMLDEF struct tml_message* tml_load_memory(const void* buffer, int size)
{
struct tml_stream stream = { TML_NULL, (int(*)(void*,void*,unsigned int))&tml_stream_memory_read };
struct tml_stream_memory f = { 0, 0, 0 };
f.buffer = (const char*)buffer;
f.total = size;
stream.data = &f;
return tml_load(&stream);
}
struct tml_track
{
unsigned int Idx, End, Ticks;
};
struct tml_tempomsg
{
unsigned int time;
unsigned char type, Tempo[3];
tml_message* next;
};
struct tml_parser
{
unsigned char *buf, *buf_end;
int last_status, message_array_size, message_count;
};
enum TMLSystemType
{
TML_TEXT = 0x01, TML_COPYRIGHT = 0x02, TML_TRACK_NAME = 0x03, TML_INST_NAME = 0x04, TML_LYRIC = 0x05, TML_MARKER = 0x06, TML_CUE_POINT = 0x07,
TML_EOT = 0x2f, TML_SMPTE_OFFSET = 0x54, TML_TIME_SIGNATURE = 0x58, TML_KEY_SIGNATURE = 0x59, TML_SEQUENCER_EVENT = 0x7f,
TML_SYSEX = 0xf0, TML_TIME_CODE = 0xf1, TML_SONG_POSITION = 0xf2, TML_SONG_SELECT = 0xf3, TML_TUNE_REQUEST = 0xf6, TML_EOX = 0xf7, TML_SYNC = 0xf8,
TML_TICK = 0xf9, TML_START = 0xfa, TML_CONTINUE = 0xfb, TML_STOP = 0xfc, TML_ACTIVE_SENSING = 0xfe, TML_SYSTEM_RESET = 0xff
};
static int tml_readbyte(struct tml_parser* p)
{
return (p->buf == p->buf_end ? -1 : *(p->buf++));
}
static int tml_readvariablelength(struct tml_parser* p)
{
unsigned int res = 0, i = 0;
unsigned char c;
for (; i != 4; i++)
{
if (p->buf == p->buf_end) { TML_WARN("Unexpected end of file"); return -1; }
c = *(p->buf++);
if (c & 0x80) res = ((res | (c & 0x7F)) << 7);
else return (int)(res | c);
}
TML_WARN("Invalid variable length byte count"); return -1;
}
static int tml_parsemessage(tml_message** f, struct tml_parser* p)
{
int deltatime = tml_readvariablelength(p), status = tml_readbyte(p);
tml_message* evt;
if (deltatime & 0xFFF00000) deltatime = 0; //throw away delays that are insanely high for malformatted midis
if (status < 0) { TML_WARN("Unexpected end of file"); return -1; }
if ((status & 0x80) == 0)
{
// Invalid, use same status as before
if ((p->last_status & 0x80) == 0) { TML_WARN("Undefined status and invalid running status"); return -1; }
p->buf--;
status = p->last_status;
}
else p->last_status = status;
if (p->message_array_size == p->message_count)
{
//start allocated memory size of message array at 64, double each time until 8192, then add 1024 entries until done
p->message_array_size += (!p->message_array_size ? 64 : (p->message_array_size > 4096 ? 1024 : p->message_array_size));
*f = (tml_message*)TML_REALLOC(*f, p->message_array_size * sizeof(tml_message));
if (!*f) { TML_ERROR("Out of memory"); return -1; }
}
evt = *f + p->message_count;
//check what message we have
if ((status == TML_SYSEX) || (status == TML_EOX)) //sysex
{
//sysex messages are not handled
p->buf += tml_readvariablelength(p);
if (p->buf > p->buf_end) { TML_WARN("Unexpected end of file"); p->buf = p->buf_end; return -1; }
evt->type = 0;
}
else if (status == 0xFF) //meta events
{
int meta_type = tml_readbyte(p), buflen = tml_readvariablelength(p);
unsigned char* metadata = p->buf;
if (meta_type < 0) { TML_WARN("Unexpected end of file"); return -1; }
if (buflen > 0 && (p->buf += buflen) > p->buf_end) { TML_WARN("Unexpected end of file"); p->buf = p->buf_end; return -1; }
switch (meta_type)
{
case TML_EOT:
if (buflen != 0) { TML_WARN("Invalid length for EndOfTrack event"); return -1; }
if (!deltatime) return TML_EOT; //no need to store this message
evt->type = TML_EOT;
break;
case TML_SET_TEMPO:
if (buflen != 3) { TML_WARN("Invalid length for SetTempo meta event"); return -1; }
evt->type = TML_SET_TEMPO;
((struct tml_tempomsg*)evt)->Tempo[0] = metadata[0];
((struct tml_tempomsg*)evt)->Tempo[1] = metadata[1];
((struct tml_tempomsg*)evt)->Tempo[2] = metadata[2];
break;
default:
evt->type = 0;
}
}
else //channel message
{
int param;
if ((param = tml_readbyte(p)) < 0) { TML_WARN("Unexpected end of file"); return -1; }
evt->key = (param & 0x7f);
evt->channel = (status & 0x0f);
switch (evt->type = (status & 0xf0))
{
case TML_NOTE_OFF:
case TML_NOTE_ON:
case TML_KEY_PRESSURE:
case TML_CONTROL_CHANGE:
if ((param = tml_readbyte(p)) < 0) { TML_WARN("Unexpected end of file"); return -1; }
evt->velocity = (param & 0x7f);
break;
case TML_PITCH_BEND:
if ((param = tml_readbyte(p)) < 0) { TML_WARN("Unexpected end of file"); return -1; }
evt->pitch_bend = ((param & 0x7f) << 7) | evt->key;
break;
case TML_PROGRAM_CHANGE:
case TML_CHANNEL_PRESSURE:
evt->velocity = 0;
break;
default: //ignore system/manufacture messages
evt->type = 0;
break;
}
}
if (deltatime || evt->type)
{
evt->time = deltatime;
p->message_count++;
}
return evt->type;
}
TMLDEF tml_message* tml_load(struct tml_stream* stream)
{
int num_tracks, division, trackbufsize = 0;
unsigned char midi_header[14], *trackbuf = TML_NULL;
struct tml_message* messages = TML_NULL;
struct tml_track *tracks, *t, *tracksEnd;
struct tml_parser p = { TML_NULL, TML_NULL, 0, 0, 0 };
// Parse MIDI header
if (stream->read(stream->data, midi_header, 14) != 14) { TML_ERROR("Unexpected end of file"); return messages; }
if (midi_header[0] != 'M' || midi_header[1] != 'T' || midi_header[2] != 'h' || midi_header[3] != 'd' ||
midi_header[7] != 6 || midi_header[9] > 2) { TML_ERROR("Doesn't look like a MIDI file: invalid MThd header"); return messages; }
if (midi_header[12] & 0x80) { TML_ERROR("File uses unsupported SMPTE timing"); return messages; }
num_tracks = (int)(midi_header[10] << 8) | midi_header[11];
division = (int)(midi_header[12] << 8) | midi_header[13]; //division is ticks per beat (quarter-note)
if (num_tracks <= 0 && division <= 0) { TML_ERROR("Doesn't look like a MIDI file: invalid track or division values"); return messages; }
// Allocate temporary tracks array for parsing
tracks = (struct tml_track*)TML_MALLOC(sizeof(struct tml_track) * num_tracks);
tracksEnd = &tracks[num_tracks];
for (t = tracks; t != tracksEnd; t++) t->Idx = t->End = t->Ticks = 0;
// Read all messages for all tracks
for (t = tracks; t != tracksEnd; t++)
{
unsigned char track_header[8];
int track_length;
if (stream->read(stream->data, track_header, 8) != 8) { TML_WARN("Unexpected end of file"); break; }
if (track_header[0] != 'M' || track_header[1] != 'T' || track_header[2] != 'r' || track_header[3] != 'k')
{ TML_WARN("Invalid MTrk header"); break; }
// Get size of track data and read into buffer (allocate bigger buffer if needed)
track_length = track_header[7] | (track_header[6] << 8) | (track_header[5] << 16) | (track_header[4] << 24);
if (track_length < 0) { TML_WARN("Invalid MTrk header"); break; }
if (trackbufsize < track_length) { TML_FREE(trackbuf); trackbuf = (unsigned char*)TML_MALLOC(trackbufsize = track_length); }
if (stream->read(stream->data, trackbuf, track_length) != track_length) { TML_WARN("Unexpected end of file"); break; }
t->Idx = p.message_count;
for (p.buf_end = (p.buf = trackbuf) + track_length; p.buf != p.buf_end;)
{
int type = tml_parsemessage(&messages, &p);
if (type == TML_EOT || type < 0) break; //file end or illegal data encountered
}
if (p.buf != p.buf_end) { TML_WARN( "Track length did not match data length"); }
t->End = p.message_count;
}
TML_FREE(trackbuf);
// Change message time signature from delta ticks to actual msec values and link messages ordered by time
if (p.message_count)
{
tml_message *PrevMessage = TML_NULL, *Msg, *MsgEnd, Swap;
unsigned int ticks = 0, tempo_ticks = 0; //tick counter and value at last tempo change
int step_smallest, msec, tempo_msec = 0; //msec value at last tempo change
double ticks2time = 500000 / (1000.0 * division); //milliseconds per tick
// Loop through all messages over all tracks ordered by time
for (step_smallest = 0; step_smallest != 0x7fffffff; ticks += step_smallest)
{
step_smallest = 0x7fffffff;
msec = tempo_msec + (int)((ticks - tempo_ticks) * ticks2time);
for (t = tracks; t != tracksEnd; t++)
{
if (t->Idx == t->End) continue;
for (Msg = &messages[t->Idx], MsgEnd = &messages[t->End]; Msg != MsgEnd && t->Ticks + Msg->time == ticks; Msg++, t->Idx++)
{
t->Ticks += Msg->time;
if (Msg->type == TML_SET_TEMPO)
{
unsigned char* Tempo = ((struct tml_tempomsg*)Msg)->Tempo;
ticks2time = ((Tempo[0]<<16)|(Tempo[1]<<8)|Tempo[2])/(1000.0 * division);
tempo_msec = msec;
tempo_ticks = ticks;
}
if (Msg->type)
{
Msg->time = msec;
if (PrevMessage) { PrevMessage->next = Msg; PrevMessage = Msg; }
else { Swap = *Msg; *Msg = *messages; *messages = Swap; PrevMessage = messages; }
}
}
if (Msg != MsgEnd && t->Ticks + Msg->time > ticks)
{
int step = (int)(t->Ticks + Msg->time - ticks);
if (step < step_smallest) step_smallest = step;
}
}
}
if (PrevMessage) PrevMessage->next = TML_NULL;
else p.message_count = 0;
}
TML_FREE(tracks);
if (p.message_count == 0)
{
TML_FREE(messages);
messages = TML_NULL;
}
return messages;
}
TMLDEF tml_message* tml_load_tsf_stream(struct tsf_stream* stream)
{
return tml_load((struct tml_stream*)stream);
}
TMLDEF int tml_get_info(tml_message* Msg, int* out_used_channels, int* out_used_programs, int* out_total_notes, unsigned int* out_time_first_note, unsigned int* out_time_length)
{
int used_programs = 0, used_channels = 0, total_notes = 0;
unsigned int time_first_note = 0xffffffff, time_length = 0;
unsigned char channels[16] = { 0 }, programs[128] = { 0 };
for (;Msg; Msg = Msg->next)
{
time_length = Msg->time;
if (Msg->type == TML_PROGRAM_CHANGE && !programs[(int)Msg->program]) { programs[(int)Msg->program] = 1; used_programs++; }
if (Msg->type != TML_NOTE_ON) continue;
if (time_first_note == 0xffffffff) time_first_note = time_length;
if (!channels[Msg->channel]) { channels[Msg->channel] = 1; used_channels++; }
total_notes++;
}
if (time_first_note == 0xffffffff) time_first_note = 0;
if (out_used_channels ) *out_used_channels = used_channels;
if (out_used_programs ) *out_used_programs = used_programs;
if (out_total_notes ) *out_total_notes = total_notes;
if (out_time_first_note) *out_time_first_note = time_first_note;
if (out_time_length ) *out_time_length = time_length;
return total_notes;
}
TMLDEF int tml_get_tempo_value(tml_message* msg)
{
unsigned char* Tempo;
if (!msg || msg->type != TML_SET_TEMPO) return 0;
Tempo = ((struct tml_tempomsg*)msg)->Tempo;
return ((Tempo[0]<<16)|(Tempo[1]<<8)|Tempo[2]);
}
TMLDEF void tml_free(tml_message* f)
{
TML_FREE(f);
}
#ifdef __cplusplus
}
#endif
#endif //TML_IMPLEMENTATION

File diff suppressed because it is too large Load diff

View file

@ -26,10 +26,11 @@ void window_resize(int width, int height)
mainwin.dpi = sapp_dpi_scale(); mainwin.dpi = sapp_dpi_scale();
mainwin.width = sapp_width(); mainwin.width = sapp_width();
mainwin.height = sapp_height(); mainwin.height = sapp_height();
mainwin.rwidth = mainwin.width/mainwin.dpi;
mainwin.rheight = mainwin.height/mainwin.dpi;
render_winsize(); float aspect = mainwin.width/mainwin.height;
float raspect = mainwin.rwidth/mainwin.rheight;
mainwin.pheight = mainwin.rheight;
mainwin.pwidth = mainwin.rwidth*aspect/raspect;
JSValue vals[2] = { int2js(width), int2js(height) }; JSValue vals[2] = { int2js(width), int2js(height) };
send_signal("window_resize", 2, vals); send_signal("window_resize", 2, vals);

View file

@ -3,11 +3,10 @@
struct window { struct window {
int id; int id;
int width; float width, height; // The actual width and height of the window
int height; float rwidth, rheight; // The desired rendering resolution, what the assets are at
float pwidth, pheight; // The calculated width and height passed to rendering
double dpi; double dpi;
int rwidth;
int rheight;
int render; int render;
int mouseFocus; int mouseFocus;
int keyboardFocus; int keyboardFocus;

View file

@ -46,6 +46,7 @@
#include "sokol/sokol_audio.h" #include "sokol/sokol_audio.h"
#include "sokol/sokol_time.h" #include "sokol/sokol_time.h"
#include "sokol/sokol_args.h" #include "sokol/sokol_args.h"
#include "sokol/sokol_fetch.h"
#include <stb_ds.h> #include <stb_ds.h>
#include <stb_truetype.h> #include <stb_truetype.h>
#include "stb_image.h" #include "stb_image.h"
@ -153,6 +154,7 @@ void c_frame()
} }
void c_clean() { void c_clean() {
sfetch_shutdown();
gif_rec_end("out.gif"); gif_rec_end("out.gif");
out_memusage(".prosperon/jsmem.txt"); out_memusage(".prosperon/jsmem.txt");
script_stop(); script_stop();
@ -280,26 +282,6 @@ int main(int argc, char **argv) {
signal(SIGFPE, seghandle); signal(SIGFPE, seghandle);
// signal(SIGBUS, seghandle); // signal(SIGBUS, seghandle);
#endif
#ifdef STEAM
steaminit();
#endif
#ifdef DISCORD
struct IDiscordCore *core;
DiscordCreate(DISCORD_VERSION, &(struct DiscordCreateParams){
.client_id = 1176355046590533714,
.flags = DiscordCreateFlags_Default
}, &core);
struct IDiscordUserManager *dum;
struct IDiscordActivityManager *dam;
dam = core->get_activity_manager(core);
struct DiscordActivity da;
sprintf(da.state, "Playing Solo Pinball");
sprintf(da.details, "COMPetitive");
dam->update_activity(dam, &da, NULL, NULL);
#endif #endif
resources_init(); resources_init();
@ -319,6 +301,10 @@ dam->update_activity(dam, &da, NULL, NULL);
strcat(cmdstr, argv[i]); strcat(cmdstr, argv[i]);
if (argc > i+1) strcat(cmdstr, " "); if (argc > i+1) strcat(cmdstr, " ");
} }
while (!LOADED_GAME)
sfetch_dowork();
script_evalf("cmd_args('%s');", cmdstr); script_evalf("cmd_args('%s');", cmdstr);
out_memusage(".prosperon/jsmem.txt"); out_memusage(".prosperon/jsmem.txt");

View file

@ -8,7 +8,6 @@ in vec4 vColor;
out vec2 TexCoords; out vec2 TexCoords;
out vec4 fColor; out vec4 fColor;
out vec2 fst;
uniform vs_params { mat4 projection; }; uniform vs_params { mat4 projection; };
@ -17,7 +16,6 @@ void main()
gl_Position = projection * vec4(pos + (vert * wh), 0.0, 1.0); gl_Position = projection * vec4(pos + (vert * wh), 0.0, 1.0);
TexCoords = uv + vec2(vert.x*st.x, st.y - vert.y*st.y); TexCoords = uv + vec2(vert.x*st.x, st.y - vert.y*st.y);
fst = st / wh;
fColor = vColor; fColor = vColor;
} }
@ -26,49 +24,17 @@ void main()
@fs fs @fs fs
in vec2 TexCoords; in vec2 TexCoords;
in vec4 fColor; in vec4 fColor;
in vec2 fst;
out vec4 color; out vec4 color;
uniform texture2D text; uniform texture2D text;
uniform sampler smp; uniform sampler smp;
float osize = 1.0;
void main() void main()
{ {
float lettera = texture(sampler2D(text,smp),TexCoords).r; float lettera = texture(sampler2D(text,smp),TexCoords).r;
if (lettera < 0.1f) discard;
if (lettera <= 0.1f) color = fColor;
{
vec2 uvpos = TexCoords - fst;
for (int x = 0; x < 3; x++) {
for (int y = 0; y < 3; y++) {
float pa = texture(sampler2D(text,smp), uvpos + (fst*vec2(x,y))).r;
if (pa > 0.1) {
color = vec4(0.0,0.0,0.0, fColor.a);
return;
}
}
}
discard;
}
// vec2 lsize = fst / textureSize(dtext,0).xy;
/* vec2 uvpos = TexCoords - fst;
for (int x = 0; x < 3; x++) {
for (int y = 0; 0 < 3; y++) {
float pa = texture(sampler2D(text,smp), uvpos + (fst * vec2(x,y))).r;
if (pa <= 0.1) {
color = vec4(0.0,0.0,0.0,fColor.a);
return;
}
}
}
*/
color = vec4(fColor.xyz, fColor.a);
} }
@end @end

View file

@ -1,40 +0,0 @@
var binds = [];
var cbs = [];
var fats = [];
var count = 1000000;
var a = {
n: 1
}
function test_a() {
this.n++;
}
var start = Date.now();
for (var i = 0; i < count; i++)
binds.push(test_a.bind(a));
console.log(`Make bind time: ${Date.now()-start} ms`);
start = Date.now();
for (var i = 0; i < count; i++)
fats.push(() => test_a.call(a));
console.log(`Make fat time: ${Date.now()-start} ms`);
start = Date.now();
for (var i = 0; i < count; i++) {
binds[i]();
}
console.log(`Bind time: ${Date.now()-start} ms`);
start = Date.now();
for (var i = 0; i < count; i++) {
fats[i]();
}
console.log(`Fat time: ${Date.now()-start} ms`);
start = Date.now();
for (var i = 0; i < count; i++)
test_a.call(a);
console.log(`Call time: ${Date.now()-start} ms`);

View file

@ -1,24 +0,0 @@
var binds = [];
var a = {
n: 1,
test() { this.n++; }
};
var count = 10000000;
var start = Date.now();
for (var i = 0; i < count; i++)
binds.push(a.test.bind(a));
console.log(`Make bind time: ${Date.now()-start} ms`);
start = Date.now();
for (var i = 0; i < count; i++)
binds[i]();
console.log(`Bind time: ${Date.now()-start} ms`);
start = Date.now();
for (var i = 0; i < count; i++)
a['test']();
console.log(`Call time: ${Date.now()-start} ms`);