ANTRequest's ANTwasm Specification (Version 0.0.2)

ANT.wasm is a way to make games in WebAssembly and have it run in the ANTRequest Ecosystem. The guiding principle is simple: it either runs in WebAssembly, or it doesnt run at all.

to use ANT.wasm you can use This Specification to insure interoperability. If you do not Like where this is going please fork.

Table Of Contents

Table Of Contents

Status of this document

this document written on is Semantic version 0.0.2. this document is self-published independently.

i am still Figuring things out. this is not final design and might be vague, impossible, or otherwise not implementable. im still seeking to bring this closer to my vision.

This Specification Depends On

This Specification uses external references

WebAssembly

As a refresher here are some concepts you need to know.

Coordinate System

All drawing coordinates and mouse coordinates are in CSS pixels, as defined by the CSS Reference Pixel.

1 CSS pixel is the visual angle of one pixel on a device with a pixel density of 96dpi at arm's length. Edges MUST scale coordinates appropriately for the display's physical pixel density. Games SHOULD NOT assume that 1 CSS pixel equals 1 device pixel.

For example, on a Retina display (2x scaling), a rectangle drawn at draw_rect(0, 0, 100, 100) will occupy 200 device pixels. The game does not need to account for this scaling—the Edge handles it.

Supported Formats

the Following Formats MUST be supported.

the Following Formats MAY be supported too.

Phases

Your Wasm package is called a game. Your Game has the following phases. in order of appearance

NameDescription
Loading Phase Here is where the Edge loads and verifies the ANT.zip. if it is marked as Untrusted the Edge MUST abort proceeding.
Initialization Phase Here is where you Initialize your game before it runs.
game Phase Here is where you let the player play. this is activated by calling start_game.
closing Phase Here is where the Edge cleans up the game's resources.

Internal Abstract Operation

It is assumed Imports and Exports are called to the invoking Wasm Module unless otherwise stated.

If any of the following Invariants are violated, that is a spec bug.

[[%StringFromBytes%]] (of: [[FileHandler]], ptr: i32, len: i32): [[String]]

Do the following in order

  1. Go to ptr (inclusive) until (ptr + len) (exclusive) of of and take the raw bytes as $string.
  2. Assume: $string is the UTF-8 bytes of the intended string.
  3. If $string contains illegal UTF-8 characters return GENERIC_FAILURE (-1).
  4. Return $string.

[[%BytesFromString%]] (string: [[String]]): i32

