1
1
Fork 0
mirror of https://github.com/QB64-Phoenix-Edition/QB64pe.git synced 2024-09-28 11:17:46 +00:00

Merge pull request #164 from mkilgore/midi-support-new

Add MIDI support and `Compiler Settings` command line options
This commit is contained in:
Matt Kilgore 2022-09-09 08:05:03 -04:00 committed by GitHub
commit 7390a089d3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
41 changed files with 764 additions and 2877 deletions

View file

@ -41,7 +41,13 @@ jobs:
- name: Install dependencies - name: Install dependencies
if: ${{ matrix.os == 'ubuntu-latest' }} if: ${{ matrix.os == 'ubuntu-latest' }}
run: sudo apt update && sudo apt install build-essential x11-utils mesa-common-dev libglu1-mesa-dev libasound2-dev zlib1g-dev run: sudo apt update && sudo apt install build-essential x11-utils mesa-common-dev libglu1-mesa-dev libasound2-dev zlib1g-dev pulseaudio dbus-x11 libportaudio2
# Pulseaudio puts a dummy ALSA device in place, which allows us to do
# audio testing on Linux
- name: Start Pulseaudio
if: ${{ matrix.os == 'ubuntu-latest' }}
run: dbus-launch pulseaudio --start
- name: Calculate Version - name: Calculate Version
shell: bash shell: bash

View file

@ -181,6 +181,7 @@ include $(PATH_INTERNAL_C)/parts/audio/conversion/build.mk
include $(PATH_INTERNAL_C)/parts/audio/decode/mp3_mini/build.mk include $(PATH_INTERNAL_C)/parts/audio/decode/mp3_mini/build.mk
include $(PATH_INTERNAL_C)/parts/audio/decode/ogg/build.mk include $(PATH_INTERNAL_C)/parts/audio/decode/ogg/build.mk
include $(PATH_INTERNAL_C)/parts/audio/out/build.mk include $(PATH_INTERNAL_C)/parts/audio/out/build.mk
include $(PATH_INTERNAL_C)/parts/audio/extras/build.mk
include $(PATH_INTERNAL_C)/parts/audio/build.mk include $(PATH_INTERNAL_C)/parts/audio/build.mk
include $(PATH_INTERNAL_C)/parts/core/build.mk include $(PATH_INTERNAL_C)/parts/core/build.mk
include $(PATH_INTERNAL_C)/parts/input/game_controller/build.mk include $(PATH_INTERNAL_C)/parts/input/game_controller/build.mk

View file

@ -66,6 +66,8 @@ Repository Layout
- `tests/` - Contains the tests run on QB64-PE during CI to verify changes. - `tests/` - Contains the tests run on QB64-PE during CI to verify changes.
- `compile_tests/` - `compile_tests/`
- Testcases related to specific dependencies that QB64 can pull in. These tests are largely intended to test that QB64-PE and the Makefile correctly pulls in the proper dependencies. - Testcases related to specific dependencies that QB64 can pull in. These tests are largely intended to test that QB64-PE and the Makefile correctly pulls in the proper dependencies.
- `c`
- The source for the C++-based tests.
- `qbasic_testcases/` - `qbasic_testcases/`
- A variety of collected QB64 sample programs - A variety of collected QB64 sample programs
- `dist/` - `dist/`
@ -80,6 +82,8 @@ Repository Layout
- Runs the distribution test collecitons. - Runs the distribution test collecitons.
- `run_tests.sh` - `run_tests.sh`
- Runs all individual test collections. - Runs all individual test collections.
- `run_c_tests.sh`
- Runs all the C++ test cases.
- `setup_lnx.sh` - `setup_lnx.sh`
- Used as part of the Linux release to install dependencies and compile QB64-PE. - Used as part of the Linux release to install dependencies and compile QB64-PE.
- `setup_osx.command` - `setup_osx.command`

54
docs/testing.md Normal file
View file

@ -0,0 +1,54 @@
QB64-PE Testing Framework
=========================
QB64-PE features two separate testing frameworks, one for QB64-based tests
(mainly for the compiler and language functionality), and one for C++-based
tests (for `libqb`).
QB64-based Tests
----------------
The QB64-based tests live in `./tests/compile_tests`. Each folder in that
directory represents a different category of tests, and within each of those
category folders are `*.bas` files. Accompanying each `*.bas` file is either an
`*.output` or `*.err` file with the same base name as a coresponding `.bas`
file. For test with an `*.output`, the `*.output` file contains the text that
the program compiled from the `*.bas` file should produce. For `*.err` tests,
the `*.err` file contains the text of the error the QB64-PE compiler should
produce when attempting to compile that code.
Tests can also have an optional `*.flags` file. The contents of this file will
be provide as command line arguments to QB64-PE when compiling the test source.
These tests are run via the `./tests/compile_tests.sh` script. The script
searches the `./tests/compile_tests` directory for any `*.bas` files, and then
uses the provide QB64-PE compiler to test them.
C++-based Tests
---------------
The C++-based testing lives in `./tests/c/`. The tests themselves exist as
`.cpp` files that compile into individual programs (each has its own `main()`).
The tests make use of `test.h` to run their tests and give proper output, and
failure is reported via the exit code.
The C++ tests are compiled using the `./tests/build.mk` make build logic. It's
fairly straight forward, each test executable gets its own name and then its
own combination of source/object files necessary to produce it. If you're
testing functionality from `libqb`, then you need to link the proper object
files into your test. Additionally, any extra compiler flags can be defined
individually for each test.
`./tests/run_c_tests.sh` is a script that runs all of the C++ tests during the
build. Internally it has a list of the names of all the test executables (to
avoid having to use `make` to discover them). It expects the tests to have
already been built via a `make build-tests` call, and runs the executables one
at a time and checks their exit code for errors.
QBasic Testcases
----------------
The QBasic testcases are a selection of QBasic programs that live in
`./tests/qb64_testcases`. During the build process all of these programs are
tested to verify that QB64-PE is still capable of compiling them with no
errors. The behavior of the compiled programs is not verified.

View file

@ -1,6 +1,7 @@
libqb-objs-y += $(PATH_LIBQB)/src/threading.o libqb-objs-y += $(PATH_LIBQB)/src/threading.o
libqb-objs-y += $(PATH_LIBQB)/src/buffer.o libqb-objs-y += $(PATH_LIBQB)/src/buffer.o
libqb-objs-y += $(PATH_LIBQB)/src/filepath.o
libqb-objs-y += $(PATH_LIBQB)/src/threading-$(PLATFORM).o libqb-objs-y += $(PATH_LIBQB)/src/threading-$(PLATFORM).o

View file

@ -41,6 +41,9 @@
# endif # endif
# define AUDIO_DEBUG_CHECK(_exp_) // Don't do anything in release builds # define AUDIO_DEBUG_CHECK(_exp_) // Don't do anything in release builds
#endif #endif
// We always use 48000
#define MA_DEFAULT_SAMPLE_RATE 48000
//----------------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------------

View file

@ -0,0 +1,15 @@
#ifndef INCLUDE_LIBQB_FILEPATH_H
#define INCLUDE_LIBQB_FILEPATH_H
// Takes a path + filename, and returns just the filename portion
// Returns either NULL or empty string if it has none.
const char *filepath_get_filename(const char *path);
// Takes a filename and returns just the extension at the end
// Returns either NULL or empty string if it has none.
const char *filepath_get_extension(const char *fliename);
// Returns true if the path is to a file that matches the provided extension
bool filepath_has_extension(const char *path, const char *extension);
#endif

View file

@ -0,0 +1,77 @@
// Implementation of these functions was pulled from miniaudio.h (MIT)
#include "libqb-common.h"
#include <string.h>
const char *filepath_get_filename(const char *path)
{
const char *fileName;
if (path == NULL) {
return NULL;
}
fileName = path;
/* We just loop through the path until we find the last slash. */
while (path[0] != '\0') {
if (path[0] == '/' || path[0] == '\\') {
fileName = path;
}
path += 1;
}
/* At this point the file name is sitting on a slash, so just move forward. */
while (fileName[0] != '\0' && (fileName[0] == '/' || fileName[0] == '\\')) {
fileName += 1;
}
return fileName;
}
const char *filepath_get_extension(const char *path)
{
const char *extension;
const char *lastOccurance;
if (path == NULL) {
path = "";
}
extension = filepath_get_filename(path);
lastOccurance = NULL;
/* Just find the last '.' and return. */
while (extension[0] != '\0') {
if (extension[0] == '.') {
extension += 1;
lastOccurance = extension;
}
extension += 1;
}
return (lastOccurance != NULL) ? lastOccurance : extension;
}
bool filepath_has_extension(const char *path, const char *extension)
{
const char *ext1;
const char *ext2;
if (path == NULL || extension == NULL) {
return false;
}
ext1 = extension;
ext2 = filepath_get_extension(path);
#if defined(_MSC_VER) || defined(__DMC__)
return _stricmp(ext1, ext2) == 0;
#else
return strcasecmp(ext1, ext2) == 0;
#endif
}

View file

@ -27,13 +27,12 @@
# define uint8 uint8_t # define uint8 uint8_t
# endif # endif
# define ptrszint intptr_t
# define uptrszint uintptr_t
# ifdef QB64_64 # ifdef QB64_64
# define ptrszint int64
# define uptrszint uint64
# define ptrsz 8 # define ptrsz 8
# else # else
# define ptrszint int32
# define uptrszint uint32
# define ptrsz 4 # define ptrsz 4
# endif # endif
#endif #endif

View file

