1
1
Fork 0
mirror of https://github.com/QB64-Phoenix-Edition/QB64pe.git synced 2024-06-14 16:10:14 +00:00
QB64-PE/internal/c/qbx.cpp
2022-10-23 12:57:02 +05:30

2567 lines
86 KiB
C++
Executable file

#include "common.h"
#include "audio.h"
#include "gui.h"
extern int32 func__cinp(int32 toggle,
int32 passed); // Console INP scan code reader
extern int func__capslock();
extern int func__scrolllock();
extern int func__numlock();
extern void sub__capslock(int32 options);
extern void sub__scrolllock(int32 options);
extern void sub__numlock(int32 options);
extern void sub__consolefont(qbs *FontName, int FontSize);
extern void sub__console_cursor(int32 visible, int32 cursorsize, int32 passed);
extern int32 func__getconsoleinput();
extern void unlockvWatchHandle();
extern int32 vWatchHandle();
#ifdef DEPENDENCY_ZLIB
#include <zlib.h>
qbs *func__deflate(qbs *text);
qbs *func__inflate(qbs *text, int64 originalsize, int32 passed);
#endif
#ifdef QB64_MACOSX
#include <ApplicationServices/ApplicationServices.h>
#endif
/* testing only
#ifdef QB64_WINDOWS
HWND FindMyTopMostWindow()
{
DWORD dwProcID = GetCurrentProcessId();
HWND hWnd = GetTopWindow(GetDesktopWindow());
while(hWnd)
{
DWORD dwWndProcID = 0;
GetWindowThreadProcessId(hWnd, &dwWndProcID);
if(dwWndProcID == dwProcID)
return hWnd;
hWnd = GetNextWindow(hWnd, GW_HWNDNEXT);
}
return NULL;
}
void SetMidiVolume(int32 vol){
//DWORD vol = MAKELONG(((volume*65535L)/100), ((volume*65535L)/100));
MIDIOUTCAPS midiCaps;
midiOutGetDevCaps(0, &midiCaps, sizeof(midiCaps));
if (midiCaps.dwSupport & MIDICAPS_VOLUME)
midiOutSetVolume(0, vol);
}
#endif
*/
extern void error(int32 error_number);
extern int32 sub_gl_called;
#ifdef QB64_GUI
#ifdef DEPENDENCY_GL
#include "parts/core/gl_header_for_parsing/temp/gl_helper_code.h"
double pi_as_double = 3.14159265358979;
void gluPerspective(double fovy, double aspect, double zNear, double zFar) {
double xmin, xmax, ymin, ymax;
ymax = zNear * tan(fovy * pi_as_double / 360.0);
ymin = -ymax;
xmin = ymin * aspect;
xmax = ymax * aspect;
glFrustum(xmin, xmax, ymin, ymax, zNear, zFar);
}
#endif
#endif
// forward references
void QBMAIN(void *);
void TIMERTHREAD();
extern int32 requestedKeyboardOverlayImage;
void requestKeyboardOverlayImage(int32 handle) {
requestedKeyboardOverlayImage = handle;
}
// extern functions
extern qbs *func__dir(qbs *context);
extern int32 func__scaledwidth();
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();
extern int32 func__resizeheight();
extern int32 FontLoad(uint8 *content, int32 content_bytes,
int32 default_pixel_height, int32 which_font,
int32 options);
extern int32 FontRenderTextUTF32(int i, uint32 *codepoint, int32 codepoints,
int32 options, uint8 **out_data, int32 *out_x,
int32 *out_y, int32 *out_x_pre_increment,
int32 *out_x_post_increment);
extern int32 FontRenderTextASCII(int i, uint8 *codepoint, int32 codepoints,
int32 options, uint8 **out_data, int32 *out_x,
int32 *out_y, int32 *out_x_pre_increment,
int32 *out_x_post_increment);
extern void sub__title(qbs *title);
extern void sub__echo(qbs *message);
extern void sub__assert(int32 expression, qbs *assert_message, int32 passed);
extern void sub__finishdrop();
extern int32 func__filedrop();
extern void sub__filedrop(int32 on_off = NULL);
extern int32 func__totaldroppedfiles();
extern qbs *func__droppedfile(int32 fileIndex, int32 passed);
extern void sub__glrender(int32 method);
extern void sub__displayorder(int32 method1, int32 method2, int32 method3,
int32 method4);
extern int64 GetTicks();
extern int32 func__memexists(void *blk);
extern void sub__memfill(mem_block *dblk, ptrszint doff, ptrszint dbytes,
ptrszint soff, ptrszint sbytes);
extern void sub__memfill_nochecks(ptrszint doff, ptrszint dbytes, ptrszint soff,
ptrszint sbytes);
extern void sub__memfill_1(mem_block *dblk, ptrszint doff, ptrszint dbytes,
int8 val);
extern void sub__memfill_nochecks_1(ptrszint doff, ptrszint dbytes, int8 val);
extern void sub__memfill_2(mem_block *dblk, ptrszint doff, ptrszint dbytes,
int16 val);
extern void sub__memfill_nochecks_2(ptrszint doff, ptrszint dbytes, int16 val);
extern void sub__memfill_4(mem_block *dblk, ptrszint doff, ptrszint dbytes,
int32 val);
extern void sub__memfill_nochecks_4(ptrszint doff, ptrszint dbytes, int32 val);
extern void sub__memfill_8(mem_block *dblk, ptrszint doff, ptrszint dbytes,
int64 val);
extern void sub__memfill_nochecks_8(ptrszint doff, ptrszint dbytes, int64 val);
extern void sub__memfill_SINGLE(mem_block *dblk, ptrszint doff, ptrszint dbytes,
float val);
extern void sub__memfill_nochecks_SINGLE(ptrszint doff, ptrszint dbytes,
float val);
extern void sub__memfill_DOUBLE(mem_block *dblk, ptrszint doff, ptrszint dbytes,
double val);
extern void sub__memfill_nochecks_DOUBLE(ptrszint doff, ptrszint dbytes,
double val);
extern void sub__memfill_FLOAT(mem_block *dblk, ptrszint doff, ptrszint dbytes,
long double val);
extern void sub__memfill_nochecks_FLOAT(ptrszint doff, ptrszint dbytes,
long double val);
extern void sub__memfill_OFFSET(mem_block *dblk, ptrszint doff, ptrszint dbytes,
ptrszint val);
extern void sub__memfill_nochecks_OFFSET(ptrszint doff, ptrszint dbytes,
ptrszint val);
extern void *func__memget(mem_block *blk, ptrszint off, ptrszint bytes);
extern void new_mem_lock();
extern void free_mem_lock(mem_lock *lock);
extern mem_block func__mem(ptrszint offset, ptrszint size, int32 type,
ptrszint elementsize, mem_lock *lock);
extern mem_block func__mem_at_offset(ptrszint offset, ptrszint size);
extern void sub__memfree(void *);
extern void sub__memcopy(void *sblk, ptrszint soff, ptrszint bytes, void *dblk,
ptrszint doff);
extern mem_block func__memnew(ptrszint);
extern mem_block func__memimage(int32, int32);
extern mem_block func__memsound(int32 i, int32 targetChannel);
extern int64 func__shellhide(qbs *str);
extern int64 func_shell(qbs *str);
extern void sub_shell(qbs *str, int32 passed);
extern void sub_shell2(qbs *str, int32 passed);
extern void sub_shell3(qbs *str, int32 passed);
extern void sub__consoletitle(qbs *);
extern void sub__screenshow();
extern void sub__screenhide();
extern int32 func__screenhide();
extern int32 func_windowexists();
extern int32 func_screenicon();
extern int32 func_screenwidth();
extern int32 func_screenheight();
extern int32 func__borderwidth();
extern int32 func__titlebarheight();
extern void sub_screenicon();
extern void sub__console(int32);
extern int32 func__console();
extern void sub__controlchr(int32);
extern int32 func__controlchr();
extern void sub__blink(int32);
extern int32 func__blink();
extern int32 func__hasfocus();
extern void set_foreground_window(ptrszint i);
extern qbs *func__title();
extern int32 func__handle();
extern int32 func__fileexists(qbs *);
extern int32 func__direxists(qbs *);
extern int32 func_stick(int32 i, int32 axis_group, int32 passed);
extern int32 func_strig(int32 i, int32 controller, int32 passed);
extern void sub__maptriangle(int32 cull_options, float sx1, float sy1,
float sx2, float sy2, float sx3, float sy3,
int32 si, float dx1, float dy1, float dz1,
float dx2, float dy2, float dz2, float dx3,
float dy3, float dz3, int32 di,
int32 smooth_options, int32 passed);
extern void sub__depthbuffer(int32 options, int32 dst, int32 passed);
extern int32 func_play(int32 ignore);
extern void sub_paletteusing(void *element, int32 bits);
extern int64 func_read_int64(uint8 *data, ptrszint *data_offset,
ptrszint data_size);
extern int64 func_read_uint64(uint8 *data, ptrszint *data_offset,
ptrszint data_size);
extern void key_on();
extern void key_off();
extern void key_list();
extern void key_assign(int32 i, qbs *str);
extern int32 func__screeny();
extern int32 func__screenx();
extern void sub__screenmove(int32 x, int32 y, int32 passed);
extern void sub__mousemove(float x, float y);
extern qbs *func__os();
extern void sub__mapunicode(int32 unicode_code, int32 ascii_code);
extern int32 func__mapunicode(int32 ascii_code);
extern void field_new(int32 fileno);
extern void field_add(qbs *str, int64 size);
extern void field_get(int32 fileno, int64 seekpos, int32 passed);
extern void field_put(int32 fileno, int64 seekpos, int32 passed);
extern int32 func__keydown(int32 x);
extern int32 func__keyhit();
extern void sub_files(qbs *str, int32 passed);
extern int32 func_lpos(int32);
extern void sub__printimage(int32 i);
extern float func__mousemovementx(int32 context, int32 passed);
extern float func__mousemovementy(int32 context, int32 passed);
extern void sub__screenprint(qbs *txt);
extern void sub__screenclick(int32 x, int32 y, int32 button, int32 passed);
extern int32 func__screenimage(int32 x1, int32 y1, int32 x2, int32 y2,
int32 passed);
extern void sub_lock(int32 i, int64 start, int64 end, int32 passed);
extern void sub_unlock(int32 i, int64 start, int64 end, int32 passed);
void chain_restorescreenstate(int32);
void chain_savescreenstate(int32);
extern void sub__fullscreen(int32 method, int32 passed);
extern void sub__allowfullscreen(int32 method, int32 smooth);
extern int32 func__fullscreen();
extern int32 func__fullscreensmooth();
extern void sub__clipboard(qbs *);
extern qbs *func__clipboard();
extern int32 func__clipboardimage();
extern void sub__clipboardimage(int32 src);
extern int32 func__exit();
extern char *fixdir(qbs *);
extern void revert_input_check();
extern int32 func__openhost(qbs *);
extern int32 func__openconnection(int32);
extern int32 func__openclient(qbs *);
extern int32 func__connected(int32);
extern qbs *func__connectionaddress(int32);
extern int32 func__environcount();
extern qbs *func_environ(qbs *);
extern qbs *func_environ(int32);
extern void sub_environ(qbs *);
extern void sub_draw(qbs *);
extern void qbs_maketmp(qbs *);
extern void sub_run(qbs *);
extern void sub_run_init();
extern void sndcloseall();
extern void freeallimages();
extern void call_interrupt(int32, void *, void *);
extern void call_interruptx(int32, void *, void *);
extern void restorepalette(img_struct *im);
extern void pset(int32 x, int32 y, uint32 col);
extern uint32 newimg();
extern int32 freeimg(uint32);
extern void imgrevert(int32);
extern int32 imgframe(uint8 *o, int32 x, int32 y, int32 bpp);
extern int32 imgnew(int32 x, int32 y, int32 bpp);
extern int32 imgload(char *filename, int32 bpp);
extern void sub__putimage(double f_dx1, double f_dy1, double f_dx2,
double f_dy2, int32 src, int32 dst, double f_sx1,
double f_sy1, double f_sx2, double f_sy2,
int32 passed);
extern int32 fontopen(char *name, double d_height, int32 flags);
extern int32 selectfont(int32 f, img_struct *im);
extern void sndsetup();
extern uint32 sib();
extern uint32 sib_mod0();
extern uint8 *rm8();
extern uint16 *rm16();
extern uint32 *rm32();
extern void cpu_call();
extern int64 build_int64(uint32 val2, uint32 val1);
extern uint64 build_uint64(uint32 val2, uint32 val1);
extern void fix_error();
extern double get_error_erl();
extern uint32 get_error_err();
extern char *human_error(int32 errorcode);
extern void end();
extern int32 stop_program_state();
extern uint8 *mem_static_malloc(uint32 size);
extern void mem_static_restore(uint8 *restore_point);
extern uint8 *cmem_dynamic_malloc(uint32 size);
extern void cmem_dynamic_free(uint8 *block);
extern void sub_defseg(int32 segment, int32 passed);
extern int32 func_peek(int32 offset);
extern void sub_poke(int32 offset, int32 value);
extern void more_return_points();
extern void qb64_generatesound(double f, double l, uint8 wait);
extern uint8 *soundwave(double frequency, double length, double volume,
double fadein, double fadeout);
extern int32 wavesize(double length);
extern qbs *qbs_new_descriptor();
extern void qbs_free_descriptor(qbs *str);
extern void qbs_free(qbs *str);
extern void qbs_cmem_concat_list();
extern void qbs_concat_list();
extern void qbs_tmp_concat_list();
extern void qbs_concat(uint32 bytesrequired);
extern void qbs_concat_cmem(uint32 bytesrequired);
extern qbs *qbs_new_cmem(int32 size, uint8 tmp);
extern qbs *qbs_new_txt(const char *txt);
extern qbs *qbs_new_txt_len(const char *txt, int32 len);
extern qbs *qbs_new_fixed(uint8 *offset, uint32 size, uint8 tmp);
extern qbs *qbs_new(int32 size, uint8 tmp);
extern void set_qbs_size(ptrszint *target_qbs, int32 newlength);
extern qbs *qbs_set(qbs *deststr, qbs *srcstr);
extern qbs *qbs_add(qbs *str1, qbs *str2);
extern qbs *qbs_ucase(qbs *str);
extern qbs *qbs_lcase(qbs *str);
extern qbs *func_chr(int32 value);
extern qbs *func_varptr_helper(uint8 type, uint16 offset);
extern qbs *qbs_left(qbs *str, int32 l);
extern qbs *qbs_right(qbs *str, int32 l);
extern qbs *func_mksmbf(float val);
extern qbs *func_mkdmbf(double val);
extern float func_cvsmbf(qbs *str);
extern double func_cvdmbf(qbs *str);
extern qbs *bit2string(uint32 bsize, int64 v);
extern qbs *ubit2string(uint32 bsize, uint64 v);
extern uint64 string2ubit(qbs *str, uint32 bsize);
extern int64 string2bit(qbs *str, uint32 bsize);
extern void sub_lset(qbs *dest, qbs *source);
extern void sub_rset(qbs *dest, qbs *source);
extern qbs *func_space(int32 spaces);
extern qbs *func_string(int32 characters, int32 asciivalue);
extern int32 func_instr(int32 start, qbs *str, qbs *substr, int32 passed);
extern int32 func__instrrev(int32 start, qbs *str, qbs *substr, int32 passed);
extern void sub_mid(qbs *dest, int32 start, int32 l, qbs *src, int32 passed);
extern qbs *func_mid(qbs *str, int32 start, int32 l, int32 passed);
extern qbs *qbs_ltrim(qbs *str);
extern qbs *qbs_rtrim(qbs *str);
extern qbs *qbs__trim(qbs *str);
extern int32 func__str_nc_compare(qbs *s1, qbs *s2);
extern int32 func__str_compare(qbs *s1, qbs *s2);
extern qbs *qbs_inkey();
extern void sub__keyclear(int32 buf, int32 passed);
extern qbs *qbs_str(int64 value);
extern qbs *qbs_str(int32 value);
extern qbs *qbs_str(int16 value);
extern qbs *qbs_str(int8 value);
extern qbs *qbs_str(uint64 value);
extern qbs *qbs_str(uint32 value);
extern qbs *qbs_str(uint16 value);
extern qbs *qbs_str(uint8 value);
extern qbs *qbs_str(float value);
extern qbs *qbs_str(double value);
extern qbs *qbs_str(long double value);
extern int32 qbs_equal(qbs *str1, qbs *str2);
extern int32 qbs_notequal(qbs *str1, qbs *str2);
extern int32 qbs_greaterthan(qbs *str1, qbs *str2);
extern int32 qbs_lessthan(qbs *str1, qbs *str2);
extern int32 qbs_lessorequal(qbs *str1, qbs *str2);
extern int32 qbs_greaterorequal(qbs *str1, qbs *str2);
extern double func_deg2rad(double degree);
extern double func_deg2grad(double degree);
extern double func_rad2deg(double degree);
extern double func_rad2grad(double degree);
extern double func_grad2deg(double degree);
extern double func_grad2rad(double degree);
extern double func_arcsec(double num);
extern double func_arccsc(double num);
extern double func_arccot(double num);
extern double func_sech(double num);
extern double func_csch(double num);
extern double func_coth(double num);
extern double func_sec(double num);
extern double func_csc(double num);
extern double func_cot(double num);
extern double func_pi(double multiplier, int32 passed);
extern int32 qbs_asc(qbs *);
extern int32 qbs_asc(qbs *, uint32);
extern int32 qbs_len(qbs *str);
extern void lineclip(int32 x1, int32 y1, int32 x2, int32 y2, int32 xmin,
int32 ymin, int32 xmax, int32 ymax);
extern void qbg_palette(uint32 attribute, uint32 col, int32 passed);
extern void qbg_sub_color(uint32 col1, uint32 col2, uint32 bordercolor,
int32 passed);
extern void defaultcolors();
extern void validatepage(int32 n);
extern void qbg_screen(int32 mode, int32 color_switch, int32 active_page,
int32 visual_page, int32 refresh, int32 passed);
extern void sub_pcopy(int32 src, int32 dst);
extern void qbsub_width(int32 option, int32 value1, int32 value2, int32 value3,
int32 value4, int32 passed);
extern void pset(int32 x, int32 y, uint32 col);
extern void pset_and_clip(int32 x, int32 y, uint32 col);
extern void qb32_boxfill(float x1f, float y1f, float x2f, float y2f,
uint32 col);
extern void fast_boxfill(int32 x1, int32 y1, int32 x2, int32 y2, uint32 col);
extern void fast_line(int32 x1, int32 y1, int32 x2, int32 y2, uint32 col);
extern void qb32_line(float x1f, float y1f, float x2f, float y2f, uint32 col,
uint32 style);
extern void sub_line(float x1, float y1, float x2, float y2, uint32 col,
int32 bf, uint32 style, int32 passed);
extern void sub_paint32(float x, float y, uint32 fillcol, uint32 bordercol,
int32 passed);
extern void sub_paint32x(float x, float y, uint32 fillcol, uint32 bordercol,
int32 passed);
extern void sub_paint(float x, float y, uint32 fillcol, uint32 bordercol,
qbs *backgroundstr, int32 passed);
extern void sub_paint(float x, float y, qbs *fillstr, uint32 bordercol,
qbs *backgroundstr, int32 passed);
extern void sub_circle(double x, double y, double r, uint32 col, double start,
double end, double aspect, int32 passed);
extern uint32 point(int32 x, int32 y);
extern double func_point(float x, float y, int32 passed);
extern void sub_pset(float x, float y, uint32 col, int32 passed);
extern void sub_preset(float x, float y, uint32 col, int32 passed);
extern void printchr(int32 character);
extern int32 printchr2(int32 x, int32 y, uint32 character, int32 i);
extern int32 chrwidth(int32 character);
extern void newline();
extern void makefit(qbs *text);
extern void lprint_makefit(qbs *text);
extern void tab();
extern void qbs_print(qbs *str, int32 finish_on_new_line);
extern void qbs_lprint(qbs *str, int32 finish_on_new_line);
extern void qbg_sub_window(float x1, float y1, float x2, float y2,
int32 passed);
extern void qbg_sub_view_print(int32 topline, int32 bottomline, int32 passed);
extern void qbg_sub_view(int32 x1, int32 y1, int32 x2, int32 y2,
int32 fillcolor, int32 bordercolor, int32 passed);
extern void sub_cls(int32 method, uint32 use_color, int32 passed);
extern void qbg_sub_locate(int32 row, int32 column, int32 cursor, int32 start,
int32 stop, int32 passed);
extern int32 hexoct2uint64(qbs *h);
extern void qbs_input(int32 numvariables, uint8 newline);
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);
// extern long double func_abs(long double d);
// extern float func_abs(float d);
// extern void sub_open(qbs *name,int32 type,int32 access,int32 sharing,int32
// i,int32 record_length,int32 passed);
extern void sub_open(qbs *name, int32 type, int32 access, int32 sharing,
int32 i, int64 record_length, int32 passed);
extern void sub_open_gwbasic(qbs *typestr, int32 i, qbs *name,
int64 record_length, int32 passed);
extern void sub_close(int32 i2, int32 passed);
extern int32 file_input_chr(int32 i);
extern void file_input_nextitem(int32 i, int32 lastc);
extern void sub_file_print(int32 i, qbs *str, int32 extraspace, int32 tab,
int32 newline);
extern int32 n_roundincrement();
extern int32 n_float();
extern int32 n_int64();
extern int32 n_uint64();
extern int32 n_inputnumberfromdata(uint8 *data, ptrszint *data_offset,
ptrszint data_size);
extern int32 n_inputnumberfromfile(int32 fileno);
extern void sub_file_line_input_string(int32 fileno, qbs *deststr);
extern void sub_file_input_string(int32 fileno, qbs *deststr);
extern int64 func_file_input_int64(int32 fileno);
extern uint64 func_file_input_uint64(int32 fileno);
extern void sub_read_string(uint8 *data, ptrszint *data_offset,
ptrszint data_size, qbs *deststr);
extern long double func_read_float(uint8 *data, ptrszint *data_offset,
ptrszint data_size, int32 typ);
extern long double func_file_input_float(int32 fileno, int32 typ);
extern void *byte_element(uint64 offset, int32 length);
extern void *byte_element(uint64 offset, int32 length,
byte_element_struct *info);
extern void sub_get(int32 i, int64 offset, void *element, int32 passed);
extern void sub_get2(int32 i, int64 offset, qbs *str, int32 passed);
extern void sub_put(int32 i, int64 offset, void *element, int32 passed);
extern void sub_put2(int32 i, int64 offset, void *element, int32 passed);
extern void sub_graphics_get(float x1f, float y1f, float x2f, float y2f,
void *element, uint32 mask, int32 passed);
extern void sub_graphics_put(float x1f, float y1f, void *element, int32 option,
uint32 mask, int32 passed);
extern void sub_date(qbs *date);
extern qbs *func_date();
extern void sub_time(qbs *str);
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);
extern long double func_exp_float(long double value);
extern void sub_sleep(int32 seconds, int32 passed);
extern qbs *func__bin(int64 value, int32 neg_bits);
extern qbs *func__bin_float(long double value);
extern qbs *func_oct(int64 value, int32 neg_bits);
extern qbs *func_oct_float(long double value);
extern qbs *func_hex(int64 value, int32 neg_size);
extern qbs *func_hex_float(long double value);
extern ptrszint func_lbound(ptrszint *array, int32 index, int32 num_indexes);
extern ptrszint func_ubound(ptrszint *array, int32 index, int32 num_indexes);
extern int32 func_sgn(uint8 v);
extern int32 func_sgn(int8 v);
extern int32 func_sgn(uint16 v);
extern int32 func_sgn(int16 v);
extern int32 func_sgn(uint32 v);
extern int32 func_sgn(int32 v);
extern int32 func_sgn(uint64 v);
extern int32 func_sgn(int64 v);
extern int32 func_sgn(float v);
extern int32 func_sgn(double v);
extern int32 func_sgn(long double v);
extern int32 func_inp(int32 port);
extern void sub_wait(int32 port, int32 andexpression, int32 xorexpression,
int32 passed);
extern qbs *func_tab(int32 pos);
extern qbs *func_spc(int32 spaces);
extern float func_pmap(float val, int32 option);
extern uint32 func_screen(int32 y, int32 x, int32 returncol, int32 passed);
extern void sub_bsave(qbs *filename, int32 offset, int32 size);
extern void sub_bload(qbs *filename, int32 offset, int32 passed);
extern int64 func_lof(int32 i);
extern int32 func_eof(int32 i);
extern void sub_seek(int32 i, int64 pos);
extern int64 func_seek(int32 i);
extern int64 func_loc(int32 i);
extern qbs *func_input(int32 n, int32 i, int32 passed);
extern double func_sqr(double value);
extern void sub_beep();
extern void snd_check();
extern qbs *func_command(int32 index, int32 passed);
extern int32 func__commandcount();
extern void sub_kill(qbs *str);
extern void sub_name(qbs *oldname, qbs *newname);
extern void sub_chdir(qbs *str);
extern void sub_mkdir(qbs *str);
extern void sub_rmdir(qbs *str);
extern long double pow2(long double x, long double y);
extern int32 func_freefile();
extern void sub__mousehide();
extern void sub__mouseshow(qbs *style, int32 passed);
extern float func__mousex(int32 context, int32 passed);
extern float func__mousey(int32 context, int32 passed);
extern int32 func__mouseinput(int32 context, int32 passed);
extern int32 func__mousebutton(int32 i, int32 context, int32 passed);
extern int32 func__mousewheel(int32 context, int32 passed);
extern int32 func__mousepipeopen();
extern void sub__mouseinputpipe(int32 context);
extern void sub__mousepipeclose(int32 context);
extern void call_absolute(int32 args, uint16 offset);
extern void call_interrupt(int32 i);
extern void sub_play(qbs *str);
extern int32 func__newimage(int32 x, int32 y, int32 bpp, int32 passed);
extern int32 func__loadimage(qbs *f, int32 bpp, int32 passed);
extern int32 func__copyimage(int32 i, int32 mode, int32 passed);
extern void sub__freeimage(int32 i, int32 passed);
extern void sub__source(int32 i);
extern void sub__dest(int32 i);
extern int32 func__source();
extern int32 func__dest();
extern int32 func__display();
extern void sub__blend(int32 i, int32 passed);
extern void sub__dontblend(int32 i, int32 passed);
extern void sub__clearcolor(uint32 c, int32 i, int32 passed);
extern void sub__setalpha(int32 a, uint32 c, uint32 c2, int32 i, int32 passed);
extern int32 func__width(int32 i, int32 passed);
extern int32 func__height(int32 i, int32 passed);
extern int32 func__pixelsize(int32 i, int32 passed);
extern int32 func__clearcolor(int32 i, int32 passed);
extern int32 func__blend(int32 i, int32 passed);
extern uint32 func__defaultcolor(int32 i, int32 passed);
extern uint32 func__backgroundcolor(int32 i, int32 passed);
extern uint32 func__palettecolor(int32 n, int32 i, int32 passed);
extern void sub__palettecolor(int32 n, uint32 c, int32 i, int32 passed);
extern void sub__copypalette(int32 i, int32 i2, int32 passed);
extern void sub__printstring(float x, float y, qbs *text, int32 i,
int32 passed);
extern int32 func__printwidth(qbs *text, int32 i, int32 passed);
extern int32 func__loadfont(qbs *filename, int32 size, qbs *requirements,
int32 passed);
extern void sub__font(int32 f, int32 i, int32 passed);
extern int32 func__fontwidth(int32 f, int32 passed);
extern int32 func__fontheight(int32 f, int32 passed);
extern int32 func__font(int32 i, int32 passed);
extern void sub__freefont(int32 f);
extern void sub__printmode(int32 mode, int32 i, int32 passed);
extern int32 func__printmode(int32 i, int32 passed);
uint32 func__rgb32(int32 r, int32 g, int32 b, int32 a);
uint32 func__rgb32(int32 r, int32 g, int32 b);
uint32 func__rgb32(int32 i, int32 a);
uint32 func__rgb32(int32 i);
uint32 func__rgba32(int32 r, int32 g, int32 b, int32 a);
int32 func__alpha32(uint32 col);
int32 func__red32(uint32 col);
int32 func__green32(uint32 col);
int32 func__blue32(uint32 col);
extern uint32 matchcol(int32 r, int32 g, int32 b);
extern uint32 matchcol(int32 r, int32 g, int32 b, int32 i);
extern uint32 func__rgb(int32 r, int32 g, int32 b, int32 i, int32 passed);
extern uint32 func__rgba(int32 r, int32 g, int32 b, int32 a, int32 i,
int32 passed);
extern int32 func__alpha(uint32 col, int32 i, int32 passed);
extern int32 func__red(uint32 col, int32 i, int32 passed);
extern int32 func__green(uint32 col, int32 i, int32 passed);
extern int32 func__blue(uint32 col, int32 i, int32 passed);
extern void sub_end();
extern int32 print_using(qbs *f, int32 s2, qbs *dest, qbs *pu_str);
extern int32 print_using_integer64(qbs *format, int64 value, int32 start,
qbs *output);
extern int32 print_using_uinteger64(qbs *format, uint64 value, int32 start,
qbs *output);
extern int32 print_using_single(qbs *format, float value, int32 start,
qbs *output);
extern int32 print_using_double(qbs *format, double value, int32 start,
qbs *output);
extern int32 print_using_float(qbs *format, long double value, int32 start,
qbs *output);
extern qbs *b2string(char v);
extern qbs *ub2string(char v);
extern qbs *i2string(int16 v);
extern qbs *ui2string(int16 v);
extern qbs *l2string(int32 v);
extern qbs *ul2string(uint32 v);
extern qbs *i642string(int64 v);
extern qbs *ui642string(uint64 v);
extern qbs *s2string(float v);
extern qbs *d2string(double v);
extern qbs *f2string(long double v);
extern qbs *o2string(ptrszint v);
extern qbs *uo2string(uptrszint v);
extern char string2b(qbs *str);
extern uint8 string2ub(qbs *str);
extern int16 string2i(qbs *str);
extern uint16 string2ui(qbs *str);
extern int32 string2l(qbs *str);
extern uint32 string2ul(qbs *str);
extern int64 string2i64(qbs *str);
extern uint64 string2ui64(qbs *str);
extern float string2s(qbs *str);
extern double string2d(qbs *str);
extern long double string2f(qbs *str);
extern ptrszint string2o(qbs *str);
extern uptrszint string2uo(qbs *str);
// Cobalt(aka Dave) added the next 2 lines
uint64 func__shr(uint64 a1, int b1);
uint64 func__shl(uint64 a1, int b1);
int64 func__readbit(uint64 a1, int b1);
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);
extern void setbits(uint32 bsize, uint8 *base, ptrszint i, int64 val);
// shared global variables
extern int32 sleep_break;
extern uint64 mem_lock_id;
extern mem_lock *mem_lock_tmp;
extern int64 exit_code;
extern int32 lock_mainloop; // 0=unlocked, 1=lock requested, 2=locked
extern int64 device_event_index;
extern int32 exit_ok;
extern qbs *func_command_str;
int32 timer_event_occurred = 0; // inc/dec as each GOSUB to QBMAIN ()
// begins/ends
int32 timer_event_id = 0;
int32 key_event_occurred = 0; // inc/dec as each GOSUB to QBMAIN () begins/ends
int32 key_event_id = 0;
int32 strig_event_occurred = 0; // inc/dec as each GOSUB to QBMAIN ()
// begins/ends
int32 strig_event_id = 0;
uint32 ercl;
uint32 inclercl;
char *includedfilename;
uint16 call_absolute_offsets[256];
uint32 dbgline;
uint32 qbs_cmem_sp = 256;
uint32 cmem_sp = 65536;
ptrszint dblock; // 32bit offset of dblock
uint8 close_program = 0;
int32 tab_spc_cr_size = 1; // 1=PRINT(default), 2=FILE
int32 tab_fileno = 0; // only valid if tab_spc_cr_size=2
int32 tab_LPRINT = 0; // 1=dest is LPRINT image
uint64 *nothingvalue; // a pointer to 8 empty bytes in dblock
uint32 error_err = 0;
double error_erl = 0;
uint32 qbs_tmp_list_nexti = 1;
uint32 error_occurred = 0;
uint32 new_error = 0;
uint32 bkp_new_error = 0;
qbs *nothingstring;
uint32 qbevent = 0;
uint8 suspend_program = 0;
uint8 stop_program = 0;
uint32 error_retry = 0;
uint8 cmem[1114099]; // 16*65535+65535+3 (enough for highest referencable dword
// in conv memory)
uint8 *cmem_static_pointer = &cmem[0] + 1280 + 65536;
uint8 *cmem_dynamic_base = &cmem[0] + 655360;
uint8 *mem_static;
uint8 *mem_static_pointer;
uint8 *mem_static_limit;
double last_line = 0;
uint32 error_goto_line = 0;
uint32 error_handling = 0;
uint32 next_return_point = 0;
uint32 *return_point = (uint32 *)malloc(4 * 16384);
uint32 return_points = 16384;
void *qbs_input_variableoffsets[257];
int32 qbs_input_variabletypes[257];
// qbmain specific global variables
char g_tmp_char;
uint8 g_tmp_uchar;
int16 g_tmp_short;
uint16 g_tmp_ushort;
int32 g_tmp_long;
uint32 g_tmp_ulong;
int8 g_tmp_int8;
uint8 g_tmp_uint8;
int16 g_tmp_int16;
uint16 g_tmp_uint16;
int32 g_tmp_int32;
uint32 g_tmp_uint32;
int64 g_tmp_int64;
uint64 g_tmp_uint64;
float g_tmp_float;
double g_tmp_double;
long double g_tmp_longdouble;
qbs *g_tmp_str;
qbs *g_swap_str;
qbs *pass_str;
ptrszint data_offset = 0;
// inline functions
inline void swap_8(void *a, void *b) {
uint8 x;
x = *(uint8 *)a;
*(uint8 *)a = *(uint8 *)b;
*(uint8 *)b = x;
}
inline void swap_16(void *a, void *b) {
uint16 x;
x = *(uint16 *)a;
*(uint16 *)a = *(uint16 *)b;
*(uint16 *)b = x;
}
inline void swap_32(void *a, void *b) {
uint32 x;
x = *(uint32 *)a;
*(uint32 *)a = *(uint32 *)b;
*(uint32 *)b = x;
}
inline void swap_64(void *a, void *b) {
uint64 x;
x = *(uint64 *)a;
*(uint64 *)a = *(uint64 *)b;
*(uint64 *)b = x;
}
inline void swap_longdouble(void *a, void *b) {
long double x;
x = *(long double *)a;
*(long double *)a = *(long double *)b;
*(long double *)b = x;
}
void swap_string(qbs *a, qbs *b) {
static qbs *c;
c = qbs_new(a->len, 0);
memcpy(c->chr, a->chr, a->len);
qbs_set(a, b);
qbs_set(b, c);
qbs_free(c);
}
void swap_block(void *a, void *b, uint32 bytes) {
static uint32 quads;
quads = bytes >> 2;
static uint32 *a32, *b32;
a32 = (uint32 *)a;
b32 = (uint32 *)b;
while (quads--) {
static uint32 c;
c = *a32;
*a32++ = *b32;
*b32++ = c;
}
bytes &= 3;
static uint8 *a8, *b8;
a8 = (uint8 *)a32;
b8 = (uint8 *)b32;
while (bytes--) {
static uint8 c;
c = *a8;
*a8++ = *b8;
*b8++ = c;
}
}
extern ptrszint *qbs_tmp_list;
template <typename T> static T qbs_cleanup(uint32 base, T passvalue) {
while (qbs_tmp_list_nexti > base) {
qbs_tmp_list_nexti--;
if (qbs_tmp_list[qbs_tmp_list_nexti] != -1)
qbs_free((qbs *)qbs_tmp_list[qbs_tmp_list_nexti]);
} // clear any temp. strings created
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); }
inline long double func_abs(long double d) { return fabs(d); }
inline float func_abs(float d) { return fabs(d); }
inline uint8 func_abs(uint8 d) { return d; }
inline uint16 func_abs(uint16 d) { return d; }
inline uint32 func_abs(uint32 d) { return d; }
inline uint64 func_abs(uint64 d) { return d; }
inline int8 func_abs(int8 d) { return abs(d); }
inline int16 func_abs(int16 d) { return abs(d); }
inline int32 func_abs(int32 d) { return abs(d); }
inline int64 func_abs(int64 d) { return llabs(d); }
extern int32 disableEvents;
ptrszint check_lbound(ptrszint *array, int32 index, int32 num_indexes) {
static ptrszint ret;
disableEvents = 1;
ret = func_lbound((ptrszint *)(*array), index, num_indexes);
new_error = 0;
disableEvents = 0;
return ret;
}
ptrszint check_ubound(ptrszint *array, int32 index, int32 num_indexes) {
static ptrszint ret;
disableEvents = 1;
ret = func_ubound((ptrszint *)(*array), index, num_indexes);
new_error = 0;
disableEvents = 0;
return ret;
}
uint64 call_getubits(uint32 bsize, ptrszint *array, ptrszint i) {
return getubits(bsize, (uint8 *)(*array), i);
}
int64 call_getbits(uint32 bsize, ptrszint *array, ptrszint i) {
return getbits(bsize, (uint8 *)(*array), i);
}
void call_setbits(uint32 bsize, ptrszint *array, ptrszint i, int64 val) {
setbits(bsize, (uint8 *)(*array), i, val);
}
int32 logical_drives() {
#ifdef QB64_WINDOWS
return GetLogicalDrives();
#else
return 0;
#endif
}
inline ptrszint array_check(uptrszint index, uptrszint limit) {
// nb. forces signed index into an unsigned variable for quicker comparison
if (index < limit)
return index;
error(9);
return 0;
}
inline int32 func_sgn(uint8 v) {
if (v)
return 1;
else
return 0;
}
inline int32 func_sgn(int8 v) {
if (v)
if (v > 0)
return 1;
else
return -1;
return 0;
}
inline int32 func_sgn(uint16 v) {
if (v)
return 1;
else
return 0;
}
inline int32 func_sgn(int16 v) {
if (v)
if (v > 0)
return 1;
else
return -1;
return 0;
}
inline int32 func_sgn(uint32 v) {
if (v)
return 1;
else
return 0;
}
inline int32 func_sgn(int32 v) {
if (v)
if (v > 0)
return 1;
else
return -1;
return 0;
}
inline int32 func_sgn(uint64 v) {
if (v)
return 1;
else
return 0;
}
inline int32 func_sgn(int64 v) {
if (v)
if (v > 0)
return 1;
else
return -1;
return 0;
}
inline int32 func_sgn(float v) {
if (v)
if (v > 0)
return 1;
else
return -1;
return 0;
}
inline int32 func_sgn(double v) {
if (v)
if (v > 0)
return 1;
else
return -1;
return 0;
}
inline int32 func_sgn(long double v) {
if (v)
if (v > 0)
return 1;
else
return -1;
return 0;
}
// a740g: ROR & ROL additions start
// The rotation functions below are the way they are for a couple of reasons:
// 1. They are safer (well folks seem to think so; see https://en.wikipedia.org/wiki/Circular_shift#Implementing_circular_shifts)
// 2. We are using C library constants and there is just 1 numeric literal - '1'
// 3. GGC recognizes the 'pattern' and will optimize it out to 'roX' and 3 more instructions when using O2
inline uint8_t func__rol8(uint8_t value, unsigned int count) {
const unsigned int mask = CHAR_BIT * sizeof(value) - 1;
count &= mask;
return (value << count) | (value >> (-count & mask));
}
inline uint8_t func__ror8(uint8_t value, unsigned int count) {
const unsigned int mask = CHAR_BIT * sizeof(value) - 1;
count &= mask;
return (value >> count) | (value << (-count & mask));
}
inline uint16_t func__rol16(uint16_t value, unsigned int count) {
const unsigned int mask = CHAR_BIT * sizeof(value) - 1;
count &= mask;
return (value << count) | (value >> (-count & mask));
}
inline uint16_t func__ror16(uint16_t value, unsigned int count) {
const unsigned int mask = CHAR_BIT * sizeof(value) - 1;
count &= mask;
return (value >> count) | (value << (-count & mask));
}
inline uint32_t func__rol32(uint32_t value, unsigned int count) {
const unsigned int mask = CHAR_BIT * sizeof(value) - 1;
count &= mask;
return (value << count) | (value >> (-count & mask));
}
inline uint32_t func__ror32(uint32_t value, unsigned int count) {
const unsigned int mask = CHAR_BIT * sizeof(value) - 1;
count &= mask;
return (value >> count) | (value << (-count & mask));
}
inline uint64_t func__rol64(uint64_t value, unsigned int count) {
const unsigned int mask = CHAR_BIT * sizeof(value) - 1;
count &= mask;
return (value << count) | (value >> (-count & mask));
}
inline uint64_t func__ror64(uint64_t value, unsigned int count) {
const unsigned int mask = CHAR_BIT * sizeof(value) - 1;
count &= mask;
return (value >> count) | (value << (-count & mask));
}
// a740g: ROR & ROL additions end
// bit-shifting
inline uint64 func__shl(uint64 a1, int b1) { return a1 << b1; }
inline uint64 func__shr(uint64 a1, int b1) { return a1 >> b1; }
inline int64 func__readbit(uint64 a1, int b1) {
if (a1 & 1ull << b1)
return -1;
else
return 0;
}
inline uint64 func__setbit(uint64 a1, int b1) { return a1 | 1ull << b1; }
inline uint64 func__resetbit(uint64 a1, int b1) { return a1 & ~(1ull << b1); }
inline uint64 func__togglebit(uint64 a1, int b1) { return a1 ^ 1ull << b1; }
// Working with 32bit colors:
inline uint32 func__rgb32(int32 r, int32 g, int32 b, int32 a) {
if (r < 0)
r = 0;
if (r > 255)
r = 255;
if (g < 0)
g = 0;
if (g > 255)
g = 255;
if (b < 0)
b = 0;
if (b > 255)
b = 255;
if (a < 0)
a = 0;
if (a > 255)
a = 255;
return (a << 24) + (r << 16) + (g << 8) + b;
}
inline uint32 func__rgb32(int32 r, int32 g, int32 b) {
if (r < 0)
r = 0;
if (r > 255)
r = 255;
if (g < 0)
g = 0;
if (g > 255)
g = 255;
if (b < 0)
b = 0;
if (b > 255)
b = 255;
return (r << 16) + (g << 8) + b | 0xFF000000;
}
inline uint32 func__rgb32(int32 i, int32 a) {
if (i < 0)
i = 0;
if (i > 255)
i = 255;
if (a < 0)
a = 0;
if (a > 255)
a = 255;
return (a << 24) + (i << 16) + (i << 8) + i;
}
inline uint32 func__rgb32(int32 i) {
if (i < 0)
i = 0;
if (i > 255)
i = 255;
return (i << 16) + (i << 8) + i | 0xFF000000;
}
inline uint32 func__rgba32(int32 r, int32 g, int32 b, int32 a) {
if (r < 0)
r = 0;
if (r > 255)
r = 255;
if (g < 0)
g = 0;
if (g > 255)
g = 255;
if (b < 0)
b = 0;
if (b > 255)
b = 255;
if (a < 0)
a = 0;
if (a > 255)
a = 255;
return (a << 24) + (r << 16) + (g << 8) + b;
}
inline int32 func__alpha32(uint32 col) { return col >> 24; }
inline int32 func__red32(uint32 col) { return col >> 16 & 0xFF; }
inline int32 func__green32(uint32 col) { return col >> 8 & 0xFF; }
inline int32 func__blue32(uint32 col) { return col & 0xFF; }
inline uint16 varptr_dblock_check(uint8 *off) {
// note: 66816 is the top of DBLOCK (SEG:80+OFF:65536)
if (off < (&cmem[66816])) { // in DBLOCK?
return ((uint16)(off - &cmem[1280]));
} else {
return ((uint32)(off - cmem)) & 15;
}
}
inline uint16 varseg_dblock_check(uint8 *off) {
// note: 66816 is the top of DBLOCK (SEG:80+OFF:65536)
if (off < (&cmem[66816])) { // in DBLOCK?
return 80;
} else {
return ((uint32)(off - cmem)) / 16;
}
}
#ifdef QB64_WINDOWS
#include "..\\temp\\global.txt"
#include "..\\temp\\regsf.txt"
#else
#include "../temp/global.txt"
#include "../temp/regsf.txt"
#endif
extern int32 ScreenResize;
extern int32 ScreenResizeScale;
// set_dynamic_info is called immediately when
// main() begins, to set global, static variables
// controlling app init
void set_dynamic_info() {
#ifdef QB64_WINDOWS
#include "..\\temp\\dyninfo.txt"
#else
#include "../temp/dyninfo.txt"
#endif
}
void sub_clear(int32 ignore, int32 ignore2, int32 stack, int32 passed) {
static ptrszint tmp_long;
// note: stack can be ignored
#ifdef QB64_WINDOWS
#include "..\\temp\\clear.txt"
#else
#include "../temp/clear.txt"
#endif
// reset DATA read offset
data_offset = 0;
// close open files
sub_close(NULL, NULL); // closes all open files
// free images
freeallimages();
// stop & free sounds (note: QB also stops any sound from the PLAY command)
// invalidate RETURN location(s)
next_return_point = 0;
// reset error goto location to 'unhandled'
error_goto_line = 0;
// invalidate RESUME
error_handling = 0;
return;
}
int32 run_from_line = 0;
// run_from_line's value is an index in a list of possible "run from" locations
// when 0, the program runs from the beginning
void sub__icon(int32 i, int32 i2, int32 passed);
void sub__display();
void sub__autodisplay();
int32 func__autodisplay();
int32 func__errorline() { return ercl; }
int32 func__inclerrorline() { return inclercl; }
qbs *func__inclerrorfile() { return qbs_new_txt(includedfilename); }
qbs *func__errormessage(int32 errorcode, int32 passed) {
if (!passed)
errorcode = get_error_err();
return qbs_new_txt(human_error(errorcode));
}
void chain_input() {
// note: common data or not, every program must check for chained data,
// it could be sharing files or screen state
// check if command$ contains a tmp chain directive
int32 FF;
if ((func_command(0, 0))->len >= 32) {
if (qbs_equal(qbs_right(func_command(0, 0), 4),
qbs_new_txt_len(".tmp", 4))) {
if (qbs_equal(func_mid(func_command(0, 0),
(func_command(0, 0))->len - 31, 25, 1),
qbs_new_txt_len("(unique-tag:=/@*$+-)chain", 25))) {
FF = func_freefile();
sub_open(func_mid(func_command(0, 0),
(func_command(0, 0))->len - 11, 12, 1),
2, NULL, NULL, FF, NULL, 0);
static int32 int32val, int32val2;
static int64 int64val, int64val2;
static int64 bytes, bytei;
static qbs *tqbs;
static ptrszint tmp_long;
// CHDIR directive
static uint8 chdir_data[4096];
sub_get(FF, NULL, byte_element((uint64)&int32val, 4),
0); // assume CHDIR directive 512
sub_get(FF, NULL, byte_element((uint64)&int32val, 4),
0); // assume len
sub_get(FF, NULL, byte_element((uint64)chdir_data, int32val),
0); // data
chdir_data[int32val] = 0;
chain_restorescreenstate(FF);
// get first command
sub_get(FF, NULL, byte_element((uint64)&int32val, 4), 0);
// read COMMON data
#ifdef QB64_WINDOWS
#include "..\\temp\\inpchain.txt"
#else
#include "../temp/inpchain.txt"
#endif
sub_close(FF, 1);
sub_kill(func_mid(func_command(0, 0),
(func_command(0, 0))->len - 11, 12, 1));
chdir((char *)chdir_data);
// remove chain tag from COMMAND$
func_command_str->len -= 32;
// remove trailing space (if any)
if (func_command_str->len)
func_command_str->len--;
}
}
}
}
void sub_chain(qbs *f) {
if (new_error)
return;
#ifdef QB64_WINDOWS
// run program
static qbs *str = NULL;
if (str == NULL)
str = qbs_new(0, 0);
static qbs *str2 = NULL;
if (str2 == NULL)
str2 = qbs_new(0, 0);
static int32 i, i2, x;
static qbs *strz = NULL;
if (!strz)
strz = qbs_new(0, 0);
static char *cp;
if (!f->len) {
error(53);
return;
} // file not found (as in QB)
qbs_set(str, f);
qbs_set(str2, qbs_ucase(str));
static qbs *f_exe = NULL;
if (!f_exe)
f_exe = qbs_new(0, 0);
static qbs *f_bas = NULL;
if (!f_bas)
f_bas = qbs_new(0, 0); // no parameters
static qbs *f_path = NULL;
if (!f_path)
f_path = qbs_new(0, 0);
static int32 path_len;
static qbs *current_path = NULL;
if (!current_path)
current_path = qbs_new(0, 0);
static qbs *thisexe_path = NULL;
if (!thisexe_path)
thisexe_path = qbs_new(0, 0);
// note: supports arguments after filename
f_bas->len = 0;
for (i = 0; i < str->len; i++) {
if (str->chr[i] == 46) {
//.bas?
if ((i + 3) < str->len) {
if ((str2->chr[i + 1] == 66) && (str2->chr[i + 2] == 65) &&
(str2->chr[i + 3] == 83)) { //"BAS"
qbs_set(f_bas, str);
f_bas->len = i + 4; // arguments truncated
qbs_set(f_exe, str); // change .bas to .exe
f_exe->chr[i + 1] = 101;
f_exe->chr[i + 2] = 120;
f_exe->chr[i + 3] = 101; //"exe"
goto extensions_ready;
} //"BAS"
} // bas
//.exe?
if ((i + 3) < str->len) {
if ((str2->chr[i + 1] == 69) && (str2->chr[i + 2] == 88) &&
(str2->chr[i + 3] == 69)) { //"EXE"
qbs_set(f_bas, str);
f_bas->len =
i + 4; // arguments truncated, change .exe to .bas
f_bas->chr[i + 1] = 98;
f_bas->chr[i + 2] = 97;
f_exe->chr[i + 3] = 115; //"bas"
qbs_set(f_exe, str); // note: exe kept as is
goto extensions_ready;
} //"EXE"
} // exe
break; // no meaningful extension found
} //"."
}
// no extension given!
// note: It is more 'likely' that the user will want to pass arguments than
// chain a
// filename containing spaces. Therefore, only everything left of
// left-most space will be considered the path+filename.
i2 = str->len; // last character index of filename
for (i = str->len - 1; i; i--) {
if (str->chr[i] == 32)
i2 = i;
}
qbs_set(str2, qbs_right(str, str->len - i2)); //[+extension]
str->len = i2; //[path+]file
qbs_set(f_exe, qbs_add(qbs_add(str, qbs_new_txt(".exe ")), str2));
qbs_set(f_bas, qbs_add(str, qbs_new_txt(".bas")));
extensions_ready:
// normalize dir slashes
fixdir(f_exe);
fixdir(f_bas);
// get path (strip paths from f_exe & f_bas)
f_path->len = 0;
for (i = f_bas->len - 1; i >= 0; i--) {
if ((f_bas->chr[i] == 92) || (f_bas->chr[i] == 47) ||
(f_bas->chr[i] == 58)) {
qbs_set(f_path, f_bas);
f_path->len = i + 1;
if (f_bas->chr[i] == 58) {
f_path->chr[i + 1] = 92;
f_path->len++;
} // add "\" to ":"
// strip paths
memmove(f_exe->chr, &f_exe->chr[i + 1], f_exe->len - (i + 1));
f_exe->len -= (i + 1);
memmove(f_bas->chr, &f_bas->chr[i + 1], f_bas->len - (i + 1));
f_bas->len -= (i + 1);
break;
}
}
static uint8 path_data[4096];
static int32 defaultpath;
defaultpath = 0;
if (!f_path->len) { // use current path if no path specified
defaultpath = 1;
// get current path (add \ if necessary)
i = GetCurrentDirectory(4096, (char *)path_data);
qbs_set(f_path, func_space(i + 1));
memcpy(f_path->chr, path_data, i);
if ((f_path->chr[i - 1] != 92) && (f_path->chr[i - 1] != 47)) {
f_path->chr[i] = 92;
} else {
f_path->len--;
}
}
// get current program's exe's path (including "\")
GetModuleFileName(NULL, (char *)path_data, 4096);
i = strlen((char *)path_data);
for (i2 = i - 1; i2 >= 0; i2--) {
x = path_data[i2];
if ((x == 92) || (x == 47) || (x == 58)) {
if (x == 58)
i2++;
i2++;
break;
}
}
qbs_set(thisexe_path, func_space(i2));
memcpy(thisexe_path->chr, path_data, i2);
thisexe_path->chr[i2] = 92; //"\"
// 1. create & open a temporary file to pass information to the chained
// program
double TD;
int32 TL, FF;
qbs *TS = NULL;
if (TS == NULL)
TS = qbs_new(0, 0);
qbs *TFS = NULL;
if (TFS == NULL)
TFS = qbs_new(0, 0);
TD = func_timer(0.001E+0, 1);
TL = qbr(floor(TD));
TL = qbr((TD - TL) * 999);
if (TL < 100)
TL = 100; // ensure value is a 3 digit number
qbs_set(TS, qbs_ltrim(qbs_str((int32)(TL))));
qbs_set(TFS, qbs_add(qbs_add(qbs_new_txt_len("chain", 5), TS),
qbs_new_txt_len(".tmp", 4)));
FF = func_freefile();
sub_open(TFS, 2, NULL, NULL, FF, NULL, 0); // opened in BINARY mode
// add common data
static int32 int32val, int32val2;
static int64 int64val, int64val2;
static qbs *tqbs;
static int64 bytes, bytei;
static ptrszint tmp_long;
// CHDIR directive
int32val = 512;
sub_put(FF, NULL, byte_element((uint64)&int32val, 4), 0);
int32val = f_path->len - 1;
sub_put(FF, NULL, byte_element((uint64)&int32val, 4), 0);
sub_put(FF, NULL, byte_element((uint64)f_path->chr, f_path->len - 1),
0); //-1 removes trailing "\"
chain_savescreenstate(FF);
#ifdef QB64_WINDOWS
#include "..\\temp\\chain.txt"
#else
#include "../temp/chain.txt"
#endif
// add "end of commands" value
int32val = 0;
sub_put(FF, NULL, byte_element((uint64)&int32val, 4), 0);
sub_close(FF, 1);
// move chain???.tmp file to path
if (!defaultpath) {
qbs_set(str, qbs_new_txt("move /Y "));
qbs_set(str, qbs_add(str, qbs_new_txt_len("\x022", 1)));
qbs_set(str, qbs_add(str, TFS));
qbs_set(str, qbs_add(str, qbs_new_txt_len("\x022", 1)));
qbs_set(str, qbs_add(str, qbs_new_txt(" ")));
qbs_set(str, qbs_add(str, qbs_new_txt_len("\x022", 1)));
qbs_set(str, qbs_add(str, f_path));
str->len--; // remove trailing "\" of dest path
qbs_set(str, qbs_add(str, qbs_new_txt_len("\x022", 1)));
qbs_set(strz, qbs_add(str, qbs_new_txt_len("\0", 1)));
WinExec((char *)strz->chr, SW_HIDE);
}
static int32 method;
method = 1;
chain_retry:
if (method == 1) {
qbs_set(str, qbs_add(f_path, f_exe));
}
if (method == 2) {
// move chain???.tmp file to 'thisexe_path' path
qbs_set(str, qbs_new_txt("move /Y "));
qbs_set(str, qbs_add(str, qbs_new_txt_len("\x022", 1)));
qbs_set(str, qbs_add(str, f_path));
qbs_set(str, qbs_add(str, TFS));
qbs_set(str, qbs_add(str, qbs_new_txt_len("\x022", 1)));
qbs_set(str, qbs_add(str, qbs_new_txt(" ")));
qbs_set(str, qbs_add(str, qbs_new_txt_len("\x022", 1)));
qbs_set(str, qbs_add(str, thisexe_path));
str->len--; // remove trailing "\" of dest path
qbs_set(str, qbs_add(str, qbs_new_txt_len("\x022", 1)));
qbs_set(strz, qbs_add(str, qbs_new_txt_len("\0", 1)));
sub_shell(str, 1);
qbs_set(str, qbs_add(thisexe_path, f_exe));
}
if (method == 3) {
// attempt .bas compilation
qbs_set(str, qbs_new_txt_len("\x022", 1));
qbs_set(str, qbs_add(str, thisexe_path));
qbs_set(str, qbs_add(str, qbs_new_txt("qb64pe.exe")));
qbs_set(str, qbs_add(str, qbs_new_txt_len("\x022", 1)));
qbs_set(str, qbs_add(str, qbs_new_txt(" -c ")));
qbs_set(str, qbs_add(str, f_path));
qbs_set(str, qbs_add(str, f_bas));
sub_shell(str, 1);
qbs_set(str, qbs_add(thisexe_path, f_exe));
}
// add a space
qbs_set(str, qbs_add(str, qbs_new_txt(" ")));
// add chain tag
qbs_set(str, qbs_add(str, qbs_new_txt_len("(unique-tag:=/@*$+-)", 20)));
// add chain file name
qbs_set(str, qbs_add(str, TFS));
// add NULL terminator
qbs_set(strz, qbs_add(str, qbs_new_txt_len("\0", 1)));
#ifdef QB64_WINDOWS
if (WinExec((char *)strz->chr, SW_SHOWDEFAULT) > 31) {
goto run_exit;
} else {
goto run_failed;
}
#else
system((char *)strz->chr);
// success?
goto run_exit;
#endif
// exit this program
run_exit:
close_program = 1;
end();
exit(99); //<--this line should never actually be executed
// failed
run_failed:
if (method == 1) {
method = 2;
goto chain_retry;
}
if (method == 2) {
method = 3;
goto chain_retry;
}
qbs_set(str, qbs_add(thisexe_path, TFS));
sub_kill(str); // remove tmp file (chain specific)
error(53);
return; // file not found
#endif
}
// note: index 0 is unused
int32 device_last = 0; // last used device
int32 device_max = 1000; // number of allocated indexes
device_struct *devices =
(device_struct *)calloc(1000 + 1, sizeof(device_struct));
// device_struct helper functions
uint8 getDeviceEventButtonValue(device_struct *device, int32 eventIndex,
int32 objectIndex) {
return *(device->events + eventIndex * device->event_size +
device->lastaxis * 4 + device->lastwheel * 4 + objectIndex);
}
void setDeviceEventButtonValue(device_struct *device, int32 eventIndex,
int32 objectIndex, uint8 value) {
*(device->events + eventIndex * device->event_size + device->lastaxis * 4 +
device->lastwheel * 4 + objectIndex) = value;
}
float getDeviceEventAxisValue(device_struct *device, int32 eventIndex,
int32 objectIndex) {
return *(float *)(device->events + eventIndex * device->event_size +
objectIndex * 4);
}
void setDeviceEventAxisValue(device_struct *device, int32 eventIndex,
int32 objectIndex, float value) {
*(float *)(device->events + eventIndex * device->event_size +
objectIndex * 4) = value;
}
float getDeviceEventWheelValue(device_struct *device, int32 eventIndex,
int32 objectIndex) {
return *(float *)(device->events + eventIndex * device->event_size +
device->lastaxis * 4 + objectIndex * 4);
}
void setDeviceEventWheelValue(device_struct *device, int32 eventIndex,
int32 objectIndex, float value) {
*(float *)(device->events + eventIndex * device->event_size +
device->lastaxis * 4 + objectIndex * 4) = value;
}
void setupDevice(device_struct *device) {
int32 size =
device->lastaxis * 4 + device->lastwheel * 4 + device->lastbutton;
size += 8; // for appended ordering index
size += 7;
size = size - (size & 7); // align to closest 8-byte boundary
device->event_size = size;
device->events = (uint8 *)calloc(
2,
device->event_size); // create initial 'current' and 'previous' events
device->max_events = 2;
device->queued_events = 2;
device->connected = 1;
device->used = 1;
}
int32 createDeviceEvent(device_struct *device) {
uint8 *cp, *cp2;
if (device->queued_events ==
device->max_events) { // expand/shift event buffer
if (device->max_events >= QUEUED_EVENTS_LIMIT) {
// discard base message
memmove(device->events, device->events + device->event_size,
(device->queued_events - 1) * device->event_size);
device->queued_events--;
} else {
cp = (uint8 *)calloc(device->max_events * 2,
device->event_size); // create new buffer
memcpy(cp, device->events,
device->queued_events *
device->event_size); // copy events from old buffer into
// new buffer
cp2 = device->events;
device->events = cp;
device->max_events *= 2;
free(cp2);
}
}
// copy previous event data into new event
memmove(device->events + device->queued_events * device->event_size,
device->events + (device->queued_events - 1) * device->event_size,
device->event_size);
*(int64 *)(device->events + (device->queued_events * device->event_size) +
(device->event_size - 8)) =
device_event_index++; // set global event index
int32 eventIndex = device->queued_events;
return eventIndex;
}
void commitDeviceEvent(device_struct *device) { device->queued_events++; }
int32 func__devices() { return device_last; }
int32 device_selected = 0;
qbs *func__device(int32 i, int32 passed) {
if (!passed)
i = device_selected;
if (i < 1 || i > device_last) {
error(5);
return qbs_new(0, 1);
}
return qbs_new_txt(devices[i].name);
}
int32 func__deviceinput(int32 i, int32 passed) {
static device_struct *d;
static int32 retval;
retval = -1;
device_selected = -1;
if (!passed) {
// find oldest event across all devices
static int32 i2;
static int64 index, lowest_index;
i2 = -1;
for (i = 1; i <= device_last; i++) {
d = &devices[i];
if (d->queued_events > 2) {
index = *(int64 *)((d->events + d->event_size * 2) +
(d->event_size - 8));
if ((i2 == -1) || (index < lowest_index)) {
i2 = i;
lowest_index = index;
retval = i2;
} // first/lower
} // queued_events>2
} // i
if (i2 != -1)
i = i2;
else
return 0;
}
if (i < 1 || i > device_last)
error(5);
d = &devices[i];
device_selected = i;
if (d->queued_events > 2) {
memmove(d->events, ((uint8 *)d->events) + d->event_size,
(d->queued_events - 1) * d->event_size);
d->queued_events--;
return retval;
}
return 0;
}
int32 func__button(int32 i, int32 passed) {
if (device_selected < 1 || device_selected > device_last) {
error(5);
return 0;
}
static device_struct *d;
d = &devices[device_selected];
if (!passed)
i = 1;
if (i < 1 || i > d->lastbutton) {
error(5);
return 0;
}
if (getDeviceEventButtonValue(d, 1, i - 1))
return -1;
return 0;
}
int32 func__buttonchange(int32 i, int32 passed) {
if (device_selected < 1 || device_selected > device_last) {
error(5);
return 0;
}
static device_struct *d;
d = &devices[device_selected];
if (!passed)
i = 1;
if (i < 1 || i > d->lastbutton) {
error(5);
return 0;
}
static int32 old_value, value;
value = getDeviceEventButtonValue(d, 1, i - 1);
old_value = getDeviceEventButtonValue(d, 0, i - 1);
if (value > old_value)
return -1;
if (value < old_value)
return 1;
return 0;
}
float func__axis(int32 i, int32 passed) {
if (device_selected < 1 || device_selected > device_last) {
error(5);
return 0;
}
static device_struct *d;
d = &devices[device_selected];
if (!passed)
i = 1;
if (i < 1 || i > d->lastaxis) {
error(5);
return 0;
}
return getDeviceEventAxisValue(d, 1, i - 1);
}
float func__wheel(int32 i, int32 passed) {
if (device_selected < 1 || device_selected > device_last) {
error(5);
return 0;
}
static device_struct *d;
d = &devices[device_selected];
if (!passed)
i = 1;
if (i < 1 || i > d->lastwheel) {
error(5);
return 0;
}
return getDeviceEventWheelValue(d, 1, i - 1);
}
int32 func__lastbutton(int32 di, int32 passed) {
if (!passed)
di = device_selected;
if (di < 1 || di > device_last)
error(5);
static device_struct *d;
d = &devices[di];
return d->lastbutton;
}
int32 func__lastaxis(int32 di, int32 passed) {
if (!passed)
di = device_selected;
if (di < 1 || di > device_last)
error(5);
static device_struct *d;
d = &devices[di];
return d->lastaxis;
}
int32 func__lastwheel(int32 di, int32 passed) {
if (!passed)
di = device_selected;
if (di < 1 || di > device_last)
error(5);
static device_struct *d;
d = &devices[di];
return d->lastwheel;
}
onstrig_struct *onstrig = (onstrig_struct *)calloc(
65536, sizeof(onstrig_struct)); // note: up to 256 controllers with up to
// 256 buttons each supported
int32 onstrig_inprogress = 0;
void onstrig_setup(int32 i, int32 controller, int32 controller_passed,
uint32 id, int64 pass) {
// note: pass is ignored by ids not requiring a pass value
if (new_error)
return;
if (i < 0 || i > 65535) {
error(5);
return;
}
if (controller_passed) {
if (controller < 1 || controller > 65535) {
error(5);
return;
}
} else {
controller = 1;
if (i & 2) {
controller = 2;
i -= 2;
}
}
static int32 button;
button = (i >> 2) + 1;
if (i & 1) {
error(5);
return;
} //'currently down' state cannot be used as an ON STRIG event
if (controller > 256 || button > 256)
return; // error-less exit for (currently) unsupported ranges
i = (controller - 1) * 256 + (button - 1); // reindex
onstrig[i].state = 0;
onstrig[i].pass = pass;
onstrig[i].id = id; // id must be set last because it is the trigger
// variable
if (device_last == 0)
func__devices(); // init device interface (if not already setup)
}
void sub_strig(int32 i, int32 controller, int32 option, int32 passed) {
// ref: "[(?[,?])]{ON|OFF|STOP}"
if (new_error)
return;
// Note: QuickBASIC ignores STRIG ON and STRIG OFF statements--the
// statements are provided for compatibility with earlier versions,
// Reference: http://www.antonis.de/qbebooks/gwbasman/strig.html
// QB64 makes STRIG ON/OFF/STOP change the checking status for all
// buttons
static int32 i1, i2;
if (passed > 0) {
if (i < 0 || i > 65535) {
error(5);
return;
}
if (passed & 2) {
if (controller < 1 || controller > 65535) {
error(5);
return;
}
} else {
controller = 1;
if (i & 2) {
controller = 2;
i -= 2;
}
}
static int32 button;
button = (i >> 2) + 1;
if (i & 1) {
error(5);
return;
} //'currently down' state cannot be used as an ON STRIG event
if (controller > 256 || button > 256)
return; // error-less exit for (currently) unsupported ranges
i = (controller - 1) * 256 + (button - 1); // reindex
i1 = i;
i2 = i;
} else {
i1 = 0;
i2 = 65535;
}
for (i = i1; i <= i2; i++) {
// ref: uint8 active;//0=OFF, 1=ON, 2=STOP
if (option == 1) { // ON
onstrig[i].active = 1;
if (onstrig[i].state)
qbevent = 1;
}
if (option == 2) { // OFF
onstrig[i].active = 0;
onstrig[i].state = 0;
}
if (option == 3) { // STOP
onstrig[i].active = 2;
if (onstrig[i].state)
onstrig[i].state = 1;
}
} // i
}
onkey_struct *onkey = (onkey_struct *)calloc(32, sizeof(onkey_struct));
int32 onkey_inprogress = 0;
void onkey_setup(int32 i, uint32 id, int64 pass) {
// note: pass is ignored by ids not requiring a pass value
if (new_error)
return;
if ((i < 1) || (i > 31)) {
error(5);
return;
}
onkey[i].state = 0;
onkey[i].pass = pass;
onkey[i].id = id; // id must be set last because it is the trigger variable
}
void sub_key(int32 i, int32 option) {
// ref: "(?){ON|OFF|STOP}"
if (new_error)
return;
if ((i < 0) || (i > 31)) {
error(5);
return;
}
static int32 i1, i2;
i1 = i;
i2 = i;
if (!i) {
i1 = i;
i2 = 31;
} // set all keys!
for (i = i1; i <= i2; i++) {
// ref: uint8 active;//0=OFF, 1=ON, 2=STOP
if (option == 1) { // ON
onkey[i].active = 1;
if (onkey[i].state)
qbevent = 1;
}
if (option == 2) { // OFF
onkey[i].active = 0;
onkey[i].state = 0;
}
if (option == 3) { // STOP
onkey[i].active = 2;
if (onkey[i].state)
onkey[i].state = 1;
}
} // i
}
int32 ontimer_nextfree = 1;
int32 *ontimer_freelist = (int32 *)malloc(32);
uint32 ontimer_freelist_size = 8; // number of elements in the freelist
uint32 ontimer_freelist_available = 0; // element (if any) which is available)
ontimer_struct *ontimer = (ontimer_struct *)malloc(sizeof(ontimer_struct));
// note: index 0 of the above cannot be allocated/freed
int32 ontimerthread_lock = 0;
void stop_timers() {
ontimerthread_lock = 1;
while (ontimerthread_lock != 2)
;
}
void start_timers() { ontimerthread_lock = 0; }
int32 func__freetimer() {
if (new_error)
return 0;
static int32 i;
if (ontimer_freelist_available) {
i = ontimer_freelist[ontimer_freelist_available--];
} else {
ontimerthread_lock = 1;
while (ontimerthread_lock == 1)
Sleep(0); // mutex
ontimer = (ontimer_struct *)realloc(
ontimer, sizeof(ontimer_struct) * (ontimer_nextfree + 1));
if (!ontimer)
error(257); // out of memory
ontimerthread_lock = 0; // mutex
i = ontimer_nextfree;
ontimer[i].state = 0; // state is not set to 0 if reusing an existing
// index as event could still be in progress
}
ontimer[i].active = 0;
ontimer[i].id = 0;
ontimer[i].allocated = 1;
if (i == ontimer_nextfree)
ontimer_nextfree++;
return i;
}
void freetimer(int32 i) {
ontimer[i].allocated = 0;
ontimer[i].id = 0;
if (ontimer_freelist_available == ontimer_freelist_size) {
ontimer_freelist_size *= 2;
ontimer_freelist =
(int32 *)realloc(ontimer_freelist, ontimer_freelist_size * 4);
}
ontimer_freelist[++ontimer_freelist_available] = i;
}
void ontimer_setup(int32 i, double sec, uint32 id, int64 pass) {
// note: pass is ignored by ids not requiring a pass value
if (new_error)
return;
if ((i < 0) || (i >= ontimer_nextfree)) {
error(5);
return;
}
if (!ontimer[i].allocated) {
error(5);
return;
}
if (ontimer[i].state == 1)
ontimer[i].state = 0; // retract prev event if not in progress
ontimer[i].seconds = sec;
ontimer[i].pass = pass;
ontimer[i].last_time = 0;
ontimer[i].id = id; // id must be set last because it is the trigger
// variable
}
void sub_timer(int32 i, int32 option, int32 passed) {
// ref: "[(?)]{ON|OFF|STOP|FREE}"
if (new_error)
return;
if (!passed)
i = 0;
if ((i < 0) || (i >= ontimer_nextfree)) {
error(5);
return;
}
if (!ontimer[i].allocated) {
error(5);
return;
}
// ref: uint8 active;//0=OFF, 1=ON, 2=STOP
if (option == 1) { // ON
ontimer[i].active = 1;
return;
}
if (option == 2) { // OFF
ontimer[i].active = 0;
if (ontimer[i].state == 1)
ontimer[i].state = 0; // retract event if not in progress
ontimer[i].last_time =
0; // when ON is next used, event will be triggered immediately
return;
}
if (option == 3) { // STOP
ontimer[i].active = 2;
return;
}
if (option == 4) { // FREE
if (i == 0) {
error(5);
return;
}
ontimer[i].active = 0;
if (ontimer[i].state == 1)
ontimer[i].state = 0; // retract event if not in progress
freetimer(i);
// note: if an event is still in progress, it will set state to 0 when
// it finishes
// which may delay the first instance of this index if it is
// immediately reused
return;
}
}
#ifdef QB64_WINDOWS
void TIMERTHREAD_WINDOWS(void *unused) {
TIMERTHREAD();
return;
}
#else
void *TIMERTHREAD_LINUX(void *unused) {
TIMERTHREAD();
return NULL;
}
#endif
void TIMERTHREAD() {
static int32 i;
static double time_now = 100000;
while (1) {
quick_lock:
if (ontimerthread_lock == 1)
ontimerthread_lock = 2; // mutex, verify lock
if (!ontimerthread_lock) { // mutex
time_now = ((double)GetTicks()) * 0.001;
for (i = 0; i < ontimer_nextfree; i++) {
if (ontimer[i].allocated) {
if (ontimer[i].id) {
if (ontimer[i].active) {
if (!ontimer[i].state) {
if (time_now - ontimer[i].last_time >
ontimer[i].seconds) {
if (!ontimer[i].last_time) {
ontimer[i].last_time = time_now;
} else {
// keep measured time for accurate
// number of calls overall
ontimer[i].last_time +=
ontimer[i].seconds;
// if difference between actual time and
// measured time is beyond 'seconds' set
// measured to actual
if (fabs(time_now -
ontimer[i].last_time) >=
ontimer[i].seconds)
ontimer[i].last_time = time_now;
ontimer[i].state = 1;
qbevent = 1;
}
} // time check
} // state==0
} // active
} // id
} // allocated
if (ontimerthread_lock == 1)
goto quick_lock;
} // i
} // not locked
Sleep(1);
if (stop_program) {
exit_ok |= 2;
return;
} // close thread #2
} // while(1)
return;
}
void events() {
int32 i, x, d, di;
int64 i64;
// onstrig events
onstrig_recheck:
if (!error_handling) { // no new calls happen whilst error handling
di = 0;
for (d = 1; d <= device_last; d++) {
if (devices[d].type == 1) {
if (di <= 255) {
for (i = 0; i <= 255; i++) {
if (onstrig[(di << 8) + i].id) {
if (onstrig[(di << 8) + i].active ==
1) { // if STOPped, event will be postponed
if (onstrig[(di << 8) + i].state) {
if (!onstrig_inprogress) {
onstrig_inprogress = 1;
onstrig[(di << 8) + i].state--;
x = onstrig[(di << 8) + i].id;
i64 = onstrig[(di << 8) + i].pass;
switch (x) {
#ifdef QB64_WINDOWS
#include "..\\temp\\onstrig.txt"
#else
#include "../temp/onstrig.txt"
#endif
// example.....
// case 1:
//...
// break;
default:
break;
} // switch
onstrig_inprogress = 0;
goto onstrig_recheck;
} //! inprogress
} // state
} // active==1
} // id
} // i
} // di<=255
di++;
} // type==1
} // d
} //! error_handling
// onkey events
onkey_recheck:
if (!error_handling) { // no new calls happen whilst error handling
for (i = 1; i <= 31; i++) {
if (onkey[i].id) {
if (onkey[i].active ==
1) { // if STOPped, event will be postponed
if (onkey[i].state) {
if (!onkey_inprogress) {
onkey_inprogress = 1;
onkey[i].state--;
x = onkey[i].id;
i64 = onkey[i].pass;
switch (x) {
#ifdef QB64_WINDOWS
#include "..\\temp\\onkey.txt"
#else
#include "../temp/onkey.txt"
#endif
// example.....
// case 1:
//...
// break;
default:
break;
} // switch
onkey_inprogress = 0;
goto onkey_recheck;
} //! inprogress
} // state
} // active==1
} // id
} // i
} //! error_handling
// ontimer events
if (!error_handling) { // no new on timer calls happen whilst error handling
for (i = 0; i < ontimer_nextfree; i++) {
if (ontimer[i].allocated) {
if (ontimer[i].id) {
if (ontimer[i].active ==
1) { // if timer STOPped, event will be postponed
if (ontimer[i].state == 1) {
ontimer[i].state = 2; // event in progress
x = ontimer[i].id;
i64 = ontimer[i].pass;
switch (x) {
#ifdef QB64_WINDOWS
#include "..\\temp\\ontimer.txt"
#else
#include "../temp/ontimer.txt"
#endif
// example.....
// case 1:
//...
// break;
default:
break;
} // switch
ontimer[i].state = 0; // event finished
sleep_break = 1;
} // state==1
} // active==1
} // id
} // allocated
} // i
} //! error_handling
}
extern int64 display_lock_request;
extern int64 display_lock_confirmed;
extern int64 display_lock_released;
uint32 r;
void evnt(uint32 linenumber, uint32 inclinenumber = 0,
const char *incfilename = NULL) {
if (disableEvents)
return;
qbevent = 0;
if (sub_gl_called == 0) {
if (display_lock_request > display_lock_confirmed) {
display_lock_confirmed = display_lock_request;
while ((display_lock_released < display_lock_confirmed) &&
(!close_program) && (!suspend_program) && (!stop_program))
Sleep(1);
}
}
r = 0;
while (suspend_program || stop_program) {
if (stop_program)
end();
Sleep(10);
}
if (new_error) {
ercl = linenumber;
inclercl = inclinenumber;
includedfilename = (char *)incfilename;
fix_error();
if (error_retry) {
error_retry = 0;
r = 1;
}
} else {
if (sub_gl_called == 0)
events();
}
}
uint8 *redim_preserve_cmem_buffer =
(uint8 *)malloc(65536); // used for temporary storage only (move to libqbx?)
#include "myip.cpp"
void division_by_zero_handler(int ignore) { error(11); }
// void SIGSEGV_handler(int ignore){
// error(256);//assume stack overflow? (the most likely cause)
//}
#ifdef QB64_WINDOWS
void QBMAIN_WINDOWS(void *unused) {
QBMAIN(NULL);
return;
}
#else
void *QBMAIN_LINUX(void *unused) {
QBMAIN(NULL);
return NULL;
}
#endif
void QBMAIN(void *unused) {
fpu_reinit();
#ifdef QB64_WINDOWS
signal(SIGFPE, division_by_zero_handler);
// signal(SIGSEGV, SIGSEGV_handler);
#else
struct sigaction sig_act;
sig_act.sa_handler = division_by_zero_handler;
sigemptyset(&(sig_act.sa_mask));
sig_act.sa_flags = 0;
sigaction(SIGFPE, &sig_act, NULL);
#endif
ptrszint tmp_long;
int32 tmp_fileno;
qbs *tqbs;
uint32 qbs_tmp_base = qbs_tmp_list_nexti;
static mem_lock *sf_mem_lock = NULL;
if (!sf_mem_lock) {
new_mem_lock();
sf_mem_lock = mem_lock_tmp;
sf_mem_lock->type = 3;
}
#ifdef QB64_WINDOWS
#include "..\\temp\\maindata.txt"
#include "..\\temp\\mainerr.txt"
#include "..\\temp\\runline.txt"
if (timer_event_occurred) {
timer_event_occurred--;
#include "..\\temp\\ontimerj.txt"
}
if (key_event_occurred) {
key_event_occurred--;
#include "..\\temp\\onkeyj.txt"
}
if (strig_event_occurred) {
strig_event_occurred--;
#include "..\\temp\\onstrigj.txt"
}
chain_input();
#include "..\\temp\\main.txt"
#else
#include "../temp/maindata.txt"
#include "../temp/mainerr.txt"
#include "../temp/runline.txt"
if (timer_event_occurred) {
timer_event_occurred--;
#include "../temp/ontimerj.txt"
}
if (key_event_occurred) {
key_event_occurred--;
#include "../temp/onkeyj.txt"
}
if (strig_event_occurred) {
strig_event_occurred--;
#include "../temp/onstrigj.txt"
}
chain_input();
#include "../temp/main.txt"
#endif
//} (closed by main.txt)