Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /******************************************************************************/
- /******************************************************************************/
- //"gdi_maze_game_2025-04-25\src\kit_utils\draw\draw_textf.cpp":
- #include <public_stuff.hpp>
- #ifdef _DRAW_TEXTF_USED
- #if TEXT_FMT_BUFFER_LEN < 2
- #error "TEXT_FMT_BUFFER_LEN must be >= 2"
- #endif
- #define FMT_BUFFER d_tf_fmt_buffer
- static char d_tf_fmt_buffer[ TEXT_FMT_BUFFER_LEN ];
- #define ERR_RECT TEXT_ERROR_RECT
- Rect2d get_text_rectf(const char* str_fmt, s32 x, s32 y,
- bool use_negative_position_margin,
- const Color8* font, ...)
- {
- va_list va;
- va_start(va, font); // Since font is the last named variable
- s32 result = vsnPrintf(FMT_BUFFER, sizeof(FMT_BUFFER)-1, str_fmt, va);
- FMT_BUFFER[ sizeof(FMT_BUFFER)-1 ] = 0; // Manual null-terminator just in case
- va_end(va);
- if(result < 0) return ERR_RECT;
- return get_text_rect(FMT_BUFFER, x, y, use_negative_position_margin, font);
- }
- Rect2d get_text_rectvf(const char* str_fmt, s32 x, s32 y, va_list va,
- bool use_negative_position_margin, const Color8* font)
- {
- s32 result = vsnPrintf(FMT_BUFFER, sizeof(FMT_BUFFER)-1, str_fmt, va);
- FMT_BUFFER[ sizeof(FMT_BUFFER)-1 ] = 0; // Manual null-terminator just in case
- if(result < 0) return ERR_RECT;
- return get_text_rect(FMT_BUFFER, x, y, use_negative_position_margin, font);
- }
- // Draws the current contents of the built-in destination buffer
- Rect2d draw_current_textf_buffer(s32 x, s32 y, u32 maxLength,
- bool use_negative_position_margin,
- const Color8* font, Color8* dst)
- {
- maxLength = (!maxLength) ? sizeof(FMT_BUFFER)-1
- : MIN(maxLength, sizeof(FMT_BUFFER)-1);
- return draw_text(FMT_BUFFER, x, y, maxLength,
- use_negative_position_margin, font, dst);
- }
- Rect2d draw_textf(const char* str_fmt, s32 x, s32 y, u32 maxLength,
- bool use_negative_position_margin,
- const Color8* font, Color8* dst, ...)
- {
- va_list va;
- va_start(va, dst); // Since dst is the last named variable
- s32 result = vsnPrintf(FMT_BUFFER, sizeof(FMT_BUFFER)-1, str_fmt, va);
- FMT_BUFFER[ sizeof(FMT_BUFFER)-1 ] = 0; // Manual null-terminator just in case
- va_end(va);
- if(result < 0) return ERR_RECT;
- maxLength = (!maxLength) ? sizeof(FMT_BUFFER)-1
- : MIN(maxLength, sizeof(FMT_BUFFER)-1);
- return draw_text(FMT_BUFFER, x, y, maxLength,
- use_negative_position_margin, font, dst);
- }
- #endif
- /******************************************************************************/
- /******************************************************************************/
- //"gdi_maze_game_2025-04-25\src\kit_utils\draw\draw_vslice.cpp":
- #include <public_stuff.hpp>
- #ifdef DRAW_VSLICE_USED
- #define CHECK_BOUNDS 0
- // Rounds a number to the nearest value,
- // (Only works if _x is positive!)
- #ifndef POS_RND
- #define POS_RND(_x) (s32)( (_x) + 0.5f )
- #endif /* POS_RND */
- static Color8 tex_missing[8 + 2*2] = {2,2, 0,0,0,0,0,0,
- 0b00000000, 0b11000111,
- 0b11000111, 0b00000000,
- };
- // Sretches a vertical column of the source's pixels,
- // using nearest-neighbor interpolation
- // (Does not take bitmap offsets into account!)
- void draw_vslice(s32 dst_x, f32 height,
- f32 _src_x, const Color8* src,
- Color8* dst)
- {
- if(u32(dst_x) >= CANVAS_W) return;
- if(dst == nullptr) return;
- if(src == nullptr) src = tex_missing;
- const s32 src_w = s32(src[0].v);
- const f32 src_h = f32(src[1].v);
- const s32 src_x = s32( CLAMP(_src_x, 0.0f, 1.0f) * (f32(src_w)-0.0001f) );
- #if defined(_DEBUG) && CHECK_BOUNDS==1
- const Color8* dst_start = dst;
- const Color8* dst_end = dst + CANVAS_W*CANVAS_H;
- #endif
- s32 src_y_lo = 0;
- s32 src_y_hi = src_h-1;
- height = MAX(height, 0.0f);
- if(height > 1.0f){
- const s32 src_height_pix = POS_RND((1.0f/height) * (src_h/2));
- src_y_lo = s32(src_h/2) - src_height_pix;
- src_y_hi = s32(src_h/2)-1 + src_height_pix;
- }
- const f32 src_span = f32(src_y_hi - src_y_lo + 1);
- height = MIN(height, 1.0f);
- const s32 dst_height_pix = POS_RND(height * f32(CANVAS_H/2));
- const s32 dst_y_lo = (CANVAS_H/2) - dst_height_pix;
- const s32 dst_y_hi = (CANVAS_H/2)-1 + dst_height_pix;
- const s32 dst_span = (dst_y_hi - dst_y_lo + 0);
- src += 8;
- src += src_x;
- dst += dst_x + dst_y_lo*CANVAS_W;
- // +1 to make sure tex_mul is always slightly below 1.0f
- f32 tex_add = 1.0f/(dst_span+1);
- f32 tex_mul = 0;
- const s32 upper_limit = dst_span*CANVAS_W;
- for(s32 y=0; y<=upper_limit; y+=CANVAS_W){
- Color8* pix = dst+y;
- #if defined(_DEBUG) && CHECK_BOUNDS==1
- if(pix < dst_start || pix >= dst_end){
- _printf("ATTEMPTED TO WRITE BEYOND DST: (%p, %p, %p)\n",
- pix, dst_start, dst_end); continue;
- }
- #endif
- s32 src_y = s32( src_y_lo + src_span*tex_mul );
- tex_mul += tex_add;
- #if defined(_DEBUG) && CHECK_BOUNDS==1
- if(src_y < 0 || src_y >= src_h){
- _printf("ATTEMPTED TO READ BEYOND SRC! (%i, %i, %i)\n",
- src_y, src_y_lo, src_y_hi); continue;
- }
- #endif
- *pix = src[src_y * src_w];
- }
- }
- #endif
- /******************************************************************************/
- /******************************************************************************/
- //"gdi_maze_game_2025-04-25\src\kit_utils\draw\fill_rect.cpp":
- #include <public_stuff.hpp>
- #ifdef FILL_RECT_USED
- // dst's length must be >= the length of pixels (CANVAS_W*CANVAS_H)
- void fill_rect(s32 x, s32 y,
- s32 w, s32 h,
- Color8 color,
- Color8* dst)
- {
- if(!w || !h) return;
- if(x >= CANVAS_W) return;
- if(y >= CANVAS_H) return;
- if(x <= -w) return;
- if(y <= -h) return;
- const s32 x_start = MAX(x, 0);
- const s32 y_start = MAX(y, 0);
- const s32 x_end = MIN(x+w, CANVAS_W);
- const s32 y_end = MIN(y+h, CANVAS_H);
- const s32 row_advance = CANVAS_W - (x_end-x_start);
- --dst; // -1 so pre-increment can be used
- dst += MIN(x_start, CANVAS_W-1);
- dst += MIN(y_start, CANVAS_H-1) * CANVAS_W;
- for(y=y_start; y<y_end; ++y){
- for(x=x_start; x<x_end; ++x)
- (++dst)->v = color.v;
- dst += row_advance;
- }
- }
- #endif
- /******************************************************************************/
- /******************************************************************************/
- //"gdi_maze_game_2025-04-25\src\kit_utils\draw\fill_tri.cpp":
- // THESE FUNCTIONS ARE NOT THREAD-SAFE,
- // SINCE THE SAME EDGE BUFFERS ARE USED BETWEEN CALLS
- #include <public_stuff.hpp>
- #include <algorithm>
- #include <cmath>
- // Returns the middle part of x(y) = x0 + ((x1-x0)/(y1-y0)) * (y - y0)
- static inline f32 _getInterpConstant(Fpoint2d& p0, Fpoint2d& p1){
- f32 divisor = p1.y-p0.y;
- if(divisor == 0) divisor = 0.000001f; // Prevents divide-by-zero
- return (p1.x-p0.x)/divisor;
- }
- #define _INTERP(_y, _p0, _constant) ( (_p0).x + (_constant) * ((_y)-(_p0.y)) )
- #define _INTERP_AC(_y) _INTERP(_y, a, aci)
- #define _INTERP_AB(_y) _INTERP(_y, a, abi)
- #define _INTERP_BC(_y) _INTERP(_y, b, bci)
- static inline Fpoint2d _round_and_convert(Fpoint3d in){
- Fpoint2d out;
- out.x = roundf(in.x);
- out.y = roundf(in.y);
- return out;
- }
- // Fpoint2d cross product's magnitude (I think?)
- static inline f32 _Fp2d_crossmag(const Fpoint2d& a,
- const Fpoint2d& b,
- const Fpoint2d& origin = {0,0})
- {
- const Fpoint2d oa = { a.x-origin.y, a.y-origin.y };
- const Fpoint2d ob = { b.x-origin.y, b.y-origin.y };
- return (oa.x*ob.y) - (oa.y*ob.x);
- }
- /*
- Point2d edges_start[CANVAS_H]; // .y is for the scanline index
- Point2d edges_end[CANVAS_H]; // .y is unused
- u32 edges_count;
- static ATTR_NOINLINE void _interpolate_triangle(const Fpoint3d* verts,
- const Triangle& tri)
- {
- edges_count = 0; // Initialize number of rows to 0
- // z isn't needed here, so convert to Fpoint2d,
- // while also aligning to the nearest pixel boundary
- Fpoint2d a = _round_and_convert(verts[tri.a]);
- Fpoint2d b = _round_and_convert(verts[tri.b]);
- Fpoint2d c = _round_and_convert(verts[tri.c]);
- // Sort points vertically, so that a & c are top and bottom respectively
- if(a.y > c.y) std::swap(a, c);
- if(a.y > b.y) std::swap(a, b);
- if(b.y > c.y) std::swap(b, c);
- // Return early if triangle's points are completely off-screen horizontally
- if( (a.x < 0 && b.x < 0 && c.x < 0) ||
- (a.x>=CANVAS_W && b.x>=CANVAS_W && c.x>=CANVAS_W) )
- {
- return;
- }
- // Return early if triangle's points are completely off-screen vertically
- // (Points are sorted vertically, so only c.y and a.y need to be checked)
- if(c.y < 0 || a.y >= CANVAS_H) return;
- // 'Is point b on the left or right side of line ac
- // (as it appears on-screen)?'
- const bool isRightBend = _Fp2d_crossmag(a, b, c) > 0;
- // Precalculate interpolation constants
- const f32 aci = _getInterpConstant(a, c);
- const f32 abi = _getInterpConstant(a, b);
- const f32 bci = _getInterpConstant(b, c);
- // Interpolate edges of the triangle
- // Prevents south edge trim if last row was off-screen
- bool lastRowOffScreen = false;
- // Triangle is a single scanline tall (just a horizontal line)!
- if(a.y == c.y){
- // (Since the south edge is trimmed, this is likely redundant,
- // as this line would never be drawn in the first place!
- s32 a_x = (s32)a.x, a_y = (s32)a.y;
- s32 b_x = (s32)b.x;
- s32 c_x = (s32)c.x;
- edges_start[edges_count].x = MIN3(a_x, b_x, c_x);
- edges_start[edges_count].y = a_y;
- edges_end [edges_count].x = MAX3(a_x, b_x, c_x);
- edges_count = (edges_start[edges_count].x < CANVAS_W) &&
- (edges_end [edges_count].x >= 0);
- // Triangle is >1 scanline(s) tall
- } else {
- #define skip_row \
- { if(!lastRowOffScreen && (yi == (abc_max-1))){ lastRowOffScreen = true; } continue; }
- #define ab_max abc_max // Aliases for consistency
- #define bc_max abc_max
- f32 abc_max;
- Point2d* rows_ac;
- Point2d* rows_abc;
- // Line ac is edge start
- if(isRightBend){
- rows_ac = edges_start;
- rows_abc = edges_end;
- // Line ac is edge end (so swap start and end)
- } else {
- rows_ac = edges_end;
- rows_abc = edges_start;
- }
- // If b.y < 1, nothing from a to b-1 would render
- if(b.y > 0){
- ab_max = MIN(b.y, CANVAS_H);
- for(f32 yi=MAX(a.y,0); yi<ab_max; ++yi){
- // edges_start accessed directly for its y component
- edges_start[edges_count].y = (s32)yi;
- // a -> c, a -> b
- rows_ac [edges_count].x = (s32)_INTERP_AC(yi);
- rows_abc[edges_count].x = (s32)_INTERP_AB(yi);
- if(edges_start[edges_count].x >= CANVAS_W) skip_row; // If start is past screen
- if(edges_end [edges_count].x < 0 ) skip_row; // If end is before screen
- ++edges_count; // Only increment edges_count if scanline is valid to draw on
- }
- }
- // If b.y >= CANVAS_H, everything from b to c is hidden
- if(b.y < CANVAS_H){
- bc_max = MIN(c.y+1, CANVAS_H); //c.y+1 so the for-loop includes c.y
- for(f32 yi=MAX(b.y,0); yi<bc_max; ++yi){
- // edges_start accessed directly for its y component
- edges_start[edges_count].y = (s32)yi;
- // a -> c, b -> c
- rows_ac [edges_count].x = (s32)_INTERP_AC(yi);
- rows_abc[edges_count].x = (s32)_INTERP_BC(yi);
- if(edges_start[edges_count].x >= CANVAS_W) skip_row; // If start is past screen
- if(edges_end [edges_count].x < 0 ) skip_row; // If end is before screen
- ++edges_count; // Only increment edges_count if scanline is valid to draw on
- }
- }
- }
- // (Trimming the south-east edge should prevent overdraw)
- // Trim south edge unless the last row OR c.y is off-screen
- if(!lastRowOffScreen && (c.y < CANVAS_H))
- edges_count = MAX(edges_count-1, 0);
- // Clip triangle width to target screen space, and trim east edge
- for(u32 row=0; row<edges_count; ++row){
- edges_start[row].x = MAX(edges_start[row].x, 0);
- edges_end [row].x = MIN(edges_end [row].x-1, CANVAS_W-1);
- }
- }
- const static Triangle tri = { 0, 1, 2 };
- void fill_tri(f32 x_0, f32 y_0,
- f32 x_1, f32 y_1,
- f32 x_2, f32 y_2,
- Color8 color)
- {
- Fpoint3d verts[3];
- verts[0] = {x_0, y_0};
- verts[1] = {x_1, y_1};
- verts[2] = {x_2, y_2};
- _interpolate_triangle(verts, tri);
- // For each row of triangle
- for(u32 row=0; row<edges_count; ++row){
- #if defined(_DEBUG) && 0
- if( edges_start[row].y < 0 ){ _printf("y<0\n" ); continue; }
- else if(edges_start[row].y >= CANVAS_H){ _printf("y>=w\n"); continue; }
- #endif
- s32 y_pos = edges_start[row].y * CANVAS_W;
- s32 start = edges_start[row].x + y_pos;
- s32 end = edges_end [row].x + y_pos;
- // For each column of row
- for(s32 i=start; i<=end; ++i)
- pixels[i].v = color.v;
- }
- }
- void fill_tris(const Fpoint3d* verts,
- const Triangle* tris, u32 tris_len)
- {
- if(verts == nullptr) return;
- if(tris == nullptr) return;
- if(tris_len == 0) return;
- // For each triangle
- for(u32 tri=0; tri<tris_len; ++tri){
- _interpolate_triangle(verts, tris[tri]);
- Color8 color = tris[tri].color;
- // For each row of triangle
- for(u32 row=0; row<edges_count; ++row){
- s32 y_pos = edges_start[row].y * CANVAS_W;
- s32 start = edges_start[row].x + y_pos;
- s32 end = edges_end [row].x + y_pos;
- // For each column of row
- for(s32 i=start; i<=end; ++i)
- pixels[i].v = color.v;
- }
- }
- }
- void fill_tris2(const Fpoint3d* verts, const Triangle* tris,
- const u32* indices, u32 indices_len)
- {
- if(verts == nullptr) return;
- if(tris == nullptr) return;
- if(indices == nullptr) return;
- if(indices_len == 0) return;
- // For each triangle
- for(u32 index=0; index<indices_len; ++index){
- const Triangle& tri = tris[ indices[index] ];
- _interpolate_triangle(verts, tri);
- Color8 color = tri.color;
- // For each row of triangle
- for(u32 row=0; row<edges_count; ++row){
- s32 y_pos = edges_start[row].y * CANVAS_W;
- s32 start = edges_start[row].x + y_pos;
- s32 end = edges_end [row].x + y_pos;
- // For each column of row
- for(s32 i=start; i<=end; ++i)
- pixels[i].v = color.v;
- }
- }
- }
- */
- /******************************************************************************/
- /******************************************************************************/
- //"gdi_maze_game_2025-04-25\src\kit_utils\draw\font_pico8.cpp":
- #include <public_stuff.hpp>
- #ifdef FONT_PICO8_USED
- // This is how pixels are stored. Each bit corresponds to
- // one pixel of a given char. the pixels storage order is as follows:
- //
- // -----
- // |CDE|
- // |9AB|
- // |678|
- // |345|
- // |012|
- // -----
- //
- // For example, a char with the data of "0b111100110000010" would look like:
- //
- // ----- (A question mark)
- // |###|
- // |..#|
- // |.##|
- // |...|
- // |.#.|
- // -----
- //
- // Glyphs are 3x5 pixels each, first char is 32 (' '), 96 chars in total.
- // This means that this font has data for chars 32-127, and nothing more
- //
- // (96-1 is used here, to make it so that if you have a font that takes up
- // all 256 chars, it will still fit into a byte (2^8-1 = 255, not 256).)
- u8 font_pico8_packed[184] = { 3, 5, 32, 96-1, // 184B
- 0b00000000, 0b00000000, 0b01000001, 0b00010010,
- 0b10000000, 0b10110110, 0b11101111, 0b10101011,
- 0b01111011, 0b01101111, 0b11000100, 0b10111110,
- 0b11011011, 0b00000000, 0b01000100, 0b01001010,
- 0b00100010, 0b10010001, 0b01010100, 0b01110101,
- 0b00010101, 0b10111010, 0b00010000, 0b00000001,
- 0b00000000, 0b00001110, 0b00000100, 0b00000000,
- 0b00100010, 0b10001001, 0b01101111, 0b11111011,
- 0b01001011, 0b11011010, 0b01110011, 0b11111110,
- 0b00111100, 0b01001111, 0b10111110, 0b00111101,
- 0b10011111, 0b10111111, 0b11001111, 0b01001001,
- 0b11110010, 0b11101111, 0b01111011, 0b11110010,
- 0b00111101, 0b00000100, 0b00100001, 0b10000010,
- 0b01000000, 0b01000101, 0b11000100, 0b01110001,
- 0b01000100, 0b01010100, 0b00000100, 0b11110011,
- 0b01001110, 0b10101011, 0b11110110, 0b11111101,
- 0b10111011, 0b11011110, 0b01001001, 0b11111100,
- 0b10110110, 0b01111011, 0b10010110, 0b00100111,
- 0b11001011, 0b11011111, 0b11000100, 0b11101101,
- 0b11011011, 0b01001011, 0b11111010, 0b00100100,
- 0b10111101, 0b01011101, 0b11111011, 0b00100100,
- 0b01101001, 0b11111011, 0b10110111, 0b11101101,
- 0b11010110, 0b11010110, 0b11001001, 0b01111011,
- 0b10101111, 0b01010101, 0b10111011, 0b01111110,
- 0b01111100, 0b00101100, 0b01001001, 0b01110111,
- 0b11011011, 0b11101010, 0b01101101, 0b11111111,
- 0b10110110, 0b10101101, 0b11011010, 0b11110011,
- 0b11101101, 0b00100011, 0b01111110, 0b01001001,
- 0b01000110, 0b01001001, 0b00110001, 0b01001001,
- 0b00000011, 0b10101000, 0b00001110, 0b00000000,
- 0b00000000, 0b10010100, 0b10111110, 0b11000111,
- 0b10111011, 0b11100001, 0b11001001, 0b10110001,
- 0b01110110, 0b01111000, 0b01110110, 0b00100100,
- 0b00111011, 0b11011110, 0b00011100, 0b01111101,
- 0b10001011, 0b01001011, 0b11000111, 0b10100100,
- 0b10100011, 0b01011101, 0b11110001, 0b00100100,
- 0b01101000, 0b01111111, 0b10110100, 0b00011101,
- 0b11010110, 0b00011010, 0b01111001, 0b00001111,
- 0b10101111, 0b01000010, 0b11010111, 0b01100011,
- 0b10001100, 0b00100001, 0b11101001, 0b01110000,
- 0b01011011, 0b11101000, 0b00101101, 0b11111110,
- 0b00010110, 0b10101101, 0b10001010, 0b11110011,
- 0b11000101, 0b11000011, 0b11000011, 0b10011010,
- 0b00101100, 0b01001001, 0b10011010, 0b10101100,
- 0b00100001, 0b00100111, 0b01011110, 0b00000001,
- };
- // This is where it unpacks to. It has the same ordering of pixels,
- // except instead of 1 bit per pixel, it's 1 byte.
- //
- // For example, every 15 bytes is the next char, so to find the address of
- // a given char, you'd basically do:
- // "&font_pico8[15 * char_value]"
- // OR
- // (font_pico8 + (15 * char_value))
- //
- // The first 4 bytes are: char_width, char_height, transparency, (reserved)
- Color8 font_pico8[4 + 3*5 * 256]; // 3844B
- #endif
- /******************************************************************************/
- /******************************************************************************/
- //"gdi_maze_game_2025-04-25\src\kit_utils\draw\unpack_font.cpp":
- #include <public_stuff.hpp>
- #ifdef UNPACK_FONT_USED
- bool unpack_font(Color8* dst, const u8* src,
- Color8 fontColor,
- Color8 transparencyColor)
- {
- if(!dst || !src) return false;
- u32 w = dst[0].v = src[0];
- u32 h = dst[1].v = src[1];
- u32 first = src[2];
- u32 numchars = src[3];
- dst[2] = transparencyColor;
- dst[3].v = 0; // (Reserved)
- // Initialize all pixels to the transparent color
- memSet(&dst[4].v, transparencyColor.v, w*h*256);
- // Due to the fact the value in src is only a single byte wide,
- // this value must be incremented to get the real value, since if
- // the font has all 256 chars, only 255 of them can be written otherwise.
- ++numchars;
- u32 size = w*h;
- dst += 4 + size*first; // Seek to first pixel of unpacked font data
- src += 4; // Seek to start of packed font data
- u32 i = 0;
- for(u32 c=0; c<numchars; ++c)
- for(u32 p=0; p< size; ++p)
- {
- dst[i] = (is_bit_set(src, i)) ? fontColor : transparencyColor;
- ++i;
- }
- return true;
- }
- #endif
- /******************************************************************************/
- /******************************************************************************/
- //"gdi_maze_game_2025-04-25\src\kit_utils\misc\is_bit_set.cpp":
- #include <public_stuff.hpp>
- bool is_bit_set(const void* buffer, u32 which_bit){
- union {
- u32 value;
- struct {
- u32 bit : 3;
- u32 byte : 29;
- };
- } _which_bit;
- _which_bit.value = which_bit;
- return 1&( (((u8*)buffer)[_which_bit.byte]) >> _which_bit.bit );
- }
- /******************************************************************************/
- /******************************************************************************/
- //"gdi_maze_game_2025-04-25\src\kit_utils\misc\kit_misc.cpp":
- #include <public_stuff.hpp>
- #ifdef FRAND_USED
- #include <stdlib.h>
- #if RAND_MAX == 32767
- #define GET_FRAND_VALUE(cast) ( (cast)(rand()<<15|rand())/0x3FFFFFFF )
- #elif RAND_MAX == 2147483647
- #define GET_FRAND_VALUE(cast) ( (cast)rand()/0x7FFFFFFF )
- #else
- #error "no definition of GET_FRAND_VALUE() available for current RAND_MAX"
- #endif
- f64 frand(){ //0.0f -> 1.0f
- return GET_FRAND_VALUE(f64);
- }
- f64 frand2(){ //-1.0f -> 1.0f
- return GET_FRAND_VALUE(f64)*2.0f - 1.0f;
- }
- f32 frandf(){ //0.0f -> 1.0f
- return GET_FRAND_VALUE(f32);
- }
- f32 frandf2(){ //-1.0f -> 1.0f
- return GET_FRAND_VALUE(f32)*2.0f - 1.0f;
- }
- #endif
- //...
- /******************************************************************************/
- /******************************************************************************/
- //"gdi_maze_game_2025-04-25\src\kit_utils\misc\print_event.cpp":
- #include <public_stuff.hpp>
- #ifdef PRINT_EVENT_USED
- #ifdef _DEBUG
- static char key_evt_text[][5] = { // EVENT_KEY_?
- "NULL",
- "CHAR",
- "UP",
- "DOWN",
- };
- static char mouse_evt_text[][7] = { // EVENT_MOUSE_?
- "NULL",
- "MOVED",
- "HWHEEL",
- "VWHEEL",
- "UP",
- "DOWN",
- };
- static char cursor_evt_text[][9] = { // EVENT_CURSOR_?
- "NULL",
- "TRAPPED",
- "RELEASED",
- };
- void print_event(Event& evt){
- u16 subevent = SUBEVENT_ID(evt.type);
- switch(EVENT_ID(evt.type)){
- case EVENT_NULL:
- {
- _printf("EVENT_NULL = {\n");
- _printf(" .type = EVENT_NULL,\n");
- _printf(" .timestamp = %llu,\n", evt.common.timestamp);
- } break;
- case EVENT_COMMON:
- {
- _printf("EVENT_COMMON = {\n");
- _printf(" .type = EVENT_COMMON,\n");
- _printf(" .timestamp = %llu,\n", evt.common.timestamp);
- } break;
- case EVENT_QUIT:
- {
- _printf("EVENT_COMMON = {\n");
- _printf(" .type = EVENT_COMMON,\n");
- _printf(" .timestamp = %llu,\n", evt.common.timestamp);
- } break;
- case EVENT_KEY:
- {
- _printf("EVENT_KEY = {\n");
- _printf(" .type = EVENT_KEY_%s,\n", key_evt_text[subevent]);
- _printf(" .timestamp = %llu,\n\n", evt.key.timestamp);
- _printf(" .kmods = 0x%04X = {\n", evt.key.kmods);
- _printf(" .lshift = %i,\n", evt.key.sym.kmod.lshift);
- _printf(" .rshift = %i,\n", evt.key.sym.kmod.rshift);
- _printf(" .lctrl = %i,\n", evt.key.sym.kmod.lctrl);
- _printf(" .rctrl = %i,\n", evt.key.sym.kmod.rctrl);
- _printf(" .lalt = %i,\n", evt.key.sym.kmod.lalt);
- _printf(" .ralt = %i,\n", evt.key.sym.kmod.ralt);
- _printf(" .lgui = %i,\n", evt.key.sym.kmod.lgui);
- _printf(" .rgui = %i,\n", evt.key.sym.kmod.rgui);
- _printf(" .numlock = %i,\n", evt.key.sym.kmod.numlock);
- _printf(" .capslock = %i,\n", evt.key.sym.kmod.capslock);
- _printf(" .altgraph = %i,\n", evt.key.sym.kmod.altgraph);
- _printf(" .scrollock = %i,\n", evt.key.sym.kmod.scrollock);
- _printf(" }\n\n");
- _printf(" .pkey = 0x%02X,\n", evt.key.pkey);
- _printf(" .vkey = 0x%02X,\n", evt.key.vkey);
- _printf(" .pressed = %s,\n", BOOL_STR(evt.key.pressed));
- _printf(" .ischar = %s,\n", BOOL_STR(evt.key.ischar));
- _printf(" .repeat = %s,\n", BOOL_STR(evt.key.repeat));
- } break;
- case EVENT_MOUSE:
- {
- _printf("EVENT_MOUSE = {\n");
- _printf(" .type = EVENT_MOUSE_%s,\n\n", mouse_evt_text[subevent]);
- _printf(" .button = 0x%02X,\n", evt.mouse.button);
- _printf(" .pressed = %s,\n", BOOL_STR(evt.mouse.pressed));
- _printf(" .dblClick = %s,\n\n", BOOL_STR(evt.mouse.dblClick));
- _printf(" .timestamp = %llu,\n\n", evt.mouse.timestamp);
- _printf(" .x = %5.2f,\n", evt.mouse.x);
- _printf(" .y = %5.2f,\n", evt.mouse.y);
- _printf(" .dx = %5.2f,\n", evt.mouse.dx);
- _printf(" .dy = %5.2f,\n", evt.mouse.dy);
- } break;
- case EVENT_CURSOR:
- {
- _printf("EVENT_CURSOR = {\n");
- _printf(" .type = EVENT_CURSOR_%s,\n", cursor_evt_text[subevent]);
- _printf(" .timestamp = %llu,\n", evt.common.timestamp);
- } break;
- default:
- {
- _printf("EVENT_UNKNOWN = {\n");
- _printf(" .type = 0x%08X,\n", evt.type);
- _printf(" .timestamp = %llu,\n", evt.common.timestamp);
- }
- }
- _printf("}\n");
- }
- #endif /* _DEBUG */
- #endif /* PRINT_EVENT_USED */
- /******************************************************************************/
- /******************************************************************************/
- //"gdi_maze_game_2025-04-25\src\kit_utils\misc\snPrintf.cpp":
- #include <public_stuff.hpp>
- #undef snprintf
- #undef vsnprintf
- #define STB_SPRINTF_IMPLEMENTATION
- #include "../../../dep/stb_sprintf.h"
- s32 snPrintf(char* str_dst, size_t len_max, const char* str_fmt, ...){
- va_list va;
- va_start(va, str_fmt);
- s32 result = 0;
- if(len_max > 0 && len_max <= INT_MAX){
- result = stbsp_vsnprintf(str_dst, (int)len_max, str_fmt, va);
- } else {
- result = stbsp_vsprintf(str_dst, str_fmt, va);
- }
- va_end(va);
- return result;
- }
- s32 vsnPrintf(char* str_dst, size_t len_max, const char* str_fmt, va_list va){
- if(len_max > 0 && len_max <= INT_MAX){
- return stbsp_vsnprintf(str_dst, (int)len_max, str_fmt, va);
- } else {
- return stbsp_vsprintf(str_dst, str_fmt, va);
- }
- }
- /******************************************************************************/
- /******************************************************************************/
- //"gdi_maze_game_2025-04-25\src\kit_utils\sound\AudioData.cpp":
- #include <public_stuff.hpp>
- #ifdef SOUND_STUFF_USED
- void AudioDataHeader::printHeader(const char* name){
- if(name != nullptr){ _printf("%s = {\n", name); }
- else { _printf("%p = {\n", this); }
- #ifdef _DEBUG
- _printf(" ->magic = \"%.4s\"; (0x%08X)\n", (char*)&magic, magic);
- const char* fmt_txt = "?";
- switch(format){
- case SMPFMT_U8 : fmt_txt = "U8"; break;
- case SMPFMT_S8 : fmt_txt = "S8"; break;
- case SMPFMT_U16LSB: fmt_txt = "U16LSB"; break;
- case SMPFMT_S16LSB: fmt_txt = "S16LSB"; break;
- case SMPFMT_S24LSB: fmt_txt = "S24LSB"; break;
- case SMPFMT_S32LSB: fmt_txt = "S32LSB"; break;
- case SMPFMT_F32LSB: fmt_txt = "F32LSB"; break;
- case SMPFMT_F64LSB: fmt_txt = "F64LSB"; break;
- case SMPFMT_U16MSB: fmt_txt = "U16MSB"; break;
- case SMPFMT_S16MSB: fmt_txt = "S16MSB"; break;
- case SMPFMT_S24MSB: fmt_txt = "S24MSB"; break;
- case SMPFMT_S32MSB: fmt_txt = "S32MSB"; break;
- case SMPFMT_F32MSB: fmt_txt = "F32MSB"; break;
- case SMPFMT_F64MSB: fmt_txt = "F64MSB"; break;
- default : fmt_txt = "UNKNOWN";
- }
- _printf(" ->format = SMPFMT_%s; (0x%04X)\n", fmt_txt, format);
- _printf(" ->headerSize = %u;\n", headerSize);
- _printf(" ->dataSize = %llu;\n", dataSize);
- _printf(" ->loopStart = %llu;\n", loopStart);
- _printf(" ->loopEnd = %llu;\n", loopEnd);
- _printf(" ->numSamples = %llu;\n", numSamples);
- _printf(" ->sampleRate = %u;\n", sampleRate);
- _printf(" ->bitRate = %u;\n", bitRate);
- _printf(" ->loopCount = %u;\n", loopCount);
- _printf(" ->channels = %u;\n", channels);
- _printf(" ->_reserved = %u;\n", _reserved);
- _printf(" ->fmt_version = %u;\n", fmt_version);
- _printf(" ->mode = %u;\n", mode);
- _printf(" ->metadata_type = %u;\n", metadata_type);
- _printf(" ->samples = %p;\n", samples);
- _printf(" ->userdata = %p;\n", userdata);
- _printf("};");
- #else
- _printf(" (AudioDataHeader::printHeader() is not available in release build!)\n}\n");
- #endif /* _DEBUG */
- }
- bool AudioData::_allocate_hdr(u16 headerSize, u64 dataSize){
- if(hdr) return false;
- if(headerSize < sizeof(AudioDataHeader)) return false;
- hdr = (AudioDataHeader*)mem_alloc(headerSize+dataSize);
- if(hdr == nullptr) return false;
- mem_set(hdr, 0, headerSize+dataSize);
- hdr->magic = KPM_FILE_SIG;
- hdr->headerSize = headerSize;
- hdr->dataSize = dataSize;
- hdr->samples = (u8*)hdr + hdr->headerSize;
- return true;
- }
- AudioData::AudioData(AudioSampleFormatEnum format,
- u64 numSamples, u16 channels, u32 sampleRate)
- {
- if(hdr) return;
- const u64 dataSize = GET_AUDIO_BYTESIZE(format)*numSamples*channels;
- if(!_allocate_hdr(sizeof(AudioDataHeader), dataSize)) return;
- // (Redundant assignments are commented out here)
- //hdr->magic = KPM_FILE_SIG;
- hdr->format = format;
- //hdr->headerSize = sizeof(AudioDataHeader);
- //hdr->dataSize = dataSize;
- //hdr->loopStart = 0;
- hdr->loopEnd = numSamples;
- hdr->numSamples = numSamples;
- hdr->sampleRate = sampleRate;
- hdr->bitRate = GET_AUDIO_BITSIZE(format)*sampleRate*channels;
- //hdr->loopCount = 0;
- hdr->channels = channels;
- //hdr->_reserved = 0;
- hdr->fmt_version = 1; // 1 indicates the version kit_sdl2 uses
- //hdr->mode = 0; // PCM or float data
- //hdr->metadata_type = 0; // No metadata
- //hdr->samples = (u8*)hdr + hdr->headerSize;
- //hdr->userdata = nullptr;
- }
- #ifdef AUDIODATA_FILELOAD_USED
- #define KPCM_FILE_SIG 0x4D43506B //.kpm's old file signature
- AudioData::AudioData(const char* filePath,
- AudioDataLoaderCallback callback)
- {
- if(hdr) return;
- if(filePath == nullptr) return;
- if(!fileio_exists(filePath)) return;
- AudioDataHeader* _hdr;
- if(callback == nullptr){ // Load .kpm file
- size_t fileSize;
- _hdr = (AudioDataHeader*)fileio_read(filePath, &fileSize);
- if(_hdr == nullptr) return;
- // Check for the current and old version of .kpm's file signature
- // (but only if the fileSize is enough for a u32)
- if(fileSize >= sizeof(u32) &&
- (_hdr->magic != KPM_FILE_SIG && _hdr->magic != KPCM_FILE_SIG))
- {
- _free_hdr_copy: mem_free(&_hdr); return;
- }
- else if(fileSize < sizeof(AudioDataHeader)) goto _free_hdr_copy;
- /*
- if(_hdr->magic != KIT_MAGIC_KPM) throw "magic != KIT_MAGIC_KPM";
- if(!isFormatValid(_hdr->format)) throw "format is invalid";
- if(_hdr->headerSize < sizeof(AudioDataHeader)) throw "headerSize < sizeof(AudioDataHeader)";
- if(_hdr->dataSize != (fileSize-_hdr->headerSize)) throw "dataSize is invalid";
- //(channels are checked before numSamples to prevent divide-by-zero exceptions)
- if(_hdr->channels!=1 && _hdr->channels!=2) throw "audio is neither mono nor stereo";
- //(numSamples is checked before loopStart/loopEnd, as their checks rely upon numSamples)
- if(_hdr->numSamples != (_hdr->dataSize/KIT_ASTREAM_FMT_BYTESIZE(_hdr->format))/_hdr->channels) throw "numSamples is invalid";
- if(_hdr->loopStart >= _hdr->numSamples) throw "loopStart >= numSamples";
- if(_hdr->loopEnd > _hdr->numSamples) throw "loopEnd > numSamples";
- if(_hdr->sampleRate < 1000) throw "sampleRate < 1000";
- if(_hdr->bitRate != _hdr->sampleRate*_hdr->channels*KIT_ASTREAM_FMT_BITSIZE(_hdr->format)) throw "bitRate is invalid";
- if(_hdr->bitRemainder != 0) throw "bitRemainder != 0";
- if(_hdr->mode != 0) throw "only mode 0 kPCM files are currently supported";
- */
- // The only difference between 0 and 1 is that bitsPerSample is offset by -1
- if(_hdr->fmt_version == 0) ++_hdr->format;
- _hdr->magic = KPM_FILE_SIG; // If it was previously kPCM, now it is kPxM
- _hdr->fmt_version = 1;
- } else {
- _hdr = callback(filePath);
- if(_hdr == nullptr) return;
- }
- size_t totalSize = _hdr->headerSize + _hdr->dataSize;
- hdr = (AudioDataHeader*)mem_alloc(totalSize);
- if(hdr == nullptr){ mem_free(&_hdr); return; }
- mem_copy(hdr, _hdr, totalSize);
- mem_free(&_hdr);
- hdr->samples = (u8*)hdr + hdr->headerSize;
- }
- #endif /* AUDIODATA_FILELOAD_USED */
- AudioData::~AudioData(){
- mem_free(&hdr);
- }
- #ifdef AUDIODATA_SAVEAUDIO_USED
- bool AudioData::saveAudio(const char* filePath,
- AudioDataSaverCallback callback)
- {
- if(hdr == nullptr) return false;
- if(filePath == nullptr) return false;
- if(callback == nullptr){ //save .kpm
- if(!fileio_write(filePath, hdr, hdr->headerSize+hdr->dataSize))
- return false;
- } else {
- if(!callback(filePath, *hdr))
- return false;
- }
- return true;
- }
- #endif
- #ifdef AUDIODATA_CONVERTFORMAT_USED
- static bool _fmt_is_valid(u16 fmt){
- switch(fmt){
- case SMPFMT_U8 :
- case SMPFMT_S8 :
- case SMPFMT_U16:
- case SMPFMT_S16:
- case SMPFMT_S24:
- case SMPFMT_S32:
- case SMPFMT_F32:
- case SMPFMT_F64: return true; // Lol
- default: return false;
- }
- }
- // = 2^(bits-1)
- #define ABS_S8_MIN (128) //ABS_Sx_MIN is a horrible name for this,
- #define ABS_S16_MIN (32768) //but it's the name i chose within 10 seconds
- #define ABS_S24_MIN (8388608) //(so i may or may not change it, idk)
- #define ABS_S32_MIN (2147483648)
- struct _s24 { u8 a, b, c; } //mostly for memory alignment purposes
- ATTR_PACKED; //(explicitly pack just in case; probably unnecessary)
- union _s24u {
- _s24 v;
- s32 n : 24;
- inline _s24u(_s24 _v) : v(_v) {}
- inline _s24u(s32 _n) : n(_n&0x7FFFFF) {}
- };
- static inline f64 frm_s24(_s24 x){ return (f64)_s24u(x).n/ABS_S24_MIN; }
- static inline _s24 to_s24(f64 x){ return _s24u((s32)(x*0x7FFFFF)).v; }
- bool AudioData::convertFormat(AudioSampleFormatEnum format){
- if(hdr == nullptr) return false;
- if(hdr->format == format) return true;
- if(!_fmt_is_valid(hdr->format)) return false;
- if(!_fmt_is_valid(format)) return false;
- u64 totalSamples = hdr->numSamples*hdr->channels;
- u64 dataSize = GET_AUDIO_BYTESIZE(format)*totalSamples;
- u32 bitRate = GET_AUDIO_BITSIZE(format)*hdr->sampleRate*hdr->channels;
- mem_Wrapper temp_samples(totalSamples*sizeof(f64));
- f64* tmp = (f64*)temp_samples.ptr;
- void* smp = hdr->samples;
- #define FOR_TS_BRK(x) for(u64 i=0; i<totalSamples; ++i){ x; } break
- #define SMPCAST(_type) ( ((_type*)smp)[i] )
- #define FRM_CONV(_type, _scaling_factor, _modifier) \
- ( ((f64)SMPCAST(_type) _modifier) _scaling_factor )
- // Convert all source samples to 64-bit floats
- switch(hdr->format){
- case SMPFMT_U8 : FOR_TS_BRK( tmp[i] = FRM_CONV(u8 , /ABS_S8_MIN , -128) );
- case SMPFMT_S8 : FOR_TS_BRK( tmp[i] = FRM_CONV(s8 , /ABS_S8_MIN , ) );
- case SMPFMT_U16: FOR_TS_BRK( tmp[i] = FRM_CONV(u16, /ABS_S16_MIN, -32768) );
- case SMPFMT_S16: FOR_TS_BRK( tmp[i] = FRM_CONV(s16, /ABS_S16_MIN, ) );
- case SMPFMT_S24: FOR_TS_BRK( tmp[i] = frm_s24(SMPCAST(_s24)) );
- case SMPFMT_S32: FOR_TS_BRK( tmp[i] = FRM_CONV(s32, /ABS_S32_MIN, ) );
- case SMPFMT_F32: FOR_TS_BRK( tmp[i] = FRM_CONV(f32, , ) );
- case SMPFMT_F64: mem_copy(tmp, smp, hdr->dataSize); break;
- }
- //resize header to match destination format's dataSize
- if(!mem_realloc(&hdr, hdr->headerSize+dataSize)) return false;
- //update relevant header values
- hdr->format = format;
- hdr->dataSize = dataSize;
- hdr->bitRate = bitRate;
- hdr->samples = (u8*)hdr + hdr->headerSize;
- smp = hdr->samples;
- #define TO_CONV(_type, _scl_fct, _mod) ( (_type)( tmp[i] _scl_fct _mod ) )
- //convert the f64 samples to the desired format
- switch(hdr->format){ //(hdr->format = format now)
- case SMPFMT_U8 : FOR_TS_BRK( SMPCAST( u8 ) = TO_CONV(u8 , * 127, +128) );
- case SMPFMT_S8 : FOR_TS_BRK( SMPCAST( s8 ) = TO_CONV(s8 , * 127, ) );
- case SMPFMT_U16: FOR_TS_BRK( SMPCAST( u16) = TO_CONV(u16, *32767, +32768) );
- case SMPFMT_S16: FOR_TS_BRK( SMPCAST( s16) = TO_CONV(s16, *32767, ) );
- case SMPFMT_S24: FOR_TS_BRK( SMPCAST(_s24) = to_s24(tmp[i]) );
- case SMPFMT_S32: FOR_TS_BRK( SMPCAST( s32) = TO_CONV(s32, *0x7FFFFFFF, ) );
- case SMPFMT_F32: FOR_TS_BRK( SMPCAST( f32) = TO_CONV(f32, , ) );
- case SMPFMT_F64: mem_copy(smp, tmp, hdr->dataSize); break;
- }
- return true;
- }
- #endif
- #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement