From 3bea14cd54cc1b822ea71a63cf991c4f644d324b Mon Sep 17 00:00:00 2001 From: rexim Date: Sat, 17 Feb 2024 22:45:45 +0700 Subject: [PATCH] Port the Snake Game --- game.c => examples/tsoding_ball.c | 0 examples/tsoding_snake/stb_sprintf.h | 1906 ++++++++++++++++++++++++ examples/tsoding_snake/tsoding_snake.c | 896 +++++++++++ examples/tsoding_snake/tsoding_snake.h | 26 + fonts/AnekLatin-Light.ttf | Bin 0 -> 110816 bytes fonts/OFL.txt | 93 ++ index.html | 4 +- raylib.js | 60 + wasm/{game.wasm => tsoding_ball.wasm} | Bin wasm/tsoding_snake.wasm | Bin 0 -> 80444 bytes 10 files changed, 2983 insertions(+), 2 deletions(-) rename game.c => examples/tsoding_ball.c (100%) create mode 100644 examples/tsoding_snake/stb_sprintf.h create mode 100644 examples/tsoding_snake/tsoding_snake.c create mode 100644 examples/tsoding_snake/tsoding_snake.h create mode 100644 fonts/AnekLatin-Light.ttf create mode 100644 fonts/OFL.txt rename wasm/{game.wasm => tsoding_ball.wasm} (100%) create mode 100755 wasm/tsoding_snake.wasm diff --git a/game.c b/examples/tsoding_ball.c similarity index 100% rename from game.c rename to examples/tsoding_ball.c diff --git a/examples/tsoding_snake/stb_sprintf.h b/examples/tsoding_snake/stb_sprintf.h new file mode 100644 index 0000000..ca432a6 --- /dev/null +++ b/examples/tsoding_snake/stb_sprintf.h @@ -0,0 +1,1906 @@ +// stb_sprintf - v1.10 - public domain snprintf() implementation +// originally by Jeff Roberts / RAD Game Tools, 2015/10/20 +// http://github.com/nothings/stb +// +// allowed types: sc uidBboXx p AaGgEef n +// lengths : hh h ll j z t I64 I32 I +// +// Contributors: +// Fabian "ryg" Giesen (reformatting) +// github:aganm (attribute format) +// +// Contributors (bugfixes): +// github:d26435 +// github:trex78 +// github:account-login +// Jari Komppa (SI suffixes) +// Rohit Nirmal +// Marcin Wojdyr +// Leonard Ritter +// Stefano Zanotti +// Adam Allison +// Arvid Gerstmann +// Markus Kolb +// +// LICENSE: +// +// See end of file for license information. + +#ifndef STB_SPRINTF_H_INCLUDE +#define STB_SPRINTF_H_INCLUDE + +/* +Single file sprintf replacement. + +Originally written by Jeff Roberts at RAD Game Tools - 2015/10/20. +Hereby placed in public domain. + +This is a full sprintf replacement that supports everything that +the C runtime sprintfs support, including float/double, 64-bit integers, +hex floats, field parameters (%*.*d stuff), length reads backs, etc. + +Why would you need this if sprintf already exists? Well, first off, +it's *much* faster (see below). It's also much smaller than the CRT +versions code-space-wise. We've also added some simple improvements +that are super handy (commas in thousands, callbacks at buffer full, +for example). Finally, the format strings for MSVC and GCC differ +for 64-bit integers (among other small things), so this lets you use +the same format strings in cross platform code. + +It uses the standard single file trick of being both the header file +and the source itself. If you just include it normally, you just get +the header file function definitions. To get the code, you include +it from a C or C++ file and define STB_SPRINTF_IMPLEMENTATION first. + +It only uses va_args macros from the C runtime to do it's work. It +does cast doubles to S64s and shifts and divides U64s, which does +drag in CRT code on most platforms. + +It compiles to roughly 8K with float support, and 4K without. +As a comparison, when using MSVC static libs, calling sprintf drags +in 16K. + +API: +==== +int stbsp_sprintf( char * buf, char const * fmt, ... ) +int stbsp_snprintf( char * buf, int count, char const * fmt, ... ) + Convert an arg list into a buffer. stbsp_snprintf always returns + a zero-terminated string (unlike regular snprintf). + +int stbsp_vsprintf( char * buf, char const * fmt, va_list va ) +int stbsp_vsnprintf( char * buf, int count, char const * fmt, va_list va ) + Convert a va_list arg list into a buffer. stbsp_vsnprintf always returns + a zero-terminated string (unlike regular snprintf). + +int stbsp_vsprintfcb( STBSP_SPRINTFCB * callback, void * user, char * buf, char const * fmt, va_list va ) + typedef char * STBSP_SPRINTFCB( char const * buf, void * user, int len ); + Convert into a buffer, calling back every STB_SPRINTF_MIN chars. + Your callback can then copy the chars out, print them or whatever. + This function is actually the workhorse for everything else. + The buffer you pass in must hold at least STB_SPRINTF_MIN characters. + // you return the next buffer to use or 0 to stop converting + +void stbsp_set_separators( char comma, char period ) + Set the comma and period characters to use. + +FLOATS/DOUBLES: +=============== +This code uses a internal float->ascii conversion method that uses +doubles with error correction (double-doubles, for ~105 bits of +precision). This conversion is round-trip perfect - that is, an atof +of the values output here will give you the bit-exact double back. + +One difference is that our insignificant digits will be different than +with MSVC or GCC (but they don't match each other either). We also +don't attempt to find the minimum length matching float (pre-MSVC15 +doesn't either). + +If you don't need float or doubles at all, define STB_SPRINTF_NOFLOAT +and you'll save 4K of code space. + +64-BIT INTS: +============ +This library also supports 64-bit integers and you can use MSVC style or +GCC style indicators (%I64d or %lld). It supports the C99 specifiers +for size_t and ptr_diff_t (%jd %zd) as well. + +EXTRAS: +======= +Like some GCCs, for integers and floats, you can use a ' (single quote) +specifier and commas will be inserted on the thousands: "%'d" on 12345 +would print 12,345. + +For integers and floats, you can use a "$" specifier and the number +will be converted to float and then divided to get kilo, mega, giga or +tera and then printed, so "%$d" 1000 is "1.0 k", "%$.2d" 2536000 is +"2.53 M", etc. For byte values, use two $:s, like "%$$d" to turn +2536000 to "2.42 Mi". If you prefer JEDEC suffixes to SI ones, use three +$:s: "%$$$d" -> "2.42 M". To remove the space between the number and the +suffix, add "_" specifier: "%_$d" -> "2.53M". + +In addition to octal and hexadecimal conversions, you can print +integers in binary: "%b" for 256 would print 100. + +PERFORMANCE vs MSVC 2008 32-/64-bit (GCC is even slower than MSVC): +=================================================================== +"%d" across all 32-bit ints (4.8x/4.0x faster than 32-/64-bit MSVC) +"%24d" across all 32-bit ints (4.5x/4.2x faster) +"%x" across all 32-bit ints (4.5x/3.8x faster) +"%08x" across all 32-bit ints (4.3x/3.8x faster) +"%f" across e-10 to e+10 floats (7.3x/6.0x faster) +"%e" across e-10 to e+10 floats (8.1x/6.0x faster) +"%g" across e-10 to e+10 floats (10.0x/7.1x faster) +"%f" for values near e-300 (7.9x/6.5x faster) +"%f" for values near e+300 (10.0x/9.1x faster) +"%e" for values near e-300 (10.1x/7.0x faster) +"%e" for values near e+300 (9.2x/6.0x faster) +"%.320f" for values near e-300 (12.6x/11.2x faster) +"%a" for random values (8.6x/4.3x faster) +"%I64d" for 64-bits with 32-bit values (4.8x/3.4x faster) +"%I64d" for 64-bits > 32-bit values (4.9x/5.5x faster) +"%s%s%s" for 64 char strings (7.1x/7.3x faster) +"...512 char string..." ( 35.0x/32.5x faster!) +*/ + +#if defined(__clang__) + #if defined(__has_feature) && defined(__has_attribute) + #if __has_feature(address_sanitizer) + #if __has_attribute(__no_sanitize__) + #define STBSP__ASAN __attribute__((__no_sanitize__("address"))) + #elif __has_attribute(__no_sanitize_address__) + #define STBSP__ASAN __attribute__((__no_sanitize_address__)) + #elif __has_attribute(__no_address_safety_analysis__) + #define STBSP__ASAN __attribute__((__no_address_safety_analysis__)) + #endif + #endif + #endif +#elif defined(__GNUC__) && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)) + #if defined(__SANITIZE_ADDRESS__) && __SANITIZE_ADDRESS__ + #define STBSP__ASAN __attribute__((__no_sanitize_address__)) + #endif +#endif + +#ifndef STBSP__ASAN +#define STBSP__ASAN +#endif + +#ifdef STB_SPRINTF_STATIC +#define STBSP__PUBLICDEC static +#define STBSP__PUBLICDEF static STBSP__ASAN +#else +#ifdef __cplusplus +#define STBSP__PUBLICDEC extern "C" +#define STBSP__PUBLICDEF extern "C" STBSP__ASAN +#else +#define STBSP__PUBLICDEC extern +#define STBSP__PUBLICDEF STBSP__ASAN +#endif +#endif + +#if defined(__has_attribute) + #if __has_attribute(format) + #define STBSP__ATTRIBUTE_FORMAT(fmt,va) __attribute__((format(printf,fmt,va))) + #endif +#endif + +#ifndef STBSP__ATTRIBUTE_FORMAT +#define STBSP__ATTRIBUTE_FORMAT(fmt,va) +#endif + +#ifdef _MSC_VER +#define STBSP__NOTUSED(v) (void)(v) +#else +#define STBSP__NOTUSED(v) (void)sizeof(v) +#endif + +#include // for va_arg(), va_list() +#include // size_t, ptrdiff_t + +#ifndef STB_SPRINTF_MIN +#define STB_SPRINTF_MIN 512 // how many characters per callback +#endif +typedef char *STBSP_SPRINTFCB(const char *buf, void *user, int len); + +#ifndef STB_SPRINTF_DECORATE +#define STB_SPRINTF_DECORATE(name) stbsp_##name // define this before including if you want to change the names +#endif + +STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(vsprintf)(char *buf, char const *fmt, va_list va); +STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(vsnprintf)(char *buf, int count, char const *fmt, va_list va); +STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(sprintf)(char *buf, char const *fmt, ...) STBSP__ATTRIBUTE_FORMAT(2,3); +STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(snprintf)(char *buf, int count, char const *fmt, ...) STBSP__ATTRIBUTE_FORMAT(3,4); + +STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(vsprintfcb)(STBSP_SPRINTFCB *callback, void *user, char *buf, char const *fmt, va_list va); +STBSP__PUBLICDEC void STB_SPRINTF_DECORATE(set_separators)(char comma, char period); + +#endif // STB_SPRINTF_H_INCLUDE + +#ifdef STB_SPRINTF_IMPLEMENTATION + +#define stbsp__uint32 unsigned int +#define stbsp__int32 signed int + +#ifdef _MSC_VER +#define stbsp__uint64 unsigned __int64 +#define stbsp__int64 signed __int64 +#else +#define stbsp__uint64 unsigned long long +#define stbsp__int64 signed long long +#endif +#define stbsp__uint16 unsigned short + +#ifndef stbsp__uintptr +#if defined(__ppc64__) || defined(__powerpc64__) || defined(__aarch64__) || defined(_M_X64) || defined(__x86_64__) || defined(__x86_64) || defined(__s390x__) +#define stbsp__uintptr stbsp__uint64 +#else +#define stbsp__uintptr stbsp__uint32 +#endif +#endif + +#ifndef STB_SPRINTF_MSVC_MODE // used for MSVC2013 and earlier (MSVC2015 matches GCC) +#if defined(_MSC_VER) && (_MSC_VER < 1900) +#define STB_SPRINTF_MSVC_MODE +#endif +#endif + +#ifdef STB_SPRINTF_NOUNALIGNED // define this before inclusion to force stbsp_sprintf to always use aligned accesses +#define STBSP__UNALIGNED(code) +#else +#define STBSP__UNALIGNED(code) code +#endif + +#ifndef STB_SPRINTF_NOFLOAT +// internal float utility functions +static stbsp__int32 stbsp__real_to_str(char const **start, stbsp__uint32 *len, char *out, stbsp__int32 *decimal_pos, double value, stbsp__uint32 frac_digits); +static stbsp__int32 stbsp__real_to_parts(stbsp__int64 *bits, stbsp__int32 *expo, double value); +#define STBSP__SPECIAL 0x7000 +#endif + +static char stbsp__period = '.'; +static char stbsp__comma = ','; +static struct +{ + short temp; // force next field to be 2-byte aligned + char pair[201]; +} stbsp__digitpair = +{ + 0, + "00010203040506070809101112131415161718192021222324" + "25262728293031323334353637383940414243444546474849" + "50515253545556575859606162636465666768697071727374" + "75767778798081828384858687888990919293949596979899" +}; + +STBSP__PUBLICDEF void STB_SPRINTF_DECORATE(set_separators)(char pcomma, char pperiod) +{ + stbsp__period = pperiod; + stbsp__comma = pcomma; +} + +#define STBSP__LEFTJUST 1 +#define STBSP__LEADINGPLUS 2 +#define STBSP__LEADINGSPACE 4 +#define STBSP__LEADING_0X 8 +#define STBSP__LEADINGZERO 16 +#define STBSP__INTMAX 32 +#define STBSP__TRIPLET_COMMA 64 +#define STBSP__NEGATIVE 128 +#define STBSP__METRIC_SUFFIX 256 +#define STBSP__HALFWIDTH 512 +#define STBSP__METRIC_NOSPACE 1024 +#define STBSP__METRIC_1024 2048 +#define STBSP__METRIC_JEDEC 4096 + +static void stbsp__lead_sign(stbsp__uint32 fl, char *sign) +{ + sign[0] = 0; + if (fl & STBSP__NEGATIVE) { + sign[0] = 1; + sign[1] = '-'; + } else if (fl & STBSP__LEADINGSPACE) { + sign[0] = 1; + sign[1] = ' '; + } else if (fl & STBSP__LEADINGPLUS) { + sign[0] = 1; + sign[1] = '+'; + } +} + +static STBSP__ASAN stbsp__uint32 stbsp__strlen_limited(char const *s, stbsp__uint32 limit) +{ + char const * sn = s; + + // get up to 4-byte alignment + for (;;) { + if (((stbsp__uintptr)sn & 3) == 0) + break; + + if (!limit || *sn == 0) + return (stbsp__uint32)(sn - s); + + ++sn; + --limit; + } + + // scan over 4 bytes at a time to find terminating 0 + // this will intentionally scan up to 3 bytes past the end of buffers, + // but becase it works 4B aligned, it will never cross page boundaries + // (hence the STBSP__ASAN markup; the over-read here is intentional + // and harmless) + while (limit >= 4) { + stbsp__uint32 v = *(stbsp__uint32 *)sn; + // bit hack to find if there's a 0 byte in there + if ((v - 0x01010101) & (~v) & 0x80808080UL) + break; + + sn += 4; + limit -= 4; + } + + // handle the last few characters to find actual size + while (limit && *sn) { + ++sn; + --limit; + } + + return (stbsp__uint32)(sn - s); +} + +STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(vsprintfcb)(STBSP_SPRINTFCB *callback, void *user, char *buf, char const *fmt, va_list va) +{ + static char hex[] = "0123456789abcdefxp"; + static char hexu[] = "0123456789ABCDEFXP"; + char *bf; + char const *f; + int tlen = 0; + + bf = buf; + f = fmt; + for (;;) { + stbsp__int32 fw, pr, tz; + stbsp__uint32 fl; + + // macros for the callback buffer stuff + #define stbsp__chk_cb_bufL(bytes) \ + { \ + int len = (int)(bf - buf); \ + if ((len + (bytes)) >= STB_SPRINTF_MIN) { \ + tlen += len; \ + if (0 == (bf = buf = callback(buf, user, len))) \ + goto done; \ + } \ + } + #define stbsp__chk_cb_buf(bytes) \ + { \ + if (callback) { \ + stbsp__chk_cb_bufL(bytes); \ + } \ + } + #define stbsp__flush_cb() \ + { \ + stbsp__chk_cb_bufL(STB_SPRINTF_MIN - 1); \ + } // flush if there is even one byte in the buffer + #define stbsp__cb_buf_clamp(cl, v) \ + cl = v; \ + if (callback) { \ + int lg = STB_SPRINTF_MIN - (int)(bf - buf); \ + if (cl > lg) \ + cl = lg; \ + } + + // fast copy everything up to the next % (or end of string) + for (;;) { + while (((stbsp__uintptr)f) & 3) { + schk1: + if (f[0] == '%') + goto scandd; + schk2: + if (f[0] == 0) + goto endfmt; + stbsp__chk_cb_buf(1); + *bf++ = f[0]; + ++f; + } + for (;;) { + // Check if the next 4 bytes contain %(0x25) or end of string. + // Using the 'hasless' trick: + // https://graphics.stanford.edu/~seander/bithacks.html#HasLessInWord + stbsp__uint32 v, c; + v = *(stbsp__uint32 *)f; + c = (~v) & 0x80808080; + if (((v ^ 0x25252525) - 0x01010101) & c) + goto schk1; + if ((v - 0x01010101) & c) + goto schk2; + if (callback) + if ((STB_SPRINTF_MIN - (int)(bf - buf)) < 4) + goto schk1; + #ifdef STB_SPRINTF_NOUNALIGNED + if(((stbsp__uintptr)bf) & 3) { + bf[0] = f[0]; + bf[1] = f[1]; + bf[2] = f[2]; + bf[3] = f[3]; + } else + #endif + { + *(stbsp__uint32 *)bf = v; + } + bf += 4; + f += 4; + } + } + scandd: + + ++f; + + // ok, we have a percent, read the modifiers first + fw = 0; + pr = -1; + fl = 0; + tz = 0; + + // flags + for (;;) { + switch (f[0]) { + // if we have left justify + case '-': + fl |= STBSP__LEFTJUST; + ++f; + continue; + // if we have leading plus + case '+': + fl |= STBSP__LEADINGPLUS; + ++f; + continue; + // if we have leading space + case ' ': + fl |= STBSP__LEADINGSPACE; + ++f; + continue; + // if we have leading 0x + case '#': + fl |= STBSP__LEADING_0X; + ++f; + continue; + // if we have thousand commas + case '\'': + fl |= STBSP__TRIPLET_COMMA; + ++f; + continue; + // if we have kilo marker (none->kilo->kibi->jedec) + case '$': + if (fl & STBSP__METRIC_SUFFIX) { + if (fl & STBSP__METRIC_1024) { + fl |= STBSP__METRIC_JEDEC; + } else { + fl |= STBSP__METRIC_1024; + } + } else { + fl |= STBSP__METRIC_SUFFIX; + } + ++f; + continue; + // if we don't want space between metric suffix and number + case '_': + fl |= STBSP__METRIC_NOSPACE; + ++f; + continue; + // if we have leading zero + case '0': + fl |= STBSP__LEADINGZERO; + ++f; + goto flags_done; + default: goto flags_done; + } + } + flags_done: + + // get the field width + if (f[0] == '*') { + fw = va_arg(va, stbsp__uint32); + ++f; + } else { + while ((f[0] >= '0') && (f[0] <= '9')) { + fw = fw * 10 + f[0] - '0'; + f++; + } + } + // get the precision + if (f[0] == '.') { + ++f; + if (f[0] == '*') { + pr = va_arg(va, stbsp__uint32); + ++f; + } else { + pr = 0; + while ((f[0] >= '0') && (f[0] <= '9')) { + pr = pr * 10 + f[0] - '0'; + f++; + } + } + } + + // handle integer size overrides + switch (f[0]) { + // are we halfwidth? + case 'h': + fl |= STBSP__HALFWIDTH; + ++f; + if (f[0] == 'h') + ++f; // QUARTERWIDTH + break; + // are we 64-bit (unix style) + case 'l': + fl |= ((sizeof(long) == 8) ? STBSP__INTMAX : 0); + ++f; + if (f[0] == 'l') { + fl |= STBSP__INTMAX; + ++f; + } + break; + // are we 64-bit on intmax? (c99) + case 'j': + fl |= (sizeof(size_t) == 8) ? STBSP__INTMAX : 0; + ++f; + break; + // are we 64-bit on size_t or ptrdiff_t? (c99) + case 'z': + fl |= (sizeof(ptrdiff_t) == 8) ? STBSP__INTMAX : 0; + ++f; + break; + case 't': + fl |= (sizeof(ptrdiff_t) == 8) ? STBSP__INTMAX : 0; + ++f; + break; + // are we 64-bit (msft style) + case 'I': + if ((f[1] == '6') && (f[2] == '4')) { + fl |= STBSP__INTMAX; + f += 3; + } else if ((f[1] == '3') && (f[2] == '2')) { + f += 3; + } else { + fl |= ((sizeof(void *) == 8) ? STBSP__INTMAX : 0); + ++f; + } + break; + default: break; + } + + // handle each replacement + switch (f[0]) { + #define STBSP__NUMSZ 512 // big enough for e308 (with commas) or e-307 + char num[STBSP__NUMSZ]; + char lead[8]; + char tail[8]; + char *s; + char const *h; + stbsp__uint32 l, n, cs; + stbsp__uint64 n64; +#ifndef STB_SPRINTF_NOFLOAT + double fv; +#endif + stbsp__int32 dp; + char const *sn; + + case 's': + // get the string + s = va_arg(va, char *); + if (s == 0) + s = (char *)"null"; + // get the length, limited to desired precision + // always limit to ~0u chars since our counts are 32b + l = stbsp__strlen_limited(s, (pr >= 0) ? pr : ~0u); + lead[0] = 0; + tail[0] = 0; + pr = 0; + dp = 0; + cs = 0; + // copy the string in + goto scopy; + + case 'c': // char + // get the character + s = num + STBSP__NUMSZ - 1; + *s = (char)va_arg(va, int); + l = 1; + lead[0] = 0; + tail[0] = 0; + pr = 0; + dp = 0; + cs = 0; + goto scopy; + + case 'n': // weird write-bytes specifier + { + int *d = va_arg(va, int *); + *d = tlen + (int)(bf - buf); + } break; + +#ifdef STB_SPRINTF_NOFLOAT + case 'A': // float + case 'a': // hex float + case 'G': // float + case 'g': // float + case 'E': // float + case 'e': // float + case 'f': // float + va_arg(va, double); // eat it + s = (char *)"No float"; + l = 8; + lead[0] = 0; + tail[0] = 0; + pr = 0; + cs = 0; + STBSP__NOTUSED(dp); + goto scopy; +#else + case 'A': // hex float + case 'a': // hex float + h = (f[0] == 'A') ? hexu : hex; + fv = va_arg(va, double); + if (pr == -1) + pr = 6; // default is 6 + // read the double into a string + if (stbsp__real_to_parts((stbsp__int64 *)&n64, &dp, fv)) + fl |= STBSP__NEGATIVE; + + s = num + 64; + + stbsp__lead_sign(fl, lead); + + if (dp == -1023) + dp = (n64) ? -1022 : 0; + else + n64 |= (((stbsp__uint64)1) << 52); + n64 <<= (64 - 56); + if (pr < 15) + n64 += ((((stbsp__uint64)8) << 56) >> (pr * 4)); +// add leading chars + +#ifdef STB_SPRINTF_MSVC_MODE + *s++ = '0'; + *s++ = 'x'; +#else + lead[1 + lead[0]] = '0'; + lead[2 + lead[0]] = 'x'; + lead[0] += 2; +#endif + *s++ = h[(n64 >> 60) & 15]; + n64 <<= 4; + if (pr) + *s++ = stbsp__period; + sn = s; + + // print the bits + n = pr; + if (n > 13) + n = 13; + if (pr > (stbsp__int32)n) + tz = pr - n; + pr = 0; + while (n--) { + *s++ = h[(n64 >> 60) & 15]; + n64 <<= 4; + } + + // print the expo + tail[1] = h[17]; + if (dp < 0) { + tail[2] = '-'; + dp = -dp; + } else + tail[2] = '+'; + n = (dp >= 1000) ? 6 : ((dp >= 100) ? 5 : ((dp >= 10) ? 4 : 3)); + tail[0] = (char)n; + for (;;) { + tail[n] = '0' + dp % 10; + if (n <= 3) + break; + --n; + dp /= 10; + } + + dp = (int)(s - sn); + l = (int)(s - (num + 64)); + s = num + 64; + cs = 1 + (3 << 24); + goto scopy; + + case 'G': // float + case 'g': // float + h = (f[0] == 'G') ? hexu : hex; + fv = va_arg(va, double); + if (pr == -1) + pr = 6; + else if (pr == 0) + pr = 1; // default is 6 + // read the double into a string + if (stbsp__real_to_str(&sn, &l, num, &dp, fv, (pr - 1) | 0x80000000)) + fl |= STBSP__NEGATIVE; + + // clamp the precision and delete extra zeros after clamp + n = pr; + if (l > (stbsp__uint32)pr) + l = pr; + while ((l > 1) && (pr) && (sn[l - 1] == '0')) { + --pr; + --l; + } + + // should we use %e + if ((dp <= -4) || (dp > (stbsp__int32)n)) { + if (pr > (stbsp__int32)l) + pr = l - 1; + else if (pr) + --pr; // when using %e, there is one digit before the decimal + goto doexpfromg; + } + // this is the insane action to get the pr to match %g semantics for %f + if (dp > 0) { + pr = (dp < (stbsp__int32)l) ? l - dp : 0; + } else { + pr = -dp + ((pr > (stbsp__int32)l) ? (stbsp__int32) l : pr); + } + goto dofloatfromg; + + case 'E': // float + case 'e': // float + h = (f[0] == 'E') ? hexu : hex; + fv = va_arg(va, double); + if (pr == -1) + pr = 6; // default is 6 + // read the double into a string + if (stbsp__real_to_str(&sn, &l, num, &dp, fv, pr | 0x80000000)) + fl |= STBSP__NEGATIVE; + doexpfromg: + tail[0] = 0; + stbsp__lead_sign(fl, lead); + if (dp == STBSP__SPECIAL) { + s = (char *)sn; + cs = 0; + pr = 0; + goto scopy; + } + s = num + 64; + // handle leading chars + *s++ = sn[0]; + + if (pr) + *s++ = stbsp__period; + + // handle after decimal + if ((l - 1) > (stbsp__uint32)pr) + l = pr + 1; + for (n = 1; n < l; n++) + *s++ = sn[n]; + // trailing zeros + tz = pr - (l - 1); + pr = 0; + // dump expo + tail[1] = h[0xe]; + dp -= 1; + if (dp < 0) { + tail[2] = '-'; + dp = -dp; + } else + tail[2] = '+'; +#ifdef STB_SPRINTF_MSVC_MODE + n = 5; +#else + n = (dp >= 100) ? 5 : 4; +#endif + tail[0] = (char)n; + for (;;) { + tail[n] = '0' + dp % 10; + if (n <= 3) + break; + --n; + dp /= 10; + } + cs = 1 + (3 << 24); // how many tens + goto flt_lead; + + case 'f': // float + fv = va_arg(va, double); + doafloat: + // do kilos + if (fl & STBSP__METRIC_SUFFIX) { + double divisor; + divisor = 1000.0f; + if (fl & STBSP__METRIC_1024) + divisor = 1024.0; + while (fl < 0x4000000) { + if ((fv < divisor) && (fv > -divisor)) + break; + fv /= divisor; + fl += 0x1000000; + } + } + if (pr == -1) + pr = 6; // default is 6 + // read the double into a string + if (stbsp__real_to_str(&sn, &l, num, &dp, fv, pr)) + fl |= STBSP__NEGATIVE; + dofloatfromg: + tail[0] = 0; + stbsp__lead_sign(fl, lead); + if (dp == STBSP__SPECIAL) { + s = (char *)sn; + cs = 0; + pr = 0; + goto scopy; + } + s = num + 64; + + // handle the three decimal varieties + if (dp <= 0) { + stbsp__int32 i; + // handle 0.000*000xxxx + *s++ = '0'; + if (pr) + *s++ = stbsp__period; + n = -dp; + if ((stbsp__int32)n > pr) + n = pr; + i = n; + while (i) { + if ((((stbsp__uintptr)s) & 3) == 0) + break; + *s++ = '0'; + --i; + } + while (i >= 4) { + *(stbsp__uint32 *)s = 0x30303030; + s += 4; + i -= 4; + } + while (i) { + *s++ = '0'; + --i; + } + if ((stbsp__int32)(l + n) > pr) + l = pr - n; + i = l; + while (i) { + *s++ = *sn++; + --i; + } + tz = pr - (n + l); + cs = 1 + (3 << 24); // how many tens did we write (for commas below) + } else { + cs = (fl & STBSP__TRIPLET_COMMA) ? ((600 - (stbsp__uint32)dp) % 3) : 0; + if ((stbsp__uint32)dp >= l) { + // handle xxxx000*000.0 + n = 0; + for (;;) { + if ((fl & STBSP__TRIPLET_COMMA) && (++cs == 4)) { + cs = 0; + *s++ = stbsp__comma; + } else { + *s++ = sn[n]; + ++n; + if (n >= l) + break; + } + } + if (n < (stbsp__uint32)dp) { + n = dp - n; + if ((fl & STBSP__TRIPLET_COMMA) == 0) { + while (n) { + if ((((stbsp__uintptr)s) & 3) == 0) + break; + *s++ = '0'; + --n; + } + while (n >= 4) { + *(stbsp__uint32 *)s = 0x30303030; + s += 4; + n -= 4; + } + } + while (n) { + if ((fl & STBSP__TRIPLET_COMMA) && (++cs == 4)) { + cs = 0; + *s++ = stbsp__comma; + } else { + *s++ = '0'; + --n; + } + } + } + cs = (int)(s - (num + 64)) + (3 << 24); // cs is how many tens + if (pr) { + *s++ = stbsp__period; + tz = pr; + } + } else { + // handle xxxxx.xxxx000*000 + n = 0; + for (;;) { + if ((fl & STBSP__TRIPLET_COMMA) && (++cs == 4)) { + cs = 0; + *s++ = stbsp__comma; + } else { + *s++ = sn[n]; + ++n; + if (n >= (stbsp__uint32)dp) + break; + } + } + cs = (int)(s - (num + 64)) + (3 << 24); // cs is how many tens + if (pr) + *s++ = stbsp__period; + if ((l - dp) > (stbsp__uint32)pr) + l = pr + dp; + while (n < l) { + *s++ = sn[n]; + ++n; + } + tz = pr - (l - dp); + } + } + pr = 0; + + // handle k,m,g,t + if (fl & STBSP__METRIC_SUFFIX) { + char idx; + idx = 1; + if (fl & STBSP__METRIC_NOSPACE) + idx = 0; + tail[0] = idx; + tail[1] = ' '; + { + if (fl >> 24) { // SI kilo is 'k', JEDEC and SI kibits are 'K'. + if (fl & STBSP__METRIC_1024) + tail[idx + 1] = "_KMGT"[fl >> 24]; + else + tail[idx + 1] = "_kMGT"[fl >> 24]; + idx++; + // If printing kibits and not in jedec, add the 'i'. + if (fl & STBSP__METRIC_1024 && !(fl & STBSP__METRIC_JEDEC)) { + tail[idx + 1] = 'i'; + idx++; + } + tail[0] = idx; + } + } + }; + + flt_lead: + // get the length that we copied + l = (stbsp__uint32)(s - (num + 64)); + s = num + 64; + goto scopy; +#endif + + case 'B': // upper binary + case 'b': // lower binary + h = (f[0] == 'B') ? hexu : hex; + lead[0] = 0; + if (fl & STBSP__LEADING_0X) { + lead[0] = 2; + lead[1] = '0'; + lead[2] = h[0xb]; + } + l = (8 << 4) | (1 << 8); + goto radixnum; + + case 'o': // octal + h = hexu; + lead[0] = 0; + if (fl & STBSP__LEADING_0X) { + lead[0] = 1; + lead[1] = '0'; + } + l = (3 << 4) | (3 << 8); + goto radixnum; + + case 'p': // pointer + fl |= (sizeof(void *) == 8) ? STBSP__INTMAX : 0; + pr = sizeof(void *) * 2; + fl &= ~STBSP__LEADINGZERO; // 'p' only prints the pointer with zeros + // fall through - to X + + case 'X': // upper hex + case 'x': // lower hex + h = (f[0] == 'X') ? hexu : hex; + l = (4 << 4) | (4 << 8); + lead[0] = 0; + if (fl & STBSP__LEADING_0X) { + lead[0] = 2; + lead[1] = '0'; + lead[2] = h[16]; + } + radixnum: + // get the number + if (fl & STBSP__INTMAX) + n64 = va_arg(va, stbsp__uint64); + else + n64 = va_arg(va, stbsp__uint32); + + s = num + STBSP__NUMSZ; + dp = 0; + // clear tail, and clear leading if value is zero + tail[0] = 0; + if (n64 == 0) { + lead[0] = 0; + if (pr == 0) { + l = 0; + cs = 0; + goto scopy; + } + } + // convert to string + for (;;) { + *--s = h[n64 & ((1 << (l >> 8)) - 1)]; + n64 >>= (l >> 8); + if (!((n64) || ((stbsp__int32)((num + STBSP__NUMSZ) - s) < pr))) + break; + if (fl & STBSP__TRIPLET_COMMA) { + ++l; + if ((l & 15) == ((l >> 4) & 15)) { + l &= ~15; + *--s = stbsp__comma; + } + } + }; + // get the tens and the comma pos + cs = (stbsp__uint32)((num + STBSP__NUMSZ) - s) + ((((l >> 4) & 15)) << 24); + // get the length that we copied + l = (stbsp__uint32)((num + STBSP__NUMSZ) - s); + // copy it + goto scopy; + + case 'u': // unsigned + case 'i': + case 'd': // integer + // get the integer and abs it + if (fl & STBSP__INTMAX) { + stbsp__int64 i64 = va_arg(va, stbsp__int64); + n64 = (stbsp__uint64)i64; + if ((f[0] != 'u') && (i64 < 0)) { + n64 = (stbsp__uint64)-i64; + fl |= STBSP__NEGATIVE; + } + } else { + stbsp__int32 i = va_arg(va, stbsp__int32); + n64 = (stbsp__uint32)i; + if ((f[0] != 'u') && (i < 0)) { + n64 = (stbsp__uint32)-i; + fl |= STBSP__NEGATIVE; + } + } + +#ifndef STB_SPRINTF_NOFLOAT + if (fl & STBSP__METRIC_SUFFIX) { + if (n64 < 1024) + pr = 0; + else if (pr == -1) + pr = 1; + fv = (double)(stbsp__int64)n64; + goto doafloat; + } +#endif + + // convert to string + s = num + STBSP__NUMSZ; + l = 0; + + for (;;) { + // do in 32-bit chunks (avoid lots of 64-bit divides even with constant denominators) + char *o = s - 8; + if (n64 >= 100000000) { + n = (stbsp__uint32)(n64 % 100000000); + n64 /= 100000000; + } else { + n = (stbsp__uint32)n64; + n64 = 0; + } + if ((fl & STBSP__TRIPLET_COMMA) == 0) { + do { + s -= 2; + *(stbsp__uint16 *)s = *(stbsp__uint16 *)&stbsp__digitpair.pair[(n % 100) * 2]; + n /= 100; + } while (n); + } + while (n) { + if ((fl & STBSP__TRIPLET_COMMA) && (l++ == 3)) { + l = 0; + *--s = stbsp__comma; + --o; + } else { + *--s = (char)(n % 10) + '0'; + n /= 10; + } + } + if (n64 == 0) { + if ((s[0] == '0') && (s != (num + STBSP__NUMSZ))) + ++s; + break; + } + while (s != o) + if ((fl & STBSP__TRIPLET_COMMA) && (l++ == 3)) { + l = 0; + *--s = stbsp__comma; + --o; + } else { + *--s = '0'; + } + } + + tail[0] = 0; + stbsp__lead_sign(fl, lead); + + // get the length that we copied + l = (stbsp__uint32)((num + STBSP__NUMSZ) - s); + if (l == 0) { + *--s = '0'; + l = 1; + } + cs = l + (3 << 24); + if (pr < 0) + pr = 0; + + scopy: + // get fw=leading/trailing space, pr=leading zeros + if (pr < (stbsp__int32)l) + pr = l; + n = pr + lead[0] + tail[0] + tz; + if (fw < (stbsp__int32)n) + fw = n; + fw -= n; + pr -= l; + + // handle right justify and leading zeros + if ((fl & STBSP__LEFTJUST) == 0) { + if (fl & STBSP__LEADINGZERO) // if leading zeros, everything is in pr + { + pr = (fw > pr) ? fw : pr; + fw = 0; + } else { + fl &= ~STBSP__TRIPLET_COMMA; // if no leading zeros, then no commas + } + } + + // copy the spaces and/or zeros + if (fw + pr) { + stbsp__int32 i; + stbsp__uint32 c; + + // copy leading spaces (or when doing %8.4d stuff) + if ((fl & STBSP__LEFTJUST) == 0) + while (fw > 0) { + stbsp__cb_buf_clamp(i, fw); + fw -= i; + while (i) { + if ((((stbsp__uintptr)bf) & 3) == 0) + break; + *bf++ = ' '; + --i; + } + while (i >= 4) { + *(stbsp__uint32 *)bf = 0x20202020; + bf += 4; + i -= 4; + } + while (i) { + *bf++ = ' '; + --i; + } + stbsp__chk_cb_buf(1); + } + + // copy leader + sn = lead + 1; + while (lead[0]) { + stbsp__cb_buf_clamp(i, lead[0]); + lead[0] -= (char)i; + while (i) { + *bf++ = *sn++; + --i; + } + stbsp__chk_cb_buf(1); + } + + // copy leading zeros + c = cs >> 24; + cs &= 0xffffff; + cs = (fl & STBSP__TRIPLET_COMMA) ? ((stbsp__uint32)(c - ((pr + cs) % (c + 1)))) : 0; + while (pr > 0) { + stbsp__cb_buf_clamp(i, pr); + pr -= i; + if ((fl & STBSP__TRIPLET_COMMA) == 0) { + while (i) { + if ((((stbsp__uintptr)bf) & 3) == 0) + break; + *bf++ = '0'; + --i; + } + while (i >= 4) { + *(stbsp__uint32 *)bf = 0x30303030; + bf += 4; + i -= 4; + } + } + while (i) { + if ((fl & STBSP__TRIPLET_COMMA) && (cs++ == c)) { + cs = 0; + *bf++ = stbsp__comma; + } else + *bf++ = '0'; + --i; + } + stbsp__chk_cb_buf(1); + } + } + + // copy leader if there is still one + sn = lead + 1; + while (lead[0]) { + stbsp__int32 i; + stbsp__cb_buf_clamp(i, lead[0]); + lead[0] -= (char)i; + while (i) { + *bf++ = *sn++; + --i; + } + stbsp__chk_cb_buf(1); + } + + // copy the string + n = l; + while (n) { + stbsp__int32 i; + stbsp__cb_buf_clamp(i, n); + n -= i; + STBSP__UNALIGNED(while (i >= 4) { + *(stbsp__uint32 volatile *)bf = *(stbsp__uint32 volatile *)s; + bf += 4; + s += 4; + i -= 4; + }) + while (i) { + *bf++ = *s++; + --i; + } + stbsp__chk_cb_buf(1); + } + + // copy trailing zeros + while (tz) { + stbsp__int32 i; + stbsp__cb_buf_clamp(i, tz); + tz -= i; + while (i) { + if ((((stbsp__uintptr)bf) & 3) == 0) + break; + *bf++ = '0'; + --i; + } + while (i >= 4) { + *(stbsp__uint32 *)bf = 0x30303030; + bf += 4; + i -= 4; + } + while (i) { + *bf++ = '0'; + --i; + } + stbsp__chk_cb_buf(1); + } + + // copy tail if there is one + sn = tail + 1; + while (tail[0]) { + stbsp__int32 i; + stbsp__cb_buf_clamp(i, tail[0]); + tail[0] -= (char)i; + while (i) { + *bf++ = *sn++; + --i; + } + stbsp__chk_cb_buf(1); + } + + // handle the left justify + if (fl & STBSP__LEFTJUST) + if (fw > 0) { + while (fw) { + stbsp__int32 i; + stbsp__cb_buf_clamp(i, fw); + fw -= i; + while (i) { + if ((((stbsp__uintptr)bf) & 3) == 0) + break; + *bf++ = ' '; + --i; + } + while (i >= 4) { + *(stbsp__uint32 *)bf = 0x20202020; + bf += 4; + i -= 4; + } + while (i--) + *bf++ = ' '; + stbsp__chk_cb_buf(1); + } + } + break; + + default: // unknown, just copy code + s = num + STBSP__NUMSZ - 1; + *s = f[0]; + l = 1; + fw = fl = 0; + lead[0] = 0; + tail[0] = 0; + pr = 0; + dp = 0; + cs = 0; + goto scopy; + } + ++f; + } +endfmt: + + if (!callback) + *bf = 0; + else + stbsp__flush_cb(); + +done: + return tlen + (int)(bf - buf); +} + +// cleanup +#undef STBSP__LEFTJUST +#undef STBSP__LEADINGPLUS +#undef STBSP__LEADINGSPACE +#undef STBSP__LEADING_0X +#undef STBSP__LEADINGZERO +#undef STBSP__INTMAX +#undef STBSP__TRIPLET_COMMA +#undef STBSP__NEGATIVE +#undef STBSP__METRIC_SUFFIX +#undef STBSP__NUMSZ +#undef stbsp__chk_cb_bufL +#undef stbsp__chk_cb_buf +#undef stbsp__flush_cb +#undef stbsp__cb_buf_clamp + +// ============================================================================ +// wrapper functions + +STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(sprintf)(char *buf, char const *fmt, ...) +{ + int result; + va_list va; + va_start(va, fmt); + result = STB_SPRINTF_DECORATE(vsprintfcb)(0, 0, buf, fmt, va); + va_end(va); + return result; +} + +typedef struct stbsp__context { + char *buf; + int count; + int length; + char tmp[STB_SPRINTF_MIN]; +} stbsp__context; + +static char *stbsp__clamp_callback(const char *buf, void *user, int len) +{ + stbsp__context *c = (stbsp__context *)user; + c->length += len; + + if (len > c->count) + len = c->count; + + if (len) { + if (buf != c->buf) { + const char *s, *se; + char *d; + d = c->buf; + s = buf; + se = buf + len; + do { + *d++ = *s++; + } while (s < se); + } + c->buf += len; + c->count -= len; + } + + if (c->count <= 0) + return c->tmp; + return (c->count >= STB_SPRINTF_MIN) ? c->buf : c->tmp; // go direct into buffer if you can +} + +static char * stbsp__count_clamp_callback( const char * buf, void * user, int len ) +{ + stbsp__context * c = (stbsp__context*)user; + (void) sizeof(buf); + + c->length += len; + return c->tmp; // go direct into buffer if you can +} + +STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( vsnprintf )( char * buf, int count, char const * fmt, va_list va ) +{ + stbsp__context c; + + if ( (count == 0) && !buf ) + { + c.length = 0; + + STB_SPRINTF_DECORATE( vsprintfcb )( stbsp__count_clamp_callback, &c, c.tmp, fmt, va ); + } + else + { + int l; + + c.buf = buf; + c.count = count; + c.length = 0; + + STB_SPRINTF_DECORATE( vsprintfcb )( stbsp__clamp_callback, &c, stbsp__clamp_callback(0,&c,0), fmt, va ); + + // zero-terminate + l = (int)( c.buf - buf ); + if ( l >= count ) // should never be greater, only equal (or less) than count + l = count - 1; + buf[l] = 0; + } + + return c.length; +} + +STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(snprintf)(char *buf, int count, char const *fmt, ...) +{ + int result; + va_list va; + va_start(va, fmt); + + result = STB_SPRINTF_DECORATE(vsnprintf)(buf, count, fmt, va); + va_end(va); + + return result; +} + +STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(vsprintf)(char *buf, char const *fmt, va_list va) +{ + return STB_SPRINTF_DECORATE(vsprintfcb)(0, 0, buf, fmt, va); +} + +// ======================================================================= +// low level float utility functions + +#ifndef STB_SPRINTF_NOFLOAT + +// copies d to bits w/ strict aliasing (this compiles to nothing on /Ox) +#define STBSP__COPYFP(dest, src) \ + { \ + int cn; \ + for (cn = 0; cn < 8; cn++) \ + ((char *)&dest)[cn] = ((char *)&src)[cn]; \ + } + +// get float info +static stbsp__int32 stbsp__real_to_parts(stbsp__int64 *bits, stbsp__int32 *expo, double value) +{ + double d; + stbsp__int64 b = 0; + + // load value and round at the frac_digits + d = value; + + STBSP__COPYFP(b, d); + + *bits = b & ((((stbsp__uint64)1) << 52) - 1); + *expo = (stbsp__int32)(((b >> 52) & 2047) - 1023); + + return (stbsp__int32)((stbsp__uint64) b >> 63); +} + +static double const stbsp__bot[23] = { + 1e+000, 1e+001, 1e+002, 1e+003, 1e+004, 1e+005, 1e+006, 1e+007, 1e+008, 1e+009, 1e+010, 1e+011, + 1e+012, 1e+013, 1e+014, 1e+015, 1e+016, 1e+017, 1e+018, 1e+019, 1e+020, 1e+021, 1e+022 +}; +static double const stbsp__negbot[22] = { + 1e-001, 1e-002, 1e-003, 1e-004, 1e-005, 1e-006, 1e-007, 1e-008, 1e-009, 1e-010, 1e-011, + 1e-012, 1e-013, 1e-014, 1e-015, 1e-016, 1e-017, 1e-018, 1e-019, 1e-020, 1e-021, 1e-022 +}; +static double const stbsp__negboterr[22] = { + -5.551115123125783e-018, -2.0816681711721684e-019, -2.0816681711721686e-020, -4.7921736023859299e-021, -8.1803053914031305e-022, 4.5251888174113741e-023, + 4.5251888174113739e-024, -2.0922560830128471e-025, -6.2281591457779853e-026, -3.6432197315497743e-027, 6.0503030718060191e-028, 2.0113352370744385e-029, + -3.0373745563400371e-030, 1.1806906454401013e-032, -7.7705399876661076e-032, 2.0902213275965398e-033, -7.1542424054621921e-034, -7.1542424054621926e-035, + 2.4754073164739869e-036, 5.4846728545790429e-037, 9.2462547772103625e-038, -4.8596774326570872e-039 +}; +static double const stbsp__top[13] = { + 1e+023, 1e+046, 1e+069, 1e+092, 1e+115, 1e+138, 1e+161, 1e+184, 1e+207, 1e+230, 1e+253, 1e+276, 1e+299 +}; +static double const stbsp__negtop[13] = { + 1e-023, 1e-046, 1e-069, 1e-092, 1e-115, 1e-138, 1e-161, 1e-184, 1e-207, 1e-230, 1e-253, 1e-276, 1e-299 +}; +static double const stbsp__toperr[13] = { + 8388608, + 6.8601809640529717e+028, + -7.253143638152921e+052, + -4.3377296974619174e+075, + -1.5559416129466825e+098, + -3.2841562489204913e+121, + -3.7745893248228135e+144, + -1.7356668416969134e+167, + -3.8893577551088374e+190, + -9.9566444326005119e+213, + 6.3641293062232429e+236, + -5.2069140800249813e+259, + -5.2504760255204387e+282 +}; +static double const stbsp__negtoperr[13] = { + 3.9565301985100693e-040, -2.299904345391321e-063, 3.6506201437945798e-086, 1.1875228833981544e-109, + -5.0644902316928607e-132, -6.7156837247865426e-155, -2.812077463003139e-178, -5.7778912386589953e-201, + 7.4997100559334532e-224, -4.6439668915134491e-247, -6.3691100762962136e-270, -9.436808465446358e-293, + 8.0970921678014997e-317 +}; + +#if defined(_MSC_VER) && (_MSC_VER <= 1200) +static stbsp__uint64 const stbsp__powten[20] = { + 1, + 10, + 100, + 1000, + 10000, + 100000, + 1000000, + 10000000, + 100000000, + 1000000000, + 10000000000, + 100000000000, + 1000000000000, + 10000000000000, + 100000000000000, + 1000000000000000, + 10000000000000000, + 100000000000000000, + 1000000000000000000, + 10000000000000000000U +}; +#define stbsp__tento19th ((stbsp__uint64)1000000000000000000) +#else +static stbsp__uint64 const stbsp__powten[20] = { + 1, + 10, + 100, + 1000, + 10000, + 100000, + 1000000, + 10000000, + 100000000, + 1000000000, + 10000000000ULL, + 100000000000ULL, + 1000000000000ULL, + 10000000000000ULL, + 100000000000000ULL, + 1000000000000000ULL, + 10000000000000000ULL, + 100000000000000000ULL, + 1000000000000000000ULL, + 10000000000000000000ULL +}; +#define stbsp__tento19th (1000000000000000000ULL) +#endif + +#define stbsp__ddmulthi(oh, ol, xh, yh) \ + { \ + double ahi = 0, alo, bhi = 0, blo; \ + stbsp__int64 bt; \ + oh = xh * yh; \ + STBSP__COPYFP(bt, xh); \ + bt &= ((~(stbsp__uint64)0) << 27); \ + STBSP__COPYFP(ahi, bt); \ + alo = xh - ahi; \ + STBSP__COPYFP(bt, yh); \ + bt &= ((~(stbsp__uint64)0) << 27); \ + STBSP__COPYFP(bhi, bt); \ + blo = yh - bhi; \ + ol = ((ahi * bhi - oh) + ahi * blo + alo * bhi) + alo * blo; \ + } + +#define stbsp__ddtoS64(ob, xh, xl) \ + { \ + double ahi = 0, alo, vh, t; \ + ob = (stbsp__int64)xh; \ + vh = (double)ob; \ + ahi = (xh - vh); \ + t = (ahi - xh); \ + alo = (xh - (ahi - t)) - (vh + t); \ + ob += (stbsp__int64)(ahi + alo + xl); \ + } + +#define stbsp__ddrenorm(oh, ol) \ + { \ + double s; \ + s = oh + ol; \ + ol = ol - (s - oh); \ + oh = s; \ + } + +#define stbsp__ddmultlo(oh, ol, xh, xl, yh, yl) ol = ol + (xh * yl + xl * yh); + +#define stbsp__ddmultlos(oh, ol, xh, yl) ol = ol + (xh * yl); + +static void stbsp__raise_to_power10(double *ohi, double *olo, double d, stbsp__int32 power) // power can be -323 to +350 +{ + double ph, pl; + if ((power >= 0) && (power <= 22)) { + stbsp__ddmulthi(ph, pl, d, stbsp__bot[power]); + } else { + stbsp__int32 e, et, eb; + double p2h, p2l; + + e = power; + if (power < 0) + e = -e; + et = (e * 0x2c9) >> 14; /* %23 */ + if (et > 13) + et = 13; + eb = e - (et * 23); + + ph = d; + pl = 0.0; + if (power < 0) { + if (eb) { + --eb; + stbsp__ddmulthi(ph, pl, d, stbsp__negbot[eb]); + stbsp__ddmultlos(ph, pl, d, stbsp__negboterr[eb]); + } + if (et) { + stbsp__ddrenorm(ph, pl); + --et; + stbsp__ddmulthi(p2h, p2l, ph, stbsp__negtop[et]); + stbsp__ddmultlo(p2h, p2l, ph, pl, stbsp__negtop[et], stbsp__negtoperr[et]); + ph = p2h; + pl = p2l; + } + } else { + if (eb) { + e = eb; + if (eb > 22) + eb = 22; + e -= eb; + stbsp__ddmulthi(ph, pl, d, stbsp__bot[eb]); + if (e) { + stbsp__ddrenorm(ph, pl); + stbsp__ddmulthi(p2h, p2l, ph, stbsp__bot[e]); + stbsp__ddmultlos(p2h, p2l, stbsp__bot[e], pl); + ph = p2h; + pl = p2l; + } + } + if (et) { + stbsp__ddrenorm(ph, pl); + --et; + stbsp__ddmulthi(p2h, p2l, ph, stbsp__top[et]); + stbsp__ddmultlo(p2h, p2l, ph, pl, stbsp__top[et], stbsp__toperr[et]); + ph = p2h; + pl = p2l; + } + } + } + stbsp__ddrenorm(ph, pl); + *ohi = ph; + *olo = pl; +} + +// given a float value, returns the significant bits in bits, and the position of the +// decimal point in decimal_pos. +/-INF and NAN are specified by special values +// returned in the decimal_pos parameter. +// frac_digits is absolute normally, but if you want from first significant digits (got %g and %e), or in 0x80000000 +static stbsp__int32 stbsp__real_to_str(char const **start, stbsp__uint32 *len, char *out, stbsp__int32 *decimal_pos, double value, stbsp__uint32 frac_digits) +{ + double d; + stbsp__int64 bits = 0; + stbsp__int32 expo, e, ng, tens; + + d = value; + STBSP__COPYFP(bits, d); + expo = (stbsp__int32)((bits >> 52) & 2047); + ng = (stbsp__int32)((stbsp__uint64) bits >> 63); + if (ng) + d = -d; + + if (expo == 2047) // is nan or inf? + { + *start = (bits & ((((stbsp__uint64)1) << 52) - 1)) ? "NaN" : "Inf"; + *decimal_pos = STBSP__SPECIAL; + *len = 3; + return ng; + } + + if (expo == 0) // is zero or denormal + { + if (((stbsp__uint64) bits << 1) == 0) // do zero + { + *decimal_pos = 1; + *start = out; + out[0] = '0'; + *len = 1; + return ng; + } + // find the right expo for denormals + { + stbsp__int64 v = ((stbsp__uint64)1) << 51; + while ((bits & v) == 0) { + --expo; + v >>= 1; + } + } + } + + // find the decimal exponent as well as the decimal bits of the value + { + double ph, pl; + + // log10 estimate - very specifically tweaked to hit or undershoot by no more than 1 of log10 of all expos 1..2046 + tens = expo - 1023; + tens = (tens < 0) ? ((tens * 617) / 2048) : (((tens * 1233) / 4096) + 1); + + // move the significant bits into position and stick them into an int + stbsp__raise_to_power10(&ph, &pl, d, 18 - tens); + + // get full as much precision from double-double as possible + stbsp__ddtoS64(bits, ph, pl); + + // check if we undershot + if (((stbsp__uint64)bits) >= stbsp__tento19th) + ++tens; + } + + // now do the rounding in integer land + frac_digits = (frac_digits & 0x80000000) ? ((frac_digits & 0x7ffffff) + 1) : (tens + frac_digits); + if ((frac_digits < 24)) { + stbsp__uint32 dg = 1; + if ((stbsp__uint64)bits >= stbsp__powten[9]) + dg = 10; + while ((stbsp__uint64)bits >= stbsp__powten[dg]) { + ++dg; + if (dg == 20) + goto noround; + } + if (frac_digits < dg) { + stbsp__uint64 r; + // add 0.5 at the right position and round + e = dg - frac_digits; + if ((stbsp__uint32)e >= 24) + goto noround; + r = stbsp__powten[e]; + bits = bits + (r / 2); + if ((stbsp__uint64)bits >= stbsp__powten[dg]) + ++tens; + bits /= r; + } + noround:; + } + + // kill long trailing runs of zeros + if (bits) { + stbsp__uint32 n; + for (;;) { + if (bits <= 0xffffffff) + break; + if (bits % 1000) + goto donez; + bits /= 1000; + } + n = (stbsp__uint32)bits; + while ((n % 1000) == 0) + n /= 1000; + bits = n; + donez:; + } + + // convert to string + out += 64; + e = 0; + for (;;) { + stbsp__uint32 n; + char *o = out - 8; + // do the conversion in chunks of U32s (avoid most 64-bit divides, worth it, constant denomiators be damned) + if (bits >= 100000000) { + n = (stbsp__uint32)(bits % 100000000); + bits /= 100000000; + } else { + n = (stbsp__uint32)bits; + bits = 0; + } + while (n) { + out -= 2; + *(stbsp__uint16 *)out = *(stbsp__uint16 *)&stbsp__digitpair.pair[(n % 100) * 2]; + n /= 100; + e += 2; + } + if (bits == 0) { + if ((e) && (out[0] == '0')) { + ++out; + --e; + } + break; + } + while (out != o) { + *--out = '0'; + ++e; + } + } + + *decimal_pos = tens; + *start = out; + *len = e; + return ng; +} + +#undef stbsp__ddmulthi +#undef stbsp__ddrenorm +#undef stbsp__ddmultlo +#undef stbsp__ddmultlos +#undef STBSP__SPECIAL +#undef STBSP__COPYFP + +#endif // STB_SPRINTF_NOFLOAT + +// clean up +#undef stbsp__uint16 +#undef stbsp__uint32 +#undef stbsp__int32 +#undef stbsp__uint64 +#undef stbsp__int64 +#undef STBSP__UNALIGNED + +#endif // STB_SPRINTF_IMPLEMENTATION + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/examples/tsoding_snake/tsoding_snake.c b/examples/tsoding_snake/tsoding_snake.c new file mode 100644 index 0000000..32cbdf5 --- /dev/null +++ b/examples/tsoding_snake/tsoding_snake.c @@ -0,0 +1,896 @@ +#include "./tsoding_snake.h" +#include + +// #define FEATURE_DYNAMIC_CAMERA +// #define FEATURE_DEV + +#define STB_SPRINTF_IMPLEMENTATION +#include "stb_sprintf.h" + +#define TRUE 1 +#define FALSE 0 + +static char logf_buf[4096] = {0}; +#define LOGF(...) \ + do { \ + stbsp_snprintf(logf_buf, sizeof(logf_buf), __VA_ARGS__); \ + platform_log(logf_buf); \ + } while(0) + +static void platform_assert(const char *file, i32 line, b32 cond, const char *message) +{ + if (!cond) { + TraceLog(LOG_FATAL, "%s:%d: GAME ASSERTION FAILED: %s\n", file, line, message); + } +} +#define ASSERT(cond, message) platform_assert(__FILE__, __LINE__, cond, message) +#define UNREACHABLE() platform_assert(__FILE__, __LINE__, false, "unreachable") + +// NOTE: This implies that the platform has to carefully choose the resolution so the cells fit into the screen +#define CELL_SIZE 100 +#define COLS 16 +#define ROWS 9 + +#define BACKGROUND_COLOR 0xFF181818 +#define CELL1_COLOR BACKGROUND_COLOR +#define CELL2_COLOR 0xFF183018 +#define SNAKE_BODY_COLOR 0xFF189018 +#define SNAKE_SPINE_COLOR 0xFF185018 +#define SNAKE_SPINE_THICCNESS_PERCENT 0.05f +#define EGG_BODY_COLOR 0xFF31A6FF +#define EGG_SPINE_COLOR 0xFF3166BB +#define DEBUG_COLOR 0xFF0000FF + +#define SNAKE_INIT_SIZE 3 + +#define STEP_INTEVAL 0.125f + +#define RAND_A 6364136223846793005ULL +#define RAND_C 1442695040888963407ULL + +typedef enum { + ALIGN_LEFT, + ALIGN_RIGHT, + ALIGN_CENTER, +} Align; + +static void fill_text_aligned(i32 x, i32 y, const char *text, u32 size, u32 color, Align align) +{ + u32 width = platform_text_width(text, size); + switch (align) { + case ALIGN_LEFT: break; + case ALIGN_CENTER: x -= width/2; break; + case ALIGN_RIGHT: x -= width; break; + } + platform_fill_text(x, y, text, size, color); +} + +static u32 my_rand(void) +{ + static u64 rand_state = 0; + rand_state = rand_state*RAND_A + RAND_C; + return (rand_state >> 32)&0xFFFFFFFF; +} + +static void *memset(void *mem, u32 c, u32 n) +{ + void *result = mem; + u8 *bytes = mem; + while (n-- > 0) *bytes++ = c; + return result; +} + +typedef enum { + DIR_RIGHT = 0, + DIR_UP, + DIR_LEFT, + DIR_DOWN, + COUNT_DIRS, +} Dir; + +static Dir dir_opposite(Dir dir) +{ + ASSERT(0 <= dir && dir < COUNT_DIRS, "Invalid direction"); + return (dir + 2)%COUNT_DIRS; +} + +typedef struct { + f32 x, y, w, h; +} Rect; + +typedef struct { + f32 lens[COUNT_DIRS]; +} Sides; + +static Sides rect_sides(Rect rect) +{ + Sides sides = { + .lens = { + [DIR_LEFT] = rect.x, + [DIR_RIGHT] = rect.x + rect.w, + [DIR_UP] = rect.y, + [DIR_DOWN] = rect.y + rect.h, + } + }; + return sides; +} + +static Rect sides_rect(Sides sides) +{ + Rect rect = { + .x = sides.lens[DIR_LEFT], + .y = sides.lens[DIR_UP], + .w = sides.lens[DIR_RIGHT] - sides.lens[DIR_LEFT], + .h = sides.lens[DIR_DOWN] - sides.lens[DIR_UP], + }; + return rect; +} + +typedef struct { + i32 x, y; +} Cell; + +typedef struct { + f32 x, y; +} Vec; + +#define SNAKE_CAP (ROWS*COLS) +typedef struct { + Cell items[SNAKE_CAP]; + u32 begin; + u32 size; +} Snake; + +typedef struct { + Rect items[SNAKE_CAP]; + Vec vels[SNAKE_CAP]; + u8 masks[SNAKE_CAP]; + u32 size; +} Dead_Snake; + +typedef enum { + STATE_GAMEPLAY = 0, + STATE_PAUSE, + STATE_GAMEOVER, +} State; + +#define DIR_QUEUE_CAP 3 +typedef struct { + u32 begin; + u32 size; + Dir items[DIR_QUEUE_CAP]; +} Dir_Queue; + +typedef struct { + u32 width; + u32 height; + + Vec camera_pos; + Vec camera_vel; + + State state; + Snake snake; + Dead_Snake dead_snake; + Cell egg; + b32 eating_egg; + + Dir dir; + Dir_Queue next_dirs; + b32 dir_keys[COUNT_DIRS]; + + f32 step_cooldown; + +#ifdef FEATURE_DEV + f32 dt_scale; +#endif + + b32 infinite_field; + + u32 score; + char score_buffer[256]; +} Game; + +static Game game = {0}; + +static Rect cell_rect(Cell cell) +{ + Rect result = { + .x = cell.x*CELL_SIZE, + .y = cell.y*CELL_SIZE, + .w = CELL_SIZE, + .h = CELL_SIZE, + }; + return result; +} + +#define ring_empty(ring) ((ring)->size == 0) + +#define ring_cap(ring) (sizeof((ring)->items)/sizeof((ring)->items[0])) + +#define ring_push_back(ring, item) \ + do { \ + ASSERT((ring)->size < ring_cap(ring), "Ring buffer overflow"); \ + u32 index = ((ring)->begin + (ring)->size)%ring_cap(ring); \ + (ring)->items[index] = (item); \ + (ring)->size += 1; \ + } while (0) + +#define ring_displace_back(ring, item) \ + do { \ + u32 index = ((ring)->begin + (ring)->size)%ring_cap(ring); \ + (ring)->items[index] = (item); \ + if ((ring)->size < ring_cap(ring)) { \ + (ring)->size += 1; \ + } else { \ + (ring)->begin = ((ring)->begin + 1)%ring_cap(ring); \ + } \ + } while (0) + +#define ring_pop_front(ring) \ + do { \ + ASSERT((ring)->size > 0, "Ring buffer underflow"); \ + (ring)->begin = ((ring)->begin + 1)%ring_cap(ring); \ + (ring)->size -= 1; \ + } while (0) + +#define ring_back(ring) \ + (ASSERT((ring)->size > 0, "Ring buffer is empty"), \ + &(ring)->items[((ring)->begin + (ring)->size - 1)%ring_cap(ring)]) +#define ring_front(ring) \ + (ASSERT((ring)->size > 0, "Ring buffer is empty"), \ + &(ring)->items[(ring)->begin]) +#define ring_get(ring, index) \ + (ASSERT((ring)->size > 0, "Ring buffer is empty"), \ + &(ring)->items[((ring)->begin + (index))%ring_cap(ring)]) + +static b32 cell_eq(Cell a, Cell b) +{ + return a.x == b.x && a.y == b.y; +} + +static i32 is_cell_snake_body(Cell cell) +{ + // TODO: ignoring the tail feel hacky @tail-ignore + for (u32 index = 1; index < game.snake.size; ++index) { + if (cell_eq(*ring_get(&game.snake, index), cell)) { + return index; + } + } + return -1; +} + +static i32 emod(i32 a, i32 b) +{ + return (a%b + b)%b; +} + +static Cell cell_wrap(Cell cell) +{ + cell.x = emod(cell.x, COLS); + cell.y = emod(cell.y, ROWS); + return cell; +} + +static Cell dir_cell_data[COUNT_DIRS] = { + [DIR_LEFT] = {.x = -1}, + [DIR_RIGHT] = {.x = 1}, + [DIR_UP] = {.y = -1}, + [DIR_DOWN] = {.y = 1}, +}; + +static Cell cell_add(Cell a, Cell b) +{ + a.x += b.x; + a.y += b.y; + return a; +} + +#define dir_cell(dir) (ASSERT((u32) dir < COUNT_DIRS, "Invalid direction"), dir_cell_data[dir]) +#define dir_vec(dir) cell_vec(dir_cell(dir)) + +static Cell step_cell(Cell head, Dir dir) +{ + if (game.infinite_field) { + return cell_add(head, dir_cell(dir)); + } else { + return cell_wrap(cell_add(head, dir_cell(dir))); + } +} + +#define SNAKE_INIT_ROW (ROWS/2) + +static void random_egg(b32 first) +{ + i32 col1 = 0; + i32 col2 = COLS - 1; + i32 row1 = 0; + i32 row2 = ROWS - 1; + + // TODO: make a single formula that works for any mode + if (game.infinite_field) { + col1 = (i32)(game.camera_pos.x - game.width*0.5f + CELL_SIZE)/CELL_SIZE; + col2 = (i32)(game.camera_pos.x + game.width*0.5f - CELL_SIZE)/CELL_SIZE; + row1 = (i32)(game.camera_pos.y - game.height*0.5f + CELL_SIZE)/CELL_SIZE; + row2 = (i32)(game.camera_pos.y + game.height*0.5f - CELL_SIZE)/CELL_SIZE; + } + +#define RANDOM_EGG_MAX_ATTEMPTS 1000 + u32 attempt = 0; + do { + game.egg.x = my_rand()%(col2 - col1 + 1) + col1; + game.egg.y = my_rand()%(row2 - row1 + 1) + row1; + attempt += 1; + } while ((is_cell_snake_body(game.egg) >= 0 || (first && game.egg.y == SNAKE_INIT_ROW)) && attempt < RANDOM_EGG_MAX_ATTEMPTS); + + ASSERT(attempt <= RANDOM_EGG_MAX_ATTEMPTS, "TODO: make sure we have always at least one free visible cell"); +} + +// TODO: animation on restart +static void game_restart(u32 width, u32 height) +{ + memset(&game, 0, sizeof(game)); + +#ifdef FEATURE_DEV + game.dt_scale = 1.0f; +#endif + + game.width = width; + game.height = height; + game.camera_pos.x = width/2; + game.camera_pos.y = height/2; + + for (u32 i = 0; i < SNAKE_INIT_SIZE; ++i) { + Cell head = {.x = i, .y = SNAKE_INIT_ROW}; + ring_push_back(&game.snake, head); + } + random_egg(TRUE); + game.dir = DIR_RIGHT; + // TODO: Using snprintf to render Score is an overkill + // I believe snprintf should be only used for LOGF and in the "release" build stbsp_snprintf should not be included at all + stbsp_snprintf(game.score_buffer, sizeof(game.score_buffer), "Score: %u", game.score); +} + +static f32 lerpf(f32 a, f32 b, f32 t) +{ + return (b - a)*t + a; +} + +static f32 ilerpf(f32 a, f32 b, f32 v) +{ + return (v - a)/(b - a); +} + +static void fill_rect(Rect rect, u32 color) +{ + platform_fill_rect( + rect.x - game.camera_pos.x + game.width/2, + rect.y - game.camera_pos.y + game.height/2, + rect.w, rect.h, color); +} + +#ifdef FEATURE_DEV +static void stroke_rect(Rect rect, u32 color) +{ + platform_stroke_rect( + rect.x - game.camera_pos.x + game.width/2, + rect.y - game.camera_pos.y + game.height/2, + rect.w, rect.h, color); +} +#endif + +static Rect scale_rect(Rect r, float a) +{ + r.x = lerpf(r.x, r.x + r.w*0.5f, 1.0f - a); + r.y = lerpf(r.y, r.y + r.h*0.5f, 1.0f - a); + r.w = lerpf(0.0f, r.w, a); + r.h = lerpf(0.0f, r.h, a); + return r; +} + +static void fill_cell(Cell cell, u32 color, f32 a) +{ + fill_rect(scale_rect(cell_rect(cell), a), color); +} + +static void fill_sides(Sides sides, u32 color) +{ + fill_rect(sides_rect(sides), color); +} + +static Dir cells_dir(Cell a, Cell b) +{ + for (Dir dir = 0; dir < COUNT_DIRS; ++dir) { + if (cell_eq(step_cell(a, dir), b)) return dir; + } + UNREACHABLE(); + return 0; +} + +static Vec cell_center(Cell a) +{ + return (Vec) { + .x = a.x*CELL_SIZE + CELL_SIZE/2, + .y = a.y*CELL_SIZE + CELL_SIZE/2, + }; +} + +static Sides slide_sides(Sides sides, Dir dir, f32 a) +{ + f32 d = sides.lens[dir] - sides.lens[dir_opposite(dir)]; + sides.lens[dir] += lerpf(0, d, a); + sides.lens[dir_opposite(dir)] += lerpf(0, d, a); + return sides; +} + +Vec sides_center(Sides sides) +{ + return (Vec) { + .x = sides.lens[DIR_LEFT] + (sides.lens[DIR_RIGHT] - sides.lens[DIR_LEFT])*0.5f, + .y = sides.lens[DIR_UP] + (sides.lens[DIR_DOWN] - sides.lens[DIR_UP])*0.5f, + }; +} + +static void fill_spine(Vec center, Dir dir, float len) +{ + f32 thicc = CELL_SIZE*SNAKE_SPINE_THICCNESS_PERCENT; + Sides sides = { + .lens = { + [DIR_LEFT] = center.x - thicc, + [DIR_RIGHT] = center.x + thicc, + [DIR_UP] = center.y - thicc, + [DIR_DOWN] = center.y + thicc, + } + }; + if (dir == DIR_RIGHT || dir == DIR_DOWN) sides.lens[dir] += len; + if (dir == DIR_LEFT || dir == DIR_UP) sides.lens[dir] -= len; + fill_sides(sides, SNAKE_SPINE_COLOR); +} + +static void fill_fractured_spine(Sides sides, u8 mask) +{ + f32 thicc = CELL_SIZE*SNAKE_SPINE_THICCNESS_PERCENT; + Vec center = sides_center(sides); + for (Dir dir = 0; dir < COUNT_DIRS; ++dir) { + if (mask&(1< 1e-6; ++i) { + x -= (x*x - a)/(2*x); + } + return x; +} + +static f32 vec_len(Vec a) +{ + return sqrtf(a.x*a.x + a.y*a.y); +} + +void game_resize(u32 width, u32 height) +{ + game.width = width; + game.height = height; +} + +void game_update(f32 dt) +{ +#ifdef FEATURE_DEV + dt *= game.dt_scale; + + #define DEV_DT_SCALE_STEP 0.05f + if (IsKeyPressed(KEY_Z)) { + game.dt_scale -= DEV_DT_SCALE_STEP; + if (game.dt_scale < 0.0f) game.dt_scale = 0.0f; + LOGF("dt scale = %f", game.dt_scale); + } + if (IsKeyPressed(KEY_X)) { + game.dt_scale += DEV_DT_SCALE_STEP; + LOGF("dt scale = %f", game.dt_scale); + } + if (IsKeyPressed(KEY_C)) { + game.dt_scale = 1.0f; + LOGF("dt scale = %f", game.dt_scale); + } +#endif + +#define CAMERA_VELOCITY_FACTOR 0.80f + if (game.infinite_field) { + game.camera_pos.x += game.camera_vel.x*CAMERA_VELOCITY_FACTOR*dt; + game.camera_pos.y += game.camera_vel.y*CAMERA_VELOCITY_FACTOR*dt; + game.camera_vel = vec_sub( + cell_center(*ring_back(&game.snake)), + game.camera_pos); + } + + switch (game.state) { + case STATE_GAMEPLAY: { + if (IsKeyPressed(KEY_W)) { + ring_displace_back(&game.next_dirs, DIR_UP); + } + if (IsKeyPressed(KEY_S)) { + ring_displace_back(&game.next_dirs, DIR_DOWN); + } + if (IsKeyPressed(KEY_A)) { + ring_displace_back(&game.next_dirs, DIR_LEFT); + } + if (IsKeyPressed(KEY_D)) { + ring_displace_back(&game.next_dirs, DIR_RIGHT); + } + if (IsKeyPressed(KEY_SPACE)) { + game.state = STATE_PAUSE; + } + if (IsKeyPressed(KEY_R)) { + game_restart(game.width, game.height); + } + + game.step_cooldown -= dt; + if (game.step_cooldown <= 0.0f) { + if (!ring_empty(&game.next_dirs)) { + if (dir_opposite(game.dir) != *ring_front(&game.next_dirs)) { + game.dir = *ring_front(&game.next_dirs); + } + ring_pop_front(&game.next_dirs); + } + + Cell next_head = step_cell(*ring_back(&game.snake), game.dir); + + if (cell_eq(game.egg, next_head)) { + ring_push_back(&game.snake, next_head); + random_egg(FALSE); + game.eating_egg = TRUE; +#ifdef FEATURE_DYNAMIC_CAMERA + game.infinite_field = TRUE; +#endif + game.score += 1; + stbsp_snprintf(game.score_buffer, sizeof(game.score_buffer), "Score: %u", game.score); + } else { + i32 next_head_index = is_cell_snake_body(next_head); + if (next_head_index >= 0) { + // NOTE: reseting step_cooldown to 0 is important bcause the whole smooth movement is based on it. + // Without this reset the head of the snake "detaches" from the snake on the Game Over, when + // step_cooldown < 0.0f + game.step_cooldown = 0.0f; + game.state = STATE_GAMEOVER; + + game.dead_snake.size = game.snake.size; + Vec head_center = cell_center(next_head); + for (u32 i = 0; i < game.snake.size; ++i) { +#define GAMEOVER_EXPLOSION_RADIUS 1000.0f +#define GAMEOVER_EXPLOSION_MAX_VEL 200.0f + Cell cell = *ring_get(&game.snake, i); + game.dead_snake.items[i] = cell_rect(cell); + if (!cell_eq(cell, next_head)) { + Vec vel_vec = vec_sub(cell_center(cell), head_center); + f32 vel_len = vec_len(vel_vec); + f32 t = ilerpf(0.0f, GAMEOVER_EXPLOSION_RADIUS, vel_len); + if (t > 1.0f) t = 1.0f; + t = 1.0f - t; + f32 noise_x = (my_rand()%1000)*0.01; + f32 noise_y = (my_rand()%1000)*0.01; + vel_vec.x = vel_vec.x/vel_len*GAMEOVER_EXPLOSION_MAX_VEL*t + noise_x; + vel_vec.y = vel_vec.y/vel_len*GAMEOVER_EXPLOSION_MAX_VEL*t + noise_y; + game.dead_snake.vels[i] = vel_vec; + // TODO: additional velocities along the body of the dead snake + } else { + game.dead_snake.vels[i].x = 0; + game.dead_snake.vels[i].y = 0; + } + + // @tail-ignore + if (i > 0) { + game.dead_snake.masks[i] = 0; + if (i > 1) { + game.dead_snake.masks[i] |= 1 << cells_dir(cell, *ring_get(&game.snake, i - 1)); + } + if (i < game.snake.size - 1) { + game.dead_snake.masks[i] |= 1 << cells_dir(cell, *ring_get(&game.snake, i + 1)); + } + } + if (i == game.snake.size - 1) { + game.dead_snake.masks[i] |= 1 << game.dir; + } + } + + game.dead_snake.masks[next_head_index] |= 1 << cells_dir( + *ring_get(&game.snake, next_head_index), + *ring_get(&game.snake, game.snake.size - 1)); + + return; + } else { + ring_push_back(&game.snake, next_head); + ring_pop_front(&game.snake); + game.eating_egg = FALSE; + } + } + + game.step_cooldown = STEP_INTEVAL; + } + } + break; + + case STATE_PAUSE: { + if (IsKeyPressed(KEY_SPACE)) { + game.state = STATE_GAMEPLAY; + } + if (IsKeyPressed(KEY_R)) { + game_restart(game.width, game.height); + } + } break; + + case STATE_GAMEOVER: { + if (IsKeyPressed(KEY_A) || IsKeyPressed(KEY_S) || IsKeyPressed(KEY_D) || IsKeyPressed(KEY_W) || IsKeyPressed(KEY_SPACE)) { + game_restart(game.width, game.height); + } + + // @tail-ignore + for (u32 i = 1; i < game.dead_snake.size; ++i) { + game.dead_snake.vels[i].x *= 0.99f; + game.dead_snake.vels[i].y *= 0.99f; + game.dead_snake.items[i].x += game.dead_snake.vels[i].x*dt; + game.dead_snake.items[i].y += game.dead_snake.vels[i].y*dt; + } + } + break; + + default: { + UNREACHABLE(); + } + } +} + +#define FACTOR 100 +#define WIDTH (16*FACTOR) +#define HEIGHT (9*FACTOR) + +static Font font = {0}; + +void platform_fill_rect(i32 x, i32 y, i32 w, i32 h, u32 color) +{ + DrawRectangle(x, y, w, h, *(Color*)&color); +} + +void platform_stroke_rect(i32 x, i32 y, i32 w, i32 h, u32 color) +{ + DrawRectangleLines(x, y, w, h, *(Color*)&color); +} + +u32 platform_text_width(const char *text, u32 size) +{ + return MeasureText(text, size); +} + +void platform_fill_text(i32 x, i32 y, const char *text, u32 fontSize, u32 color) +{ + Vector2 size = MeasureTextEx(font, text, fontSize, 0); + Vector2 position = {.x = x, .y = y - size.y}; + DrawTextEx(font, text, position, fontSize, 0.0, *(Color*)&color); +} + +void platform_log(const char *message) +{ + TraceLog(LOG_INFO, "%s", message); +} + +void GameFrame(void) +{ + BeginDrawing(); + game_update(GetFrameTime()); + game_render(); + EndDrawing(); +} + +void raylib_js_set_entry(void (*entry)(void)); + +int main(void) +{ + InitWindow(WIDTH, HEIGHT, "Snake"); + game_init(WIDTH, HEIGHT); + + font = LoadFontEx("fonts/AnekLatin-Light.ttf", 48, NULL, 0); + GenTextureMipmaps(&font.texture); + SetTextureFilter(font.texture, TEXTURE_FILTER_BILINEAR); + +#ifdef PLATFORM_WEB + raylib_js_set_entry(GameFrame); +#else + while (!WindowShouldClose()) { + GameFrame(); + } + + CloseWindow(); +#endif + + return 0; +} + +// TODO: inifinite field mechanics +// TODO: starvation mechanics +// TODO: bug on wrapping around when eating the first egg diff --git a/examples/tsoding_snake/tsoding_snake.h b/examples/tsoding_snake/tsoding_snake.h new file mode 100644 index 0000000..a813a36 --- /dev/null +++ b/examples/tsoding_snake/tsoding_snake.h @@ -0,0 +1,26 @@ +#ifndef TSODING_SNAKE_H_ +#define TSODING_SNAKE_H_ + +#include + +typedef unsigned char u8; +typedef unsigned int u32; +typedef unsigned long long u64; +typedef int i32; +typedef int b32; +typedef float f32; + +void platform_fill_rect(i32 x, i32 y, i32 w, i32 h, u32 color); +void platform_stroke_rect(i32 x, i32 y, i32 w, i32 h, u32 color); +void platform_fill_text(i32 x, i32 y, const char *text, u32 size, u32 color); +u32 platform_text_width(const char *text, u32 size); +void platform_panic(const char *file_path, i32 line, const char *message); +void platform_log(const char *message); + +void game_init(u32 width, u32 height); +void game_resize(u32 width, u32 height); +void game_render(void); +void game_update(f32 dt); +void game_keydown(int key); + +#endif // TSODING_SNAKE_H_ diff --git a/fonts/AnekLatin-Light.ttf b/fonts/AnekLatin-Light.ttf new file mode 100644 index 0000000000000000000000000000000000000000..6fce026a06693f86df488345103efc4688524641 GIT binary patch literal 110816 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 literal 0 HcmV?d00001 diff --git a/fonts/OFL.txt b/fonts/OFL.txt new file mode 100644 index 0000000..26d3591 --- /dev/null +++ b/fonts/OFL.txt @@ -0,0 +1,93 @@ +Copyright 2021 The Anek Project Authors (https://github.com/EkType/Anek) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/index.html b/index.html index 5f29ff6..7540063 100644 --- a/index.html +++ b/index.html @@ -45,7 +45,7 @@ diff --git a/raylib.js b/raylib.js index 0f8da8f..e86c10c 100644 --- a/raylib.js +++ b/raylib.js @@ -11,6 +11,16 @@ function make_environment(env) { }); } +let iota = 0; +const LOG_ALL = iota++; // Display all logs +const LOG_TRACE = iota++; // Trace logging, intended for internal use only +const LOG_DEBUG = iota++; // Debug logging, used for internal debugging, it should be disabled on release builds +const LOG_INFO = iota++; // Info logging, used for program execution info +const LOG_WARNING = iota++; // Warning logging, used on recoverable failures +const LOG_ERROR = iota++; // Error logging, used on unrecoverable failures +const LOG_FATAL = iota++; // Fatal logging, used to abort program: exit(EXIT_FAILURE) +const LOG_NONE = iota++; // Disable logging + class RaylibJs { // TODO: We stole the font from the website // (https://raylib.com/) and it's slightly different than @@ -187,6 +197,22 @@ class RaylibJs { return args[0]; } + TraceLog(logLevel, text_ptr, ... args) { + // TODO: Implement printf style formatting for TraceLog + const buffer = this.wasm.instance.exports.memory.buffer; + const text = cstr_by_ptr(buffer, text_ptr); + switch(logLevel) { + case LOG_ALL: console.log(`ALL: ${text} ${args}`); break; + case LOG_TRACE: console.log(`TRACE: ${text} ${args}`); break; + case LOG_DEBUG: console.log(`DEBUG: ${text} ${args}`); break; + case LOG_INFO: console.log(`INFO: ${text} ${args}`); break; + case LOG_WARNING: console.log(`WARNING: ${text} ${args}`); break; + case LOG_ERROR: console.log(`ERROR: ${text} ${args}`); break; + case LOG_FATAL: throw new Error(`FATAL: ${text}`); + case LOG_NONE: console.log(`NONE: ${text} ${args}`); break; + } + } + GetMousePosition(result_ptr) { const bcrect = this.ctx.canvas.getBoundingClientRect(); const x = this.currentMousePosition.x - bcrect.left; @@ -235,6 +261,40 @@ class RaylibJs { return this.ctx.measureText(text).width; } + // TODO: codepoints are not implemented + LoadFontEx(result_ptr, fileName_ptr/*, fontSize, codepoints, codepointCount*/) { + const buffer = this.wasm.instance.exports.memory.buffer; + const fileName = cstr_by_ptr(buffer, fileName_ptr); + // TODO: dynamically generate the name for the font + // Support more than one custom font + const font = new FontFace("myfont", `url(${fileName})`); + document.fonts.add(font); + font.load(); + } + + GenTextureMipmaps() {} + SetTextureFilter() {} + + MeasureTextEx(result_ptr, font, text_ptr, fontSize, spacing) { + const buffer = this.wasm.instance.exports.memory.buffer; + const text = cstr_by_ptr(buffer, text_ptr); + const result = new Float32Array(buffer, result_ptr, 2); + this.ctx.font = fontSize+"px myfont"; + const metrics = this.ctx.measureText(text) + result[0] = metrics.width; + result[1] = fontSize; + } + + DrawTextEx(font, text_ptr, position_ptr, fontSize, spacing, tint_ptr) { + const buffer = this.wasm.instance.exports.memory.buffer; + const text = cstr_by_ptr(buffer, text_ptr); + const [posX, posY] = new Float32Array(buffer, position_ptr, 2); + const tint = getColorFromMemory(buffer, tint_ptr); + this.ctx.fillStyle = tint; + this.ctx.font = fontSize+"px myfont"; + this.ctx.fillText(text, posX, posY + fontSize); + } + raylib_js_set_entry(entry) { this.entryFunction = this.wasm.instance.exports.__indirect_function_table.get(entry); } diff --git a/wasm/game.wasm b/wasm/tsoding_ball.wasm similarity index 100% rename from wasm/game.wasm rename to wasm/tsoding_ball.wasm diff --git a/wasm/tsoding_snake.wasm b/wasm/tsoding_snake.wasm new file mode 100755 index 0000000000000000000000000000000000000000..52b5439021abfab9fd7f01779e1ddca18763ab8f GIT binary patch literal 80444 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 O4OOenwj5KA{eJ