@ -3,48 +3,24 @@ MINIAUDIO_REAL_SRCS := \
audio.cpp \ audio.cpp \
miniaudio_impl.cpp miniaudio_impl.cpp
MINIAUDIO_REAL_EXTRAS_SRCS := \
extras/libxmp-lite/common.c \
extras/libxmp-lite/control.c \
extras/libxmp-lite/dataio.c \
extras/libxmp-lite/effects.c \
extras/libxmp-lite/filter.c \
extras/libxmp-lite/format.c \
extras/libxmp-lite/hio.c \
extras/libxmp-lite/it_load.c \
extras/libxmp-lite/itsex.c \
extras/libxmp-lite/lfo.c \
extras/libxmp-lite/load.c \
extras/libxmp-lite/load_helpers.c \
extras/libxmp-lite/md5.c \
extras/libxmp-lite/memio.c \
extras/libxmp-lite/misc.c \
extras/libxmp-lite/mix_all.c \
extras/libxmp-lite/mixer.c \
extras/libxmp-lite/mod_load.c \
extras/libxmp-lite/period.c \
extras/libxmp-lite/player.c \
extras/libxmp-lite/read_event.c \
extras/libxmp-lite/s3m_load.c \
extras/libxmp-lite/sample.c \
extras/libxmp-lite/scan.c \
extras/libxmp-lite/smix.c \
extras/libxmp-lite/virtual.c \
extras/libxmp-lite/win32.c \
extras/libxmp-lite/xm_load.c
MINIAUDIO_STUB_SRCS := \ MINIAUDIO_STUB_SRCS := \
stub_audio.cpp stub_audio.cpp
# We always produce both lists so that `make clean` will clean them up even # We always produce both lists so that `make clean` will clean them up even
# when not passed a paticular DEP_* flag # when not passed a paticular DEP_* flag
MINIAUDIO_REAL_OBJS := $(patsubst %.cpp,$(PATH_INTERNAL_C)/parts/audio/%.o,$(MINIAUDIO_REAL_SRCS)) MINIAUDIO_REAL_OBJS := $(patsubst %.cpp,$(PATH_INTERNAL_C)/parts/audio/%.o,$(MINIAUDIO_REAL_SRCS))
MINIAUDIO_REAL_OBJS += $(patsubst %.c,$(PATH_INTERNAL_C)/parts/audio/%.o,$(MINIAUDIO_REAL_EXTRAS_SRCS))
MINIAUDIO_STUB_OBJS := $(patsubst %.cpp,$(PATH_INTERNAL_C)/parts/audio/%.o,$(MINIAUDIO_STUB_SRCS)) MINIAUDIO_STUB_OBJS := $(patsubst %.cpp,$(PATH_INTERNAL_C)/parts/audio/%.o,$(MINIAUDIO_STUB_SRCS))
ifdef DEP_AUDIO_MINIAUDIO ifdef DEP_AUDIO_MINIAUDIO
MINIAUDIO_OBJS := $(MINIAUDIO_REAL_OBJS) MINIAUDIO_OBJS := $(MINIAUDIO_REAL_OBJS) $(MA_VTABLES_OBJS) $(LIBXMP_LIB)
ifdef DEP_AUDIO_DECODE_MIDI
MINIAUDIO_OBJS += $(MIDI_MA_VTABLES_OBJS)
else
MINIAUDIO_OBJS += $(MIDI_MA_VTABLES_STUB_OBJS)
endif
else else
MINIAUDIO_OBJS := $(MINIAUDIO_STUB_OBJS) MINIAUDIO_OBJS := $(MINIAUDIO_STUB_OBJS)
endif endif
@ -52,7 +28,4 @@ endif
$(PATH_INTERNAL_C)/parts/audio/%.o: $(PATH_INTERNAL_C)/parts/audio/%.cpp $(PATH_INTERNAL_C)/parts/audio/%.o: $(PATH_INTERNAL_C)/parts/audio/%.cpp
$(CXX) $(CXXFLAGS) -Wall $< -c -o $@ $(CXX) $(CXXFLAGS) -Wall $< -c -o $@
$(PATH_INTERNAL_C)/parts/audio/extras/libxmp-lite/%.o: $(PATH_INTERNAL_C)/parts/audio/extras/libxmp-lite/%.c
$(CC) $(CFLAGS) -Wall -DLIBXMP_CORE_PLAYER -DLIBXMP_NO_PROWIZARD -DLIBXMP_NO_DEPACKERS -DBUILDING_STATIC $< -c -o $@
CLEAN_LIST += $(MINIAUDIO_REAL_OBJS) $(MINIAUDIO_STUB_OBJS) CLEAN_LIST += $(MINIAUDIO_REAL_OBJS) $(MINIAUDIO_STUB_OBJS)

View file

@ -0,0 +1,82 @@
LIBXMP_SRCS := \
common.c \
control.c \
dataio.c \
effects.c \
filter.c \
format.c \
hio.c \
it_load.c \
itsex.c \
lfo.c \
load.c \
load_helpers.c \
md5.c \
memio.c \
misc.c \
mix_all.c \
mixer.c \
mod_load.c \
period.c \
player.c \
read_event.c \
s3m_load.c \
sample.c \
scan.c \
smix.c \
virtual.c \
win32.c \
xm_load.c
LIBXMP_OBJS += $(patsubst %.c,$(PATH_INTERNAL_C)/parts/audio/extras/libxmp-lite/%.o,$(LIBXMP_SRCS))
LIBXMP_LIB := $(PATH_INTERNAL_C)/parts/audio/extras/libxmp-lite.a
$(PATH_INTERNAL_C)/parts/audio/extras/libxmp-lite/%.o: $(PATH_INTERNAL_C)/parts/audio/extras/libxmp-lite/%.c
$(CC) $(CFLAGS) -Wall -DLIBXMP_CORE_PLAYER -DLIBXMP_NO_PROWIZARD -DLIBXMP_NO_DEPACKERS -DBUILDING_STATIC $< -c -o $@
$(LIBXMP_LIB): $(LIBXMP_OBJS)
$(AR) rcs $@ $^
MA_VTABLES_SRCS := \
mod_ma_vtable.cpp \
radv2_ma_vtable.cpp
MA_VTABLES_OBJS := $(patsubst %.cpp,$(PATH_INTERNAL_C)/parts/audio/extras/%.o,$(MA_VTABLES_SRCS))
MIDI_MA_VTABLE_SRCS := midi_ma_vtable.cpp
MIDI_MA_VTABLE_STUB_SRCS := midi_ma_vtable_stub.cpp
MIDI_MA_VTABLES_OBJS := $(patsubst %.cpp,$(PATH_INTERNAL_C)/parts/audio/extras/%.o,$(MIDI_MA_VTABLE_SRCS))
MIDI_MA_VTABLES_STUB_OBJS := $(patsubst %.cpp,$(PATH_INTERNAL_C)/parts/audio/extras/%.o,$(MIDI_MA_VTABLE_STUB_SRCS))
# If we're using MIDI, then there should be a soundfont available to be linked in
MIDI_MA_VTABLES_OBJS += $(PATH_INTERNAL_TEMP)/soundfont.o
# Turn the soundfont into a linkable object
ifeq ($(OS),win)
# Fairly ugly, but we have to get the right relative path to objcopy on Windows
# to make the whole thing work out
$(PATH_INTERNAL_TEMP)/soundfont.o: $(PATH_INTERNAL_TEMP)/soundfont.sf2
cd $(call FIXPATH,$(PATH_INTERNAL_TEMP)) && ..\..\$(OBJCOPY) -Ibinary $(OBJCOPY_FLAGS) soundfont.sf2 soundfont.o
else
ifeq ($(OS),osx)
# Mac OS does not ship an objcopy implementation for some reason
# We're instead using xxd to produce a source file, and compiling it
$(PATH_INTERNAL_TEMP)/soundfont.c: $(PATH_INTERNAL_TEMP)/soundfont.sf2
cd $(call FIXPATH,$(PATH_INTERNAL_TEMP)) && xxd --include soundfont.sf2 > soundfont.c
$(PATH_INTERNAL_TEMP)/soundfont.o: $(PATH_INTERNAL_TEMP)/soundfont.c
$(CC) $< -c -o $@
else
# The "cd" is used to make the symbol name predictable and not dependent upon
# the "PATH_INTERNAL_TEMP" value
$(PATH_INTERNAL_TEMP)/soundfont.o: $(PATH_INTERNAL_TEMP)/soundfont.sf2
cd $(call FIXPATH,$(PATH_INTERNAL_TEMP)) && $(OBJCOPY) -Ibinary $(OBJCOPY_FLAGS) soundfont.sf2 soundfont.o
endif
endif
CLEAN_LIST += $(LIBXMP_LIB) $(LIBXMP_OBJS) $(MA_VTABLES_OBJS) $(MIDI_MA_VTABLES_OBJS) $(MIDI_MA_VTABLES_STUB_OBJS)

View file

