1
1
Fork 0
mirror of https://github.com/QB64-Phoenix-Edition/QB64pe.git synced 2024-07-04 04:50:22 +00:00

Replace time() with std::chrono, fix startup delay

Currently main() includes logic that is intended to sync time() with
GetTicks() for the purpose of using GetTicks() to get millisecond
accuracy with time(), which only has second accuracy. Unfortunately, the
'syncing' up of these time sources results in an average of a half
second delay in starting a QB64-PE program.

This logic is easly replaced with std::chrono, which provides a real
time clock which is also millisecond accurate. That removes the need to
use time() and GetTicks() together to get millisecond accuracy, and
means the delay syncing them is no longer necessary.

I also separated most of the "delay" and "time" related functions into
datetime.cpp, and included the new std::chrono code into that file.

Since I needed to call some of the rounding functions in datetime.cpp I
also moved that stuff out into its own .cpp and header files to clean
things up a bit.

Fixes: #282
This commit is contained in:
Matthew Kilgore 2023-01-08 02:41:54 -05:00
parent a3cea42e0d
commit f21ce09e2d
14 changed files with 453 additions and 457 deletions

View file

@ -25,6 +25,9 @@
#include "http.h"
#include "keyhandler.h"
#include "glut-thread.h"
#include "datetime.h"
#include "rounding.h"
#include "event.h"
int32 disableEvents = 0;
@ -41,102 +44,8 @@ int32 func__getconsoleinput(); // declare here, so we can use with SLEEP and END
uint32 rotateLeft(uint32 word, uint32 shift) { return (word << shift) | (word >> (32 - shift)); }
#ifndef QB64_WINDOWS
void Sleep(uint32 milliseconds) {
static uint64 sec, nsec;
sec = milliseconds / 1000;
nsec = (milliseconds % 1000) * 1000000;
static timespec ts;
ts.tv_sec = sec;
ts.tv_nsec = nsec;
nanosleep(&ts, NULL);
}
void ZeroMemory(void *ptr, int64 bytes) { memset(ptr, 0, bytes); }
#endif
#ifdef QB64_NOT_X86
int64 qbr(long double f) {
int64 i;
int temp = 0;
if (f > 9223372036854775807) {
temp = 1;
f = f - 9223372036854775808u;
} // if it's too large for a signed int64, make it an unsigned int64 and return that value if possible.
if (f < 0)
i = f - 0.5f;
else
i = f + 0.5f;
if (temp)
return i | 0x8000000000000000; //+9223372036854775808;
return i;
}
uint64 qbr_longdouble_to_uint64(long double f) {
if (f < 0)
return (f - 0.5f);
else
return (f + 0.5f);
}
int32 qbr_float_to_long(float f) {
if (f < 0)
return (f - 0.5f);
else
return (f + 0.5f);
}
int32 qbr_double_to_long(double f) {
if (f < 0)
return (f - 0.5f);
else
return (f + 0.5f);
}
void fpu_reinit() {} // do nothing
#else
// QBASIC compatible rounding via FPU:
// FLDS=load single
// FLDL=load double
// FLDT=load long double
int64 qbr(long double f) {
int64 i;
int temp = 0;
if (f > 9223372036854775807) {
temp = 1;
f = f - 9223372036854775808u;
} // if it's too large for a signed int64, make it an unsigned int64 and return that value if possible.
__asm__("fldt %1;"
"fistpll %0;"
: "=m"(i)
: "m"(f));
if (temp)
return i | 0x8000000000000000; // if it's an unsigned int64, manually set the bit flag
return i;
}
uint64 qbr_longdouble_to_uint64(long double f) {
uint64 i;
__asm__("fldt %1;"
"fistpll %0;"
: "=m"(i)
: "m"(f));
return i;
}
int32 qbr_float_to_long(float f) {
int32 i;
__asm__("flds %1;"
"fistpl %0;"
: "=m"(i)
: "m"(f));
return i;
}
int32 qbr_double_to_long(double f) {
int32 i;
__asm__("fldl %1;"
"fistpl %0;"
: "=m"(i)
: "m"(f));
return i;
}
void fpu_reinit() {
unsigned int mode = 0x37F;
asm("fldcw %0" : : "m"(*&mode));
}
#endif // x86 support
// bit-array access functions (note: used to be included through 'bit.cpp')
uint64 getubits(uint32 bsize, uint8 *base, ptrszint i) {
int64 bmask;
@ -220,8 +129,6 @@ void sub__printimage(int32 i);
// GUI notification variables
int32 force_display_update = 0;
void sub__delay(double seconds);
void *generic_window_handle = NULL;
int32 acceptFileDrop = 0;
#ifdef QB64_WINDOWS
@ -293,8 +200,6 @@ extern "C" int QB64_Resizable() { return ScreenResize; }
int32 sub_gl_called = 0;
extern void evnt(uint32 linenumber, uint32 inclinenumber = 0, const char *incfilename = NULL);
extern "C" int qb64_custom_event(int event, int v1, int v2, int v3, int v4, int v5, int v6, int v7, int v8, void *p1, void *p2);
#ifdef QB64_WINDOWS
extern "C" LRESULT qb64_os_event_windows(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, int *qb64_os_event_info);
@ -1180,40 +1085,6 @@ static uint16 codepage437_to_unicode16[] = {
# include "parts/video/font/ttf/src.c"
#endif
#ifdef QB64_MACOSX
# include <mach/mach_time.h>
# define ORWL_NANO (+1.0E-9)
# define ORWL_GIGA UINT64_C(1000000000)
static double orwl_timebase = 0.0;
static uint64_t orwl_timestart = 0;
int64 orwl_gettime(void) {
if (!orwl_timestart) {
mach_timebase_info_data_t tb = {0};
mach_timebase_info(&tb);
orwl_timebase = tb.numer;
orwl_timebase /= tb.denom;
orwl_timestart = mach_absolute_time();
}
struct timespec t;
double diff = (mach_absolute_time() - orwl_timestart) * orwl_timebase;
t.tv_sec = diff * ORWL_NANO;
t.tv_nsec = diff - (t.tv_sec * ORWL_GIGA);
return t.tv_sec * 1000 + t.tv_nsec / 1000000;
}
#endif
#ifdef QB64_LINUX
int64 GetTicks() {
struct timespec tp;
clock_gettime(CLOCK_MONOTONIC, &tp);
return tp.tv_sec * 1000 + tp.tv_nsec / 1000000;
}
#elif defined QB64_MACOSX
int64 GetTicks() { return orwl_gettime(); }
#else
int64 GetTicks() { return ((((int64)clock()) * ((int64)1000)) / ((int64)CLOCKS_PER_SEC)); }
#endif
/* Restricted Functionality: (Security focused approach, does not include restricting sound etc)
Block while compiling: (ONLY things that cannot be caught at runtime)
@ -1315,7 +1186,6 @@ void sub_shell4(qbs *, int32); //_DONTWAIT & _HIDE
int32 func__source();
int32 func_pos(int32 ignore);
double func_timer(double accuracy, int32 passed);
int32 func__newimage(int32 x, int32 y, int32 bpp, int32 passed);
void display();
void validatepage(int32);
@ -7387,9 +7257,6 @@ extern uint32 cmem_sp; //=65536;
extern ptrszint dblock; // 32bit offset of dblock
extern uint64 *nothingvalue;
uint32 qb64_firsttimervalue; // based on time of day
uint32 clock_firsttimervalue; // based on program launch time
uint8 wait_needed = 1;
int32 full_screen = 0; // 0,1(stretched/closest),2(1:1)
@ -7454,7 +7321,6 @@ extern uint8 stop_program;
int32 global_counter = 0;
extern double last_line;
void end(void);
extern uint32 new_error;
extern uint32 error_err; //=0;
extern double error_erl; //=0;
extern uint32 error_occurred;
@ -16779,78 +16645,6 @@ float func_rnd(float n, int32 passed) {
return (double)rnd_seed / 0x1000000;
}
double func_timer(double accuracy, int32 passed) {
if (new_error)
return 0;
static uint32 x;
static double d;
static float f;
x = GetTicks();
x -= clock_firsttimervalue;
x += qb64_firsttimervalue;
// make timer value loop after midnight
// note: there are 86400000 milliseconds in 24hrs(1 day)
x %= 86400000;
d = x; // convert to double
d /= 1000.0; // convert from ms to sec
// reduce accuracy
if (!passed) {
accuracy = 18.2;
} else {
if (accuracy <= 0.0) {
error(5);
return 0;
}
accuracy = 1.0 / accuracy;
}
d *= accuracy;
d = qbr(d);
d /= accuracy;
if (!passed) {
f = d;
d = f;
}
return d;
}
void sub__delay(double seconds) {
double ms, base, elapsed, prev_now, now; // cannot be static
base = GetTicks();
if (new_error)
return;
if (seconds < 0) {
error(5);
return;
}
if (seconds > 2147483.647) {
error(5);
return;
}
ms = seconds * 1000.0;
now = base; // force first prev=... assignment to equal base
recalculate:
prev_now = now;
now = GetTicks();
elapsed = now - base;
if (elapsed < 0) { // GetTicks looped
base = now - (prev_now - base); // calculate new base
}
if (elapsed < ms) {
int64 wait; // cannot be static
wait = ms - elapsed;
if (!wait)
wait = 1;
if (wait >= 10) {
Sleep(9);
evnt(0); // check for new events
// recalculate time
goto recalculate;
} else {
Sleep(wait);
}
}
}
void sub__fps(double fps, int32 passed) {
// passed=1 means _AUTO
// passed=2 means use fps
@ -16875,60 +16669,6 @@ void sub__fps(double fps, int32 passed) {
}
}
void sub__limit(double fps) {
if (new_error)
return;
static double prev = 0;
double ms, now, elapsed; // cannot be static
if (fps <= 0.0) {
error(5);
return;
}
ms = 1000.0 / fps;
if (ms > 60000.0) {
error(5);
return;
} // max. 1 min delay between frames allowed to avoid accidental lock-up of program
recalculate:
now = GetTicks();
if (prev == 0.0) { // first call?
prev = now;
return;
}
if (now < prev) { // value looped?
prev = now;
return;
}
elapsed = now - prev; // elapsed time since prev
if (elapsed == ms) {
prev = prev + ms;
return;
}
if (elapsed < ms) {
int64 wait; // cannot be static
wait = ms - elapsed;
if (!wait)
wait = 1;
if (wait >= 10) {
Sleep(9);
evnt(0); // check for new events
} else {
Sleep(wait);
}
// recalculate time
goto recalculate;
}
// too long since last call, adjust prev to current time
// minor overshoot up to 32ms is recovered, otherwise time is re-seeded
if (elapsed <= (ms + 32.0))
prev = prev + ms;
else
prev = now;
}
int32 generic_put(int32 i, int32 offset, uint8 *cp, int32 bytes) {
// note: generic_put & generic_get have been made largely redundant by gfs_read & gfs_write
// offset is a byte-offset from base 0 (-1=current pos)
@ -37309,53 +37049,6 @@ int main(int argc, char *argv[]) {
func_command_count = argc;
func_command_array = argv;
// struct tm:
// int tm_sec; /* seconds after the minute - [0,59] */
// int tm_min; /* minutes after the hour - [0,59] */
// int tm_hour; /* hours since midnight - [0,23] */
// int tm_mday; /* day of the month - [1,31] */
// int tm_mon; /* months since January - [0,11] */
// int tm_year; /* years since 1900 */
// int tm_wday; /* days since Sunday - [0,6] */
// int tm_yday; /* days since January 1 - [0,365] */
// int tm_isdst; /* daylight savings time flag */
tm *qb64_tm;
time_t qb64_tm_val;
time_t qb64_tm_val_old;
// call both timing routines as close as possible to each other to maximize accuracy
// wait for second "hand" to "tick over"/move
time(&qb64_tm_val_old);
// note: time() returns the time as seconds elapsed since midnight, January 1, 1970, or -1 in the case of an error.
if (qb64_tm_val_old != -1) {
do {
time(&qb64_tm_val);
} while (qb64_tm_val == qb64_tm_val_old);
} else {
qb64_tm_val = 0; // time unknown! (set to midnight, January 1, 1970)
}
clock_firsttimervalue = GetTicks();
// calculate localtime as milliseconds past midnight
qb64_tm = localtime(&qb64_tm_val);
/* re: localtime()
Return a pointer to the structure result, or NULL if the date passed to the function is:
Before midnight, January 1, 1970.
After 03:14:07, January 19, 2038, UTC (using _time32 and time32_t).
After 23:59:59, December 31, 3000, UTC (using _time64 and __time64_t).
*/
if (qb64_tm) {
qb64_firsttimervalue = qb64_tm->tm_hour * 3600 + qb64_tm->tm_min * 60 + qb64_tm->tm_sec;
qb64_firsttimervalue *= 1000;
} else {
qb64_firsttimervalue = 0; // time unknown! (set to midnight)
}
/* Used as follows for calculating TIMER value:
x=GetTicks();
x-=clock_firsttimervalue;
x+=qb64_firsttimervalue;
*/
// init truetype .ttf/.fon font library
#ifdef QB64_WINDOWS
// for caps lock, use the state of the lock (=1)
// for held keys check against (=-127)
@ -37524,12 +37217,10 @@ main_loop:
}
// update timer bytes in cmem
static uint32 cmem_ticks;
static double cmem_ticks_double;
uint64_t cmem_ticks;
cmem_ticks = (uint64_t)(func_timer(0.001, 1) * 1000);
cmem_ticks = GetTicks();
cmem_ticks -= clock_firsttimervalue;
cmem_ticks += qb64_firsttimervalue;
// make timer value loop after midnight
// note: there are 86400000 milliseconds in 24hrs(1 day)
cmem_ticks %= 86400000;

View file

@ -2,6 +2,8 @@
libqb-objs-y += $(PATH_LIBQB)/src/threading.o
libqb-objs-y += $(PATH_LIBQB)/src/buffer.o
libqb-objs-y += $(PATH_LIBQB)/src/filepath.o
libqb-objs-y += $(PATH_LIBQB)/src/datetime.o
libqb-objs-y += $(PATH_LIBQB)/src/rounding.o
libqb-objs-$(DEP_HTTP) += $(PATH_LIBQB)/src/http.o
libqb-objs-y$(DEP_HTTP) += $(PATH_LIBQB)/src/http-stub.o

View file

@ -0,0 +1,15 @@
#ifndef INCLUDE_LIBQB_DATETIME_H
#define INCLUDE_LIBQB_DATETIME_H
int64_t GetTicks();
double func_timer(double accuracy, int32_t passed);
void sub__delay(double seconds);
void sub__limit(double fps);
// We provide a 'Sleep()' function for non-Windows platforms
#ifndef QB64_WINDOWS
void Sleep(uint32_t milliseconds);
#endif
#endif

View file

@ -0,0 +1,11 @@
#ifndef INCLUDE_LIBQB_EVENT_H
#define INCLUDE_LIBQB_EVENT_H
#include <stddef.h>
void error(int32_t error_number);
void evnt(uint32_t linenumber, uint32_t inclinenumber = 0, const char *incfilename = NULL);
extern uint32_t new_error;
#endif

View file

@ -0,0 +1,122 @@
#ifndef INCLUDE_LIBQB_ROUNDING_H
#define INCLUDE_LIBQB_ROUNDING_H
#include <stdint.h>
#include "event.h"
int64_t qbr(long double);
uint64_t qbr_longdouble_to_uint64(long double);
int32_t qbr_float_to_long(float);
int32_t qbr_double_to_long(double);
void fpu_reinit();
// CSNG
static inline double func_csng_float(long double value) {
if ((value <= 3.402823466E38) && (value >= -3.402823466E38)) {
return value;
}
error(6);
return 0;
}
static inline double func_csng_double(double value) {
if ((value <= 3.402823466E38) && (value >= -3.402823466E38)) {
return value;
}
error(6);
return 0;
}
// CDBL
static inline double func_cdbl_float(long double value) {
if ((value <= 1.7976931348623157E308) &&
(value >= -1.7976931348623157E308)) {
return value;
}
error(6);
return 0;
}
// CINT
// func_cint_single uses func_cint_double
static inline int32_t func_cint_double(double value) {
if ((value < 32767.5) && (value >= -32768.5)) {
return qbr_double_to_long(value);
}
error(6);
return 0;
}
static inline int64_t func_cint_float(long double value) {
if ((value < 32767.5) && (value >= -32768.5)) {
return qbr(value);
}
error(6);
return 0;
}
static inline int16_t func_cint_long(int32_t value) {
if ((value >= -32768) && (value <= 32767))
return value;
error(6);
return 0;
}
static inline int16_t func_cint_ulong(uint32_t value) {
if (value <= 32767)
return value;
error(6);
return 0;
}
static inline int16_t func_cint_int64(int64_t value) {
if ((value >= -32768) && (value <= 32767))
return value;
error(6);
return 0;
}
static inline int16_t func_cint_uint64(uint64_t value) {
if (value <= 32767)
return value;
error(6);
return 0;
}
// CLNG
// func_clng_single uses func_clng_double
//-2147483648 to 2147483647
static inline int32_t func_clng_double(double value) {
if ((value < 2147483647.5) && (value >= -2147483648.5)) {
return qbr_double_to_long(value);
}
error(6);
return 0;
}
static inline int64_t func_clng_float(long double value) {
if ((value < 2147483647.5) && (value >= -2147483648.5)) {
return qbr(value);
}
error(6);
return 0;
}
static inline int32_t func_clng_ulong(uint32_t value) {
if (value <= 2147483647)
return value;
error(6);
return 0;
}
static inline int32_t func_clng_int64(int64_t value) {
if ((value >= -2147483648) && (value <= 2147483647))
return value;
error(6);
return 0;
}
static inline int32_t func_clng_uint64(uint64_t value) {
if (value <= 2147483647)
return value;
error(6);
return 0;
}
//_ROUND (note: round performs no error checking)
static inline int64_t func_round_double(long double value) { return qbr(value); }
static inline int64_t func_round_float(long double value) { return qbr(value); }
#endif

View file

@ -0,0 +1,196 @@
#include "libqb-common.h"
#include <sys/time.h>
#include <chrono>
#ifdef QB64_WINDOWS
# include <synchapi.h>
#endif
#include "rounding.h"
#include "event.h"
#include "datetime.h"
#ifdef QB64_MACOSX
# include <mach/mach_time.h>
# define ORWL_NANO (+1.0E-9)
# define ORWL_GIGA UINT64_C(1000000000)
static double orwl_timebase = 0.0;
static uint64_t orwl_timestart = 0;
static int64_t orwl_gettime(void) {
if (!orwl_timestart) {
mach_timebase_info_data_t tb = {0};
mach_timebase_info(&tb);
orwl_timebase = tb.numer;
orwl_timebase /= tb.denom;
orwl_timestart = mach_absolute_time();
}
struct timespec t;
double diff = (mach_absolute_time() - orwl_timestart) * orwl_timebase;
t.tv_sec = diff * ORWL_NANO;
t.tv_nsec = diff - (t.tv_sec * ORWL_GIGA);
return t.tv_sec * 1000 + t.tv_nsec / 1000000;
}
#endif
#ifdef QB64_LINUX
int64_t GetTicks() {
struct timespec tp;
clock_gettime(CLOCK_MONOTONIC, &tp);
return tp.tv_sec * 1000 + tp.tv_nsec / 1000000;
}
#elif defined QB64_MACOSX
int64_t GetTicks() { return orwl_gettime(); }
#else
int64_t GetTicks() { return ((((int64_t)clock()) * ((int64_t)1000)) / ((int64_t)CLOCKS_PER_SEC)); }
#endif
static uint64_t millis_since_midnight() {
auto currenttime = std::chrono::system_clock::now();
// Gives us the number of miliseconds past the current second
uint64_t millis_only = std::chrono::duration_cast<std::chrono::milliseconds>(currenttime.time_since_epoch()).count() % 1000;
// Convert to time_t and then hour/min/sec. localtime() takes the current
// timezone into account for us.
time_t curttime = std::chrono::system_clock::to_time_t(currenttime);
struct tm *local = localtime(&curttime);
// Compute current time as number of seconds past midnight
uint64_t seconds = local->tm_hour * 3600 + local->tm_min * 60 + local->tm_sec;
return seconds * 1000 + millis_only;
}
double func_timer(double accuracy, int32_t passed) {
if (new_error)
return 0;
double result = (double)millis_since_midnight() / 1000;
// Adjust result for requested accuracy, or default accuracy.
if (!passed) {
accuracy = 18.2;
} else {
if (accuracy <= 0.0) {
error(5);
return 0;
}
accuracy = 1.0 / accuracy;
}
result *= accuracy;
result = qbr(result);
result /= accuracy;
if (!passed) {
float f = result;
result = f;
}
return result;
}
#ifndef QB64_WINDOWS
void Sleep(uint32_t milliseconds) {
static uint64_t sec, nsec;
sec = milliseconds / 1000;
nsec = (milliseconds % 1000) * 1000000;
static timespec ts;
ts.tv_sec = sec;
ts.tv_nsec = nsec;
nanosleep(&ts, NULL);
}
#endif
void sub__delay(double seconds) {
double ms, base, elapsed, prev_now, now; // cannot be static
base = GetTicks();
if (new_error)
return;
if (seconds < 0) {
error(5);
return;
}
if (seconds > 2147483.647) {
error(5);
return;
}
ms = seconds * 1000.0;
now = base; // force first prev=... assignment to equal base
recalculate:
prev_now = now;
now = GetTicks();
elapsed = now - base;
if (elapsed < 0) { // GetTicks looped
base = now - (prev_now - base); // calculate new base
}
if (elapsed < ms) {
int64_t wait; // cannot be static
wait = ms - elapsed;
if (!wait)
wait = 1;
if (wait >= 10) {
Sleep(9);
evnt(0); // check for new events
// recalculate time
goto recalculate;
} else {
Sleep(wait);
}
}
}
void sub__limit(double fps) {
if (new_error)
return;
static double prev = 0;
double ms, now, elapsed; // cannot be static
if (fps <= 0.0) {
error(5);
return;
}
ms = 1000.0 / fps;
if (ms > 60000.0) {
error(5);
return;
} // max. 1 min delay between frames allowed to avoid accidental lock-up of program
recalculate:
now = GetTicks();
if (prev == 0.0) { // first call?
prev = now;
return;
}
if (now < prev) { // value looped?
prev = now;
return;
}
elapsed = now - prev; // elapsed time since prev
if (elapsed == ms) {
prev = prev + ms;
return;
}
if (elapsed < ms) {
int64_t wait; // cannot be static
wait = ms - elapsed;
if (!wait)
wait = 1;
if (wait >= 10) {
Sleep(9);
evnt(0); // check for new events
} else {
Sleep(wait);
}
// recalculate time
goto recalculate;
}
// too long since last call, adjust prev to current time
// minor overshoot up to 32ms is recovered, otherwise time is re-seeded
if (elapsed <= (ms + 32.0))
prev = prev + ms;
else
prev = now;
}

View file

@ -0,0 +1,91 @@
#include "libqb-common.h"
#include "rounding.h"
#ifdef QB64_NOT_X86
int64_t qbr(long double f) {
int64_t i;
int temp = 0;
if (f > 9223372036854775807) {
temp = 1;
f = f - 9223372036854775808u;
} // if it's too large for a signed int64, make it an unsigned int64 and return that value if possible.
if (f < 0)
i = f - 0.5f;
else
i = f + 0.5f;
if (temp)
return i | 0x8000000000000000; //+9223372036854775808;
return i;
}
uint64_t qbr_longdouble_to_uint64(long double f) {
if (f < 0)
return (f - 0.5f);
else
return (f + 0.5f);
}
int32_t qbr_float_to_long(float f) {
if (f < 0)
return (f - 0.5f);
else
return (f + 0.5f);
}
int32_t qbr_double_to_long(double f) {
if (f < 0)
return (f - 0.5f);
else
return (f + 0.5f);
}
void fpu_reinit() {} // do nothing
#else
// QBASIC compatible rounding via FPU:
// FLDS=load single
// FLDL=load double
// FLDT=load long double
int64_t qbr(long double f) {
int64_t i;
int temp = 0;
if (f > 9223372036854775807) {
temp = 1;
f = f - 9223372036854775808u;
} // if it's too large for a signed int64, make it an unsigned int64 and return that value if possible.
__asm__("fldt %1;"
"fistpll %0;"
: "=m"(i)
: "m"(f));
if (temp)
return i | 0x8000000000000000; // if it's an unsigned int64, manually set the bit flag
return i;
}
uint64_t qbr_longdouble_to_uint64(long double f) {
uint64_t i;
__asm__("fldt %1;"
"fistpll %0;"
: "=m"(i)
: "m"(f));
return i;
}
int32_t qbr_float_to_long(float f) {
int32_t i;
__asm__("flds %1;"
"fistpl %0;"
: "=m"(i)
: "m"(f));
return i;
}
int32_t qbr_double_to_long(double f) {
int32_t i;
__asm__("fldl %1;"
"fistpl %0;"
: "=m"(i)
: "m"(f));
return i;
}
void fpu_reinit() {
unsigned int mode = 0x37F;
asm("fldcw %0" : : "m"(*&mode));
}
#endif // x86 support

View file

@ -1,6 +1,9 @@
#include "common.h"
#include "audio.h"
#include "gui.h"
#include "event.h"
#include "rounding.h"
#include "datetime.h"
extern int32 func__cinp(int32 toggle,
int32 passed); // Console INP scan code reader
@ -56,7 +59,6 @@ qbs *func__inflate(qbs *text, int64 originalsize, int32 passed);
#endif
*/
extern void error(int32 error_number);
extern int32 sub_gl_called;
#ifdef QB64_GUI
@ -96,12 +98,8 @@ extern int32 func__scaledheight();
extern qbs *func__cwd();
extern qbs *func__startdir();
extern void sub__limit(double fps);
extern void sub__fps(double fps, int32 passed);
extern void sub__delay(double seconds);
extern void sub__resize(int32 on_off, int32 stretch_smooth);
extern int32 func__resize();
extern int32 func__resizewidth();
@ -462,7 +460,6 @@ extern long double func_val(qbs *s);
extern void sub_out(int32 port, int32 data);
extern void sub_randomize(double seed, int32 passed);
extern float func_rnd(float n, int32 passed);
extern double func_timer(double accuracy, int32 passed);
extern void sub_sound(double frequency, double lengthinclockticks);
// following are declared below to allow for inlining
// extern double func_abs(double d);
@ -516,22 +513,6 @@ extern qbs *func_time();
extern int32 func_csrlin();
extern int32 func_pos(int32 ignore);
extern double func_log(double value);
extern double func_csng_float(long double value);
extern double func_csng_double(double value);
extern double func_cdbl_float(long double value);
extern int32 func_cint_double(double value);
extern int64 func_cint_float(long double value);
extern int16 func_cint_long(int32 value);
extern int16 func_cint_ulong(uint32 value);
extern int16 func_cint_int64(int64 value);
extern int16 func_cint_uint64(uint64 value);
extern int32 func_clng_double(double value);
extern int64 func_clng_float(long double value);
extern int32 func_clng_ulong(uint32 value);
extern int32 func_clng_int64(int64 value);
extern int32 func_clng_uint64(uint64 value);
extern int64 func_round_double(long double value);
extern int64 func_round_float(long double value);
extern double func_fix_double(double value);
extern long double func_fix_float(long double value);
extern double func_exp_single(double value);
@ -702,14 +683,8 @@ uint64 func__setbit(uint64 a1, int b1);
uint64 func__resetbit(uint64 a1, int b1);
uint64 func__togglebit(uint64 a1, int b1);
#ifndef QB64_WINDOWS
extern void Sleep(uint32 milliseconds);
extern void ZeroMemory(void *ptr, int64 bytes);
#endif
extern int64 qbr(long double f);
extern uint64 qbr_longdouble_to_uint64(long double f);
extern int32 qbr_float_to_long(float f);
extern int32 qbr_double_to_long(double f);
extern void fpu_reinit(void);
extern uint64 getubits(uint32 bsize, uint8 *base, ptrszint i);
extern int64 getbits(uint32 bsize, uint8 *base, ptrszint i);
@ -870,112 +845,6 @@ template <typename T> static T qbs_cleanup(uint32 base, T passvalue) {
return passvalue;
}
// CSNG
inline double func_csng_float(long double value) {
if ((value <= 3.402823466E38) && (value >= -3.402823466E38)) {
return value;
}
error(6);
return 0;
}
inline double func_csng_double(double value) {
if ((value <= 3.402823466E38) && (value >= -3.402823466E38)) {
return value;
}
error(6);
return 0;
}
// CDBL
inline double func_cdbl_float(long double value) {
if ((value <= 1.7976931348623157E308) &&
(value >= -1.7976931348623157E308)) {
return value;
}
error(6);
return 0;
}
// CINT
// func_cint_single uses func_cint_double
inline int32 func_cint_double(double value) {
if ((value < 32767.5) && (value >= -32768.5)) {
return qbr_double_to_long(value);
}
error(6);
return 0;
}
inline int64 func_cint_float(long double value) {
if ((value < 32767.5) && (value >= -32768.5)) {
return qbr(value);
}
error(6);
return 0;
}
inline int16 func_cint_long(int32 value) {
if ((value >= -32768) && (value <= 32767))
return value;
error(6);
return 0;
}
inline int16 func_cint_ulong(uint32 value) {
if (value <= 32767)
return value;
error(6);
return 0;
}
inline int16 func_cint_int64(int64 value) {
if ((value >= -32768) && (value <= 32767))
return value;
error(6);
return 0;
}
inline int16 func_cint_uint64(uint64 value) {
if (value <= 32767)
return value;
error(6);
return 0;
}
// CLNG
// func_clng_single uses func_clng_double
//-2147483648 to 2147483647
inline int32 func_clng_double(double value) {
if ((value < 2147483647.5) && (value >= -2147483648.5)) {
return qbr_double_to_long(value);
}
error(6);
return 0;
}
inline int64 func_clng_float(long double value) {
if ((value < 2147483647.5) && (value >= -2147483648.5)) {
return qbr(value);
}
error(6);
return 0;
}
inline int32 func_clng_ulong(uint32 value) {
if (value <= 2147483647)
return value;
error(6);
return 0;
}
inline int32 func_clng_int64(int64 value) {
if ((value >= -2147483648) && (value <= 2147483647))
return value;
error(6);
return 0;
}
inline int32 func_clng_uint64(uint64 value) {
if (value <= 2147483647)
return value;
error(6);
return 0;
}
//_ROUND (note: round performs no error checking)
inline int64 func_round_double(long double value) { return qbr(value); }
inline int64 func_round_float(long double value) { return qbr(value); }
// force abs to return floating point numbers correctly
inline double func_abs(double d) { return fabs(d); }
@ -2395,8 +2264,7 @@ extern int64 display_lock_confirmed;
extern int64 display_lock_released;
uint32 r;
void evnt(uint32 linenumber, uint32 inclinenumber = 0,
const char *incfilename = NULL) {
void evnt(uint32 linenumber, uint32 inclinenumber, const char *incfilename) {
if (disableEvents)
return;

View file

@ -1 +1 @@
-13 48 72
-11 48 72

View file

@ -6,7 +6,7 @@ $ELSE
' We can't do _SCREENIMAGE on Linux or Mac OS build agents, but we can still test
' that it compiles
PRINT -13;
PRINT -11;
SYSTEM
$END IF

View file

@ -1 +1 @@
-13
-11

View file

@ -1 +1 @@
-13 48 72
-11 48 72

View file

@ -7,7 +7,7 @@ $ELSE
' We can't do _SCREENIMAGE on Linux or Mac OS build agents, but we can still
' test that it compiles
PRINT -13;
PRINT -11;
SYSTEM
$END IF

View file

@ -1 +1 @@
-13
-11