From 0ddbc3e95325c7403921d3670e2aca269a829ab8 Mon Sep 17 00:00:00 2001 From: John Alanbrook Date: Sat, 29 Nov 2025 17:26:29 -0600 Subject: [PATCH] remove more unneeded from the std --- meson.build | 1 - scripts/docstrings.cm | 1129 ------------------------------------ scripts/engine.cm | 20 +- scripts/event.cm | 15 - scripts/graphics.cm | 401 ------------- scripts/io.cm | 159 ----- scripts/json.cm | 21 +- scripts/jswota.cm | 124 ---- scripts/math.cm | 38 -- scripts/mersenne.c | 148 ----- scripts/module_resolver.cm | 94 --- scripts/os.c | 19 +- scripts/patch.ce | 69 --- scripts/resources.cm | 166 ------ scripts/test.ce | 30 - scripts/vendor.ce | 47 -- source/cell.c | 6 +- source/jsffi.c | 25 +- tests/test_actor_access.ce | 18 - tests/test_args.ce | 18 - tests/test_child_actor.ce | 8 - tests/test_event_watch.ce | 38 -- tests/test_module.ce | 15 - tests/test_use_args.ce | 18 - 24 files changed, 33 insertions(+), 2594 deletions(-) delete mode 100644 scripts/docstrings.cm delete mode 100644 scripts/event.cm delete mode 100644 scripts/graphics.cm delete mode 100644 scripts/io.cm delete mode 100644 scripts/jswota.cm delete mode 100644 scripts/math.cm delete mode 100644 scripts/mersenne.c delete mode 100644 scripts/module_resolver.cm delete mode 100644 scripts/patch.ce delete mode 100644 scripts/resources.cm delete mode 100644 scripts/test.ce delete mode 100644 scripts/vendor.ce delete mode 100644 tests/test_actor_access.ce delete mode 100644 tests/test_args.ce delete mode 100644 tests/test_child_actor.ce delete mode 100644 tests/test_event_watch.ce delete mode 100644 tests/test_module.ce delete mode 100644 tests/test_use_args.ce diff --git a/meson.build b/meson.build index e86f04ad..8a09b1f1 100644 --- a/meson.build +++ b/meson.build @@ -238,7 +238,6 @@ src += ['quickjs.c', 'libregexp.c', 'libunicode.c', 'cutils.c', 'dtoa.c'] scripts = [ 'nota.c', 'js.c', - 'mersenne.c', 'qop.c', 'wildstar.c', 'fit.c', diff --git a/scripts/docstrings.cm b/scripts/docstrings.cm deleted file mode 100644 index f2c02640..00000000 --- a/scripts/docstrings.cm +++ /dev/null @@ -1,1129 +0,0 @@ -prosperon.c_types.sprite[cell.DOC] = {} -prosperon.c_types.sprite[cell.DOC][cell.DOC] = `A 'sprite' is a simple struct for 2D drawing. It stores a rectangle (pos + size), -UV coordinates, color, and layer, as well as an associated 'image' object. The sprite -can be drawn via GPU or SDL_Renderer. Freed when no JS references remain. -`; - -prosperon.c_types.sprite[cell.DOC].set_affine = `Update this sprite's position and size from a transform's pos and scale. - -:param transform: The transform whose pos/scale will overwrite the sprite's rect. -:return: None -`; - -prosperon.c_types.sprite[cell.DOC].set_rect = `Set the sprite's rect (x, y, w, h) directly. - -:param rect: An object or array specifying x, y, width, and height. -:return: None -`; - -prosperon.c_types.sprite[cell.DOC].set_image = `Assign or replace the sprite's underlying image. Automatically updates UV if -the image has a 'rect' property. - -:param image: A JS object representing the image (with .texture, .rect, etc.). -:return: None -`; - -prosperon.c_types.sprite[cell.DOC].layer = `Get or set the sprite's z-layer integer. Sprites with higher layers typically -draw on top of lower layers. - -:param value: (when setting) An integer specifying the layer. -:return: The current layer (when getting), or None (when setting). -`; - -prosperon.c_types.sprite[cell.DOC].color = `Get or set the sprite's color tint as [r, g, b, a]. - -:param value: (when setting) An array [r, g, b, a] in the 0.0..1.0 range. -:return: The current color array (when getting), or None (when setting). -`; - - -// -// transform -// -prosperon.c_types.transform[cell.DOC] = {} -prosperon.c_types.transform[cell.DOC][cell.DOC] = `A hierarchical transform storing 3D or 2D position, rotation (as a quaternion), -and scale. Can have a parent transform. Freed automatically on GC. -`; - -prosperon.c_types.transform[cell.DOC].pos = `Get or set the transform's position as a 3D vector [x, y, z]. - -:param value: (when setting) [x, y, z]. -:return: The current position vector (when getting), or None (when setting). -`; - -prosperon.c_types.transform[cell.DOC].scale = `Get or set the transform's scale as a 3D vector [x, y, z]. -For 2D usage, z is often 1. - -:param value: (when setting) [sx, sy, sz]. -:return: The current scale (when getting), or None (when setting). -`; - -prosperon.c_types.transform[cell.DOC].rotation = `Get or set the transform's rotation as a quaternion [x, y, z, w]. -Angles in degrees or radians must first be converted prior to making a quaternion. - -:param value: (when setting) [qx, qy, qz, qw]. -:return: The current quaternion (when getting), or None (when setting). -`; - -prosperon.c_types.transform[cell.DOC].parent = `Get or set the transform's parent. If set, this transform becomes a child of -the parent (re-parenting). Must be another transform object or null. - -:param value: (when setting) Another transform or null. -:return: The current parent transform (when getting), or None (when setting). -`; - -prosperon.c_types.transform[cell.DOC].change_hook = `A user-supplied function that's called whenever the transform's local matrix changes. -If null, no hook is called. - -:param value: (when setting) A function. -:return: The current function or null. -`; - -prosperon.c_types.transform[cell.DOC].trs = `Set the transform's position, rotation, and scale in one call. - -:param pos: [x,y,z] for position, or null to keep existing. -:param quat: [qx,qy,qz,qw] for rotation, or null. -:param scale: [sx,sy,sz] for scale, or null. -:return: None -`; - -prosperon.c_types.transform[cell.DOC].phys2d = `Apply simple 2D velocity and angular velocity to this transform. - -:param velocity: [vx, vy] added to 'pos' each frame. -:param angularVel: A scalar for rotation in (radians/second). -:param dt: The time delta in seconds. -:return: None -`; - -prosperon.c_types.transform[cell.DOC].move = `Translate this transform by the specified vector. - -:param delta: [dx, dy, dz] to add to .pos -:return: None -`; - -prosperon.c_types.transform[cell.DOC].rotate = `Rotate this transform by an axis+angle. - -:param axis: [ax, ay, az] the axis of rotation. -:param angle: The angle in turns or radians (depending on usage). -:return: None -`; - -prosperon.c_types.transform[cell.DOC].angle = `Return the transform's rotation about a specified axis (x, y, or z). -For example, angle([1,0,0]) returns the roll about the X-axis. - -:param axis: Which axis [1,0,0] or [0,1,0] or [0,0,1]. -:return: The numeric angle in 'turns' or radians, depending on usage. -`; - -prosperon.c_types.transform[cell.DOC].lookat = `Rotate this transform so it looks toward the given world position. - -:param target: [x, y, z] position in world coords. -:return: None -`; - -prosperon.c_types.transform[cell.DOC].direction = `Rotate a vector by this transform's rotation, effectively "transforming" -a direction from local space to world space. - -:param localDir: [dx, dy, dz] in local transform coordinates. -:return: [dx', dy', dz'] direction in world space. -`; - -prosperon.c_types.transform[cell.DOC].unit = `Reset position, rotation, and scale to [0,0,0], identity rotation, and [1,1,1]. - -:return: None -`; - -prosperon.c_types.transform[cell.DOC].rect = `Set this transform's pos and scale from a 2D rect object {x, y, w, h}. - -:param rect: Object with .x, .y, .w, .h -:return: None -`; - -prosperon.c_types.transform[cell.DOC].array = `Return this transform's matrix as a 16-element float array in column-major order. - -:return: An array of 16 floats. -`; - -prosperon.c_types.transform[cell.DOC].torect = `Convert transform's 2D position/scale to a rect {x, y, w, h}. -Rotation is currently ignored. - -:return: A rect object {x, y, w, h}. -`; - -prosperon.c_types.transform[cell.DOC].children = `Return an array of child transforms belonging to this transform. - -:return: An array of transform objects. -`; - - -// -// font -// -prosperon.c_types.font[cell.DOC] = {} -prosperon.c_types.font[cell.DOC][cell.DOC] = `A bitmap or TTF-based font object storing glyph data. -Used for measuring/drawing text. Freed when GC sees no references. -`; - -prosperon.c_types.font[cell.DOC].linegap = `Get or set the font's additional line spacing above the built-in metrics. - -:param value: (when setting) The new line gap. -:return: The current line gap (when getting), or None (when setting). -`; - -prosperon.c_types.font[cell.DOC].height = `The baseline-to-baseline height in pixels. - -:return: The font's total height in px. -`; - -prosperon.c_types.font[cell.DOC].ascent = `How far above the baseline the font extends. - -:return: A scalar float for ascent. -`; - -prosperon.c_types.font[cell.DOC].descent = `How far below baseline the font extends. - -:return: A scalar float for descent. -`; - -prosperon.c_types.font[cell.DOC].text_size = `Measure a piece of text's width/height when rendered with this font. - -:param text: The string to measure. -:param letterSpacing: Extra spacing between characters. -:param wrap: If nonzero, word-wrap to this maximum width. -:return: [width, height] as a float array. -`; - - -// -// datastream -// -prosperon.c_types.datastream[cell.DOC]= {} -prosperon.c_types.datastream[cell.DOC][cell.DOC] = `A streaming media handle, typically for MPEG video. Freed automatically. -`; - -prosperon.c_types.datastream[cell.DOC].time = `Return the current playback time in seconds. - -:return: Current time as a float in seconds. -`; - -prosperon.c_types.datastream[cell.DOC].seek = `Seek to the specified time (in seconds). - -:param seconds: The time to jump to in the stream. -:return: None -`; - -prosperon.c_types.datastream[cell.DOC].advance = `Advance by a certain number of seconds, decoding video as needed. - -:param seconds: The amount of time to skip forward. -:return: None -`; - -prosperon.c_types.datastream[cell.DOC].duration = `Return the total duration of the video stream, in seconds, if known. - -:return: Float seconds duration, or 0 if unknown. -`; - -prosperon.c_types.datastream[cell.DOC].framerate = `Return the framerate (FPS) of the stream if known. - -:return: Float frames per second, or 0 if unknown. -`; - -prosperon.c_types.datastream[cell.DOC].callback = `A function to call whenever a new frame is decoded. If not set, no callback is invoked. - -:param fn: (when setting) A function that receives (surface). -:return: The existing function or null if none. -`; - - -// -// rtree -// -prosperon.c_types.rtree[cell.DOC] = {} -prosperon.c_types.rtree[cell.DOC][cell.DOC] = `An R-tree for spatial lookups. Insert bounding boxes, query by bounding box, etc. -`; - -prosperon.c_types.rtree[cell.DOC].add = `Insert an object that has a 'rect' property {x, y, w, h} into the tree. - -:param obj: The object to add (must have rectAtom). -:return: None -`; - -prosperon.c_types.rtree[cell.DOC].delete = `Remove an object from the tree. Must match the same rect as used when adding. - -:param obj: The object to remove. -:return: None -`; - -prosperon.c_types.rtree[cell.DOC].query = `Return an array of objects whose bounding boxes intersect the given rect. - -:param rect: {x, y, w, h} bounding region to query. -:return: Array of objects that overlap that region. -`; - -prosperon.c_types.rtree[cell.DOC].size = `Indicates how many items are stored in the rtree. - -:return: Integer count of items in the tree. -`; - -prosperon.c_types.rtree[cell.DOC].forEach = `Call a function for every item in the rtree. - -:param callback: A function called with no arguments, or possibly (item). -:return: None -`; - -prosperon.c_types.rtree[cell.DOC].has = `Return true if the specified object is in the tree, false otherwise. - -:param obj: The object to check. -:return: True if found, else false. -`; - -prosperon.c_types.rtree[cell.DOC].values = `Return an array of all items currently in the rtree. - -:return: Array of all stored objects. -`; - - -// -// PHYSFS_File -// -prosperon.c_types.PHYSFS_File[cell.DOC] = {} -prosperon.c_types.PHYSFS_File[cell.DOC][cell.DOC] = `A file handle opened via PhysFS for writing or reading. Freed automatically when references go away. -`; - -prosperon.c_types.PHYSFS_File[cell.DOC].close = `Close this file handle. Throws on error. - -:return: None -`; - -prosperon.c_types.PHYSFS_File[cell.DOC].write = `Write data (string or ArrayBuffer) to the file. Throws on error. - -:param data: The data to write (string or ArrayBuffer). -:return: None -`; - -prosperon.c_types.PHYSFS_File[cell.DOC].buffer = `Enable an internal write buffer of the given size on this file. - -:param size: Size in bytes of the buffer. -:return: None -`; - -prosperon.c_types.PHYSFS_File[cell.DOC].tell = `Return the current position in the file. - -:return: A numeric offset. -`; - -prosperon.c_types.PHYSFS_File[cell.DOC].eof = `Return whether the file pointer is at end-of-file. - -:return: True if at EOF, false otherwise. -`; - - -// -// SDL_Camera -// -prosperon.c_types.SDL_Camera[cell.DOC] = {} -prosperon.c_types.SDL_Camera[cell.DOC][cell.DOC] = `A handle to a physical camera device. Freed when references drop or camera is closed. -`; - -prosperon.c_types.SDL_Camera[cell.DOC].frame = `Acquire the latest camera frame (as an SDL_Surface). Returns null if no -new frame is available yet. Throws on error. - -:return: SDL_Surface or null. -`; - -prosperon.c_types.SDL_Camera[cell.DOC].release_frame = `Release a frame surface previously acquired via camera.frame(). Must be -done for each acquired frame. - -:param surface: The surface to release. -:return: None -`; - - -// -// SDL_Cursor -// -prosperon.c_types.SDL_Cursor[cell.DOC] = {} -prosperon.c_types.SDL_Cursor[cell.DOC][cell.DOC] = `An SDL cursor handle. Freed automatically on GC. No direct methods. -`; - -// -// SDL_Window -// -prosperon.c_types.SDL_Window[cell.DOC] = {} -prosperon.c_types.SDL_Window[cell.DOC][cell.DOC] = `An application window, created via prosperon.engine_start or SDL calls. Freed on GC. -`; - -prosperon.c_types.SDL_Window[cell.DOC].fullscreen = `Toggle fullscreen mode for this window (SDL_WINDOW_FULLSCREEN). - -:return: None -`; - -prosperon.c_types.SDL_Window[cell.DOC].make_renderer = `Create an SDL_Renderer for 2D rendering tied to this window. - -:param name: The renderer driver name, e.g. "opengl" (may be optional). -:return: An SDL_Renderer object. -`; - -prosperon.c_types.SDL_Window[cell.DOC].make_gpu = `Create an SDL_GPUDevice for low-level GPU rendering on this window. - -:param debug: If true, enable debugging in the GPU device. -:param driverName: The GPU back-end driver, e.g. "opengl". -:return: An SDL_GPUDevice. -`; - -prosperon.c_types.SDL_Window[cell.DOC].keyboard_shown = `Return whether the on-screen keyboard is visible (mobile/tablet). - -:return: True if shown, false otherwise. -`; - -prosperon.c_types.SDL_Window[cell.DOC].theme = `Currently returns null. Placeholder for retrieving OS window theme info. - -:return: null -`; - -prosperon.c_types.SDL_Window[cell.DOC].safe_area = `Return a rect describing any OS-specific "safe" region for UI, e.g. on iPhone with a notch. - -:return: A rect object {x, y, w, h}. -`; - -prosperon.c_types.SDL_Window[cell.DOC].bordered = `Enable or disable window borders. - -:param flag: True to show borders, false to hide. -:return: None -`; - -prosperon.c_types.SDL_Window[cell.DOC].set_icon = `Set the window's icon from an SDL_Surface. - -:param surface: An SDL_Surface holding the icon. -:return: None -`; - -prosperon.c_types.SDL_Window[cell.DOC].mouse_grab = `Grab or ungrab the mouse for this window (so the pointer won't leave). - -:param flag: True to grab mouse input, false to release. -:return: None -`; - -prosperon.c_types.SDL_Window[cell.DOC].title = `Get or set the window's title text in the title bar. - -:param newTitle: (when setting) A string title. -:return: The current title if getting, or None if setting. -`; - -prosperon.c_types.SDL_Window[cell.DOC].size = `Get or set the window's size as [width, height]. - -:param newSize: (when setting) e.g. [640, 480] -:return: The current [width, height] or None if setting. -`; - - -// -// SDL_Renderer -// -prosperon.c_types.SDL_Renderer[cell.DOC] = {} -prosperon.c_types.SDL_Renderer[cell.DOC][cell.DOC] = `A 2D rendering context using the SDL renderer API. Freed automatically. -`; - -prosperon.c_types.SDL_Renderer[cell.DOC].draw_color = `Set the render draw color for subsequent primitive calls (rect, line, etc.). - -:param color: [r, g, b, a] in 0..1. -:return: None -`; - -prosperon.c_types.SDL_Renderer[cell.DOC].present = `Display whatever has been rendered (swap buffers). Must be called each frame. - -:return: None -`; - -prosperon.c_types.SDL_Renderer[cell.DOC].clear = `Clear the current render target with the renderer's draw color. - -:return: None -`; - -prosperon.c_types.SDL_Renderer[cell.DOC].rect = `Draw one or more outlines of rectangles. - -:param rectOrArray: A single rect {x,y,w,h} or an array of rects. -:param color: Optional [r,g,b,a]. If provided, overrides current draw color. -:return: None -`; - -prosperon.c_types.SDL_Renderer[cell.DOC].fillrect = `Fill one or more rectangles with the renderer's current color or an optional override. - -:param rectOrArray: A single rect {x,y,w,h} or an array of rects. -:param color: Optional [r,g,b,a]. -:return: None -`; - -prosperon.c_types.SDL_Renderer[cell.DOC].line = `Draw a sequence of lines connecting points in an array. - -:param points: An array of [x,y] points. Lines connect consecutive points. -:param color: Optional [r,g,b,a]. -:return: None -`; - -prosperon.c_types.SDL_Renderer[cell.DOC].point = `Draw a list of points (pixels). - -:param points: An array of [x,y] positions. -:param color: Optional [r,g,b,a]. -:return: None -`; - -prosperon.c_types.SDL_Renderer[cell.DOC].load_texture = `Create an SDL_Texture from a given SDL_Surface for use with this renderer. - -:param surface: An SDL_Surface. -:return: An SDL_Texture object. -`; - -prosperon.c_types.SDL_Renderer[cell.DOC].texture = `Draw a texture onto the render target. - -:param tex: The SDL_Texture to draw. -:param dstRect: The destination rect {x, y, w, h}. -:param srcRect: Optional portion of the texture to draw {x, y, w, h}. -:param color: Optional color mod [r,g,b,a]. -:return: None -`; - -prosperon.c_types.SDL_Renderer[cell.DOC].slice9 = `Draw a texture with 9-slice scaling. The argument includes edges {l, r, t, b} -for the corners/borders that remain unscaled. The rest is tiled or stretched. - -:param tex: The SDL_Texture. -:param dstRect: Destination region {x, y, w, h}. -:param edges: {l, r, t, b} for corner sizes in pixels. -:param srcRect: Optional portion in the texture. -:return: None -`; - -prosperon.c_types.SDL_Renderer[cell.DOC].tile = `Tile a texture repeatedly within the specified region. Optionally use a srcRect. - -:param tex: The SDL_Texture to tile. -:param dstRect: The region to fill {x, y, w, h}. -:param srcRect: Optional portion of texture. -:param scale: A float scale factor for each tile. -:return: None -`; - -prosperon.c_types.SDL_Renderer[cell.DOC].get_image = `Read back the rendered pixels into a new SDL_Surface. If rect is null, capture entire output. - -:param rect: Optional {x,y,w,h}. -:return: An SDL_Surface with the requested region's pixels. -`; - -prosperon.c_types.SDL_Renderer[cell.DOC].fasttext = `Draw debug text using an internal fast path. Typically used for quick debugging overlays. - -:param text: The string to draw. -:param pos: The [x, y] position to draw text. -:param color: Optional [r,g,b,a]. -:return: None -`; - -prosperon.c_types.SDL_Renderer[cell.DOC].geometry = `Render custom geometry from a mesh object {pos, uv, color, indices, count} with an optional texture. - -:param texture: The SDL_Texture or null. -:param meshObject: The geometry data with typed arrays. -:return: None -`; - -prosperon.c_types.SDL_Renderer[cell.DOC].scale = `Set a scaling factor for all subsequent rendering on this renderer. - -:param scaleVec2: [sx, sy] scaling factors. -:return: None -`; - -prosperon.c_types.SDL_Renderer[cell.DOC].logical_size = `Set a "logical" size that the renderer will scale to. -For example, (320, 240) can auto-scale up to the window resolution. - -:param size: [width, height]. -:return: None -`; - -prosperon.c_types.SDL_Renderer[cell.DOC].viewport = `Set the clipping viewport for rendering. Pass null to use the full render target. - -:param rect: {x, y, w, h}, or null. -:return: None -`; - -prosperon.c_types.SDL_Renderer[cell.DOC].clip = `Set or clear the clipping rectangle for drawing. Pass null to clear. - -:param rect: {x, y, w, h} or null. -:return: None -`; - -prosperon.c_types.SDL_Renderer[cell.DOC].vsync = `Enable or disable vertical sync. This may have no effect depending on the driver. - -:param flag: True or false. -:return: None -`; - -prosperon.c_types.SDL_Renderer[cell.DOC].coords = `Convert window coordinates to this renderer's coordinate space. - -:param pos: [x, y] in window space. -:return: [x, y] in renderer coordinate space. -`; - -prosperon.c_types.SDL_Renderer[cell.DOC].camera = `Set up a basic 2D camera matrix from a given transform. If 'centered' is true, -the origin is the center of the viewport, else top-left. - -:param cameraTransform: The transform whose pos is used. -:param centered: Boolean true or false. -:return: None -`; - -prosperon.c_types.SDL_Renderer[cell.DOC].get_viewport = `Return the current viewport rect. - -:return: {x, y, w, h} -`; - -prosperon.c_types.SDL_Renderer[cell.DOC].screen2world = `Convert a screen coordinate to world space based on the current camera transform. - -:param pos: [x, y] screen coords -:return: [wx, wy] in world space -`; - -prosperon.c_types.SDL_Renderer[cell.DOC].target = `Set or clear the current render target texture. Pass null to reset to the default/window. - -:param texture: An SDL_Texture or null -:return: None -`; - -prosperon.c_types.SDL_Renderer[cell.DOC].make_sprite_mesh = `Generate a mesh from an array of sprite objects, combining their positions, UVs, -and colors into a single geometry block. - -:param sprites: An array of sprite-like objects. -:return: A 'mesh' object with pos, uv, color, indices, etc. -`; - - -// -// SDL_Texture -// -prosperon.c_types.SDL_Texture[cell.DOC] = {} -prosperon.c_types.SDL_Texture[cell.DOC][cell.DOC] = `A 2D GPU-accelerated texture for rendering with SDL_Renderer. Freed automatically. -`; - -prosperon.c_types.SDL_Texture[cell.DOC].mode = `Set texture scale mode or filtering mode (nearest/linear). - -:param mode: A string or numeric mode to set (e.g., 'linear'). -:return: None -`; - -// -// SDL_Surface -// -prosperon.c_types.SDL_Surface[cell.DOC] = {} -prosperon.c_types.SDL_Surface[cell.DOC][cell.DOC] = `A software (CPU) image in memory. Freed when references vanish. Typically converted -to SDL_Texture for drawing, or used as raw pixel data. -`; - -prosperon.c_types.SDL_Surface[cell.DOC].blit = `Blit (copy) another surface onto this surface, scaling if needed. - -:param dstRect: Destination {x, y, w, h} -:param srcSurface: The source SDL_Surface -:param srcRect: {x, y, w, h} portion from source -:return: None -`; - -prosperon.c_types.SDL_Surface[cell.DOC].scale = `Return a new SDL_Surface scaled to [width, height] using linear filtering. - -:param newSize: [width, height] -:return: A new SDL_Surface with the scaled result. -`; - -prosperon.c_types.SDL_Surface[cell.DOC].fill = `Fill the entire surface with a single color. - -:param color: [r, g, b, a] in 0..1 -:return: None -`; - -prosperon.c_types.SDL_Surface[cell.DOC].rect = `Fill a sub-rectangle of the surface with a color. - -:param rect: {x, y, w, h} -:param color: [r, g, b, a] -:return: None -`; - -prosperon.c_types.SDL_Surface[cell.DOC].dup = `Make a copy of this surface in RGBA format. - -:return: A new SDL_Surface copy. -`; - - -// -// SDL_GPUDevice -// -prosperon.c_types.SDL_GPUDevice[cell.DOC] = {} -prosperon.c_types.SDL_GPUDevice[cell.DOC][cell.DOC] = `A handle for low-level GPU operations via SDL GPU. Freed on GC. -`; - -prosperon.c_types.SDL_GPUDevice[cell.DOC].claim_window = `Claim an existing SDL_Window so this GPU device can render to it. - -:param window: The SDL_Window to attach. -:return: None -`; - -prosperon.c_types.SDL_GPUDevice[cell.DOC].make_pipeline = `Create a new graphics pipeline from a descriptor object specifying shaders, -blend states, vertex format, etc. - -:param pipelineDesc: An object containing pipeline fields (vertexShader, blend, etc.). -:return: A SDL_GPUGraphicsPipeline handle. -`; - -prosperon.c_types.SDL_GPUDevice[cell.DOC].compute_pipeline = `Create a compute pipeline from a descriptor (shader code, threadgroup sizes, etc.). - -:param desc: An object with shader code, thread counts, etc. -:return: SDL_GPUComputePipeline handle. -`; - -prosperon.c_types.SDL_GPUDevice[cell.DOC].set_swapchain = `Specify how the swapchain (final rendered image) is composed, e.g. 'sdr', 'hdr', -and present mode like 'vsync' or 'immediate'. - -:param composition: E.g. 'sdr', 'linear', or 'hdr'. -:param presentMode: E.g. 'vsync', 'immediate', 'mailbox'. -:return: None -`; - -prosperon.c_types.SDL_GPUDevice[cell.DOC].sort_sprite = `A comparator function used for sorting sprite objects by layer, y, and texture. -Usually used internally. - -:param a: A sprite object. -:param b: Another sprite object. -:return: <0, 0, or >0 for sort ordering. -`; - -prosperon.c_types.SDL_GPUDevice[cell.DOC].make_sampler = `Create a sampler object specifying filtering, wrapping, anisotropy, etc. - -:param samplerDesc: An object with min_filter, mag_filter, etc. -:return: SDL_GPUSampler handle. -`; - -prosperon.c_types.SDL_GPUDevice[cell.DOC].load_texture = `Upload an SDL_Surface into a GPU texture, optionally compressing with DXT. Freed automatically. - -:param surface: An SDL_Surface. -:param compressionLevel: 0=none, 1=DXT1 or DXT5, 2=high quality, etc. -:return: SDL_GPUTexture -`; - -prosperon.c_types.SDL_GPUDevice[cell.DOC].texture = `Create a GPU texture with the specified format usage. - -:param desc: Object with {width, height, layers, type, format, usage, etc.} -:return: SDL_GPUTexture -`; - -prosperon.c_types.SDL_GPUDevice[cell.DOC].make_quad = `Return a simple 2-triangle quad geometry covering [0,1]x[0,1]. -Useful for post-processing passes. - -:return: A mesh {pos, uv, color, indices}. -`; - -prosperon.c_types.SDL_GPUDevice[cell.DOC].driver = `Return the name of the underlying GPU driver in use (e.g. 'OpenGL'). - -:return: A string with driver name. -`; - -prosperon.c_types.SDL_GPUDevice[cell.DOC].make_shader = `Compile raw shader code (vertex or fragment) in e.g. SPIR-V, MSL, or DXIL format. - -:param desc: {code:ArrayBuffer, stage:'vertex'|'fragment', format:'spv'|..., entrypoint:'main', ...} -:return: SDL_GPUShader object -`; - -prosperon.c_types.SDL_GPUDevice[cell.DOC].acquire_cmd_buffer = `Obtain a new command buffer for recording GPU commands. Must be submitted or canceled. - -:return: SDL_GPUCommandBuffer handle -`; - -prosperon.c_types.SDL_GPUDevice[cell.DOC].upload = `Upload CPU data into a list of GPU buffers, optionally reusing or returning a -transfer buffer. Typically you provide (cmdBuf, arrayOfTypedArrays, [transferBuffer]). - -:param cmdBuffer: The command buffer in which to record copy commands. -:param buffers: An array of typed-array data to upload, each must have a 'gpu' property or so. -:param transferBuffer: Optional existing GPU transfer buffer to reuse. -:return: The transfer buffer used or newly created. -`; - -prosperon.c_types.SDL_GPUDevice[cell.DOC].wait_for_fences = `Wait on an array of GPU fence objects, optionally requiring all or any. - -:param fences: An array of SDL_GPUFence objects. -:param waitAll: Boolean, true to wait for all fences, false for any. -:return: True if fences signaled, false on timeout or error. -`; - -prosperon.c_types.SDL_GPUDevice[cell.DOC].query_fence = `Check if the given fence has been signaled yet. Non-blocking. - -:param fence: SDL_GPUFence handle -:return: True if signaled, false if still pending -`; - -prosperon.c_types.SDL_GPUDevice[cell.DOC].shader_format = `Return an array of supported GPU shader binary formats (like 'spv', 'dxbc', etc.). - -:return: Array of strings naming supported formats. -`; - -prosperon.c_types.SDL_GPUDevice[cell.DOC].slice9 = `Generate a 9-slice tiling geometry in one shot. For advanced usage with GPU pipeline. - -:param texture: An SDL_GPUTexture -:param dstRect: The rectangle {x, y, w, h} -:param edges: {l, r, t, b} edge sizes -:return: A mesh object -`; - -prosperon.c_types.SDL_GPUDevice[cell.DOC].tile = `Generate geometry to tile a texture portion inside a dest rect. -Often used for repeating backgrounds. - -:param texture: The SDL_GPUTexture -:param srcRect: The portion to tile in pixels -:param dstRect: Where to fill -:param tileInfo: e.g. {repeat_x:true, repeat_y:true} -:return: A mesh object -`; - - -// -// SDL_GPUCommandBuffer -// -prosperon.c_types.SDL_GPUCommandBuffer[cell.DOC] = {} -prosperon.c_types.SDL_GPUCommandBuffer[cell.DOC][cell.DOC] = `A command buffer that accumulates rendering, copy, and compute operations. Freed after submission or GC. -`; - -prosperon.c_types.SDL_GPUCommandBuffer[cell.DOC].render_pass = `Begin a render pass with color/depth attachments. Provide an object with -'color_targets' and optional 'depth_stencil'. Returns an SDL_GPURenderPass handle. - -:param passDesc: {color_targets:[...], depth_stencil:...} -:return: SDL_GPURenderPass -`; - -prosperon.c_types.SDL_GPUCommandBuffer[cell.DOC].compute_pass = `Begin a compute pass reading/writing given arrays of textures and buffers. - -:param storageTextures: array of read/write textures -:param storageBuffers: array of read/write buffers -:return: SDL_GPUComputePass -`; - -prosperon.c_types.SDL_GPUCommandBuffer[cell.DOC].swapchain_pass = `Begin a render pass that directly targets the swapchain (the window). Clears -with the specified color. - -:param clearColor: [r,g,b,a] -:return: SDL_GPURenderPass -`; - -prosperon.c_types.SDL_GPUCommandBuffer[cell.DOC].acquire_swapchain = `Acquire the current swapchain texture from the window. Internal usage. - -:return: SDL_GPUTexture handle -`; - -prosperon.c_types.SDL_GPUCommandBuffer[cell.DOC].bind_vertex_buffer = `Bind a GPU buffer as the vertex buffer at a given slot. - -:param slot: Integer slot index. -:param buffer: The SDL_GPUBuffer. -:return: None -`; - -prosperon.c_types.SDL_GPUCommandBuffer[cell.DOC].bind_index_buffer = `Bind a GPU buffer as the index buffer (16-bit or 32-bit). - -:param buffer: The SDL_GPUBuffer. -:param offset: Optional offset in bytes. -:return: None -`; - -prosperon.c_types.SDL_GPUCommandBuffer[cell.DOC].bind_fragment_sampler = `Bind a texture+sampler pair to a particular fragment shader slot. - -:param slot: Index of the sampler binding. -:param texture: The SDL_GPUTexture -:param sampler: The SDL_GPUSampler -:return: None -`; - -prosperon.c_types.SDL_GPUCommandBuffer[cell.DOC].push_vertex_uniform_data = `Push raw data to a vertex shader uniform block. - -:param slot: The uniform buffer slot. -:param data: An ArrayBuffer with the data to upload. -:return: None -`; - -prosperon.c_types.SDL_GPUCommandBuffer[cell.DOC].push_fragment_uniform_data = `Push raw data to a fragment shader uniform block. - -:param slot: The uniform buffer slot index. -:param data: An ArrayBuffer with uniform data. -:return: None -`; - -prosperon.c_types.SDL_GPUCommandBuffer[cell.DOC].push_compute_uniform_data = `Push raw data to a compute shader uniform buffer. - -:param slot: The uniform buffer slot. -:param data: An ArrayBuffer with the data. -:return: None -`; - -prosperon.c_types.SDL_GPUCommandBuffer[cell.DOC].submit = `Submit this command buffer to the GPU and return a fence for synchronization. - -:return: An SDL_GPUFence -`; - -prosperon.c_types.SDL_GPUCommandBuffer[cell.DOC].cancel = `Cancel (discard) this command buffer without submitting. - -:return: None -`; - -prosperon.c_types.SDL_GPUCommandBuffer[cell.DOC].camera = `Write a camera transform (projection/view) to a uniform slot for 3D or 2D usage. - -:param cameraTransform: A camera object or transform with .pos, fov, etc. -:param uniformSlot: The integer uniform buffer slot to which data is pushed. -:return: None -`; - -prosperon.c_types.SDL_GPUCommandBuffer[cell.DOC].hud = `Write an orthographic full-screen "HUD" matrix to a uniform slot. Typically used -for 2D overlays. - -:param sizeVec2: [width, height] of the viewport area. -:param uniformSlot: The integer uniform buffer slot. -:return: None -`; - -prosperon.c_types.SDL_GPUCommandBuffer[cell.DOC].push_debug_group = `Push a named debug group marker onto the GPU command list (for debuggers/profilers). - -:param name: The debug label string. -:return: None -`; - -prosperon.c_types.SDL_GPUCommandBuffer[cell.DOC].pop_debug_group = `Pop the most recent debug group marker. - -:return: None -`; - -prosperon.c_types.SDL_GPUCommandBuffer[cell.DOC].debug_label = `Insert a one-off debug label at the current spot in the command list. - -:param label: The debug label string -:return: None -`; - -prosperon.c_types.SDL_GPUCommandBuffer[cell.DOC].blit = `Blit one GPU texture to another with optional flip mode, filter, and clear operations. - -:param blitDesc: { src:{texture,mip_level, etc}, dst:{texture,...}, load_op, flip, filter, clear_color:[r,g,b,a] } -:return: None -`; - - -// -// SDL_GPURenderPass -// -prosperon.c_types.SDL_GPURenderPass[cell.DOC] = {} -prosperon.c_types.SDL_GPURenderPass[cell.DOC][cell.DOC] = `A single pass of drawing commands with color/depth attachments. Freed after end() or GC. -`; - -prosperon.c_types.SDL_GPURenderPass[cell.DOC].bind_pipeline = `Bind a previously created graphics pipeline (shaders, states, vertex layouts, etc.). - -:param pipeline: The SDL_GPUGraphicsPipeline -:return: None -`; - -prosperon.c_types.SDL_GPURenderPass[cell.DOC].viewport = `Set the viewport for clipping or scaling draws, in pass-local coordinates. - -:param rect: {x,y,w,h} -:return: None -`; - -prosperon.c_types.SDL_GPURenderPass[cell.DOC].scissor = `Set a scissor rectangle for discarding pixels outside it. - -:param rect: {x,y,w,h} -:return: None -`; - -prosperon.c_types.SDL_GPURenderPass[cell.DOC].draw = `Issue a non-indexed draw call. - -:param primitiveType: e.g. SDL_GPU_PRIMITIVETYPE_TRIANGLELIST -:param baseVertex: Starting vertex offset. -:param firstVertex: The first vertex to draw. -:param vertexCount: How many vertices to draw. -:return: None -`; - -prosperon.c_types.SDL_GPURenderPass[cell.DOC].draw_indexed = `Issue an indexed draw call from the bound index buffer. - -:param primitiveType: The primitive type constant. -:param baseVertex: Offset in the vertex buffer. -:param firstIndex: Which index to start from. -:param indexCount: Number of indices to draw. -:param instanceCount: For instanced drawing, or 1 if normal. -:return: None -`; - -prosperon.c_types.SDL_GPURenderPass[cell.DOC].end = `End this render pass, finalizing the draw operations. - -:return: None -`; - -prosperon.c_types.SDL_GPURenderPass[cell.DOC].bind_index_buffer = `Bind an index buffer inside this pass, possibly overriding the global one. - -:param buffer: The SDL_GPUBuffer -:param elementSize16bit: If 2, uses 16-bit indices; if 4, uses 32-bit indices -:return: None -`; - -prosperon.c_types.SDL_GPURenderPass[cell.DOC].bind_buffers = `Bind multiple vertex buffers at consecutive slots. - -:param firstSlot: The starting vertex buffer slot. -:param arrayOfBuffers: An array of GPUBuffer objects -:return: None -`; - -prosperon.c_types.SDL_GPURenderPass[cell.DOC].bind_samplers = `Bind multiple texture/sampler pairs to either vertex or fragment slots. - -:param vertexOrFragment: Boolean, true for vertex stage, false for fragment. -:param firstSlot: The first sampler slot to bind. -:param samplerBindings: An array of {texture, sampler}. -:return: None -`; - -prosperon.c_types.SDL_GPURenderPass[cell.DOC].bind_storage_buffers = `Bind one or more storage buffers for read/write in the pipeline. - -:param firstSlot: Starting buffer slot index. -:param buffers: An array of SDL_GPUBuffer objects. -:return: None -`; - -prosperon.c_types.SDL_GPURenderPass[cell.DOC].bind_storage_textures = `Bind one or more storage textures for read/write in the pipeline. - -:param firstSlot: Starting texture slot index. -:param textures: An array of SDL_GPUTexture objects. -:return: None -`; - -// -// SDL_GPUComputePass -// -prosperon.c_types.SDL_GPUComputePass[cell.DOC] = {} -prosperon.c_types.SDL_GPUComputePass[cell.DOC][cell.DOC] = `A compute pass for dispatching compute pipelines. Freed after end() or GC. -`; - -prosperon.c_types.SDL_GPUComputePass[cell.DOC].dispatch = `Dispatch the compute pipeline with the specified threadgroup counts. - -:param x: Number of groups in X dimension -:param y: Number of groups in Y dimension -:param z: Number of groups in Z dimension -:return: None -`; - -prosperon.c_types.SDL_GPUComputePass[cell.DOC].end = `End this compute pass. - -:return: None -`; - -prosperon.c_types.SDL_GPUComputePass[cell.DOC].pipeline = `Bind a compute pipeline in this pass. - -:param computePipeline: The SDL_GPUComputePipeline -:return: None -`; - -prosperon.c_types.SDL_GPUComputePass[cell.DOC].samplers = `Bind a set of texture/sampler pairs for compute usage. - -:param arrayOfSamplerBindings: e.g. [ {texture, sampler}, ...] -:param firstSlot: The starting sampler slot. -:return: None -`; - -prosperon.c_types.SDL_GPUComputePass[cell.DOC].storage_buffers = `Bind an array of storage buffers for the compute shader. - -:param arrayOfBuffers: The buffers -:param firstSlot: Starting binding slot. -:return: None -`; - -prosperon.c_types.SDL_GPUComputePass[cell.DOC].storage_textures = `Bind an array of storage textures for the compute shader. - -:param arrayOfTextures: The textures -:param firstSlot: Starting binding slot -:return: None -`; - - -// -// SDL_GPUCopyPass -// -prosperon.c_types.SDL_GPUCopyPass[cell.DOC] = {} -prosperon.c_types.SDL_GPUCopyPass[cell.DOC][cell.DOC] = `A pass for CPU<->GPU or GPU<->GPU copy operations. No direct JS API besides internal usage. -`; - -// -// SDL_GPUFence -// -prosperon.c_types.SDL_GPUFence[cell.DOC] = {} -prosperon.c_types.SDL_GPUFence[cell.DOC][cell.DOC] = `A GPU fence for synchronization. Created upon commandBuffer.submit(). -Wait or query it with device.wait_for_fences or device.query_fence. -`; - -// -// SDL_GPUTransferBuffer -// -prosperon.c_types.SDL_GPUTransferBuffer[cell.DOC] = {} -prosperon.c_types.SDL_GPUTransferBuffer[cell.DOC][cell.DOC] = `A staging buffer used for copying data to or from GPU buffers/textures. Typically -allocated/used internally by device.upload(...). -`; - -// -// SDL_GPUShader -// -prosperon.c_types.SDL_GPUShader[cell.DOC] = {} -prosperon.c_types.SDL_GPUShader[cell.DOC][cell.DOC] = `A single compiled shader (vertex or fragment) in a GPU-friendly format -(e.g., SPIR-V, MSL). Combined into a pipeline for drawing. -`; - -// -// SDL_GPUSampler -// -prosperon.c_types.SDL_GPUSampler[cell.DOC] = {} -prosperon.c_types.SDL_GPUSampler[cell.DOC][cell.DOC] = `Defines how a texture is sampled (filter mode, address mode, anisotropy, compare op, etc.). -`; - -// -// SDL_GPUGraphicsPipeline -// -prosperon.c_types.SDL_GPUGraphicsPipeline[cell.DOC] = {} -prosperon.c_types.SDL_GPUGraphicsPipeline[cell.DOC][cell.DOC] = `Encapsulates vertex+fragment shaders, blend/cull states, and vertex attribute layouts. -Created via device.make_pipeline(...). -`; - -// -// SDL_GPUComputePipeline -// -prosperon.c_types.SDL_GPUComputePipeline[cell.DOC] = {} -prosperon.c_types.SDL_GPUComputePipeline[cell.DOC][cell.DOC] = `Encapsulates a compute shader program plus associated resource layouts. -Created via device.compute_pipeline(...). -`; - - -// Document the main prosperon object -prosperon[cell.DOC] = { - doc: `The main prosperon object providing event dispatch, signal handling, and engine management.`, - DOC: `Symbol used to store documentation references on objects.`, - on: `Register a callback function for a given event type. Returns a function to remove the callback.`, - dispatch: `Dispatch an event of the given type, calling all registered callbacks with the provided data.`, - PATH: `Array of directory paths that Prosperon will search to find scripts or modules.`, - c_types: `Prototype objects for all present defined c-types (like sprite, transform, etc)` -} - -// Document the actor object/prototype -actor[cell.DOC] = { - doc: `The actor object/prototype, serving as a base for all game actors or entities.`, - spawn: `Create a new actor from a script, optionally applying a config object, then call the new actor's 'awake' method.`, - kill: `Destroy this actor, removing it from the game along with all underlings. Frees resources and triggers garbage if defined.`, - clear: `Remove all child (underling) actors by calling kill on each.`, - delay: `Schedule a function to be called after a specified delay (in seconds) on this actor.`, - toString: `Return the script filename associated with this actor instance.` -} - -// Expand console.doc to document the console object and missing methods -console[cell.DOC] = {} -console[cell.DOC][cell.DOC] = `The console object provides various logging, debugging, and output methods.` -console[cell.DOC].spam = `Output a spam-level message for very verbose logging.` -console[cell.DOC].debug = `Output a debug-level message.` -console[cell.DOC].panic = `Output a panic-level message and exit the program.` -console[cell.DOC].assert = `If the condition is false, print an error and panic.` - -// Document the Register object -Register[cell.DOC] = { - doc: `Factory for creating and managing event registries (e.g. update, draw, etc.) within Prosperon.`, - add_cb: `Create or retrieve a registry for an event type, exposing a 'register' method for callbacks.`, - pull_registers: `Gather the names of all recognized event methods implemented by an object.`, - register_obj: `Bind an object's event method to the relevant registry. The unregistration handle goes in the actor's timers.`, - check_registers: `Automatically register recognized events (like 'update', 'gui', etc.) on an object.`, -} - -use[cell.DOC] = 'Return the value from the provided path to a module.' diff --git a/scripts/engine.cm b/scripts/engine.cm index 1978c267..b96e7cc8 100644 --- a/scripts/engine.cm +++ b/scripts/engine.cm @@ -1,16 +1,22 @@ (function engine() { -globalThis.cell = prosperon cell.DOC = Symbol() var ACTORDATA = cell.hidden.actorsym var SYSYM = '__SYSTEM__' -// Get hidden modules from cell.hidden before stripping it var hidden = cell.hidden var os = hidden.os; -var use_dyn = hidden.use_dyn -var dylib_ext = hidden.dylib_ext -var load_internal = hidden.load_internal +cell.os = null + + +var dylib_ext +switch(os.platform()) { + case 'Windows': dylib_ext = '.dll'; break; + case 'Darwin': dylib_ext = '.dylib'; break; + case 'Linux': dylib_ext = '.so'; break; +} + +var load_internal = os.load_internal function use_embed(name) { return load_internal(`js_${name}_use`) @@ -21,8 +27,6 @@ var wota = use_embed('wota') var nota = use_embed('nota') var enet = use_embed('enet') var fd = use_embed('fd') -var os = use_embed('os') -var console_mod = use_embed('console') var ENETSERVICE = 0.1 var REPLYTIMEOUT = 60 // seconds before replies are ignored @@ -141,8 +145,6 @@ var qop = use_embed('qop') var core_qop = qop.open(hidden.core_qop_blob) var utf8 = use_embed('utf8') -delete cell.hidden - function disrupt(err) { if (overling) { diff --git a/scripts/event.cm b/scripts/event.cm deleted file mode 100644 index 9b597683..00000000 --- a/scripts/event.cm +++ /dev/null @@ -1,15 +0,0 @@ -var event = this - -event.push_event[cell.DOC] = `Push a custom user event into SDL's queue, passing a callback function. - -:param event: A function to call when this event is consumed. -:return: None -` - -event.engine_input[cell.DOC] = `Poll all system events (keyboard, mouse, etc.) and call the given function with each event object. - -:param callback: A function that executes on each event consumed from the poll. -:return: None -` - -return event diff --git a/scripts/graphics.cm b/scripts/graphics.cm deleted file mode 100644 index 4ff7a118..00000000 --- a/scripts/graphics.cm +++ /dev/null @@ -1,401 +0,0 @@ -var graphics = this - -var io = use('cellfs') -var time = use('time') -var res = use('resources') -var json = use('json') -var os = use('os') -var staef = use('staef') -var qoi = use('qoi') - -var LASTUSE = Symbol() -var LOADING = Symbol() - -var cache = {} - -// cpu is the surface -graphics.Image = function(surfaceData) { - this.cpu = surfaceData || null; - this.texture = 0; - this.surface = this.cpu; - this.width = surfaceData?.width || 0; - this.height = surfaceData?.height || 0; - this.rect = {x:0, y:0, width:this.width, height:this.height}; - this[LOADING] = false; - this[LASTUSE] = time.number(); -} - -graphics.Image.prototype.unload_cpu = function() { - this.cpu = null; - this.surface = null; -} - -function calc_image_size(img) { - if (!img.rect) return - if (img.texture) { - return [img.texture.width * img.rect.width, img.texture.height * img.rect.height] - } else if (img.cpu) { - return [img.cpu.width * img.rect.width, img.cpu.height * img.rect.height] - } - return [0, 0] -} - -function decorate_rect_px(img) { - // default UV rect is the whole image if none supplied - img.rect ??= {x:0, y:0, width:1, height:1} // [u0,v0,uw,vh] in 0-1 - - var width = 0, height = 0; - if (img.texture) { - width = img.texture.width; - height = img.texture.height; - } else if (img.cpu) { - width = img.cpu.width; - height = img.cpu.height; - } else { - return; - } - - // store pixel-space version: [x, y, w, h] in texels - img.rect_px = { - x:Math.round(img.rect.x * width), - y:Math.round(img.rect.y * height), - width:Math.round(img.rect.width * width), - height:Math.round(img.rect.height * height) - } -} - -function make_handle(obj) -{ - var img = new graphics.Image(obj); - decorate_rect_px(img); - return img; -} - -function wrapSurface(surf, maybeRect){ - def h = make_handle(surf); - if(maybeRect) h.rect = maybeRect; /* honour frame sub-rect */ - return h; -} -function wrapFrames(arr){ /* [{surface,time,rect}, …] → [{image,time}] */ - return arr.map(f => { - // Handle both surface objects and objects with surface property - var surf = f.surface || f; - return { - image: wrapSurface(surf), - time: f.time || 0, - rect: f.rect /* keep for reference */ - } - }); -} -function makeAnim(frames, loop=true){ - return { frames, loop } -} - -function decode_image(bytes, ext) -{ - switch(ext) { - case 'gif': return graphics.make_gif(bytes) // returns array of surfaces - case 'ase': - case 'aseprite': return graphics.make_aseprite(bytes) - case 'qoi': return qoi.decode(bytes) // returns single surface - default: - // Try QOI first since it's fast to check - var qoi_result = qoi.decode(bytes) - if (qoi_result) return qoi_result - // Fall back to make_texture for other formats - return graphics.image_decode(bytes) // returns single surface - } -} - -function create_image(path){ - try{ - def bytes = io.slurpbytes(path); - - let raw = decode_image(bytes, path.ext()); - - /* ── Case A: single surface (from make_texture) ────────────── */ - if(raw && raw.width && raw.pixels && !Array.isArray(raw)) { - return new graphics.Image(raw) - } - - /* ── Case B: array of surfaces (from make_gif) ────────────── */ - if(Array.isArray(raw)) { - // Single frame GIF returns array with one surface - if(raw.length == 1 && !raw[0].time) { - return new graphics.Image(raw[0]) - } - // Multiple frames - create animation - return makeAnim(wrapFrames(raw), true); - } - - if(typeof raw == 'object' && !raw.width) { - if(raw.surface) - return new graphics.Image(raw.surface) - - if(raw.frames && Array.isArray(raw.frames) && raw.loop != null) - return makeAnim(wrapFrames(raw.frames), !!raw.loop); - - def anims = {}; - for(def [name, anim] of Object.entries(raw)){ - if(anim && Array.isArray(anim.frames)) - anims[name] = makeAnim(wrapFrames(anim.frames), !!anim.loop); - else if(anim && anim.surface) - anims[name] = new graphics.Image(anim.surface); - } - if(Object.keys(anims).length) return anims; - } - - throw new Error('Unsupported image structure from decoder'); - - }catch(e){ - log.error(`Error loading image ${path}: ${e.message}`); - throw e; - } -} - -var image = {} -image.dimensions = function() { - var width = 0, height = 0; - if (this.texture) { - width = this.texture.width; - height = this.texture.height; - } else if (this.cpu) { - width = this.cpu.width; - height = this.cpu.height; - } - return [width, height].scale([this.rect[2], this.rect[3]]) -} - -var spritesheet -var sheet_frames = [] -var sheetsize = 1024 - -/** -Pack multiple images into a single texture sheet for efficiency. -Currently unimplemented (returns immediately). -*/ -function pack_into_sheet(images) { - return - // This code is currently disabled with an immediate return. - // Implementation details commented out below. -} - -graphics.is_image = function(obj) { - if (obj.texture && obj.rect) return true -} - -graphics.texture_from_data = function(data) -{ - if (!(data instanceof ArrayBuffer)) return null - - var image = graphics.make_texture(data); - var img = make_handle(image) - - if (renderer_actor) img.gpu; - - return img; -} - -graphics.from_surface = function(surf) -{ - return make_handle(surf) -} - -graphics.from = function(id, data) -{ - if (typeof id != 'string') - throw new Error('Expected a string ID') - - if (data instanceof ArrayBuffer) - return graphics.texture_from_data(data) -} - -graphics.texture = function texture(path) { - if (path instanceof graphics.Image) return path - - if (typeof path != 'string') - throw new Error('need a string for graphics.texture') - - var parts = path.split(':') - var id = parts[0] - var animName = parts[1] - var frameIndex = parts[2] - - // Handle the case where animName is actually a frame index (e.g., "gears:0") - if (animName != null && frameIndex == null && !isNaN(parseInt(animName))) { - frameIndex = parseInt(animName) - animName = null - } - - if (!cache[id]) { - var ipath = res.find_image(id) - - if (!ipath) { - // If still not found, return notex - return graphics.texture('notex') - } - - var result = create_image(ipath) - cache[id] = result - } - - var cached = cache[id] - - // No further path specifiers and no frame index - return the whole thing - if (!animName && frameIndex == null) return cached - - // Handle frame index without animation name (e.g., "gears:0") - if (!animName && frameIndex != null) { - // If cached is a single animation (has .frames property) - if (cached.frames && Array.isArray(cached.frames)) { - var idx = parseInt(frameIndex) - if (isNaN(idx)) return cached - // Wrap the index - idx = idx % cached.frames.length - return cached.frames[idx].image - } - // If cached is a single Image, any frame index just returns the image - if (cached instanceof graphics.Image) { - return cached - } - } - - // If cached is a single Image, treat it as a single-frame animation - if (cached instanceof graphics.Image) { - if (frameIndex != null) { - // For single images, any frame index just returns the image - return cached - } - // animName without frameIndex for single image - return as single-frame array - return [cached] - } - - // If cached is a single animation (has .frames property) - if (cached.frames && Array.isArray(cached.frames)) { - if (frameIndex != null) { - var idx = parseInt(frameIndex) - if (isNaN(idx)) return cached - // Wrap the index - idx = idx % cached.frames.length - return cached.frames[idx].image - } - // Just animation name for single animation - return the animation - return cached - } - - // If cached is an object of multiple animations - if (typeof cached == 'object' && !cached.frames) { - var anim = cached[animName] - if (!anim) - throw new Error(`animation ${animName} not found in ${id}`) - - if (frameIndex != null) { - var idx = parseInt(frameIndex) - if (isNaN(idx)) return anim - - if (anim instanceof graphics.Image) { - // Single image animation - any frame index returns the image - return anim - } else if (anim.frames && Array.isArray(anim.frames)) { - // Multi-frame animation - wrap the index - idx = idx % anim.frames.length - return anim.frames[idx].image - } - } - - // Just animation name - return the animation - return anim - } - - return cached -} - -graphics.tex_hotreload = function tex_hotreload(file) { - var basename = file.split('/').pop().split('.')[0] - - // Check if this basename exists in our cache - if (!(basename in cache)) return - - // Find the full path for this image - var fullpath = res.find_image(basename) - if (!fullpath) return - - var img = create_image(fullpath) - var oldimg = cache[basename] - - // Preserve the GPU texture ID if it exists - var oldGPU = oldimg.gpu - - // Update the CPU surface data - oldimg.cpu = img.cpu - oldimg.surface = img.cpu - - // Clear GPU texture to force reload - oldimg.gpu = 0 - oldimg.texture = 0 - oldimg[LOADING] = false - - // Update dimensions - if (img.cpu) { - oldimg.width = img.cpu.width - oldimg.height = img.cpu.height - oldimg.rect = {x:0, y:0, width:img.cpu.width, height:img.cpu.height} - decorate_rect_px(oldimg) - } -} - -/** -Merges specific properties from nv into ov, using an array of property names. -*/ -function merge_objects(ov, nv, arr) { - arr.forEach(x => ov[x] = nv[x]) -} - -/** -Unimplemented function for creating a spritesheet out of multiple images. -*/ -function make_spritesheet(paths, width, height) { - return -} - -/** -Stores previously loaded fonts. Keyed by e.g. "path.ttf.16" -> fontObject. -*/ -var fontcache = {} -var datas = [] - -graphics.get_font = function get_font(path) { - if (typeof path != 'string') return path - var parts = path.split('.') - var size = 16 // default size - if (!isNaN(parts[1])) { - path = parts[0] - size = Number(parts[1]) - } - var fullpath = res.find_font(path) - if (!fullpath) throw new Error(`Cannot load font ${path}`) - - var fontstr = `${fullpath}.${size}` - if (fontcache[fontstr]) return fontcache[fontstr] - - var data = io.slurpbytes(fullpath) - var font = new staef.font(data, size) - - fontcache[fontstr] = font - - return font -} - -graphics.queue_sprite_mesh = function(queue) { - var sprites = queue.filter(x => x.type == 'sprite') - if (sprites.length == 0) return [] - var mesh = graphics.make_sprite_mesh(sprites) - for (var i = 0; i < sprites.length; i++) { - sprites[i].mesh = mesh - sprites[i].first_index = i*6 - sprites[i].num_indices = 6 - } - return [mesh.pos, mesh.uv, mesh.color, mesh.indices] -} - -return graphics diff --git a/scripts/io.cm b/scripts/io.cm deleted file mode 100644 index b8215026..00000000 --- a/scripts/io.cm +++ /dev/null @@ -1,159 +0,0 @@ -var io = this - -function remove_dir(path) { - var files = io.enumerate(path, false) // non-recursive first - - // Delete all files and subdirectories - for (var i = 0; i < files.length; i++) { - var file = files[i] - if (io.is_directory(file)) { - remove_dir(file) // Recurse into subdirectory - } else { - try { - io.rm(file) - } catch (e) { - log.error("Failed to remove " + file + ": " + e) - } - } - } - - // Now remove the empty directory - try { - io.rm(path) - } catch (e) { - log.error("Failed to remove directory " + path + ": " + e) - } -} - -io.rmdir = remove_dir - -io.rm[cell.DOC] = `Remove the file or empty directory at the given path. - -:param path: The file or empty directory to remove. Must be empty if a directory. -:return: None -` - -io.mkdir[cell.DOC] = `Create a directory at the given path. - -:param path: The directory path to create. -:return: None -` - -io.exists[cell.DOC] = `Return a boolean indicating whether the file or directory at the given path exists. - -:param path: The file or directory path to check. -:return: True if the path exists, otherwise false. -` - -io.stat[cell.DOC] = `Return an object describing file metadata for the given path. The object includes -filesize, modtime, createtime, and accesstime. Throw an error if the path does not exist. - -:param path: The file or directory to retrieve metadata for. -:return: An object with metadata (filesize, modtime, createtime, accesstime). -` - -io.slurpbytes[cell.DOC] = `Read the entire file at the given path as a raw ArrayBuffer. Throw on error. - -:param path: The file path to read from. -:return: An ArrayBuffer containing the file’s raw bytes. -` - -io.slurp[cell.DOC] = `Read the entire file at the given path as a string. Throw on error. - -:param path: The file path to read from. -:return: A string with the file’s contents. -` - -io.slurpwrite[cell.DOC] = `Write data (string or ArrayBuffer) to the given file path. Overwrite if it exists. -Throw on error. - -:param data: The data to write (string or ArrayBuffer). -:param path: The file path to write to. -:return: None -` - -io.mount[cell.DOC] = `Mount a directory or archive at the specified mount point. An null mount -point mounts to '/'. Throw on error. - -:param archiveOrDir: The directory or archive to mount. -:param mountPoint: The path at which to mount. If omitted or null, '/' is used. -:return: None -` - -io.unmount[cell.DOC] = `Unmount a previously mounted directory or archive. Throw on error. - -:param path: The directory or archive mount point to unmount. -:return: None -` - -io.writepath[cell.DOC] = `Set the write directory. Subsequent writes will go here by default. Throw on error. - -:param path: The directory path to set as writable. -:return: None -` - -io.match[cell.DOC] = `Return boolean indicating whether the given wildcard pattern matches the provided -string. Dots must match dots. Case is not ignored. - -Patterns can incorporate: -'?' - Matches exactly one character (except leading dots or slashes). -'*' - Matches zero or more characters (excluding path separators). -'**' - Matches zero or more characters, including path separators. -'[abc]' - A bracket expression; matches any single character from the set. Ranges like [a-z], [0-9] also work. -'[[:alpha:]]' - POSIX character classes can be used inside brackets. -'\\' - Backslash escapes the next character. -'!' - If placed immediately inside brackets (like [!abc]), it negates the set. - -:param pattern: The wildcard pattern to compare. -:param string: The string to test against the wildcard pattern. -:return: True if matched, otherwise false. -` - -io.globfs[cell.DOC] = `Return an array of files that do not match any of the provided glob patterns. It -recursively enumerates the filesystem within PHYSFS. Each pattern is treated as an -"ignore" rule, similar to .gitignore usage. - -:param patterns: An array of glob patterns to ignore. Any file matching one of these is skipped. -:return: An array of matching file paths. -` - -io.enumerate[cell.DOC] = `Return an array of files within the given directory, optionally recursing into -subdirectories. - -:param path: The directory to list. -:param recurse: Whether to recursively include subdirectories (true or false). -:return: An array of file (and directory) paths found. -` - -io.basedir[cell.DOC] = `Return the application's base directory (where the executable is located). - -:return: A string with the base directory path. -` - -io.prefdir[cell.DOC] = `Get the user-and-app-specific path where files can be written. - -:param org: The name of your organization. -:param app: The name of your application. -:return: A string with the user's directory path. -` - -io.open[cell.DOC] = `Open a file for writing, returning a file object that can be used for further -operations. Throw on error. - -:param path: The file path to open for writing. -:return: A file object for subsequent write operations. -` - -io.realdir[cell.DOC] = `Return the actual, real directory (on the host filesystem) that contains the given -file path. Return null if not found. - -:param path: The file path whose real directory is requested. -:return: A string with the real directory path, or null. -` - -io.searchpath[cell.DOC] = `Return an array of all directories in the current paths. - -:return: An array of directory paths in the search path. -` - -return io diff --git a/scripts/json.cm b/scripts/json.cm index 9750bd44..412dfe9d 100644 --- a/scripts/json.cm +++ b/scripts/json.cm @@ -1,28 +1,27 @@ var json = {} var utf8 = use('utf8') +var JS = JSON +JSON = null + +// Produce a JSON text from a Javascript object. If a record value, at any level, contains a json() method, it will be called, and the value it returns (usually a simpler record) will be JSONified. +// If the record does not have a json() method, and if whitelist is a record, then only the keys that are associated with true in the whitelist are included. +// If the space input is true, then line breaks and extra whitespace will be included in the text. json.encode = function encode(val,replacer,space = 1,whitelist) { - return JSON.stringify(val, replacer, space) + return JS.stringify(val, replacer, space) } -json.encode[cell.DOC] = `Produce a JSON text from a Javascript object. If a record value, at any level, contains a json() method, it will be called, and the value it returns (usually a simpler record) will be JSONified. - -If the record does not have a json() method, and if whitelist is a record, then only the keys that are associated with true in the whitelist are included. - -If the space input is true, then line breaks and extra whitespace will be included in the text.` - +// The text text is parsed, and the resulting value (usually a record or an array) is returned. +// The optional reviver input is a method that will be called for every key and value at every level of the result. Each value will be replaced by the result of the reviver function. This can be used to reform data-only records into method-bearing records, or to transform date strings into seconds. json.decode = function decode(text,reviver) { if (typeof text != 'string') { text = utf8.decode(text) if (!text) throw new Error("couldn't parse text: not a string") } - return JSON.parse(text,reviver) + return JS.parse(text,reviver) } -json.decode[cell.DOC] = `The text text is parsed, and the resulting value (usually a record or an array) is returned. - -The optional reviver input is a method that will be called for every key and value at every level of the result. Each value will be replaced by the result of the reviver function. This can be used to reform data-only records into method-bearing records, or to transform date strings into seconds.` return json diff --git a/scripts/jswota.cm b/scripts/jswota.cm deleted file mode 100644 index 190da5ad..00000000 --- a/scripts/jswota.cm +++ /dev/null @@ -1,124 +0,0 @@ -var blob = use('blob') -var utf8 = use('utf8') - -var INT = new blob(8, false) -stone(INT) - -var FP_HEADER = new blob(64) -FP_HEADER.write_fit(0,56) -FP_HEADER.write_fit(1,8) -stone(FP_HEADER) - -var ARRAY = new blob(8) -ARRAY.write_fit(2,8) -stone(ARRAY) - -var RECORD = new blob(8) -RECORD.write_fit(3,8) -stone(RECORD) - -var BLOB = new blob(8) -BLOB.write_fit(4,8) -stone(BLOB) - -var TEXT = new blob(8) -TEXT.write_fit(5,8) -stone(TEXT) - -var NULL_SYMBOL = new blob(64) -NULL_SYMBOL.write_fit(0,56) -NULL_SYMBOL.write_fit(7,8) -stone(NULL_SYMBOL) - -var FALSE_SYMBOL = new blob(64) -FALSE_SYMBOL.write_fit(2,56) -FALSE_SYMBOL.write_fit(7,8) -stone(FALSE_SYMBOL) - -var TRUE_SYMBOL = new blob(64) -TRUE_SYMBOL.write_fit(3,56) -TRUE_SYMBOL.write_fit(7,8) -stone(TRUE_SYMBOL) - -var PRIVATE_SYMBOL = new blob(64) -PRIVATE_SYMBOL.write_fit(8,56) -PRIVATE_SYMBOL.write_fit(7,8) -stone(PRIVATE_SYMBOL) - -var SYSTEM_SYMBOL = new blob(64) -SYSTEM_SYMBOL.write_fit(9,56) -SYSTEM_SYMBOL.write_fit(7,8) -stone(SYSTEM_SYMBOL) - -var key_cache = {} - -function encode_key(key) -{ - if (key_cache[key]) - return key_cache[key] - - var encoded_key = utf8.encode(key) - var cached_blob = new blob(64 + encoded_key.length) - cached_blob.write_fit(utf8.byte_length(key), 56) - cached_blob.write_blob(TEXT) - cached_blob.write_blob(encoded_key) - stone(cached_blob) - - key_cache[key] = cached_blob - return cached_blob -} - -function encode_val(b, val) -{ - var type = typeof val - if (type == 'number') { - b.write_blob(FP_HEADER) - b.write_number(val) - } else if (type == 'string') { - b.write_fit(utf8.byte_length(val), 56) - b.write_blob(TEXT) - b.write_blob(utf8.encode(val)) - } else if (type == 'boolean') { - if (val) - b.write_blob(TRUE_SYMBOL) - else - b.write_blob(FALSE_SYMBOL) - } else if (type == 'null') { - b.write_blob(NULL_SYMBOL) - } else if (type == 'object') { - if (Array.isArray(val)) { - b.write_fit(val.length, 56) - b.write_blob(ARRAY) - for (var v of val) - encode_val(b, v) - } else if (val instanceof blob) { - b.write_fit(val.length, 56) - b.write_blob(BLOB) - b.write_blob(val) - } else { - var keys = Object.keys(val) - b.write_fit(keys.length, 56) - b.write_blob(RECORD) - for (var key of keys) { - if (typeof val[key] == 'function') continue - b.write_blob(encode_key(key)) - encode_val(b, val[key]) - } - } - } -} - -function encode(val) -{ - var b = new blob(8*256)// guess a good length - encode_val(b,val) - - return stone(b) -} - -function decode(b) -{ - return null -} - -return { INT, FP_HEADER, ARRAY, RECORD, BLOB, TEXT, NULL_SYMBOL, FALSE_SYMBOL, TRUE_SYMBOL, PRIVATE_SYMBOL, SYSTEM_SYMBOL, encode, decode } \ No newline at end of file diff --git a/scripts/math.cm b/scripts/math.cm deleted file mode 100644 index 8f23d4bf..00000000 --- a/scripts/math.cm +++ /dev/null @@ -1,38 +0,0 @@ -var math = this - -math.dot[cell.DOC] = "Compute the dot product between two numeric arrays, returning a scalar. Extra elements are ignored." -math.project[cell.DOC] = "Project one vector onto another, returning a new array of the same dimension." -math.rotate[cell.DOC] = "Rotate a 2D point (or array of length 2) by the given angle (in turns) around an optional pivot." -math.midpoint[cell.DOC] = "Compute the midpoint of two arrays of numbers. Only the first two entries are used if 2D is intended." -math.reflect[cell.DOC] = "Reflect a vector across a plane normal. Both arguments must be numeric arrays." -math.distance[cell.DOC] = "Compute the Euclidean distance between two numeric arrays of matching length." -math.direction[cell.DOC] = "Compute the normalized direction vector from the first array to the second." -math.angle[cell.DOC] = "Given a 2D vector, return its angle from the X-axis in radians or some chosen units." -math.norm[cell.DOC] = "Return a normalized copy of the given numeric array. For 2D/3D/4D or arbitrary length." -math.angle_between[cell.DOC] = "Compute the angle between two vectors (2D/3D/4D)." -math.lerp[cell.DOC] = "Linear interpolation between two numbers: lerp(a, b, t)." -math.gcd[cell.DOC] = "Compute the greatest common divisor of two integers." -math.lcm[cell.DOC] = "Compute the least common multiple of two integers." -math.clamp[cell.DOC] = "Clamp a number between low and high. clamp(value, low, high)." -math.angledist[cell.DOC] = "Compute the signed distance between two angles in 'turn' units, e.g. 0..1 range." -math.jitter[cell.DOC] = "Apply a random +/- percentage noise to a number. Example: jitter(100, 0.05) -> ~95..105." -math.mean[cell.DOC] = "Compute the arithmetic mean of an array of numbers." -math.sum[cell.DOC] = "Sum all elements of an array of numbers." -math.sigma[cell.DOC] = "Compute standard deviation of an array of numbers." -math.median[cell.DOC] = "Compute the median of an array of numbers." -math.length[cell.DOC] = "Return the length of a vector (i.e. sqrt of sum of squares)." -math.from_to[cell.DOC] = "Return an array of points from a start to an end, spaced out by a certain distance." - -math.TAU = Math.PI * 2; -math.deg2rad = function (deg) { return deg * 0.0174533; }; -math.rad2deg = function (rad) { return rad / 0.0174533; }; -math.turn2rad = function (x) { return x * Math.TAU; }; -math.rad2turn = function (x) { return x / Math.TAU; }; -math.turn2deg = function (x) { return x * 360; }; -math.deg2turn = function (x) { return x / 360; }; - -math.rand_int = function(min, max) { - return Math.floor(Math.random() * (max - min + 1)) + min; -} - -return math diff --git a/scripts/mersenne.c b/scripts/mersenne.c deleted file mode 100644 index 6c522c22..00000000 --- a/scripts/mersenne.c +++ /dev/null @@ -1,148 +0,0 @@ -#include "quickjs.h" -#include "cell.h" -#include -#include "qjs_macros.h" - -// Random number generation constants for MT19937-64 -#define STATE_VECTOR_LENGTH 312 -#define STATE_VECTOR_M 156 -#define NN STATE_VECTOR_LENGTH -#define MM STATE_VECTOR_M -#define MATRIX_A 0xB5026F5AA96619E9ULL -#define UM 0xFFFFFFFF80000000ULL /* Most significant 33 bits */ -#define LM 0x7FFFFFFFULL /* Least significant 31 bits */ - -typedef struct tagMTRand { - uint64_t mt[STATE_VECTOR_LENGTH]; - int32_t index; -} MTRand; - -// Random number generation functions -static void m_seedRand(MTRand* rand, uint64_t seed) { - rand->mt[0] = seed; - for(rand->index = 1; rand->index < NN; rand->index++) { - rand->mt[rand->index] = (6364136223846793005ULL * (rand->mt[rand->index-1] ^ (rand->mt[rand->index-1] >> 62)) + rand->index); - } -} - -static int64_t genRandLong(MTRand* rand) { - int i; - uint64_t x; - static uint64_t mag01[2] = {0ULL, MATRIX_A}; - - if (rand->index >= NN) { /* generate NN words at one time */ - /* if init_genrand64() has not been called, */ - /* a default initial seed is used */ - if (rand->index == NN+1) - m_seedRand(rand, 5489ULL); - - for (i = 0; i < NN-MM; i++) { - x = (rand->mt[i] & UM) | (rand->mt[i+1] & LM); - rand->mt[i] = rand->mt[i+MM] ^ (x>>1) ^ mag01[(int)(x&1ULL)]; - } - for (; i < NN-1; i++) { - x = (rand->mt[i] & UM) | (rand->mt[i+1] & LM); - rand->mt[i] = rand->mt[i+(MM-NN)] ^ (x>>1) ^ mag01[(int)(x&1ULL)]; - } - x = (rand->mt[NN-1] & UM) | (rand->mt[0] & LM); - rand->mt[NN-1] = rand->mt[MM-1] ^ (x>>1) ^ mag01[(int)(x&1ULL)]; - - rand->index = 0; - } - - x = rand->mt[rand->index++]; - - x ^= (x >> 29) & 0x5555555555555555ULL; - x ^= (x << 17) & 0x71D67FFFEDA60000ULL; - x ^= (x << 37) & 0xFFF7EEE000000000ULL; - x ^= (x >> 43); - - return (int64_t)(x & 0x000FFFFFFFFFFFFFULL); /* return 52-bit value safe for JS */ -} - -static double genRand(MTRand* rand) { - /* generates a random number on [0,1)-real-interval */ - return (genRandLong(rand) >> 11) * (1.0/9007199254740992.0); -} - -/* JS Class Definition */ -static JSClassID js_mersenne_class_id; - -static void js_mersenne_finalizer(JSRuntime *rt, JSValue val) { - MTRand *mrand = JS_GetOpaque(val, js_mersenne_class_id); - js_free_rt(rt, mrand); -} - -static JSClassDef js_mersenne_class = { - "Mersenne", - .finalizer = js_mersenne_finalizer, -}; - -static MTRand *js2mersenne(JSContext *js, JSValue v) { - return JS_GetOpaque(v, js_mersenne_class_id); -} - -/* Methods */ -JSC_CCALL(mersenne_get, - MTRand *mrand = js2mersenne(js, self); - if (!mrand) return JS_ThrowTypeError(js, "Invalid mersenne context"); - return JS_NewFloat64(js, genRand(mrand)); -) - -static const JSCFunctionListEntry js_mersenne_funcs[] = { - JS_CFUNC_DEF("get", 0, js_mersenne_get), -}; - -/* Factory Function */ -static JSValue js_mersenne_use_call(JSContext *js, JSValueConst func_obj, - JSValueConst this_val, int argc, JSValueConst *argv) -{ - uint64_t seed; - - if (argc == 0 || JS_IsNull(argv[0])) { - // Use OS random - extern int randombytes(void *buf, size_t n); - randombytes(&seed, 8); - } else { - if (JS_ToFloat64(js, (double*)&seed, argv[0])) { - // Fallback to number if bigint fails or is not provided as bigint - double d; - if (JS_ToFloat64(js, &d, argv[0])) return JS_EXCEPTION; - seed = (uint64_t)d; - } - } - - MTRand *mrand = js_malloc(js, sizeof(MTRand)); - if (!mrand) return JS_ThrowOutOfMemory(js); - - m_seedRand(mrand, seed); - - JSValue obj = JS_NewObjectClass(js, js_mersenne_class_id); - if (JS_IsException(obj)) { - js_free(js, mrand); - return obj; - } - - JS_SetOpaque(obj, mrand); - - // Store seed as a read-only property - JS_DefinePropertyValueStr(js, obj, "seed", - JS_NewFloat64(js, seed), - JS_PROP_ENUMERABLE | JS_PROP_CONFIGURABLE // Read-only (no WRITABLE) - ); - - return obj; -} - -JSValue js_mersenne_use(JSContext *js) -{ - JS_NewClassID(&js_mersenne_class_id); - JS_NewClass(JS_GetRuntime(js), js_mersenne_class_id, &js_mersenne_class); - - JSValue proto = JS_NewObject(js); - JS_SetPropertyFunctionList(js, proto, js_mersenne_funcs, sizeof(js_mersenne_funcs)/sizeof(JSCFunctionListEntry)); - JS_SetClassProto(js, js_mersenne_class_id, proto); - - // Return the factory function - return JS_NewCFunction2(js, js_mersenne_use_call, "mersenne", 1, JS_CFUNC_generic, 0); -} diff --git a/scripts/module_resolver.cm b/scripts/module_resolver.cm deleted file mode 100644 index 9161ccff..00000000 --- a/scripts/module_resolver.cm +++ /dev/null @@ -1,94 +0,0 @@ -// Module resolver for handling different import styles -// Works with the PhysFS mount system set up by shop.js - -var ModuleResolver = {} - -// Resolve module imports according to the specification -ModuleResolver.resolve = function(request, from_path) { - // Handle scheme-qualified imports - if (request.includes('://')) { - var parts = request.split('://') - var scheme = parts[0] - var path = parts[1] - - // Direct mapping to mount points - return '/' + scheme + '/' + path - } - - // Handle relative imports - if (request.startsWith('./') || request.startsWith('../')) { - // Relative imports are resolved from the importing module's directory - if (from_path) { - var dir = from_path.substring(0, from_path.lastIndexOf('/')) - return resolve_relative(dir, request) - } - return request - } - - // Handle bare imports - // PhysFS will search through all mounted directories - // The mount order ensures proper precedence - return request -} - -// Helper to resolve relative paths -function resolve_relative(base, relative) { - var parts = base.split('/') - var rel_parts = relative.split('/') - - for (var i = 0; i < rel_parts.length; i++) { - var part = rel_parts[i] - if (part == '.') { - continue - } else if (part == '..') { - parts.pop() - } else { - parts.push(part) - } - } - - return parts.join('/') -} - -// Get the shop configuration if available -ModuleResolver.get_shop_config = function() { - try { - var shop = use('shop') - if (shop) { - return shop.load_config() - } - } catch (e) { - // Shop not available yet - } - return null -} - -// Check if a bare import should be routed to an alias -ModuleResolver.check_alias = function(request) { - var config = ModuleResolver.get_shop_config() - if (!config) return null - - var first_segment = request.split('/')[0] - - // Check dependencies - if (config.dependencies && config.dependencies[first_segment]) { - return '/' + request - } - - // Check aliases - if (config.aliases && config.aliases[first_segment]) { - var actual = config.aliases[first_segment] - return '/' + actual + request.substring(first_segment.length) - } - - // Check for single-alias fallback - if (config.dependencies && Object.keys(config.dependencies).length == 1) { - // If only one dependency and no local file matches, route there - var only_dep = Object.keys(config.dependencies)[0] - return '/' + only_dep + '/' + request - } - - return null -} - -return ModuleResolver \ No newline at end of file diff --git a/scripts/os.c b/scripts/os.c index 8e82bcf4..31f120da 100644 --- a/scripts/os.c +++ b/scripts/os.c @@ -406,14 +406,12 @@ static JSValue js_os_load_internal(JSContext *js, JSValue self, int argc, JSValu #else handle = dlopen(NULL, RTLD_LAZY); #endif - if (argc < 1) { + if (argc < 1) return JS_ThrowTypeError(js, "load_internal requires a symbol name"); - } const char *symbol_name = JS_ToCString(js, argv[0]); - if (!symbol_name) { + if (!symbol_name) return JS_ThrowTypeError(js, "symbol name must be a string"); - } JSValue (*symbol)(JSContext *js); #if defined(_WIN32) @@ -424,18 +422,9 @@ static JSValue js_os_load_internal(JSContext *js, JSValue self, int argc, JSValu JS_FreeCString(js, symbol_name); - if (!symbol) { - const char *error_msg = "Symbol not found"; -#ifndef _WIN32 - const char *dl_error = dlerror(); - if (dl_error) { - error_msg = dl_error; - } -#endif - return JS_ThrowReferenceError(js, "Failed to get symbol: %s", error_msg); - } + if (!symbol) + return JS_NULL; - // Return the symbol as a pointer value return symbol(js); } diff --git a/scripts/patch.ce b/scripts/patch.ce deleted file mode 100644 index 8ecc030f..00000000 --- a/scripts/patch.ce +++ /dev/null @@ -1,69 +0,0 @@ -// cell patch - Create a patch for a module - -var io = use('cellfs') -var shop = use('shop') - -if (args.length < 1) { - log.console("Usage: cell patch ") - log.console("Example: cell patch jj_mod") - log.console("") - log.console("This creates a patch file in .cell/patches/ that will be") - log.console("applied when building the module.") - $_.stop() - return -} - -var module_name = args[0] - -if (!io.exists('.cell/shop.toml')) { - log.error("No shop.toml found. Run 'cell init' first.") - $_.stop() - return -} - -var config = shop.load_config() -if (!config || !config.dependencies || !config.dependencies[module_name]) { - log.error("Module '" + module_name + "' not found in dependencies") - $_.stop() - return -} - -// Ensure patches directory exists -if (!io.exists('.cell/patches')) { - io.mkdir('.cell/patches') -} - -var patch_file = '.cell/patches/' + module_name + '-fix.patch' - -if (io.exists(patch_file)) { - log.console("Patch already exists: " + patch_file) - log.console("Edit it directly or delete it to create a new one.") - $_.stop() - return -} - -// Create patch template -var patch_template = `# Patch for ${module_name} -# -# To create a patch: -# 1. Make a copy of the module: cp -r .cell/modules/${module_name}@* /tmp/${module_name}-orig -# 2. Edit files in .cell/modules/${module_name}@* -# 3. Generate patch: diff -ruN /tmp/${module_name}-orig .cell/modules/${module_name}@* > ${patch_file} -# -# This patch will be automatically applied during 'cell build' -` - -io.slurpwrite(patch_file, patch_template) - -// Add to shop.toml -if (!config.patches) { - config.patches = {} -} -config.patches[module_name] = patch_file -shop.save_config(config) - -log.console("Created patch skeleton: " + patch_file) -log.console("Follow the instructions in the file to create your patch.") -log.console("The patch will be applied automatically during 'cell build'.") - -$_.stop() \ No newline at end of file diff --git a/scripts/resources.cm b/scripts/resources.cm deleted file mode 100644 index 65916c08..00000000 --- a/scripts/resources.cm +++ /dev/null @@ -1,166 +0,0 @@ -var io = use('cellfs') - -Object.defineProperty(Function.prototype, "hashify", { - value: function () { - var hash = {} - var fn = this - function hashified(...args) { - var key = args[0] - if (hash[key] == null) hash[key] = fn(...args) - return hash[key] - } - return hashified - }, -}) - -// Merge of the old resources.js and packer.js functionalities -var Resources = {} - -// Recognized resource extensions -Resources.scripts = ["js"] -Resources.images = ["qoi", "png", "gif", "jpg", "jpeg", "ase", "aseprite"] -Resources.sounds = ["wav", "flac", "mp3", "qoa"] -Resources.fonts = ["ttf"] - -// Helper function: get extension from path in lowercase (e.g., "image.png" -> "png") -function getExtension(path) { - var idx = path.lastIndexOf('.') - if (idx < 0) return '' - return path.substring(idx + 1).toLowerCase() -} - -// Return true if ext is in at least one of the recognized lists -function isRecognizedExtension(ext) { - if (!ext) return false - if (Resources.scripts.includes(ext)) return true - if (Resources.images.includes(ext)) return true - if (Resources.sounds.includes(ext)) return true - if (Resources.fonts.includes(ext)) return true - if (Resources.lib.includes('.' + ext)) return true // for .so or .dll - return false -} - -function find_in_path(filename, exts = []) { - if (typeof filename != 'string') return null - - if (filename.includes('.')) { - var candidate = filename // possibly need "/" ? - if (io.exists(candidate) && !io.is_directory(candidate)) return candidate - return null - } - - // Only check extensions if exts is provided and not empty - if (exts.length > 0) { - for (var ext of exts) { - var candidate = filename + '.' + ext - if (io.exists(candidate) && !io.is_directory(candidate)) return candidate - } - } else { - // Fallback to extensionless file only if no extensions are specified - var candidate = filename - if (io.exists(candidate) && !io.is_directory(candidate)) return candidate - } - return null -} - -// Return a canonical path (the real directory plus the path) -Resources.canonical = function(file) { - return io.realdir(file) + file -} - -// The resource finders -Resources.find_image = function(file) { - return find_in_path(file, Resources.images) -}.hashify() - -Resources.find_sound = function(file) { - return find_in_path(file, Resources.sounds) -}.hashify() - -Resources.find_script = function(file) { - return find_in_path(file, Resources.scripts) -}.hashify() - -Resources.find_font = function(file) { - return find_in_path(file, Resources.fonts) -}.hashify() - -// .prosperonignore reading helper -function read_ignore(dir) { - var path = dir + '/.prosperonignore' - var patterns = [] - if (io.exists(path)) { - var lines = io.slurp(path).split('\n') - for (var line of lines) { - line = line.trim() - if (!line || line.startsWith('#')) continue - patterns.push(line) - } - } - return patterns -} - -// Return a list of recognized files in the directory (and subdirectories), -// skipping those matched by .prosperonignore. Directory paths are skipped. -Resources.getAllFiles = function(dir = "") { - var patterns = read_ignore(dir) - var all = io.globfs(patterns, dir) - var results = [] - for (var f of all) { - var fullPath = dir + '/' + f - try { - var st = io.stat(fullPath) - // skip directories (filesize=0) or unrecognized extension - if (!st.filesize) continue - var ext = getExtension(f) - if (!isRecognizedExtension(ext)) continue - results.push(fullPath) - } catch(e) {} - } - return results -} -Resources.getAllFiles[cell.DOC] = ` -Return a list of recognized files in the given directory that are not matched by -.prosperonignore, skipping directories. Recognized extensions include scripts, -images, sounds, fonts, and libs. - -:param dir: The directory to search. -:return: An array of recognized file paths. -` - -// Categorize files by resource type -Resources.gatherStats = function(filePaths) { - var stats = { - scripts:0, images:0, sounds:0, fonts:0, lib:0, other:0, total:filePaths.length - } - for (var path of filePaths) { - var ext = getExtension(path) - if (Resources.scripts.includes(ext)) { - stats.scripts++ - continue - } - if (Resources.images.includes(ext)) { - stats.images++ - continue - } - if (Resources.sounds.includes(ext)) { - stats.sounds++ - continue - } - if (Resources.fonts.includes(ext)) { - stats.fonts++ - continue - } - stats.other++ - } - return stats -} -Resources.gatherStats[cell.DOC] = ` -Analyze a list of recognized files and categorize them by scripts, images, sounds, -fonts, libs, or other. Return a stats object with these counts and the total. - -:param filePaths: An array of file paths to analyze. -:return: { scripts, images, sounds, fonts, lib, other, total } -` - -return Resources diff --git a/scripts/test.ce b/scripts/test.ce deleted file mode 100644 index 29541a49..00000000 --- a/scripts/test.ce +++ /dev/null @@ -1,30 +0,0 @@ -// Test runner - runs test suites in parallel and reports results - -var def = arg - -if (arg.length == 0) - arg = [ - 'send', - 'stop', - 'blob', - 'clock', - 'couple', - 'disrupt', - 'empty', // this one should be an error - 'text', - 'http', - 'use', - 'parseq', - 'kill' - ] - -for (var test of def) - $_.start(e => { - - }, 'tests/' + test, $_) - -$_.delay($_.stop, 1) - -$_.receiver(e => { - log.console(json.encode(e)) -}) \ No newline at end of file diff --git a/scripts/vendor.ce b/scripts/vendor.ce deleted file mode 100644 index 54b734a4..00000000 --- a/scripts/vendor.ce +++ /dev/null @@ -1,47 +0,0 @@ -// cell vendor - Copy all dependencies into modules/ for hermetic builds - -var io = use('cellfs') -var shop = use('shop') - -if (!io.exists('.cell/shop.toml')) { - log.error("No shop.toml found. Run 'cell init' first.") - $_.stop() - return -} - -var config = shop.load_config() -if (!config || !config.dependencies) { - log.console("No dependencies to vendor") - $_.stop() - return -} - -log.console("Vendoring dependencies...") - -for (var alias in config.dependencies) { - var locator = config.dependencies[alias] - var parsed = shop.parse_locator(locator) - - if (!parsed) { - log.error("Invalid locator: " + locator) - continue - } - - var module_dir = '.cell/modules/' + alias + '@' + parsed.version - - if (config.replace && config.replace[locator]) { - // Already using local path - log.console(alias + " - using local path: " + config.replace[locator]) - } else if (!io.exists(module_dir)) { - log.console(alias + " - not found at " + module_dir) - log.console(" Run 'cell get " + locator + "' to fetch it") - } else { - log.console(alias + " - already vendored at " + module_dir) - } -} - -log.console("") -log.console("All dependencies are vendored in .cell/modules/") -log.console("This ensures hermetic, reproducible builds.") - -$_.stop() \ No newline at end of file diff --git a/source/cell.c b/source/cell.c index 22348b31..b4ef3fa4 100644 --- a/source/cell.c +++ b/source/cell.c @@ -843,13 +843,13 @@ void script_startup(cell_rt *prt) // Add core QOP blob to hidden JSValue globalThis = JS_GetGlobalObject(js); - JSValue prosp = JS_GetPropertyStr(js, globalThis, "prosperon"); - JSValue hidden = JS_GetPropertyStr(js, prosp, "hidden"); + JSValue cell = JS_GetPropertyStr(js, globalThis, "cell"); + JSValue hidden = JS_GetPropertyStr(js, cell, "hidden"); size_t archive_size = qop_core.data_size - qop_core.files_offset; JSValue blob = js_new_blob_stoned_copy(js, qop_core.data + qop_core.files_offset, archive_size); JS_SetPropertyStr(js, hidden, "core_qop_blob", blob); JS_FreeValue(js, hidden); - JS_FreeValue(js, prosp); + JS_FreeValue(js, cell); JS_FreeValue(js, globalThis); // Find and load engine.cm from QOP archive diff --git a/source/jsffi.c b/source/jsffi.c index f33a86c3..69604738 100644 --- a/source/jsffi.c +++ b/source/jsffi.c @@ -87,14 +87,7 @@ double js2angle(JSContext *js,JSValue v) { return n * HMM_TurnToRad; } -static uint32_t rng_state = 123456789; -static uint32_t xorshift32(){ - uint32_t x = rng_state; - x ^= x << 13; - x ^= x >> 17; - x ^= x << 5; - return rng_state = x; -} +JSValue js_os_use(JSContext *js); void ffi_load(JSContext *js) { @@ -103,19 +96,13 @@ void ffi_load(JSContext *js) JSValue globalThis = JS_GetGlobalObject(js); - JSValue prosp = JS_NewObject(js); - JS_SetPropertyStr(js,globalThis,"prosperon", prosp); + JSValue cell = JS_NewObject(js); + JS_SetPropertyStr(js,globalThis,"cell", cell); JSValue hidden_fn = JS_NewObject(js); - -#if defined(_WIN32) - JS_SetPropertyStr(js, hidden_fn, "dylib_ext", JS_NewString(js, ".dll")); -#elif defined(__APPLE__) - JS_SetPropertyStr(js, hidden_fn, "dylib_ext", JS_NewString(js, ".dylib")); -#else - JS_SetPropertyStr(js, hidden_fn, "dylib_ext", JS_NewString(js, ".so")); -#endif + JS_SetPropertyStr(js, cell, "hidden", hidden_fn); + JS_SetPropertyStr(js, hidden_fn, "os", js_os_use(js)); const char actorsym_script[] = "var sym = Symbol(`actordata`); sym;"; @@ -132,7 +119,5 @@ void ffi_load(JSContext *js) rt->init_wota = NULL; } - JS_SetPropertyStr(js, prosp, "hidden", hidden_fn); - JS_FreeValue(js,globalThis); } diff --git a/tests/test_actor_access.ce b/tests/test_actor_access.ce deleted file mode 100644 index 85228d1f..00000000 --- a/tests/test_actor_access.ce +++ /dev/null @@ -1,18 +0,0 @@ -// Test that actors have access to $_ -log.console("Testing actor access to $_:"); - -// In an actor script, $_ should be available -if (typeof $_ != 'null') { - log.console("✓ Actor has access to $_"); - log.console(" $_.random is a", typeof $_.random); - log.console(" $_.clock is a", typeof $_.clock); - - // Test spawning another actor - var child = this.spawn('test_child_actor'); - - // Test using a module - var testModule = use('test_module'); - log.console("✓ Module loaded, result:", testModule.test()); -} else { - log.error("✗ Actor does NOT have access to $_"); -} \ No newline at end of file diff --git a/tests/test_args.ce b/tests/test_args.ce deleted file mode 100644 index d0438342..00000000 --- a/tests/test_args.ce +++ /dev/null @@ -1,18 +0,0 @@ -// Test module to verify argument passing - -log.console("Test args module loaded"); -log.console("Number of arguments:", arg.length); -log.console("Arguments received:", arg); - -function createMessage(prefix) { - prefix = prefix || "default"; - return prefix + ": " + arg.join(", "); -} - -return { - args: arg, - message: createMessage(arg[0]), - allArgs: function() { - return "All arguments: " + arg.join(", "); - } -}; \ No newline at end of file diff --git a/tests/test_child_actor.ce b/tests/test_child_actor.ce deleted file mode 100644 index 4eddf891..00000000 --- a/tests/test_child_actor.ce +++ /dev/null @@ -1,8 +0,0 @@ -// Child actor test -log.console("Child actor spawned"); - -if (typeof $_ != 'null') { - log.console("✓ Child actor has access to $_"); -} else { - log.error("✗ Child actor does NOT have access to $_"); -} \ No newline at end of file diff --git a/tests/test_event_watch.ce b/tests/test_event_watch.ce deleted file mode 100644 index 38c66e60..00000000 --- a/tests/test_event_watch.ce +++ /dev/null @@ -1,38 +0,0 @@ -// Test event watching functionality -use('input'); - -// Start watching events -input.watch($_); - -$_.receiver(msg => { - if (msg.type) { - log.console("Received event:", msg.type); - - // Log specific event details - switch(msg.type) { - case "key_down": - case "key_up": - log.console(" Key:", msg.key, "Scancode:", msg.scancode, "Down:", msg.down); - break; - case "mouse_motion": - log.console(" Mouse position:", msg.pos, "Delta:", msg.d_pos); - break; - case "mouse_button_down": - case "mouse_button_up": - log.console(" Button:", msg.button, "Position:", msg.mouse, "Down:", msg.down); - break; - } - - // Stop watching after receiving 10 events - if (!$_.event_count) $_.event_count = 0; - $_.event_count++; - - if ($_.event_count >= 10) { - log.console("Received 10 events, stopping watch"); - input.unwatch($_); - } - } -}); - -log.console("Event watcher started. Press keys or move mouse to generate events."); -log.console("Will stop after 10 events."); \ No newline at end of file diff --git a/tests/test_module.ce b/tests/test_module.ce deleted file mode 100644 index be0ea6c3..00000000 --- a/tests/test_module.ce +++ /dev/null @@ -1,15 +0,0 @@ -// Test module - should NOT have access to $_ - -function test() { - if (typeof $_ != 'null') { - log.error("✗ Module incorrectly has access to $_!"); - return "ERROR: Module has $_ access"; - } else { - log.console("✓ Module correctly does NOT have access to $_"); - return "Module loaded without $_ access"; - } -} - -return { - test: test -}; \ No newline at end of file diff --git a/tests/test_use_args.ce b/tests/test_use_args.ce deleted file mode 100644 index 894ab8e8..00000000 --- a/tests/test_use_args.ce +++ /dev/null @@ -1,18 +0,0 @@ -// Test script to verify use() with arguments - -log.console("Testing use() with arguments:"); - -// Test 1: Load module without arguments -var module1 = use('test_args'); -log.console("Module 1 message:", module1.message); -log.console("Module 1 args:", module1.args); - -// Test 2: Load module with arguments -var module2 = use('test_args', 'hello', 'world', 123); -log.console("Module 2 message:", module2.message); -log.console("Module 2 all args:", module2.allArgs()); - -// Test 3: Verify modules are cached (should return same as module1) -var module3 = use('test_args'); -log.console("Module 3 (cached) message:", module3.message); -log.console("Are module1 and module3 the same?", module1 == module3); \ No newline at end of file