@ -18,23 +18,58 @@
// //
//----------------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------------
#pragma once
//----------------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------------
// HEADER FILES // HEADER FILES
//----------------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------------
#include "libqb-common.h"
#include "audio.h"
#include "filepath.h"
#include <string.h>
#include "../miniaudio.h" #include "../miniaudio.h"
#include "tinysoundfont/awe32rom.h"
#define TSF_IMPLEMENTATION #define TSF_IMPLEMENTATION
#include "tinysoundfont/tsf.h" #include "tinysoundfont/tsf.h"
#define TML_IMPLEMENTATION #define TML_IMPLEMENTATION
#include "tinysoundfont/tml.h" #include "tinysoundfont/tml.h"
//-----------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------- #include "vtables.h"
// CONSTANTS
//----------------------------------------------------------------------------------------------------- extern "C" {
#define TSF_DEFAULT_SOUNDFONT_FILENAME "soundfont.sf2" // These symbols reference a soundfont compiled into the program
//
// We provide a macro to expand to the correct symbol name
#if defined(QB64_WINDOWS) && defined(QB64_32)
// On 32-bit Windows, we use objcopy, and the symbols do not have an
// underscore prefix
extern char binary_soundfont_sf2_start[];
extern char binary_soundfont_sf2_end[];
# define SOUNDFONT_BIN binary_soundfont_sf2_start
# define SOUNDFONT_SIZE (binary_soundfont_sf2_end - binary_soundfont_sf2_start)
#elif defined(QB64_WINDOWS) || defined(QB64_LINUX)
// On Linux and 64-bit Windows, we use objcopy, and the symbols do have an
// underscore prefix.
extern char _binary_soundfont_sf2_start[];
extern char _binary_soundfont_sf2_end[];
# define SOUNDFONT_BIN _binary_soundfont_sf2_start
# define SOUNDFONT_SIZE (_binary_soundfont_sf2_end - _binary_soundfont_sf2_start)
#else
// On Mac OS we use xxd, which gives an array and size
extern unsigned char soundfont_sf2[];
extern unsigned int soundfont_sf2_len;
# define SOUNDFONT_BIN soundfont_sf2
# define SOUNDFONT_SIZE soundfont_sf2_len
#endif
}
//----------------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------------
struct ma_tsf { struct ma_tsf {
@ -83,7 +118,7 @@ static ma_result ma_tsf_get_data_format(ma_tsf *pTsf, ma_format *pFormat, ma_uin
*pSampleRate = 0; *pSampleRate = 0;
} }
if (pChannelMap != NULL) { if (pChannelMap != NULL) {
MA_ZERO_MEMORY(pChannelMap, sizeof(*pChannelMap) * channelMapCap); memset(pChannelMap, 0, sizeof(*pChannelMap) * channelMapCap);
} }
if (pTsf == NULL) { if (pTsf == NULL) {
@ -302,7 +337,7 @@ static ma_result ma_tsf_init_internal(const ma_decoding_backend_config *pConfig,
return MA_INVALID_ARGS; return MA_INVALID_ARGS;
} }
MA_ZERO_OBJECT(pTsf); memset(pTsf, 0, sizeof(&pTsf));
pTsf->format = ma_format::ma_format_s16; // We'll render 16-bit signed samples by default pTsf->format = ma_format::ma_format_s16; // We'll render 16-bit signed samples by default
if (pConfig != NULL && pConfig->preferredFormat == ma_format::ma_format_s16) { if (pConfig != NULL && pConfig->preferredFormat == ma_format::ma_format_s16) {
@ -322,6 +357,15 @@ static ma_result ma_tsf_init_internal(const ma_decoding_backend_config *pConfig,
return MA_SUCCESS; return MA_SUCCESS;
} }
ma_result ma_tsf_load_memory(ma_tsf *pTsf)
{
// Attempt to load a SoundFont from memory
pTsf->tinySoundFont = tsf_load_memory(SOUNDFONT_BIN, SOUNDFONT_SIZE);
// Return failue if loading from memory also failed. This should not happen though
return pTsf->tinySoundFont? MA_SUCCESS: MA_OUT_OF_MEMORY;
}
static ma_result ma_tsf_init(ma_read_proc onRead, ma_seek_proc onSeek, ma_tell_proc onTell, void *pReadSeekTellUserData, static ma_result ma_tsf_init(ma_read_proc onRead, ma_seek_proc onSeek, ma_tell_proc onTell, void *pReadSeekTellUserData,
const ma_decoding_backend_config *pConfig, const ma_allocation_callbacks *pAllocationCallbacks, ma_tsf *pTsf) { const ma_decoding_backend_config *pConfig, const ma_allocation_callbacks *pAllocationCallbacks, ma_tsf *pTsf) {
ma_result result; ma_result result;
@ -370,18 +414,11 @@ static ma_result ma_tsf_init(ma_read_proc onRead, ma_seek_proc onSeek, ma_tell_p
return MA_IO_ERROR; return MA_IO_ERROR;
} }
// Attempt to load a SoundFont from a file // Load soundfont
pTsf->tinySoundFont = tsf_load_filename(TSF_DEFAULT_SOUNDFONT_FILENAME); result = ma_tsf_load_memory(pTsf);
if (result != MA_SUCCESS) {
if (!pTsf->tinySoundFont) { delete[] tune;
// Attempt to load the soundfont from memory return result;
pTsf->tinySoundFont = tsf_load_memory(awe32rom, sizeof(awe32rom));
// Return failue if loading from memory also failed. This should not happen though
if (!pTsf->tinySoundFont) {
delete[] tune;
return MA_OUT_OF_MEMORY;
}
} }
// Initialize preset on special 10th MIDI channel to use percussion sound bank (128) if available // Initialize preset on special 10th MIDI channel to use percussion sound bank (128) if available
@ -424,22 +461,14 @@ static ma_result ma_tsf_init_file(const char *pFilePath, const ma_decoding_backe
} }
// Check the file extension // Check the file extension
if (!ma_path_extension_equal(pFilePath, "mid") && !ma_path_extension_equal(pFilePath, "midi")) { if (!filepath_has_extension(pFilePath, "mid") && !filepath_has_extension(pFilePath, "midi")) {
return MA_INVALID_FILE; return MA_INVALID_FILE;
} }
// Attempt to load a SoundFont from a file // Load soundfont
pTsf->tinySoundFont = tsf_load_filename(TSF_DEFAULT_SOUNDFONT_FILENAME); result = ma_tsf_load_memory(pTsf);
if (result != MA_SUCCESS)
if (!pTsf->tinySoundFont) { return result;
// Attempt to load the soundfont from memory
pTsf->tinySoundFont = tsf_load_memory(awe32rom, sizeof(awe32rom));
// Return failue if loading from memory also failed. This should not happen though
if (!pTsf->tinySoundFont) {
return MA_OUT_OF_MEMORY;
}
}
// Initialize preset on special 10th MIDI channel to use percussion sound bank (128) if available // Initialize preset on special 10th MIDI channel to use percussion sound bank (128) if available
tsf_channel_set_bank_preset(pTsf->tinySoundFont, 9, 128, 0); tsf_channel_set_bank_preset(pTsf->tinySoundFont, 9, 128, 0);
@ -537,7 +566,11 @@ static void ma_decoding_backend_uninit__tsf(void *pUserData, ma_data_source *pBa
ma_free(pTsf, pAllocationCallbacks); ma_free(pTsf, pAllocationCallbacks);
} }
static ma_decoding_backend_vtable ma_decoding_backend_vtable_tsf = {ma_decoding_backend_init__tsf, ma_decoding_backend_init_file__tsf, NULL, /* onInitFileW() */ ma_decoding_backend_vtable ma_vtable_midi = {
NULL, /* onInitMemory() */ ma_decoding_backend_init__tsf,
ma_decoding_backend_uninit__tsf}; ma_decoding_backend_init_file__tsf,
NULL, /* onInitFileW() */
NULL, /* onInitMemory() */
ma_decoding_backend_uninit__tsf
};
//----------------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------------

View file

@ -0,0 +1,4 @@
#include "vtables.h"
ma_decoding_backend_vtable ma_vtable_midi = { };

View file

@ -15,14 +15,22 @@
// //
//----------------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------------
#pragma once
//----------------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------------
// HEADER FILES // HEADER FILES
//----------------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------------
#include "libqb-common.h"
#include "audio.h"
#include "filepath.h"
#include <stdio.h>
#include <string.h>
#include "../miniaudio.h" #include "../miniaudio.h"
#define BUILDING_STATIC 1 #define BUILDING_STATIC 1
#include "libxmp-lite/xmp.h" #include "libxmp-lite/xmp.h"
#include "vtables.h"
//----------------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------------
struct ma_modplay { struct ma_modplay {
@ -65,7 +73,7 @@ static ma_result ma_modplay_get_data_format(ma_modplay *pModplay, ma_format *pFo
*pSampleRate = 0; *pSampleRate = 0;
} }
if (pChannelMap != NULL) { if (pChannelMap != NULL) {
MA_ZERO_MEMORY(pChannelMap, sizeof(*pChannelMap) * channelMapCap); memset(pChannelMap, 0, sizeof(*pChannelMap) * channelMapCap);
} }
if (pModplay == NULL) { if (pModplay == NULL) {
@ -254,7 +262,7 @@ static ma_result ma_modplay_init_internal(const ma_decoding_backend_config *pCon
return MA_INVALID_ARGS; return MA_INVALID_ARGS;
} }
MA_ZERO_OBJECT(pModplay); memset(pModplay, 0, sizeof(*pModplay));
pModplay->format = ma_format::ma_format_s16; // We'll render 16-bit signed samples by default pModplay->format = ma_format::ma_format_s16; // We'll render 16-bit signed samples by default
if (pConfig != NULL && pConfig->preferredFormat == ma_format::ma_format_s16) { if (pConfig != NULL && pConfig->preferredFormat == ma_format::ma_format_s16) {
@ -381,8 +389,8 @@ static ma_result ma_modplay_init_file(const char *pFilePath, const ma_decoding_b
} }
// Check the file extension // Check the file extension
if (!ma_path_extension_equal(pFilePath, "it") && !ma_path_extension_equal(pFilePath, "xm") && !ma_path_extension_equal(pFilePath, "s3m") && if (!filepath_has_extension(pFilePath, "it") && !filepath_has_extension(pFilePath, "xm") && !filepath_has_extension(pFilePath, "s3m") &&
!ma_path_extension_equal(pFilePath, "mod")) { !filepath_has_extension(pFilePath, "mod")) {
return MA_INVALID_FILE; return MA_INVALID_FILE;
} }
@ -498,8 +506,12 @@ static void ma_decoding_backend_uninit__modplay(void *pUserData, ma_data_source
ma_free(pModplay, pAllocationCallbacks); ma_free(pModplay, pAllocationCallbacks);
} }
static ma_decoding_backend_vtable ma_decoding_backend_vtable_modplay = {ma_decoding_backend_init__modplay, ma_decoding_backend_init_file__modplay, ma_decoding_backend_vtable ma_vtable_modplay = {
NULL, /* onInitFileW() */ ma_decoding_backend_init__modplay,
NULL, /* onInitMemory() */ ma_decoding_backend_init_file__modplay,
ma_decoding_backend_uninit__modplay}; NULL, /* onInitFileW() */
NULL, /* onInitMemory() */
ma_decoding_backend_uninit__modplay
};
//----------------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------------

View file

@ -39,16 +39,23 @@
// //
//----------------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------------
#pragma once
//----------------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------------
// HEADER FILES // HEADER FILES
//----------------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------------
#include "libqb-common.h"
#include "audio.h"
#include "filepath.h"
#include <string.h>
#include <stdio.h>
#include "../miniaudio.h" #include "../miniaudio.h"
#include "radv2/opal.cpp" #include "radv2/opal.cpp"
#define RAD_DETECT_REPEATS 1 #define RAD_DETECT_REPEATS 1
#include "radv2/player20.cpp" #include "radv2/player20.cpp"
#include "radv2/validate20.cpp" #include "radv2/validate20.cpp"
#include "vtables.h"
//----------------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------------
struct ma_radv2 { struct ma_radv2 {
@ -96,7 +103,7 @@ static ma_result ma_radv2_get_data_format(ma_radv2 *pRadv2, ma_format *pFormat,
*pSampleRate = 0; *pSampleRate = 0;
} }
if (pChannelMap != NULL) { if (pChannelMap != NULL) {
MA_ZERO_MEMORY(pChannelMap, sizeof(*pChannelMap) * channelMapCap); memset(pChannelMap, 0, sizeof(*pChannelMap) * channelMapCap);
} }
if (!pRadv2) { if (!pRadv2) {
@ -290,7 +297,7 @@ static ma_result ma_radv2_init_internal(const ma_decoding_backend_config *pConfi
return MA_INVALID_ARGS; return MA_INVALID_ARGS;
} }
MA_ZERO_OBJECT(pRadv2); memset(pRadv2, 0, sizeof(*pRadv2));
pRadv2->format = ma_format::ma_format_s16; // RADv2 Opal outputs 16-bit signed samples by default pRadv2->format = ma_format::ma_format_s16; // RADv2 Opal outputs 16-bit signed samples by default
if (pConfig != NULL && pConfig->preferredFormat == ma_format::ma_format_s16) { if (pConfig != NULL && pConfig->preferredFormat == ma_format::ma_format_s16) {
@ -425,7 +432,7 @@ static ma_result ma_radv2_init_file(const char *pFilePath, const ma_decoding_bac
} }
// Check the file extension // Check the file extension
if (!ma_path_extension_equal(pFilePath, "rad")) { if (!filepath_has_extension(pFilePath, "rad")) {
return MA_INVALID_FILE; return MA_INVALID_FILE;
} }
@ -602,8 +609,11 @@ static void ma_decoding_backend_uninit__radv2(void *pUserData, ma_data_source *p
ma_free(pRadv2, pAllocationCallbacks); ma_free(pRadv2, pAllocationCallbacks);
} }
static ma_decoding_backend_vtable ma_decoding_backend_vtable_radv2 = {ma_decoding_backend_init__radv2, ma_decoding_backend_init_file__radv2, ma_decoding_backend_vtable ma_vtable_radv2 = {
NULL, /* onInitFileW() */ ma_decoding_backend_init__radv2,
NULL, /* onInitMemory() */ ma_decoding_backend_init_file__radv2,
ma_decoding_backend_uninit__radv2}; NULL, /* onInitFileW() */
NULL, /* onInitMemory() */
ma_decoding_backend_uninit__radv2
};
//----------------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------------

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,10 @@
#ifndef INCLUDE_PARTS_AUDIO_EXTRAS_VTABLES_H
#define INCLUDE_PARTS_AUDIO_EXTRAS_VTABLES_H
#include "../miniaudio.h"
extern ma_decoding_backend_vtable ma_vtable_midi;
extern ma_decoding_backend_vtable ma_vtable_modplay;
extern ma_decoding_backend_vtable ma_vtable_radv2;
#endif

View file

@ -29,12 +29,8 @@
// The stb_vorbis implementation must come after the implementation of miniaudio // The stb_vorbis implementation must come after the implementation of miniaudio
#undef STB_VORBIS_HEADER_ONLY #undef STB_VORBIS_HEADER_ONLY
#include "extras/stb_vorbis.c" #include "extras/stb_vorbis.c"
// RADv2 format support
#include "extras/miniaudio_radv2.h" #include "extras/vtables.h"
// MIDI format support
// #include "extras/miniaudio_tinysoundfont.h"
// MOD, S3M, XM & IT support
#include "extras/miniaudio_libxmp-lite.h"
//----------------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------------
@ -43,8 +39,11 @@
// Add custom backend (format) vtables here // Add custom backend (format) vtables here
// The order in the array defines the order of priority // The order in the array defines the order of priority
// The vtables will be passed in to the resource manager config // The vtables will be passed in to the resource manager config
ma_decoding_backend_vtable *maCustomBackendVTables[] = {&ma_decoding_backend_vtable_radv2, // &ma_decoding_backend_vtable_tsf, static ma_decoding_backend_vtable *maCustomBackendVTables[] = {
&ma_decoding_backend_vtable_modplay}; &ma_vtable_radv2,
&ma_vtable_midi,
&ma_vtable_modplay,
};
//----------------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------------

Binary file not shown.

View file

@ -898,6 +898,13 @@ DIM controlvalue(1000) AS LONG
DIM controlstate(1000) AS INTEGER DIM controlstate(1000) AS INTEGER
DIM SHARED controlref(1000) AS LONG 'the line number the control was created on DIM SHARED controlref(1000) AS LONG 'the line number the control was created on
'
' Collection of flags indicating which unstable features should be used during compilation
'
REDIM SHARED unstableFlags(1) AS _BYTE
DIM UNSTABLE_MIDI AS LONG
UNSTABLE_MIDI = 1
@ -1612,7 +1619,18 @@ udtetypesize(i2) = 0 'tsize
udtenext(i3) = i2 udtenext(i3) = i2
udtenext(i2) = 0 udtenext(i2) = 0
' Reset all unstable flags
REDIM SHARED unstableFlags(1) AS _BYTE
' Indicates if a MIDI sound font was selected
'
' Captures both the line number and line contents for error reporting later-on
' in the compilation process
MidiSoundFontSet = 0
MidiSoundFontLine$ = ""
' If MidiSoundFont$ is blank, then the default is used
MidiSoundFont$ = ""
@ -1891,6 +1909,25 @@ DO
GOTO finishedlinepp GOTO finishedlinepp
END IF END IF
' We check for Unstable flags during the preprocessing step because it
' impacts what valid commands there are in all the other steps
IF LEFT$(temp$, 10) = "$UNSTABLE:" THEN
token$ = UCASE$(LTRIM$(RTRIM$(MID$(temp$, 11))))
SELECT CASE token$
CASE "MIDI"
IF NOT UseMiniaudioBackend THEN
a$ = "Midi is not supported with the old OpenAL audio backend."
GOTO errmes
END IF
unstableFlags(UNSTABLE_MIDI) = -1
CASE ELSE
a$ = "Unrecognized unstable flag " + AddQuotes$(token$)
GOTO errmes
END SELECT
END IF
cwholeline$ = wholeline$ cwholeline$ = wholeline$
wholeline$ = eleucase$(wholeline$) '********REMOVE THIS LINE LATER******** wholeline$ = eleucase$(wholeline$) '********REMOVE THIS LINE LATER********
@ -3403,6 +3440,72 @@ DO
GOTO finishedline2 GOTO finishedline2
END IF END IF
IF LEFT$(a3u$, 10) = "$UNSTABLE:" THEN
layout$ = SCase("$Unstable:")
token$ = LTRIM$(RTRIM$(MID$(a3u$, 11)))
SELECT CASE token$
CASE "MIDI"
layout$ = layout$ + SCase$("Midi")
END SELECT
GOTO finishednonexec
END IF
IF unstableFlags(UNSTABLE_MIDI) THEN
IF LEFT$(a3u$, 15) = "$MIDISOUNDFONT:" THEN
IF MidiSoundFontSet THEN
a$ = "$MIDISOUNDFONT already defined"
GOTO errmes
END IF
layout$ = SCase$("$MidiSoundFont:")
MidiSoundFont$ = LTRIM$(RTRIM$(MID$(a3$, 16)))
IF MID$(MidiSoundFont$, 1, 1) = CHR$(34) THEN
' We have a quoted filename, verify it is valid
' We don't touch the filename in the formatting
layout$ = layout$ + MidiSoundFont$
' Strip the leading quote
MidiSoundFont$ = MID$(MidiSoundFont$, 2)
' Verify that there is a quote character at the end
IF INSTR(MidiSoundFont$, CHR$(34)) = 0 THEN a$ = "Expected " + CHR$(34) + " character at the end of the file name": GOTO errmes
' Verify there are no extra characters after end quote
IF INSTR(MidiSoundFont$, CHR$(34)) <> LEN(MidiSoundFont$) THEN a$ = "Unexpected characters after the quoted file name": GOTO errmes
MidiSoundFont$ = MID$(MidiSoundFont$, 1, LEN(MidiSoundFont$) - 1)
IF NOT _FILEEXISTS(MidiSoundFont$) THEN
a$ = "Soundfont file " + AddQuotes$(MidiSoundFont$) + " could not be found!"
GOTO errmes
END IF
ELSE
' Constant values, only one for now
SELECT CASE UCASE$(MidiSoundFont$)
CASE "DEFAULT"
layout$ = layout$ + SCase$("Default")
' Clear MidiSoundFont$ to indicate the default should be used
MidiSoundFont$ = ""
CASE ELSE
a$ = "Unrecognized Soundfont option " + AddQuotes$(MidiSoundFont$)
GOTO errmes
END SELECT
END IF
MidiSoundFontSet = linenumber
MidiSoundFontLine$ = layout$
GOTO finishednonexec
END IF
END IF
END IF 'QB64 Metacommands END IF 'QB64 Metacommands
IF ExecLevel(ExecCounter) THEN IF ExecLevel(ExecCounter) THEN
@ -12342,6 +12445,22 @@ END IF
'actions are performed on the disk based files 'actions are performed on the disk based files
WriteBuffers "" WriteBuffers ""
IF MidiSoundFontSet THEN
linenumber = MidiSoundFontSet
wholeline = MidiSoundFontLine$
IF MidiSoundFont$ = "" THEN
MidiSoundFont$ = "internal/support/default_soundfont.sf2"
END IF
ON ERROR GOTO qberror_test
errNo = CopyFile&(MidiSoundFont$, tmpdir$ + "soundfont.sf2")
IF errNo <> 0 THEN a$ = "Error copying " + QuotedFilename$(MidiSoundFont$) + " to temp directory": GOTO errmes
ON ERROR GOTO qberror
END IF
'Update dependencies 'Update dependencies
o$ = LCASE$(os$) o$ = LCASE$(os$)
@ -12371,7 +12490,7 @@ IF inline_DATA = 0 AND DataOffset THEN makedeps$ = makedeps$ + " DEP_DATA=y"
IF Console THEN makedeps$ = makedeps$ + " DEP_CONSOLE=y" IF Console THEN makedeps$ = makedeps$ + " DEP_CONSOLE=y"
IF ExeIconSet OR VersionInfoSet THEN makedeps$ = makedeps$ + " DEP_ICON_RC=y" IF ExeIconSet OR VersionInfoSet THEN makedeps$ = makedeps$ + " DEP_ICON_RC=y"
IF UseMiniaudioBackend = 0 THEN IF NOT UseMiniaudioBackend THEN
IF DEPENDENCY(DEPENDENCY_AUDIO_DECODE) THEN makedeps$ = makedeps$ + " DEP_AUDIO_DECODE=y" IF DEPENDENCY(DEPENDENCY_AUDIO_DECODE) THEN makedeps$ = makedeps$ + " DEP_AUDIO_DECODE=y"
IF DEPENDENCY(DEPENDENCY_AUDIO_CONVERSION) THEN makedeps$ = makedeps$ + " DEP_AUDIO_CONVERSION=y" IF DEPENDENCY(DEPENDENCY_AUDIO_CONVERSION) THEN makedeps$ = makedeps$ + " DEP_AUDIO_CONVERSION=y"
IF DEPENDENCY(DEPENDENCY_AUDIO_OUT) THEN makedeps$ = makedeps$ + " DEP_AUDIO_OUT=y" IF DEPENDENCY(DEPENDENCY_AUDIO_OUT) THEN makedeps$ = makedeps$ + " DEP_AUDIO_OUT=y"
@ -12381,6 +12500,8 @@ ELSE
END IF END IF
END IF END IF
IF MidiSoundFontSet THEN makedeps$ = makedeps$ + " DEP_AUDIO_DECODE_MIDI=y"
IF tempfolderindex > 1 THEN makedeps$ = makedeps$ + " TEMP_ID=" + str2$(tempfolderindex) IF tempfolderindex > 1 THEN makedeps$ = makedeps$ + " TEMP_ID=" + str2$(tempfolderindex)
CxxFlagsExtra$ = ExtraCppFlags CxxFlagsExtra$ = ExtraCppFlags
@ -12708,7 +12829,7 @@ IF os$ = "LNX" THEN
PRINT #ffh, makeline$ + CHR$(10); PRINT #ffh, makeline$ + CHR$(10);
PRINT #ffh, "read -p " + CHR_QUOTE + "Press ENTER to exit..." + CHR_QUOTE + CHR$(10); PRINT #ffh, "read -p " + CHR_QUOTE + "Press ENTER to exit..." + CHR_QUOTE + CHR$(10);
CLOSE ffh CLOSE ffh
SHELL _HIDE "chmod +x " + tmpdir$ + "recompile_osx.command" SHELL _HIDE "chmod +x " + AddQuotes$(tmpdir$ + "recompile_osx.command")
ffh = FREEFILE ffh = FREEFILE
OPEN tmpdir$ + "debug_osx.command" FOR OUTPUT AS #ffh OPEN tmpdir$ + "debug_osx.command" FOR OUTPUT AS #ffh
@ -12728,7 +12849,7 @@ IF os$ = "LNX" THEN
PRINT #ffh, "gdb " + CHR$(34) + path.exe$ + file$ + extension$ + CHR$(34) + CHR$(10); PRINT #ffh, "gdb " + CHR$(34) + path.exe$ + file$ + extension$ + CHR$(34) + CHR$(10);
PRINT #ffh, "Pause" + CHR$(10); PRINT #ffh, "Pause" + CHR$(10);
CLOSE ffh CLOSE ffh
SHELL _HIDE "chmod +x " + tmpdir$ + "debug_osx.command" SHELL _HIDE "chmod +x " + AddQuotes$(tmpdir$ + "debug_osx.command")
ELSE ELSE
@ -12748,7 +12869,7 @@ IF os$ = "LNX" THEN
PRINT #ffh, "echo " + CHR_QUOTE + "Press ENTER to exit..." + CHR_QUOTE + CHR$(10); PRINT #ffh, "echo " + CHR_QUOTE + "Press ENTER to exit..." + CHR_QUOTE + CHR$(10);
PRINT #ffh, "Pause" + CHR$(10); PRINT #ffh, "Pause" + CHR$(10);
CLOSE ffh CLOSE ffh
SHELL _HIDE "chmod +x " + tmpdir$ + "recompile_lnx.sh" SHELL _HIDE "chmod +x " + AddQuotes$(tmpdir$ + "recompile_lnx.sh")
ffh = FREEFILE ffh = FREEFILE
OPEN tmpdir$ + "debug_lnx.sh" FOR OUTPUT AS #ffh OPEN tmpdir$ + "debug_lnx.sh" FOR OUTPUT AS #ffh
@ -12768,7 +12889,7 @@ IF os$ = "LNX" THEN
PRINT #ffh, "gdb " + CHR$(34) + path.exe$ + file$ + extension$ + CHR$(34) + CHR$(10); PRINT #ffh, "gdb " + CHR$(34) + path.exe$ + file$ + extension$ + CHR$(34) + CHR$(10);
PRINT #ffh, "Pause" + CHR$(10); PRINT #ffh, "Pause" + CHR$(10);
CLOSE ffh CLOSE ffh
SHELL _HIDE "chmod +x " + tmpdir$ + "debug_lnx.sh" SHELL _HIDE "chmod +x " + AddQuotes$(tmpdir$ + "debug_lnx.sh")
END IF END IF
@ -12795,7 +12916,7 @@ IF os$ = "LNX" THEN
PRINT #ff, "exit"; PRINT #ff, "exit";
PRINT #ff, CHR$(10); PRINT #ff, CHR$(10);
CLOSE #ff CLOSE #ff
SHELL _HIDE "chmod +x " + path.exe$ + file$ + extension$ + "_start.command" SHELL _HIDE "chmod +x " + AddQuotes$(path.exe$ + file$ + extension$ + "_start.command")
END IF END IF
END IF END IF
@ -12985,6 +13106,7 @@ FUNCTION ParseCMDLineArgs$ ()
PRINT PRINT
PRINT "Options:" PRINT "Options:"
PRINT " <file> Source file to load" ' '80 columns PRINT " <file> Source file to load" ' '80 columns
PRINT " -v Print version"
PRINT " -c Compile instead of edit" PRINT " -c Compile instead of edit"
PRINT " -o <output file> Write output executable to <output file>" PRINT " -o <output file> Write output executable to <output file>"
PRINT " -x Compile instead of edit and output the result to the" PRINT " -x Compile instead of edit and output the result to the"
@ -12999,8 +13121,15 @@ FUNCTION ParseCMDLineArgs$ ()
PRINT " -l:<line number> Start the IDE at the specified line number" PRINT " -l:<line number> Start the IDE at the specified line number"
PRINT " -p Purge all pre-compiled content first" PRINT " -p Purge all pre-compiled content first"
PRINT " -z Generate C code without compiling to executable" PRINT " -z Generate C code without compiling to executable"
PRINT " -f[:setting=value] compiler settings to use"
PRINT PRINT
SYSTEM SYSTEM
CASE "-v" ' Print version
_DEST _CONSOLE
IF qb64versionprinted = 0 THEN qb64versionprinted = -1: PRINT "QB64-PE Compiler V" + Version$
SYSTEM
CASE "-u" 'Invoke "Update all pages" to populate internal/help files (hidden build option) CASE "-u" 'Invoke "Update all pages" to populate internal/help files (hidden build option)
Help_Recaching = 2: Help_IgnoreCache = 1 Help_Recaching = 2: Help_IgnoreCache = 1
IF ideupdatehelpbox THEN IF ideupdatehelpbox THEN
@ -13090,6 +13219,34 @@ FUNCTION ParseCMDLineArgs$ ()
ConsoleMode = 1 'Implies -x ConsoleMode = 1 'Implies -x
NoIDEMode = 1 'Implies -c NoIDEMode = 1 'Implies -c
cmdlineswitch = -1 cmdlineswitch = -1
CASE "-f" 'temporary setting
token$ = MID$(token$, 3)
SELECT CASE LCASE$(LEFT$(token$, INSTR(token$, "=") - 1))
CASE ":useminiaudio"
IF NOT ParseBooleanSetting&(token$, UseMiniaudioBackend) THEN PrintTemporarySettingsHelpAndExit InvalidSettingError$(token$)
CASE ":optimizecppprogram"
IF NOT ParseBooleanSetting&(token$, OptimizeCppProgram) THEN PrintTemporarySettingsHelpAndExit InvalidSettingError$(token$)
CASE ":stripdebugsymbols"
IF NOT ParseBooleanSetting&(token$, StripDebugSymbols) THEN PrintTemporarySettingsHelpAndExit InvalidSettingError$(token$)
CASE ":extracppflags"
IF NOT ParseStringSetting&(token$, ExtraCppFlags) THEN PrintTemporarySettingsHelpAndExit InvalidSettingError$(token$)
CASE ":extralinkerflags"
IF NOT ParseStringSetting&(token$, ExtraLinkerFlags) THEN PrintTemporarySettingsHelpAndExit InvalidSettingError$(token$)
CASE ":maxcompilerprocesses"
IF NOT ParseLongSetting&(token$, MaxParallelProcesses) THEN PrintTemporarySettingsHelpAndExit InvalidSettingError$(token$)
IF MaxParallelProcesses = 0 THEN PrintTemporarySettingsHelpAndExit "MaxCompilerProcesses must be more than zero"
CASE ELSE
PrintTemporarySettingsHelpAndExit ""
END SELECT
CASE ELSE 'Something we don't recognise, assume it's a filename CASE ELSE 'Something we don't recognise, assume it's a filename
IF PassedFileName$ = "" THEN PassedFileName$ = token$ IF PassedFileName$ = "" THEN PassedFileName$ = token$
END SELECT END SELECT
@ -13102,6 +13259,80 @@ FUNCTION ParseCMDLineArgs$ ()
END IF END IF
END FUNCTION END FUNCTION
FUNCTION InvalidSettingError$(token$)
InvalidSettingError$ = "Invalid temporary setting switch: " + AddQuotes$(token$)
END FUNCTION
SUB PrintTemporarySettingsHelpAndExit(errstr$)
_DEST _CONSOLE
PRINT "QB64-PE Compiler V" + Version$
IF errstr$ <> "" THEN
PRINT "Error: "; errstr$
END IF
PRINT
PRINT "Note: Defaults can be changed by IDE settings"
PRINT
PRINT "Valid settings:"
PRINT " -f:UseMiniAudio=[true|false] (Use Miniaudio Audio backend, default true)"
PRINT " -f:OptimizeCppProgram=[true|false] (Use C++ Optimization flag, default false)"
PRINT " -f:StripDebugSymbols=[true|false] (Stirp C++ debug symbols, default true)"
PRINT " -f:ExtraCppFlags=[string] (Extra flags to pass to the C++ compiler)"
PRINT " -f:ExtraLinkerFlags=[string] (Extra flags to pass at link time)"
PRINT " -f:MaxCompilerProcesses=[integer] (Max C++ compiler processes to start in parallel)"
SYSTEM
END SUB
FUNCTION ParseBooleanSetting&(token$, setting AS _UNSIGNED LONG)
DIM equals AS LONG
DIM value AS STRING
equals = INSTR(token$, "=")
IF equals = -1 THEN ParseBooleanSetting& = 0: EXIT FUNCTION
value = LCASE$(MID$(token$, equals + 1))
SELECT CASE value
CASE "true", "on", "yes"
setting = -1
ParseBooleanSetting& = -1
CASE "false", "off", "no"
setting = 0
ParseBooleanSetting& = -1
CASE ELSE
ParseBooleanSetting& = 0
END SELECT
END FUNCTION
FUNCTION ParseLongSetting&(token$, setting AS _UNSIGNED LONG)
DIM equals AS LONG
DIM value AS STRING
equals = INSTR(token$, "=")
IF equals = -1 THEN ParseLongSetting& = 0: EXIT FUNCTION
setting = VAL(MID$(token$, equals + 1))
ParseLongSetting& = -1
END FUNCTION
FUNCTION ParseStringSetting&(token$, setting AS STRING)
DIM equals AS LONG
DIM value AS STRING
equals = INSTR(token$, "=")
IF equals = -1 THEN ParseStringSetting& = 0: EXIT FUNCTION
setting = MID$(token$, equals + 1)
ParseStringSetting& = -1
END FUNCTION
FUNCTION Type2MemTypeValue (t1) FUNCTION Type2MemTypeValue (t1)
t = 0 t = 0
IF t1 AND ISARRAY THEN t = t + 65536 IF t1 AND ISARRAY THEN t = t + 65536

View file

@ -4,5 +4,5 @@ listOfKeywords$ = listOfKeywords$ + "_ERRORLINE@_ERRORMESSAGE$@_EXIT@_EXPLICIT@_
listOfKeywords$ = listOfKeywords$ + "_GLCOPYTEXSUBIMAGE2D@_GLCULLFACE@_GLDELETELISTS@_GLDELETETEXTURES@_GLDEPTHFUNC@_GLDEPTHMASK@_GLDEPTHRANGE@_GLDISABLE@_GLDISABLECLIENTSTATE@_GLDRAWARRAYS@_GLDRAWBUFFER@_GLDRAWELEMENTS@_GLDRAWPIXELS@_GLEDGEFLAG@_GLEDGEFLAGPOINTER@_GLEDGEFLAGV@_GLENABLE@_GLENABLECLIENTSTATE@_GLEND@_GLENDLIST@_GLEVALCOORD1D@_GLEVALCOORD1DV@_GLEVALCOORD1F@_GLEVALCOORD1FV@_GLEVALCOORD2D@_GLEVALCOORD2DV@_GLEVALCOORD2F@_GLEVALCOORD2FV@_GLEVALMESH1@_GLEVALMESH2@_GLEVALPOINT1@_GLEVALPOINT2@_GLFEEDBACKBUFFER@_GLFINISH@_GLFLUSH@_GLFOGF@_GLFOGFV@_GLFOGI@_GLFOGIV@_GLFRONTFACE@_GLFRUSTUM@_GLGENLISTS@_GLGENTEXTURES@_GLGETBOOLEANV@_GLGETCLIPPLANE@_GLGETDOUBLEV@_GLGETERROR@_GLGETFLOATV@_GLGETINTEGERV@_GLGETLIGHTFV@_GLGETLIGHTIV@_GLGETMAPDV@_GLGETMAPFV@_GLGETMAPIV@_GLGETMATERIALFV@_GLGETMATERIALIV@_GLGETPIXELMAPFV@_GLGETPIXELMAPUIV@_GLGETPIXELMAPUSV@_GLGETPOINTERV@_GLGETPOLYGONSTIPPLE@_GLGETSTRING@_GLGETTEXENVFV@_GLGETTEXENVIV@_GLGETTEXGENDV@_GLGETTEXGENFV@_GLGETTEXGENIV@_GLGETTEXIMAGE@_GLGETTEXLEVELPARAMETERFV@_GLGETTEXLEVELPARAMETERIV@_GLGETTEXPARAMETERFV@_GLGETTEXPARAMETERIV@_GLHINT@_GLINDEXMASK@_GLINDEXPOINTER@_GLINDEXD@_GLINDEXDV@_GLINDEXF@_GLINDEXFV@_GLINDEXI@_GLINDEXIV@_GLINDEXS@_GLINDEXSV@_GLINDEXUB@_GLINDEXUBV@_GLINITNAMES@_GLINTERLEAVEDARRAYS@_GLISENABLED@_GLISLIST@_GLISTEXTURE@_GLLIGHTMODELF@_GLLIGHTMODELFV@_GLLIGHTMODELI@_GLLIGHTMODELIV@_GLLIGHTF@_GLLIGHTFV@_GLLIGHTI@_GLLIGHTIV@_GLLINESTIPPLE@_GLLINEWIDTH@_GLLISTBASE@_GLLOADIDENTITY@_GLLOADMATRIXD@_GLLOADMATRIXF@_GLLOADNAME@_GLLOGICOP@_GLMAP1D@_GLMAP1F@_GLMAP2D@_GLMAP2F@_GLMAPGRID1D@_GLMAPGRID1F@_GLMAPGRID2D@_GLMAPGRID2F@_GLMATERIALF@_GLMATERIALFV@_GLMATERIALI@_GLMATERIALIV@_GLMATRIXMODE@_GLMULTMATRIXD@_GLMULTMATRIXF@_GLNEWLIST@_GLNORMAL3B@_GLNORMAL3BV@_GLNORMAL3D@_GLNORMAL3DV@_GLNORMAL3F@_GLNORMAL3FV@_GLNORMAL3I@_GLNORMAL3IV@_GLNORMAL3S@_GLNORMAL3SV@_GLNORMALPOINTER@_GLORTHO@_GLPASSTHROUGH@_GLPIXELMAPFV@_GLPIXELMAPUIV@_GLPIXELMAPUSV@_GLPIXELSTOREF@_GLPIXELSTOREI@_GLPIXELTRANSFERF@_GLPIXELTRANSFERI@_GLPIXELZOOM@_GLPOINTSIZE@_GLPOLYGONMODE@_GLPOLYGONOFFSET@_GLPOLYGONSTIPPLE@" listOfKeywords$ = listOfKeywords$ + "_GLCOPYTEXSUBIMAGE2D@_GLCULLFACE@_GLDELETELISTS@_GLDELETETEXTURES@_GLDEPTHFUNC@_GLDEPTHMASK@_GLDEPTHRANGE@_GLDISABLE@_GLDISABLECLIENTSTATE@_GLDRAWARRAYS@_GLDRAWBUFFER@_GLDRAWELEMENTS@_GLDRAWPIXELS@_GLEDGEFLAG@_GLEDGEFLAGPOINTER@_GLEDGEFLAGV@_GLENABLE@_GLENABLECLIENTSTATE@_GLEND@_GLENDLIST@_GLEVALCOORD1D@_GLEVALCOORD1DV@_GLEVALCOORD1F@_GLEVALCOORD1FV@_GLEVALCOORD2D@_GLEVALCOORD2DV@_GLEVALCOORD2F@_GLEVALCOORD2FV@_GLEVALMESH1@_GLEVALMESH2@_GLEVALPOINT1@_GLEVALPOINT2@_GLFEEDBACKBUFFER@_GLFINISH@_GLFLUSH@_GLFOGF@_GLFOGFV@_GLFOGI@_GLFOGIV@_GLFRONTFACE@_GLFRUSTUM@_GLGENLISTS@_GLGENTEXTURES@_GLGETBOOLEANV@_GLGETCLIPPLANE@_GLGETDOUBLEV@_GLGETERROR@_GLGETFLOATV@_GLGETINTEGERV@_GLGETLIGHTFV@_GLGETLIGHTIV@_GLGETMAPDV@_GLGETMAPFV@_GLGETMAPIV@_GLGETMATERIALFV@_GLGETMATERIALIV@_GLGETPIXELMAPFV@_GLGETPIXELMAPUIV@_GLGETPIXELMAPUSV@_GLGETPOINTERV@_GLGETPOLYGONSTIPPLE@_GLGETSTRING@_GLGETTEXENVFV@_GLGETTEXENVIV@_GLGETTEXGENDV@_GLGETTEXGENFV@_GLGETTEXGENIV@_GLGETTEXIMAGE@_GLGETTEXLEVELPARAMETERFV@_GLGETTEXLEVELPARAMETERIV@_GLGETTEXPARAMETERFV@_GLGETTEXPARAMETERIV@_GLHINT@_GLINDEXMASK@_GLINDEXPOINTER@_GLINDEXD@_GLINDEXDV@_GLINDEXF@_GLINDEXFV@_GLINDEXI@_GLINDEXIV@_GLINDEXS@_GLINDEXSV@_GLINDEXUB@_GLINDEXUBV@_GLINITNAMES@_GLINTERLEAVEDARRAYS@_GLISENABLED@_GLISLIST@_GLISTEXTURE@_GLLIGHTMODELF@_GLLIGHTMODELFV@_GLLIGHTMODELI@_GLLIGHTMODELIV@_GLLIGHTF@_GLLIGHTFV@_GLLIGHTI@_GLLIGHTIV@_GLLINESTIPPLE@_GLLINEWIDTH@_GLLISTBASE@_GLLOADIDENTITY@_GLLOADMATRIXD@_GLLOADMATRIXF@_GLLOADNAME@_GLLOGICOP@_GLMAP1D@_GLMAP1F@_GLMAP2D@_GLMAP2F@_GLMAPGRID1D@_GLMAPGRID1F@_GLMAPGRID2D@_GLMAPGRID2F@_GLMATERIALF@_GLMATERIALFV@_GLMATERIALI@_GLMATERIALIV@_GLMATRIXMODE@_GLMULTMATRIXD@_GLMULTMATRIXF@_GLNEWLIST@_GLNORMAL3B@_GLNORMAL3BV@_GLNORMAL3D@_GLNORMAL3DV@_GLNORMAL3F@_GLNORMAL3FV@_GLNORMAL3I@_GLNORMAL3IV@_GLNORMAL3S@_GLNORMAL3SV@_GLNORMALPOINTER@_GLORTHO@_GLPASSTHROUGH@_GLPIXELMAPFV@_GLPIXELMAPUIV@_GLPIXELMAPUSV@_GLPIXELSTOREF@_GLPIXELSTOREI@_GLPIXELTRANSFERF@_GLPIXELTRANSFERI@_GLPIXELZOOM@_GLPOINTSIZE@_GLPOLYGONMODE@_GLPOLYGONOFFSET@_GLPOLYGONSTIPPLE@"
listOfKeywords$ = listOfKeywords$ + "_GLPOPATTRIB@_GLPOPCLIENTATTRIB@_GLPOPMATRIX@_GLPOPNAME@_GLPRIORITIZETEXTURES@_GLPUSHATTRIB@_GLPUSHCLIENTATTRIB@_GLPUSHMATRIX@_GLPUSHNAME@_GLRASTERPOS2D@_GLRASTERPOS2DV@_GLRASTERPOS2F@_GLRASTERPOS2FV@_GLRASTERPOS2I@_GLRASTERPOS2IV@_GLRASTERPOS2S@_GLRASTERPOS2SV@_GLRASTERPOS3D@_GLRASTERPOS3DV@_GLRASTERPOS3F@_GLRASTERPOS3FV@_GLRASTERPOS3I@_GLRASTERPOS3IV@_GLRASTERPOS3S@_GLRASTERPOS3SV@_GLRASTERPOS4D@_GLRASTERPOS4DV@_GLRASTERPOS4F@_GLRASTERPOS4FV@_GLRASTERPOS4I@_GLRASTERPOS4IV@_GLRASTERPOS4S@_GLRASTERPOS4SV@_GLREADBUFFER@_GLREADPIXELS@_GLRECTD@_GLRECTDV@_GLRECTF@_GLRECTFV@_GLRECTI@_GLRECTIV@_GLRECTS@_GLRECTSV@_GLRENDERMODE@_GLROTATED@_GLROTATEF@_GLSCALED@_GLSCALEF@_GLSCISSOR@_GLSELECTBUFFER@_GLSHADEMODEL@_GLSTENCILFUNC@_GLSTENCILMASK@_GLSTENCILOP@_GLTEXCOORD1D@_GLTEXCOORD1DV@_GLTEXCOORD1F@_GLTEXCOORD1FV@_GLTEXCOORD1I@_GLTEXCOORD1IV@_GLTEXCOORD1S@_GLTEXCOORD1SV@_GLTEXCOORD2D@_GLTEXCOORD2DV@_GLTEXCOORD2F@_GLTEXCOORD2FV@_GLTEXCOORD2I@_GLTEXCOORD2IV@_GLTEXCOORD2S@_GLTEXCOORD2SV@_GLTEXCOORD3D@_GLTEXCOORD3DV@_GLTEXCOORD3F@_GLTEXCOORD3FV@_GLTEXCOORD3I@_GLTEXCOORD3IV@_GLTEXCOORD3S@_GLTEXCOORD3SV@_GLTEXCOORD4D@_GLTEXCOORD4DV@_GLTEXCOORD4F@_GLTEXCOORD4FV@_GLTEXCOORD4I@_GLTEXCOORD4IV@_GLTEXCOORD4S@_GLTEXCOORD4SV@_GLTEXCOORDPOINTER@_GLTEXENVF@_GLTEXENVFV@_GLTEXENVI@_GLTEXENVIV@_GLTEXGEND@_GLTEXGENDV@_GLTEXGENF@_GLTEXGENFV@_GLTEXGENI@_GLTEXGENIV@_GLTEXIMAGE1D@_GLTEXIMAGE2D@_GLTEXPARAMETERF@_GLTEXPARAMETERFV@_GLTEXPARAMETERI@_GLTEXPARAMETERIV@_GLTEXSUBIMAGE1D@_GLTEXSUBIMAGE2D@_GLTRANSLATED@_GLTRANSLATEF@_GLVERTEX2D@_GLVERTEX2DV@_GLVERTEX2F@_GLVERTEX2FV@_GLVERTEX2I@_GLVERTEX2IV@_GLVERTEX2S@_GLVERTEX2SV@_GLVERTEX3D@_GLVERTEX3DV@_GLVERTEX3F@_GLVERTEX3FV@_GLVERTEX3I@_GLVERTEX3IV@_GLVERTEX3S@_GLVERTEX3SV@_GLVERTEX4D@_GLVERTEX4DV@_GLVERTEX4F@_GLVERTEX4FV@_GLVERTEX4I@_GLVERTEX4IV@_GLVERTEX4S@_GLVERTEX4SV@_GLVERTEXPOINTER@_GLVIEWPORT@SMOOTH@STRETCH@_ANTICLOCKWISE@_BEHIND@_CLEAR@_FILLBACKGROUND@_GLUPERSPECTIVE@_HARDWARE@_HARDWARE1@_KEEPBACKGROUND@_NONE@_OFF@_ONLY@_ONLYBACKGROUND@_ONTOP@_SEAMLESS@_SMOOTH@_SMOOTHSHRUNK@_SMOOTHSTRETCHED@" listOfKeywords$ = listOfKeywords$ + "_GLPOPATTRIB@_GLPOPCLIENTATTRIB@_GLPOPMATRIX@_GLPOPNAME@_GLPRIORITIZETEXTURES@_GLPUSHATTRIB@_GLPUSHCLIENTATTRIB@_GLPUSHMATRIX@_GLPUSHNAME@_GLRASTERPOS2D@_GLRASTERPOS2DV@_GLRASTERPOS2F@_GLRASTERPOS2FV@_GLRASTERPOS2I@_GLRASTERPOS2IV@_GLRASTERPOS2S@_GLRASTERPOS2SV@_GLRASTERPOS3D@_GLRASTERPOS3DV@_GLRASTERPOS3F@_GLRASTERPOS3FV@_GLRASTERPOS3I@_GLRASTERPOS3IV@_GLRASTERPOS3S@_GLRASTERPOS3SV@_GLRASTERPOS4D@_GLRASTERPOS4DV@_GLRASTERPOS4F@_GLRASTERPOS4FV@_GLRASTERPOS4I@_GLRASTERPOS4IV@_GLRASTERPOS4S@_GLRASTERPOS4SV@_GLREADBUFFER@_GLREADPIXELS@_GLRECTD@_GLRECTDV@_GLRECTF@_GLRECTFV@_GLRECTI@_GLRECTIV@_GLRECTS@_GLRECTSV@_GLRENDERMODE@_GLROTATED@_GLROTATEF@_GLSCALED@_GLSCALEF@_GLSCISSOR@_GLSELECTBUFFER@_GLSHADEMODEL@_GLSTENCILFUNC@_GLSTENCILMASK@_GLSTENCILOP@_GLTEXCOORD1D@_GLTEXCOORD1DV@_GLTEXCOORD1F@_GLTEXCOORD1FV@_GLTEXCOORD1I@_GLTEXCOORD1IV@_GLTEXCOORD1S@_GLTEXCOORD1SV@_GLTEXCOORD2D@_GLTEXCOORD2DV@_GLTEXCOORD2F@_GLTEXCOORD2FV@_GLTEXCOORD2I@_GLTEXCOORD2IV@_GLTEXCOORD2S@_GLTEXCOORD2SV@_GLTEXCOORD3D@_GLTEXCOORD3DV@_GLTEXCOORD3F@_GLTEXCOORD3FV@_GLTEXCOORD3I@_GLTEXCOORD3IV@_GLTEXCOORD3S@_GLTEXCOORD3SV@_GLTEXCOORD4D@_GLTEXCOORD4DV@_GLTEXCOORD4F@_GLTEXCOORD4FV@_GLTEXCOORD4I@_GLTEXCOORD4IV@_GLTEXCOORD4S@_GLTEXCOORD4SV@_GLTEXCOORDPOINTER@_GLTEXENVF@_GLTEXENVFV@_GLTEXENVI@_GLTEXENVIV@_GLTEXGEND@_GLTEXGENDV@_GLTEXGENF@_GLTEXGENFV@_GLTEXGENI@_GLTEXGENIV@_GLTEXIMAGE1D@_GLTEXIMAGE2D@_GLTEXPARAMETERF@_GLTEXPARAMETERFV@_GLTEXPARAMETERI@_GLTEXPARAMETERIV@_GLTEXSUBIMAGE1D@_GLTEXSUBIMAGE2D@_GLTRANSLATED@_GLTRANSLATEF@_GLVERTEX2D@_GLVERTEX2DV@_GLVERTEX2F@_GLVERTEX2FV@_GLVERTEX2I@_GLVERTEX2IV@_GLVERTEX2S@_GLVERTEX2SV@_GLVERTEX3D@_GLVERTEX3DV@_GLVERTEX3F@_GLVERTEX3FV@_GLVERTEX3I@_GLVERTEX3IV@_GLVERTEX3S@_GLVERTEX3SV@_GLVERTEX4D@_GLVERTEX4DV@_GLVERTEX4F@_GLVERTEX4FV@_GLVERTEX4I@_GLVERTEX4IV@_GLVERTEX4S@_GLVERTEX4SV@_GLVERTEXPOINTER@_GLVIEWPORT@SMOOTH@STRETCH@_ANTICLOCKWISE@_BEHIND@_CLEAR@_FILLBACKGROUND@_GLUPERSPECTIVE@_HARDWARE@_HARDWARE1@_KEEPBACKGROUND@_NONE@_OFF@_ONLY@_ONLYBACKGROUND@_ONTOP@_SEAMLESS@_SMOOTH@_SMOOTHSHRUNK@_SMOOTHSTRETCHED@"
listOfKeywords$ = listOfKeywords$ + "_SOFTWARE@_SQUAREPIXELS@_STRETCH@_ALLOWFULLSCREEN@_ALL@_ECHO@_INSTRREV@_TRIM$@_ACCEPTFILEDROP@_FINISHDROP@_TOTALDROPPEDFILES@_DROPPEDFILE@_DROPPEDFILE$@_SHR@_SHL@_ROR@_ROL@" ' a740g: added ROR & ROL listOfKeywords$ = listOfKeywords$ + "_SOFTWARE@_SQUAREPIXELS@_STRETCH@_ALLOWFULLSCREEN@_ALL@_ECHO@_INSTRREV@_TRIM$@_ACCEPTFILEDROP@_FINISHDROP@_TOTALDROPPEDFILES@_DROPPEDFILE@_DROPPEDFILE$@_SHR@_SHL@_ROR@_ROL@" ' a740g: added ROR & ROL
listOfKeywords$ = listOfKeywords$ + "_DEFLATE$@_INFLATE$@_READBIT@_RESETBIT@_SETBIT@_TOGGLEBIT@$ASSERTS@_ASSERT@_CAPSLOCK@_NUMLOCK@_SCROLLLOCK@_TOGGLE@_CONSOLEFONT@_CONSOLECURSOR@_CONSOLEINPUT@_CINP@$NOPREFIX@$COLOR@$DEBUG@_ENVIRONCOUNT@" listOfKeywords$ = listOfKeywords$ + "_DEFLATE$@_INFLATE$@_READBIT@_RESETBIT@_SETBIT@_TOGGLEBIT@$ASSERTS@_ASSERT@_CAPSLOCK@_NUMLOCK@_SCROLLLOCK@_TOGGLE@_CONSOLEFONT@_CONSOLECURSOR@_CONSOLEINPUT@_CINP@$NOPREFIX@$COLOR@$DEBUG@_ENVIRONCOUNT@$UNSTABLE@$MIDISOUNDFONT@"

View file

@ -1,5 +1,6 @@
#!/bin/bash #!/bin/bash
# Arg 1: qb54 location # Arg 1: qb54 location
# Arg 2: Optional category to test
PREFIX="Compilation" PREFIX="Compilation"
@ -9,10 +10,14 @@ mkdir -p $RESULTS_DIR
QB64=$1 QB64=$1
if [ "$#" -eq 2 ]; then
CATEGORY="/$2"
fi
show_failure() show_failure()
{ {
cat "$RESULTS_DIR/$1-compile_result.txt" cat "$RESULTS_DIR/$1-$2-compile_result.txt"
cat "$RESULTS_DIR/$1-compilelog.txt" cat "$RESULTS_DIR/$2-compilelog.txt"
} }
show_incorrect_result() show_incorrect_result()
@ -21,41 +26,77 @@ show_incorrect_result()
printf "GOT: '%s'\n" "$2" printf "GOT: '%s'\n" "$2"
} }
for test in ./tests/compile_tests/*
do
test=$(basename "$test")
TESTCASE="$test" # Each .bas file represents a separate test.
EXE="$RESULTS_DIR/$test - output" while IFS= read -r test
do
category=$(basename "$(dirname "$test")")
testName=$(basename "$test" .bas)
TESTCASE="$category/$testName"
EXE="$RESULTS_DIR/$category-$testName - output"
# If a .err file exists, then this test is actually testing a compilation error
testType="success"
if test -f "./tests/compile_tests/$category/$testName.err"; then
testType="error"
fi
# Clear out temp folder before next compile, avoids stale compilelog files # Clear out temp folder before next compile, avoids stale compilelog files
rm -fr ./internal/temp/* rm -fr ./internal/temp/*
"$QB64" -x "./tests/compile_tests/$test/test.bas" -o "$EXE" 1>"$RESULTS_DIR/$test-compile_result.txt" # Clean up existing EXE, so we don't use it by accident
ERR=$? rm -f "$EXE*"
cp_if_exists ./internal/temp/compilelog.txt "$RESULTS_DIR/$test-compilelog.txt"
(exit $ERR) compileResultOutput="$RESULTS_DIR/$category-$testName-compile_result.txt"
assert_success_named "Compile" "Compilation Error:" show_failure "$test"
test -f "$EXE" # A .flags file contains any extra compiler flags to provide to QB64 for this test
assert_success_named "exe exists" "$test-output executable does not exist!" show_failure "$test" compilerFlags=
if test -f "./tests/compile_tests/$category/$testName.flags"; then
if [ ! -f "./tests/compile_tests/$test/test.output" ]; then compilerFlags=$(cat "./tests/compile_tests/$category/$testName.flags")
continue
fi fi
expectedResult="$(cat "./tests/compile_tests/$test/test.output")" # -m and -q make sure that we get predictable results
"$QB64" $compilerFlags -m -q -x "./tests/compile_tests/$category/$testName.bas" -o "$EXE" 1>"$compileResultOutput"
pushd . > /dev/null
cd "./tests/compile_tests/$test"
testResult=$("../../../$EXE" 2>&1)
ERR=$? ERR=$?
popd > /dev/null cp_if_exists ./internal/temp/compilelog.txt "$RESULTS_DIR/$category-$testName-compilelog.txt"
(exit $ERR) if [ "$testType" == "success" ]; then
assert_success_named "run" "Execution Error:" echo "$testResult" (exit $ERR)
assert_success_named "Compile" "Compilation Error:" show_failure "$category" "$testName"
[ "$testResult" == "$expectedResult" ] test -f "$EXE"
assert_success_named "result" "Result is wrong:" show_incorrect_result "$expectedResult" "$testResult" assert_success_named "exe exists" "$test-output executable does not exist!" show_failure "$category" "$testName"
done
# Some tests do not have an output or err file because they should
# compile successfully but cannot be run on the build agents
if [ ! -f "./tests/compile_tests/$category/$testName.output" ]; then
continue
fi
expectedResult="$(cat "./tests/compile_tests/$category/$testName.output")"
pushd . > /dev/null
cd "./tests/compile_tests/$category"
testResult=$("../../../$EXE" 2>&1)
ERR=$?
popd > /dev/null
(exit $ERR)
assert_success_named "run" "Execution Error:" echo "$testResult"
[ "$testResult" == "$expectedResult" ]
assert_success_named "result" "Result is wrong:" show_incorrect_result "$expectedResult" "$testResult"
else
! (exit $ERR)
assert_success_named "Compile" "Compilation Success, was expecting error:" show_failure "$category" "$testName"
! test -f "$EXE"
assert_success_named "Exe exists" "'$category-$testName - output' exists, it should not!" show_failure "$category" "$testName"
expectedErr="$(cat "./tests/compile_tests/$category/$testName.err")"
diffResult=$(diff -y "./tests/compile_tests/$category/$testName.err" "$compileResultOutput")
assert_success_named "Error result" "Error reporting is wrong:" echo "$diffResult"
fi
done < <(find ./tests/compile_tests$CATEGORY -name "*.bas" -print)

View file

@ -0,0 +1,12 @@
$CONSOLE
$SCREENHIDE
_DEST _CONSOLE
CHDIR _STARTDIR$
$Unstable: Midi
$MidiSoundFont: "tests/compile_tests/midi/test-soundfont.sf2"
handle = _SndOpen("./midi.mid")
print handle;
SYSTEM

View file

@ -0,0 +1 @@
1

Binary file not shown.

View file

@ -0,0 +1,3 @@
$UNSTABLE:MIDI
$MIDISOUNDFONT: "test-soundfont.sf2" extra

View file

@ -0,0 +1,4 @@
Unexpected characters after the quoted file name
Caused by (or after):[INFORMATION UNAVAILABLE]
LINE 3:$MIDISOUNDFONT: "test-soundfont.sf2" extra

View file

@ -0,0 +1,3 @@
$UNSTABLE:MIDI
$MIDISOUNDFONT: test-soundfont.sf2"

View file

@ -0,0 +1,4 @@
Unrecognized Soundfont option "test-soundfont.sf2""
Caused by (or after):[INFORMATION UNAVAILABLE]
LINE 3:$MIDISOUNDFONT: test-soundfont.sf2"

View file

@ -0,0 +1,3 @@
$UNSTABLE:MIDI
$MIDISOUNDFONT: "test-soundfont.sf2

View file

@ -0,0 +1,4 @@
Expected " character at the end of the file name
Caused by (or after):[INFORMATION UNAVAILABLE]
LINE 3:$MIDISOUNDFONT: "test-soundfont.sf2

View file

@ -0,0 +1,3 @@
$Unstable: Midi
$MidiSoundFont: test-soundfont.sf2

View file

@ -0,0 +1,4 @@
Unrecognized Soundfont option "test-soundfont.sf2"
Caused by (or after):[INFORMATION UNAVAILABLE]
LINE 3:$MidiSoundFont: test-soundfont.sf2

View file

@ -0,0 +1,2 @@
$MIDISOUNDFONT: "test-soundfont.sf2"

View file

@ -0,0 +1,4 @@
Syntax error
Caused by (or after):$ MIDISOUNDFONT
LINE 2:$MIDISOUNDFONT: "test-soundfont.sf2"

View file

@ -0,0 +1,4 @@
$UNSTABLE:MIDI
$MIDISOUNDFONT: DEFAULT

View file

@ -0,0 +1,4 @@
Midi is not supported with the old OpenAL audio backend.
Caused by (or after):
LINE 2:$ UNSTABLE : MIDI

View file

@ -0,0 +1 @@
-f:UseMiniaudio=false

Binary file not shown.

View file

@ -0,0 +1,12 @@
$CONSOLE
$SCREENHIDE
_DEST _CONSOLE
CHDIR _STARTDIR$
$Unstable: Midi
$MidiSoundFont: Default
handle = _SndOpen("./midi.mid")
print handle;
SYSTEM

View file

@ -0,0 +1 @@
1