Do the following in order

  1. Assert: $string is encoded in UTF-8 bytes (is a MUST due to the Foundation's Global Rules).
  2. Set $length to the length of $string in UTF-8 bytes.
  3. If host_malloc is not exported return WASM_PORT_MISSING (-7).
  4. Set $pointer to the result of calling host_malloc with $length.
  5. Write the bytes of $string at $pointer (inclusive) until ($pointer + $length) (exclusive) in the current Wasm Module's Linear Memory.
  6. Return $pointer .

[[%LoadModule%]] (path: [[String]], Imports: [[ImportLibrary]])>: i32

Do the following in order

  1. If Game has Started Return INVALID_GAME_STATE_ERROR (-4).
  2. Resolve $path using ANT.zip's Application Behavior to be $resolved.
  3. If the above step fails return the appropriate Error Code.
  4. If $resolved is not a valid Wasm Module, Return RESOLUTION_ERROR (-3).
  5. Initialize and load $resolved as a Wasm Module with Imports as Imports.
  6. If Initializing and loading fails then return RESOLUTION_ERROR (-3).
  7. add 1 to the integer $wasmModulesLoaded.
  8. call $resolved's exported on_module_load if present with ($wasmModulesLoaded as ModuleId).
  9. Return $wasmModulesLoaded.

Basic Global Library

All Wasm Modules MUST expose or be exposed to the following functions, the Basic Global Library's WASM namespace is BasicGlobalLibrary.

NameTypesImport/ExportDescription
host_malloc (bytes: i32): i32 Export host_malloc MUST return a positive number indicating a pointer ($pointer) on that Wasm's Linear Memory, $pointer until ($pointer + bytes) MUST be free for the Edge to store whatever is the Edge needs. If that fails or there isnt memory to allocate to the Edge, Return the appropriate Error Code.
on_module_load (ModuleId: i32): void Export called when the Wasm Module is loaded via load_module.
tick (delta: f32): void Export for as long as the game is running, this export is called with with delta as the timedelta since the previous call in milliseconds.
current_mouse_press (): i32 Import The Mouse Key Pressed currently. a bitwise flag of the following below
current_mouse_x (): i64 Import The X coordinate of the Mouse. 0, 0 is the top left. X goes positive the more right the mouse is.
current_mouse_y (): i64 Import The X coordinate of the Mouse. 0, 0 is the top left. Y goes positive the more down the mouse is.
current_mouse_wheel (): i32 Import The Mouse's wheel direction. as bitwise flag of the following below
on_key_down (keycode: i32): i32 Export

MUST be called everytime a keyboard key is pressed.

Key codes MUST follow the USB HID Usage Tables specification, using the Usage IDs from the Keyboard/Keypad page (0x07).

Reference: USB HID Usage Tables v1.12, published by the USB Implementers Forum.

on_key_up (keycode: i32): i32 Export MUST be called everytime a keyboard key is released.

Key codes MUST follow the USB HID Usage Tables specification, using the Usage IDs from the Keyboard/Keypad page (0x07).

Reference: USB HID Usage Tables v1.12, published by the USB Implementers Forum.

Mouse bitwise

Mouse Key

NameBitwise
Left Mouse Button 1, (1 << 0) (One)
Right Mouse Button 2, (1 << 1) (Two)
Mouse Wheel Button 4, (1 << 2) (Four)

Mouse Wheel

NameBitwise
Not Scrolling 0 (Zero)
Scrolling Up 8, (1 << 3) (Eight)
Scrolling Down 16, (1 << 4) (SixTeen)

Basic Paint Library

All Wasm Modules MUST expose or be exposed to the following functions too, the Basic Paint Library's WASM namespace is screenpaint.

NameTypesImport/ExportDescription
draw_rect (x: i32, y: i32, w: i32, h: i32, color: i32): i32 Import If Game has not Started Return INVALID_GAME_STATE_ERROR (-4). draw a Rectangle at the offset x (the x/horizontal coordinate), y (the y/vertical coordinate) from the top left which is 0, 0 with color as RGBA8 color. the rectangle MUST be w (width), h (height) in size. Return GENERIC_SUCCESS (0).
draw_path (ptr: i32, len: i32, fillColor: i32, strokeColor: i32, strokeWidth: i32): i32 Import
  • If Game has not Started Return INVALID_GAME_STATE_ERROR (-4).
  • Set $path to Calling [[%StringFromBytes%]] giving the current Wasm Module's Linear Memory, ptr and len.
  • Use an SVG pathing library and parse $path in the same way SVG path d is parsed.
  • If strokeWidth is less than 0 then Set strokeWidth to 0.
  • Draw that shape parsed from the $path above with fillColor as fill, strokeColor as stroke, strokeWidth as stroke-width.
  • Return GENERIC_SUCCESS (0).
load_texture (ptr: i32, len: i32): i32 Import Do the following in order
  1. If Game has not Started Return INVALID_GAME_STATE_ERROR (-4).
  2. Set $path to Calling [[%StringFromBytes%]] giving the current Wasm Module's Linear Memory, ptr and len.
  3. Resolve $path using ANT.zip's Application Behavior to be $resolved.
  4. If $resolved does not point to a valid file, Return PATH_RESOLUTION_ERROR (-2).
  5. If $resolved does not point to a valid image file, Return RESOLUTION_ERROR (-3).
  6. If $resolved does not point to a supported image file, Return RESOLUTION_ERROR (-3).
  7. Create a Texture Handler with $resolved as texture.
  8. Return an Edge-Defined positive nonzero unique for this game session integer representing the Texture Handler created in the previous step.
draw_texture (texture_handler: i32, x: i32, y: i32, w: i32, h: i32, deg: i32): i32 Import Do the following in order
  1. If Game has not Started Return INVALID_GAME_STATE_ERROR (-4).
  2. If texture_handler does not correlate to any files (not counting directories) that were opened Return RESOLUTION_ERROR (-3).
  3. Draw the image of texture_handler at x, y relative to the top left interpreted in css pixels, rotated deg degrees clockwise.
  4. If the above step failed Return SCREEN_DISPLAY_ERROR (-9)
  5. Return GENERIC_SUCCESS (0).
texture_css_height (texture_handler: i32): i32 Import Do the following in order
  1. If Game has not Started Return INVALID_GAME_STATE_ERROR (-4).
  2. If texture_handler does not correlate to any files (not counting directories) that were opened Return RESOLUTION_ERROR (-3).
  3. Return the height of texture_handler in css pixels.
texture_css_width (texture_handler: i32): i32 Import Do the following in order
  1. If Game has not Started Return INVALID_GAME_STATE_ERROR (-4).
  2. If texture_handler does not correlate to any files (not counting directories) that were opened Return RESOLUTION_ERROR (-3).
  3. Return the width of texture_handler in css pixels.
texture_free (texture_handler: i32): i32 Import Do the following in order
  1. If Game has not Started Return INVALID_GAME_STATE_ERROR (-4).
  2. If texture_handler does not correlate to any files (not counting directories) that were opened Return RESOLUTION_ERROR (-3).
  3. Close texture_handler and free it up.
  4. Return GENERIC_SUCCESS (0)

Texture

[[TextureHandler]]

A [[TextureHandler]] is an Edge-Defined opaque identifier representing an image. It MUST:

Main

A Main is a wasm file that is called after a Core. it is the main function.

If we are talking about User Generated Content games, A Core is the actual Game where A Main is the core for a sharable package a user has created.

A Main MUST expose or be exposed to the following functions, the Main's WASM namespace is MainModule.

NameTypesImport/ExportDescription
load_module (ptr: i32, len: i32): i32 Import Do the following in order
  1. If Game has not Started Return INVALID_GAME_STATE_ERROR (-4).
  2. Set $path to Calling [[%StringFromBytes%]] giving the current Wasm Module's Linear Memory, ptr and len.
  3. If $path starts with /core/ (case-insensitive), Return PATH_RESOLUTION_ERROR (-2).
  4. If $path is /core.wasm (case-insensitive), Return PATH_RESOLUTION_ERROR (-2).
  5. If $path is /main.wasm (case-insensitive), Return PATH_RESOLUTION_ERROR (-2).
  6. Return the result of Calling [[%LoadModule%]] given $path and (Basic Global Library as Imports).
start_game (width: i32, height: i32): void Import Do the following in order
  1. Start the Game.
  2. Initialize a Screen (called Canvas) with (width) width and (height) height. if these values are negative or zero abort the game and show an error to the user. then Return SCREEN_DISPLAY_ERROR (-9). if these values cant be used then return SCREEN_DISPLAY_ERROR (-9).
  3. for as long as the game is running, call an export tick with delta as the timedelta since the previous call in milliseconds.
  4. Return the GENERIC_SUCCESS (0).

Cores

A Core is a wasm file that is first called. it is the engine so games can stay self-contained within their ANT.zip. the core MUST live at "/core.wasm" (case-sensitive) ziproot path.

If we are talking about User Generated Content games, A Core is the actual Game where A Main is the core for a sharable package a user has created.

A Core MUST expose or be exposed to the following functions, the Core's WASM namespace is CoreModule.

NameTypesImport/ExportDescription
load_module_core (ptr: i32, len: i32): i32 Import Do the following in order
  1. If Game has Started Return INVALID_GAME_STATE_ERROR (-4).
  2. Set $path to Calling [[%StringFromBytes%]] giving the current Wasm Module's Linear Memory, ptr and len.
  3. If $path is /core.wasm (case-insensitive), Return PATH_RESOLUTION_ERROR (-2).
  4. If $path does not start with /core/ (case-insensitive), Return PATH_RESOLUTION_ERROR (-2).
  5. Return the result of Calling [[%LoadModule%]] given $path and (Basic Global Library as Imports).
load_main (): void Import Do the following in order
  1. If Game has Started Return INVALID_GAME_STATE_ERROR (-4).
  2. Return the result of Calling [[%LoadModule%]] given "/main.wasm" and (Basic Global Library and Main as Imports).

Extensions

File System Extension

the File System Extension is an Extension of the Basic Global Library, anywhere where the Basic Global Library is imported or exported an Edge SHOULD choose to import this too. if they do not wish to implement it then the Methods not implemented MUST be stubbed.

the File System Extension MUST be everywhere it is supposed to be or nowhere, implementing it partially (unless otherwise specified) is a violation of this specification. when it is implemented the Wasm Module MUST be exposed to the following functions, the WASM namespace is FileExtensionV1.

the Game is the Same Game if the sha256 of the ANT.json is the same. the game MUST be verified to be the same game.

NameTypesImport/ExportDescription
file_open (ptr: i32, len: i32): i32 Import Do the following in order
  1. Set $path to Calling [[%StringFromBytes%]] giving the current Wasm Module's Linear Memory, ptr and len.
  2. If $path violates the Rules of ANT.zip's Path Sanitization Behavior, Return PATH_RESOLUTION_ERROR (-2). the exception is that paths are allowed to reference paths outside the ziproot.
  3. If $path doesnt start with one of the defined Virtual Directories, Return PATH_RESOLUTION_ERROR (-2)
  4. Create a [[FileHandler]] and set its $permissions as Defined in the Virtual Directories table.
  5. Return an Edge-Defined positive nonzero unique for this game session integer representing the File Handler created in the previous step. if this $path references the same file the Edge MAY choose to return the same integer.
file_read (file_handler: i32, wasm_ptr: i32, file_ptr: i32, file_len: i32): i32 Import Do the following in order
  1. If file_handler does not correlate to any files (not counting directories) that were opened Return RESOLUTION_ERROR (-3).
  2. Assume: there is no wasm_len due to file_len being free at wasm_ptr.
  3. Go to file_ptr (inclusive) until (file_ptr + file_len) (exclusive) of file_handler's pointed file and take the raw bytes as $bytes.
  4. Go to wasm_ptr (inclusive) until (wasm_ptr + file_len) (exclusive) of the current Wasm Module's Linear Memory and put the raw bytes $bytes there.
  5. Return GENERIC_SUCCESS (0).
file_write (file_handler: i32, wasm_ptr: i32, file_ptr: i32, wasm_len: i32): i32 Import Do the following in order
  1. If file_handler does not correlate to any files (not counting directories) that were opened Return RESOLUTION_ERROR (-3).
  2. Go to wasm_ptr (inclusive) until (wasm_ptr + wasm_len) (exclusive) of the current Wasm Module's Linear Memory take the raw bytes as $bytes.
  3. Go to wasm_ptr (inclusive) until (file_ptr + wasm_len) (exclusive) of file_handler's pointed file and and put the raw bytes $bytes there.
  4. Return GENERIC_SUCCESS (0).
file_type (ptr: i32, len: i32): i32 Import Do the following in order
  1. Set $path to Calling [[%StringFromBytes%]] giving the current Wasm Module's Linear Memory, ptr and len.
  2. If $path violates the Rules of ANT.zip's Application Behavior Return PATH_RESOLUTION_ERROR (-2).
  3. If $path points to a File, Return 1.
  4. If $path points to a Directory, Return 2.
  5. If $path points to a Symlink, Return 0.
  6. If $path doesnt point to anything, Return 0.
  7. Return 0.
file_size (file_handler: i32): i64 Import Do the following in order
  1. If file_handler does not correlate to any files (not counting directories) that were opened Return RESOLUTION_ERROR (-3).
  2. Return the size of file_handler in bytes.
file_close (file_handler: i32): i32 Import Do the following in order
  1. If file_handler does not correlate to any files (not counting directories) that were opened Return RESOLUTION_ERROR (-3).
  2. Close File file_handler.
  3. Return GENERIC_SUCCESS (0).
file_mtime (file_handler: i32): i64 OPTIONAL Import Do the following in order
  1. If file_handler does not correlate to any files (not counting directories) that were opened Return RESOLUTION_ERROR (-3).
  2. If antdatetime.utc_now_ms is stubbed, Return WASM_PORT_MISSING (-7).
  3. Return the mtime of file_handler as milliseconds since the unix epoch. the Edge MAY round the value to reduce fingerprinting. If rounding is applied, the rounded value MUST still be consistent with the actual mtime (e.g., rounded to nearest hour, not arbitrary).

Virtual Directories

Virtual Directories are a security measure to not allow games to write anywhere on the user's file system. currently there are 2

NamePermissionsDescription
/user/ ReadWrite The Game's User Directory. for save files, photos, and anything the game wants to save.
/game/ ReadOnly The Game's Asset Directory. Direct to the ANTzip.

Type Definitions

[[FileHandler]]

An [[FileHandler]] is an Edge-Defined opaque identifier representing an open file. It MUST:

Resource Limits

Edges SHOULD impose limits on:

If a limit is exceeded, the Edge SHOULD return NO_MORE_MEMORY_ERROR (-6) or LACKS_PERMS (-8) as appropriate.

Screen Capture Api Extension

the Screen Capture Api is an Extension of the Basic Global Library, anywhere where the Basic Global Library is imported or exported an Edge SHOULD choose to import this too. if they do not wish to implement it then the Methods not implemented MUST be stubbed.

the Screen Capture Api Extension MUST only be present if the File System Extension is present.

the Screen Capture Api Extension MUST be everywhere it is supposed to be or nowhere, implementing it partially (unless otherwise specified) is a violation of this specification. when it is implemented the Wasm Module MUST be exposed to the following functions, the WASM namespace is screenvideoV1.

NameTypesImport/ExportDescription
take_screenshot (): i32 Import Do the following in order
  1. If the game Has Not started yet, Return INVALID_GAME_STATE_ERROR (-4).
  2. If 5 real time seconds have not past yet since the last call, Return LACKS_PERMS (-8). this cooldown MUST be shared with all Wasm Modules in the game.
  3. Take a screenshot of the Game's Screen and save it to a file. It is very important that you only save the Game's Screen as required for privacy.
  4. Return an Edge-Defined integer representing a file handler of this screenshot according to the File System Extension. MUST be saved in the image/webp format.
start_video_recording (): i32 Import Do the following in order
  1. If the game Has Not started yet, Return INVALID_GAME_STATE_ERROR (-4).
  2. If an Active Video Handler is still open then return LACKS_PERMS (-8).
  3. Return an Edge-Defined integer representing a Video Handler.
take_video_snapshot (video_handler: i32): i32 Import Do the following in order
  1. If the game Has Not started yet, Return INVALID_GAME_STATE_ERROR (-4).
  2. If video_handler does not correlate to any Active Video Handler, Return RESOLUTION_ERROR (-3).
  3. Take a screenshot of the Game's Screen and save it as a video frame. It is very important that you only save the Game's Screen as required for privacy.
  4. Return GENERIC_SUCCESS (0).
stop_video_recording (video_handler: i32): i32 Import Do the following in order
  1. If the game Has Not started yet, Return INVALID_GAME_STATE_ERROR (-4).
  2. If video_handler does not correlate to any Active Video Handler, Return RESOLUTION_ERROR (-3).
  3. convert the video_handler to an image/webm file and store it.
  4. close the video_handler.
  5. If no frames were captured Return GENERIC_SUCCESS (0). No File is created.
  6. open that webm file and Return an Edge-Defined integer representing a [[FileHandler]] of this recording according to the File System Extension. MUST be saved in the image/webm format.

Type Definitions

[[VideoHandler]]

An [[VideoHandler]] is an Edge-Defined opaque identifier representing an active video recording session. It MUST:

[[Canvas]]

A [[Canvas]] is the rendering surface initialized by start_game. It has the following internal properties:

Datetime Api Extension

the Datetime Api is an Extension of the Basic Global Library, anywhere where the Basic Global Library is imported or exported an Edge SHOULD choose to import this too. if they do not wish to implement it then the Methods not implemented MUST be stubbed.

the Datetime Api Extension MUST be everywhere it is supposed to be or nowhere, implementing it partially (unless otherwise specified) is a violation of this specification. when it is implemented the Wasm Module MUST be exposed to the following functions, the WASM namespace is antdatetime.

NameTypesImport/ExportDescription
utc_now_ms (): i64 Import Return the milliseconds since the unix epoch. the Edge MAY round the value to reduce fingerprinting. If rounding is applied, the rounded value MUST still be consistent with the actual mtime (e.g., rounded to nearest hour, not arbitrary).
utc_offset_ms_at (timestamp: i64): i64 Import Return the utc offset in milliseconds at that timestamp in the user's local time. an Edge SHOULD consider rounding it to the nearest 15, 30, or 60 minutes to reduce fingerprinting. an Edge MAY choose to always return 0 instead, representing UTC. Positive for East, Negative for West.

Methods not implemented MUST be stubbed

Any of the following methods not chosen to be implemented MUST return WASM_PORT_MISSING (-7) without doing anything. (including but not limited to)

Error Codes

the following table will list the error codes as negative numbers, their canonical upper snakecase name, and their description.

ANTRequest would like to reserve -1 to -255 for the ANTRequest Specifications. while allowing the community to use -256 to -2 147 483 648 (i32 limit) however they like.

CodeUPPER_CASE_NAMEDescription
0 (Zero)GENERIC_SUCCESSAn Operation completed without any error.
-1 (Negative One)GENERIC_FAILUREA Generic Failure.
-2 (Negative Two)PATH_RESOLUTION_ERRORA path cant be resolved due to any reason, including bt not limited to
-3 (Negative Three)RESOLUTION_ERRORA Path requiring a Wasm Module, but doesnt point to a valid compilable Wasm Module.
-4 (Negative Four)INVALID_GAME_STATE_ERRORthe game is in a invalid state. formerly GAME_HASNT_STARTED_YET_ERROR (-4) and GAME_IS_RUNNING_ERROR (-5)
-5 (Negative Five)RESERVEDreserved for future use.
-6 (Negative Six)NO_MORE_MEMORY_ERRORThe Operation requires more memory but it cant be granted.
-7 (Negative Seven)WASM_PORT_MISSINGAn Import or Export is missing.
-8 (Negative Eight)LACKS_PERMSThe Wasm Module lacks the permissions to perform this action. (or the host lacks the permissions too)
-9 (Negative Nine)SCREEN_DISPLAY_ERRORAn error at the Screen's display happened for any reason.