diff --git a/templates/lv2-make/Makefile b/templates/lv2-make/Makefile index 29b03d0..2ff90dc 100644 --- a/templates/lv2-make/Makefile +++ b/templates/lv2-make/Makefile @@ -5,6 +5,7 @@ ifeq ($(OS), Windows_NT) LV2DIR = $(shell echo '${COMMONPROGRAMFILES}' | sed 's:\\:/:g')/LV2 LV2DIR_USER = $(shell echo '${APPDATA}' | sed 's:\\:/:g')/LV2 CC = gcc + CXX = g++ else UNAME_S = $(shell uname -s) ifeq ($(UNAME_S), Darwin) @@ -12,12 +13,14 @@ else LV2DIR = /Library/Audio/Plug-Ins/LV2 LV2DIR_USER = ${HOME}/Library/Audio/Plug-Ins/LV2 CC = clang + CXX = clang++ else DLL_SUFFIX = .so PREFIX = /usr/local LV2DIR = ${PREFIX}/lib/lv2 LV2DIR_USER = ${HOME}/.lv2 CC = gcc + CXX = g++ endif endif diff --git a/templates/vst3-make/Makefile b/templates/vst3-make/Makefile index 8b6aad5..5f22ee3 100644 --- a/templates/vst3-make/Makefile +++ b/templates/vst3-make/Makefile @@ -6,6 +6,7 @@ ifeq ($(OS), Windows_NT) VST3DIR = $(shell echo '${COMMONPROGRAMFILES}' | sed 's:\\:/:g')/VST3 VST3DIR_USER = $(shell echo '${LOCALAPPDATA}' | sed 's:\\:/:g')/Programs/Common/VST3 CC = gcc + CXX = g++ else UNAME_S = $(shell uname -s) ifeq ($(UNAME_S), Darwin) @@ -14,12 +15,14 @@ else VST3DIR = /Library/Audio/Plug-Ins/VST3 VST3DIR_USER = ${HOME}/Library/Audio/Plug-Ins/VST3 CC = clang + CXX = clang++ else DLL_SUFFIX = .so PLATFORM = $(shell uname -m)-linux VST3DIR = /usr/local/lib/vst3 VST3DIR_USER = ${HOME}/.vst3 CC = gcc + CXX = g++ endif endif diff --git a/templates/web-make/Makefile b/templates/web-make/Makefile index a8158d9..e4ef65a 100644 --- a/templates/web-make/Makefile +++ b/templates/web-make/Makefile @@ -5,6 +5,7 @@ DATA_DIR := $(or $(DATA_DIR),.) PLUGIN_DIR := $(or $(PLUGIN_DIR),src) CC = clang +CXX = clang++ CFLAGS = -Ofast -Wall -Wpedantic -Wextra CFLAGS_ALL = -I${COMMON_DIR}/src -I${DATA_DIR}/src -I${PLUGIN_DIR} --target=wasm32 -flto -fvisibility=hidden ${CFLAGS} ${CFLAGS_EXTRA} @@ -29,9 +30,20 @@ LDFLAGS_ALL += -Wl,--export=processor_midi_msg_in endif LDFLAGS_ALL += ${LDFLAGS} ${LDFLAGS_EXTRA} -C_SRCS = ${COMMON_DIR}/src/processor.c +CXXFLAGS = ${CFLAGS} +CXXFLAGS_ALL = -I${COMMON_DIR}/src -I${DATA_DIR}/src -I${PLUGIN_DIR} --target=wasm32 -flto -fvisibility=hidden ${CXXFLAGS} ${CXXFLAGS_EXTRA} + +C_SRCS = ${COMMON_DIR}/src/processor.c ${COMMON_DIR}/src/walloc.c ${COMMON_DIR}/src/memset.c C_OBJS = $(addprefix build/obj/, $(notdir $(C_SRCS:.c=.o))) +ifeq ($(CXX_SRCS_EXTRA),) +CXX_SRCS = +CXX_OBJS = +else +CXX_SRCS = ${COMMON_DIR}/src/new.cpp ${CXX_SRCS_EXTRA} +CXX_OBJS = $(addprefix build/obj/, $(notdir $(CXX_SRCS:.cpp=.o))) +endif + ALL = build/${BUNDLE_NAME}.wasm build/${BUNDLE_NAME}_processor.js build/${BUNDLE_NAME}.js default: all @@ -40,14 +52,13 @@ default: all all: ${ALL} +ifeq ($(CXX_OBJS),) build/${BUNDLE_NAME}.wasm: ${C_OBJS} | build ${CC} $^ -o $@ ${CFLAGS_ALL} ${LDFLAGS_ALL} - -.SECONDEXPANSION: - -PERCENT := % -$(C_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).c,$$(C_SRCS)) | build/obj - ${CC} $^ -o $@ -c ${CFLAGS_ALL} +else +build/${BUNDLE_NAME}.wasm: ${C_OBJS} ${CXX_OBJS} | build + ${CXX} $^ -o $@ ${CFLAGS_ALL} ${CXXFLAGS_ALL} ${LDFLAGS_ALL} +endif build/${BUNDLE_NAME}_processor.js: ${DATA_DIR}/src/processor.js | build cp $^ $@ @@ -62,3 +73,13 @@ clean: rm -fr build .PHONY: all clean + +.SECONDEXPANSION: + +PERCENT := % + +$(C_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).c,$$(C_SRCS)) | build/obj + ${CC} $^ -o $@ -c ${CFLAGS_ALL} + +$(CXX_OBJS): build/obj/%.o: $$(filter $$(PERCENT)/$$(basename $$(notdir $$@)).cpp,$$(CXX_SRCS)) | build/obj + ${CXX} $^ -o $@ -c ${CXXFLAGS_ALL} diff --git a/templates/web-make/vars.mk b/templates/web-make/vars.mk index 9949e59..89aebd5 100644 --- a/templates/web-make/vars.mk +++ b/templates/web-make/vars.mk @@ -1,7 +1,14 @@ BUNDLE_NAME := {{=it.product.bundleName}} + CFLAGS_EXTRA := {{=it.make && it.make.cflags ? it.make.cflags : ""}} {{=it.web_make && it.web_make.cflags ? it.web_make.cflags : ""}} LDFLAGS_EXTRA := {{=it.make && it.make.ldflags ? it.make.ldflags : ""}} {{=it.web_make && it.web_make.ldflags ? it.web_make.ldflags : ""}} +CXXFLAGS_EXTRA := {{=it.make && it.make.cxxflags ? it.make.cxxflags : ""}} {{=it.web_make && it.web_make.cxxflags ? it.web_make.cxxflags : ""}} + +C_SRCS_EXTRA := {{=it.make && it.make.cSrcs ? it.make.cSrcs : ""}} {{=it.web_make.cSrcs ? it.web_make.cSrcs : ""}} +CXX_SRCS_EXTRA := {{=it.make && it.make.cxxSrcs ? it.make.cxxSrcs : ""}} {{=it.web_make.cxxSrcs ? it.web_make.cxxSrcs : ""}} + COMMON_DIR := {{=it.web_make && it.web_make.commonDir ? it.web_make.commonDir : (it.make && it.make.commonDir ? it.make.commonDir : "")}} DATA_DIR := {{=it.web_make && it.web_make.dataDir ? it.web_make.dataDir : (it.make && it.make.dataDir ? it.make.dataDir : "")}} PLUGIN_DIR := {{=it.web_make && it.web_make.pluginDir ? it.web_make.pluginDir : (it.make && it.make.pluginDir ? it.make.pluginDir : "")}} + HAS_MIDI_IN := {{=it.product.buses.filter(x => x.type == "midi" && x.direction == "input").length > 0 ? "yes" : "no"}} diff --git a/templates/web/src/memset.c b/templates/web/src/memset.c new file mode 100644 index 0000000..8a3b7eb --- /dev/null +++ b/templates/web/src/memset.c @@ -0,0 +1,12 @@ +/* + * Copyright (C) 2023 Orastron Srl unipersonale + */ + +#include "memset.h" + +void *memset(void *ptr, int value, size_t num) { + unsigned char *p = (unsigned char *)ptr; + for (size_t i = 0; i < num; i++) + p[i] = (unsigned char)value; + return ptr; +} diff --git a/templates/web/src/memset.h b/templates/web/src/memset.h index 0fb33f2..61a5ad0 100644 --- a/templates/web/src/memset.h +++ b/templates/web/src/memset.h @@ -2,9 +2,19 @@ * Copyright (C) 2023 Orastron Srl unipersonale */ -void *memset(void *ptr, int value, size_t num) { - unsigned char *p = (unsigned char *)ptr; - for (size_t i = 0; i < num; i++) - p[i] = (unsigned char)value; - return ptr; +#ifndef MEMSET_H +#define MEMSET_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void *memset(void *ptr, int value, size_t num); + +#ifdef __cplusplus } +#endif + +#endif diff --git a/templates/web/src/new.cpp b/templates/web/src/new.cpp new file mode 100644 index 0000000..045d673 --- /dev/null +++ b/templates/web/src/new.cpp @@ -0,0 +1,14 @@ +#include "walloc.h" + +void * operator new(size_t size) { + return malloc(size); +} +void * operator new[](size_t size) { + return malloc(size); +} +void operator delete (void *ptr) noexcept { + free(ptr); +} +void operator delete[] (void *ptr) noexcept { + free(ptr); +} diff --git a/templates/web/src/walloc.c b/templates/web/src/walloc.c new file mode 100644 index 0000000..68cb155 --- /dev/null +++ b/templates/web/src/walloc.c @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2021, 2022, 2024 Orastron Srl unipersonale + */ + +#include "walloc.h" + +#include + +extern unsigned char __heap_base; + +typedef struct _header { + struct _header *next; + struct _header *prev; + char free; +} header; + +static char inited = 0; + +static size_t get_size(header *h) { + char *n = (char *)h->next; + return (n ? n : (char *)(__builtin_wasm_memory_size(0) << 16)) - (char *)h - sizeof(header); +} + +static void split_if_possible(header *h, size_t s, size_t size) { + if (s <= size + sizeof(header) + sizeof(header)) + return; + + header *hn = (header *)((char *)h + sizeof(header) + size); + hn->prev = h; + hn->next = h->next; + hn->free = 1; + h->next = hn; + if (hn->next) + hn->next->prev = hn; +} + +void *malloc(size_t size) { + if (size == 0) + return NULL; + + header *h = (header *)&__heap_base; + + if (!inited) { + h->next = NULL; + h->prev = NULL; + h->free = 1; + inited = 1; + } + + header *p; + for (; h; p = h, h = h->next) { + if (!h->free) + continue; + + size_t s = get_size(h); + if (s < size) + continue; + + split_if_possible(h, s, size); + + h->free = 0; + return (char *)h + sizeof(header); + } + + int32_t n = __builtin_wasm_memory_grow(0, ((size + sizeof(header) - 1) >> 16) + 1); + if (n < 0) + return NULL; + + if (p->free) + h = p; + else { + h = (header *)(n << 16); + p->next = h; + h->prev = p; + h->next = NULL; + } + + split_if_possible(h, get_size(h), size); + + h->free = 0; + return (char *)h + sizeof(header); +} + +void *realloc(void *ptr, size_t size) { + if (ptr == NULL) + return malloc(size); + + if (size == 0) { + free(ptr); + return NULL; + } + + header *h = (header *)((char *)ptr - sizeof(header)); + size_t s = get_size(h); + if (s >= size) + return ptr; + + void *p = malloc(size); + if (p == NULL) + return NULL; + + char *src = (char *)ptr; + char *dest = (char *)p; + for (size_t i = 0; i < s; i++) + dest[i] = src[i]; + + free(ptr); + + return p; +} + +void free(void *ptr) { + header *h = (header *)((char *)ptr - sizeof(header)); + h->free = 1; + + if (h->next && h->next->free) { + h->next = h->next->next; + if (h->next) + h->next->prev = h; + } + + if (h->prev && h->prev->free) { + h->prev->next = h->next; + if (h->next) + h->next->prev = h->prev; + } +} diff --git a/templates/web/src/walloc.h b/templates/web/src/walloc.h index cd5b5a7..d65dcb8 100644 --- a/templates/web/src/walloc.h +++ b/templates/web/src/walloc.h @@ -2,126 +2,21 @@ * Copyright (C) 2021, 2022, 2024 Orastron Srl unipersonale */ +#ifndef WALLOC_H +#define WALLOC_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + void *malloc(size_t size); void *realloc(void *ptr, size_t size); void free(void *ptr); -extern unsigned char __heap_base; - -typedef struct _header { - struct _header *next; - struct _header *prev; - char free; -} header; - -static char inited = 0; - -static size_t get_size(header *h) { - char *n = (char *)h->next; - return (n ? n : (char *)(__builtin_wasm_memory_size(0) << 16)) - (char *)h - sizeof(header); +#ifdef __cplusplus } +#endif -static void split_if_possible(header *h, size_t s, size_t size) { - if (s <= size + sizeof(header) + sizeof(header)) - return; - - header *hn = (header *)((char *)h + sizeof(header) + size); - hn->prev = h; - hn->next = h->next; - hn->free = 1; - h->next = hn; - if (hn->next) - hn->next->prev = hn; -} - -void *malloc(size_t size) { - if (size == 0) - return NULL; - - header *h = (header *)&__heap_base; - - if (!inited) { - h->next = NULL; - h->prev = NULL; - h->free = 1; - inited = 1; - } - - header *p; - for (; h; p = h, h = h->next) { - if (!h->free) - continue; - - size_t s = get_size(h); - if (s < size) - continue; - - split_if_possible(h, s, size); - - h->free = 0; - return (char *)h + sizeof(header); - } - - int32_t n = __builtin_wasm_memory_grow(0, ((size + sizeof(header) - 1) >> 16) + 1); - if (n < 0) - return NULL; - - if (p->free) - h = p; - else { - h = (header *)(n << 16); - p->next = h; - h->prev = p; - h->next = NULL; - } - - split_if_possible(h, get_size(h), size); - - h->free = 0; - return (char *)h + sizeof(header); -} - -void *realloc(void *ptr, size_t size) { - if (ptr == NULL) - return malloc(size); - - if (size == 0) { - free(ptr); - return NULL; - } - - header *h = (header *)((char *)ptr - sizeof(header)); - size_t s = get_size(h); - if (s >= size) - return ptr; - - void *p = malloc(size); - if (p == NULL) - return NULL; - - char *src = (char *)ptr; - char *dest = (char *)p; - for (size_t i = 0; i < s; i++) - dest[i] = src[i]; - - free(ptr); - - return p; -} - -void free(void *ptr) { - header *h = (header *)((char *)ptr - sizeof(header)); - h->free = 1; - - if (h->next && h->next->free) { - h->next = h->next->next; - if (h->next) - h->next->prev = h; - } - - if (h->prev && h->prev->free) { - h->prev->next = h->next; - if (h->next) - h->next->prev = h->prev; - } -} +#endif diff --git a/templates/web/tibia-index.js b/templates/web/tibia-index.js index 1ab6f0c..50fcb17 100644 --- a/templates/web/tibia-index.js +++ b/templates/web/tibia-index.js @@ -3,7 +3,10 @@ var sep = path.sep; module.exports = function (data, api) { api.copyFile(`src${sep}memset.h`, `src${sep}memset.h`); + api.copyFile(`src${sep}memset.c`, `src${sep}memset.c`); api.copyFile(`src${sep}walloc.h`, `src${sep}walloc.h`); + api.copyFile(`src${sep}walloc.c`, `src${sep}walloc.c`); + api.copyFile(`src${sep}new.cpp`, `src${sep}new.cpp`); api.copyFile(`src${sep}processor.c`, `src${sep}processor.c`); api.generateFileFromTemplateFile(`src${sep}data.h`, `src${sep}data.h`, data); api.generateFileFromTemplateFile(`src${sep}processor.js`, `src${sep}processor.js`, data);