Toggle menu
Toggle preferences menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.
The main server is currently down. We are running on a backup server, so editing and search functionality are temporarily disabled. Please check back in a few hours.

PocketCompiler 3DS: Difference between revisions

From GameBrew
0.38
0.43
Line 6: Line 6:
|lastupdated=2026/07/03
|lastupdated=2026/07/03
|type=Other Apps
|type=Other Apps
|version=0.38
|version=0.43
|license=Apache-2.0
|license=Apache-2.0
|download=https://dlhb.gamebrew.org/3dshomebrews/PocketCompiler3DS.7z
|download=https://dlhb.gamebrew.org/3dshomebrews/PocketCompiler3DS.7z
Line 115: Line 115:


== Changelog ==
== Changelog ==
'''v0.42'''
* '''CSS Transitions'''
** <code>transition: 0.3s ease-in-out</code> now actually animates. When a style property changes on an element with a transition duration, the old and new values are interpolated over the duration using smoothstep easing. Supports 25 numeric properties (opacity, width, height, margins, padding, position, font-size, border, transforms) plus color properties (color, background) which interpolate per-channel. The transition engine runs in the frame loop and marks transitioning nodes dirty so layout re-runs each frame to reflect the changing values.
* '''Box-Shadow'''
** <code>box-shadow: 2px 2px 4px rgba(0,0,0,0.5)</code> is parsed into offset/blur/color and drawn as a semi-transparent rect behind the element before the background fill. No real gaussian blur (3DS hardware can't do that efficiently), but the spread approximation looks reasonable for most UI shadows.
* '''Linear-Gradient Backgrounds'''
** <code>background: linear-gradient(to right, red, blue)</code> is parsed into start/end colors and a direction, then rendered as 16 interpolated color bands. Supports <code>to right/bottom/left/top</code> directions and <code>Ndeg</code> angles. Falls back to solid <code>background</code> color when no gradient is active. Transparent colors work correctly (uses explicit &quot;set&quot; flags instead of checking for zero).
* '''CSS Grid Layout'''
** <code>display: grid</code> with <code>grid-template-columns</code> now lays out children in a grid. Supports fixed pixel widths, <code>fr</code>/<code>auto</code> (equal distribution), and <code>repeat(N, ...)</code> syntax up to 8 columns. Rows auto-size to the tallest cell, gap is applied between cells, and children are vertically centered within their row.
* '''CSS <code>calc()</code>'''
** <code>calc(100% - 20px)</code> is now evaluated at layout time. Supports <code>+</code>, <code>-</code>, <code>*</code>, <code>/</code> with correct operator precedence, and all length units (px, em, rem, vw, vh, %) work inside calc terms. Self-contained in the length parser — no new systems.
* '''Form Submission'''
** Clicking a <code>&lt;button type=&quot;submit&quot;&gt;</code> or <code>&lt;input type=&quot;submit&quot;&gt;</code> inside a <code>&lt;form&gt;</code> now fires the form's <code>onsubmit</code> handler and dispatches a <code>submit</code> event. This replaces the old START-key approach which conflicted with START=exit-run-mode.
* '''Keybind Conflict Fixes'''
** Resolved button assignment conflicts between the app shell and web content event system. In run mode, only DPad (arrow keys) and Y (Space) generate keyboard events for web content. A/B/X/L/R/START are exclusively mouse clicks, cursor lock, and exit-run-mode — no more phantom keydown events alongside mouse clicks.
* '''Bug Fixes'''
** IndexedDB path overflow: <code>store</code>/<code>key</code> strings from JS are now length-validated to prevent path truncation
** IndexedDB <code>get()</code> return logic: was returning true for empty files
** IndexedDB <code>clear()</code> prefix buffer: enlarged from 80 to 128 bytes to handle longer store names
** Transition color precision: RGBA8 colors now stored as uint32 (not float) to avoid precision loss past 2^24
** Gradient transparent-color: <code>0x00000000</code> (transparent) no longer treated as &quot;unset&quot;
'''v0.41'''
* '''<code>&lt;input&gt;</code>/<code>&lt;textarea&gt;</code> text entry'''
** New <code>we_input_prompt()</code> in <code>web_events.c</code> opens the 3DS software keyboard when a click lands on an <code>&lt;input&gt;</code>/<code>&lt;textarea&gt;</code> (or an ancestor of one). Reads the current <code>value</code> attribute, shows it as initial text, writes the result back, fires <code>input</code> + <code>change</code> events, and marks the node dirty so the renderer shows the new text.
** New <code>we_text_input()</code> helper wraps <code>swkbdInit</code>/<code>swkbdInputText</code> for reuse.
* '''CSS <code>transform: translate()</code>'''
** <code>wrender_node</code> now applies <code>translate_x</code>/<code>translate_y</code> to the draw position, and folds the offset into the children's <code>ox</code>/<code>oy</code> so children move with the translated parent. ~6 lines of real logic; the parser already stored the values since v0.39.
* '''Word-wrap in the layout engine'''
** Replaced the naive <code>tw/avail_w + 1</code> character-count wrapping with proper word-boundary wrapping. Walks the text word by word, tracks line width, breaks when the next word would overflow. Hard-breaks words longer than a full line. Respects <code>white-space: pre</code> and <code>nowrap</code>.
* '''CSS <code>:hover</code> / <code>:focus</code> / <code>:nth-child</code> pseudo-classes'''
** New <code>pseudo_matches()</code> function checks <code>:hover</code>, <code>:focus</code>, <code>:active</code>, <code>:checked</code>, <code>:disabled</code>, <code>:first-child</code>, <code>:last-child</code>, <code>:nth-child(n/odd/even)</code>.
** <code>selector_matches()</code> rewritten to split selectors at <code>:</code> and check the pseudo-class after the base selector matches. Supports chained pseudos (<code>a:focus:hover</code>).
** Dynamic re-cascade: <code>we_events_update</code> marks nodes dirty on hover/focus changes; <code>we_update</code> now re-runs <code>css_cascade</code> (not just <code>layout_document</code>) when nodes are dirty, so <code>:hover</code>/<code>:focus</code> styles apply dynamically.
* '''Keyboard input to web content'''
** <code>window.prompt(message, default)</code> now opens the 3DS software keyboard and returns the typed string (was a no-op stub returning <code>undefined</code>).
** Clicking an <code>&lt;input&gt;</code>/<code>&lt;textarea&gt;</code> opens the keyboard (Feature 1 above).
* '''localStorage persistence + IndexedDB completion'''
** '''IndexedDB C API hardened''': <code>ws_idb_open</code> now checks for existing databases with the same name (no duplicates); <code>ws_idb_get</code> validates <code>fread</code> return (was a potential underflow); <code>ws_idb_clear</code> is no longer a no-op — it scans the directory with <code>opendir</code>/<code>readdir</code> and removes all files matching the store prefix; all functions now have proper NULL/bounds checks.
** '''IndexedDB JS bindings''': <code>ws_install_idb</code> now installs a real <code>indexedDB</code> object to JS with <code>open()</code>, <code>put()</code>, <code>get()</code>, <code>delete()</code>, <code>clear()</code>, <code>close()</code> methods. <code>put()</code> JSON-encodes values; <code>get()</code> safely JSON-parses them back (falls back to string if not valid JSON). The &quot;IndexedDB&quot; feature pill is now actually true.
'''v0.38'''
'''v0.38'''
* '''Crash / correctness bugs:'''
* '''Crash / correctness bugs:'''
Line 205: Line 246:


== Credits ==
== Credits ==
PocketCompiler project and idea by PlanetDogeCodes (me). Some browser runtime features, custom Canvas/WebGL Integration, and 3DS Optimizations were all made with help from GPT-5.5 xhigh. Some UI elements and DOM-style event handling were made with help from Claude Sonnet 4.6
PocketCompiler project and idea by PlanetDogeCodes (me). Some browser runtime features, custom Canvas/WebGL Integration, and 3DS Optimizations were all made with help from GPT-5.5 (xhigh) and GLM 5.2 (max). Some UI elements and DOM-style event handling were made with help from Claude Sonnet 4.6


Built with:
Built with:

Revision as of 03:30, 10 July 2026

PocketCompiler
General
AuthorPlanetDogeCodes
TypeOther Apps
Version0.43
LicenseApache-2.0
Last Updated2026/07/03
Links
Download
Website
Source

PocketCompiler is an experimental Nintendo 3DS HTML/JS/CSS compiler and code editor

It's designed to let you write HTML/JS/CSS on the 3DS, allowing for easy development. You can:

  • Edit code on the bottom screen.
  • Preview output/status on the top screen.
  • Save/load projects from the SD card.

The default project path is sdmc:/3ds/PocketCompiler/projects/

Features

  • Basic HTML parsing.
  • Simple CSS.
  • Basic JavaScript runtime capabilities.
  • DOM-like elements.
  • Keyboard/Mouse/Touch events.
  • Nearly complete iframe support.
  • document.write()
  • Limited API and link fetching.
  • IndexedDB-adjacent SD-card storage.
  • Custom Canvas rendering.
  • Custom WebGL rendering.
  • Image loading.
  • Web audio support.

Canvas / WebGL

PocketCompiler has rendering systems for:

  • canvas command buffers
  • rectangles, lines, text, placeholders
  • getContext("webgl") detection
  • buffers
  • shaders/programs
  • uniforms/attributes
  • textures
  • draw calls
  • viewport/depth/blend/scissor state
  • Citro3D backend scaffolding

This is not yet full WebGL.

Storage

PocketCompiler includes SD-card-backed storage systems:

sdmc:/3ds/PocketCompiler/idb/
sdmc:/3ds/PocketCompiler/cache_api/
sdmc:/3ds/PocketCompiler/resource_cache/

Supported or scaffolded:

  • IndexedDB-style databases/object stores
  • putgetdeleteclearcount
  • localStorage-style storage
  • sessionStorage-style storage
  • Cache API-style storage
  • binary-safe values
  • 1 MB per-value/resource cap

Audio

PocketCompiler includes a small Web Audio-style system:

  • AudioContext-like runtime
  • OscillatorNode-like node
  • GainNode-like node
  • sine/square/triangle/sawtooth tones
  • NDSP-backed output when available
  • safe fallback if audio fails

Limitations

PocketCompiler is still in early development.

It does not yet fully support:

  • Complete HTML parsing
  • Full CSS layout/cascade
  • Full modern JavaScript/browser behavior
  • Complete Promise/event-loop behavior
  • Full WebGL 1.0
  • Real GLSL shader translation
  • Full Canvas 2D API
  • Full Web Audio API
  • Full IndexedDB compatibility
  • Complete iframe isolation
  • Pointer lock

The 3DS also has very limited RAM, CPU, GPU power, and screen space, so PocketCompiler uses strict safety limits (1 MB per resource/value/cache entry, bounded event queues, bounded command buffers, bounded editor/runtime structures)

Controls

D-Pad - Arrow key movement

Circle Pad - Move mouse cursor (it's just a dot)

A - Click, Edit code line

B - Undo

X - Save project

Y - Load project

Start - Run/Compile

Select - Show controls menu

Screenshots

PocketCompiler3DS2.png PocketCompiler3DS3.png

Changelog

v0.42

  • CSS Transitions
    • transition: 0.3s ease-in-out now actually animates. When a style property changes on an element with a transition duration, the old and new values are interpolated over the duration using smoothstep easing. Supports 25 numeric properties (opacity, width, height, margins, padding, position, font-size, border, transforms) plus color properties (color, background) which interpolate per-channel. The transition engine runs in the frame loop and marks transitioning nodes dirty so layout re-runs each frame to reflect the changing values.
  • Box-Shadow
    • box-shadow: 2px 2px 4px rgba(0,0,0,0.5) is parsed into offset/blur/color and drawn as a semi-transparent rect behind the element before the background fill. No real gaussian blur (3DS hardware can't do that efficiently), but the spread approximation looks reasonable for most UI shadows.
  • Linear-Gradient Backgrounds
    • background: linear-gradient(to right, red, blue) is parsed into start/end colors and a direction, then rendered as 16 interpolated color bands. Supports to right/bottom/left/top directions and Ndeg angles. Falls back to solid background color when no gradient is active. Transparent colors work correctly (uses explicit "set" flags instead of checking for zero).
  • CSS Grid Layout
    • display: grid with grid-template-columns now lays out children in a grid. Supports fixed pixel widths, fr/auto (equal distribution), and repeat(N, ...) syntax up to 8 columns. Rows auto-size to the tallest cell, gap is applied between cells, and children are vertically centered within their row.
  • CSS calc()
    • calc(100% - 20px) is now evaluated at layout time. Supports +-*/ with correct operator precedence, and all length units (px, em, rem, vw, vh, %) work inside calc terms. Self-contained in the length parser — no new systems.
  • Form Submission
    • Clicking a <button type="submit"> or <input type="submit"> inside a <form> now fires the form's onsubmit handler and dispatches a submit event. This replaces the old START-key approach which conflicted with START=exit-run-mode.
  • Keybind Conflict Fixes
    • Resolved button assignment conflicts between the app shell and web content event system. In run mode, only DPad (arrow keys) and Y (Space) generate keyboard events for web content. A/B/X/L/R/START are exclusively mouse clicks, cursor lock, and exit-run-mode — no more phantom keydown events alongside mouse clicks.
  • Bug Fixes
    • IndexedDB path overflow: store/key strings from JS are now length-validated to prevent path truncation
    • IndexedDB get() return logic: was returning true for empty files
    • IndexedDB clear() prefix buffer: enlarged from 80 to 128 bytes to handle longer store names
    • Transition color precision: RGBA8 colors now stored as uint32 (not float) to avoid precision loss past 2^24
    • Gradient transparent-color: 0x00000000 (transparent) no longer treated as "unset"

v0.41

  • <input>/<textarea> text entry
    • New we_input_prompt() in web_events.c opens the 3DS software keyboard when a click lands on an <input>/<textarea> (or an ancestor of one). Reads the current value attribute, shows it as initial text, writes the result back, fires input + change events, and marks the node dirty so the renderer shows the new text.
    • New we_text_input() helper wraps swkbdInit/swkbdInputText for reuse.
  • CSS transform: translate()
    • wrender_node now applies translate_x/translate_y to the draw position, and folds the offset into the children's ox/oy so children move with the translated parent. ~6 lines of real logic; the parser already stored the values since v0.39.
  • Word-wrap in the layout engine
    • Replaced the naive tw/avail_w + 1 character-count wrapping with proper word-boundary wrapping. Walks the text word by word, tracks line width, breaks when the next word would overflow. Hard-breaks words longer than a full line. Respects white-space: pre and nowrap.
  • CSS :hover / :focus / :nth-child pseudo-classes
    • New pseudo_matches() function checks :hover:focus:active:checked:disabled:first-child:last-child:nth-child(n/odd/even).
    • selector_matches() rewritten to split selectors at : and check the pseudo-class after the base selector matches. Supports chained pseudos (a:focus:hover).
    • Dynamic re-cascade: we_events_update marks nodes dirty on hover/focus changes; we_update now re-runs css_cascade (not just layout_document) when nodes are dirty, so :hover/:focus styles apply dynamically.
  • Keyboard input to web content
    • window.prompt(message, default) now opens the 3DS software keyboard and returns the typed string (was a no-op stub returning undefined).
    • Clicking an <input>/<textarea> opens the keyboard (Feature 1 above).
  • localStorage persistence + IndexedDB completion
    • IndexedDB C API hardenedws_idb_open now checks for existing databases with the same name (no duplicates); ws_idb_get validates fread return (was a potential underflow); ws_idb_clear is no longer a no-op — it scans the directory with opendir/readdir and removes all files matching the store prefix; all functions now have proper NULL/bounds checks.
    • IndexedDB JS bindingsws_install_idb now installs a real indexedDB object to JS with open()put()get()delete()clear()close() methods. put() JSON-encodes values; get() safely JSON-parses them back (falls back to string if not valid JSON). The "IndexedDB" feature pill is now actually true.

v0.38

  • Crash / correctness bugs:
    • Canvas 2D silently broken — wc_install_bindings() built its property-setup script with snprintf into a 512-byte buffer, but the actual script is 854 bytes. It was truncating mid-statement, so ctx.fillStyle = 'red' and every other canvas property setter did nothing, with zero error shown. Now passed as a literal directly to duk_eval_string — no buffer, no truncation possible.
    • Event listeners could misfire — DOMEvent.js_ref was a uint8_t, silently wrapping after the 255th addEventListener() call in a session and firing the wrong callback. Widened to uint16_t.
    • Listener ref counter never reset — it was a function-local static that persisted across every recompile instead of resetting with the fresh Duktape context each page load gets. Moved to file scope with an explicit reset tied to context creation.
    • Unchecked array access in we_document_open() — switched to the existing bounds-checked accessor so a corrupted sibling chain can't read out-of-bounds memory.
  • Stack-safety hardening (3DS has only 256KB of stack):
    • ~3KB of stacked buffers in the CSS parser — css_parse_inline's 2048-byte buffer is called while css_parse_stylesheet's 1024-byte buffer is still live. Both made static (verified safe: parsing is never re-entrant).
    • Unbounded layout recursion — nothing stopped a deeply-nested DOM tree (up to the 1024-node cap) from recursing that many stack frames deep. Added a depth guard capped well above any realistic page.
  • Version v0.37 was skipped due to issues with a beta build.
  • CIA files will be added in version 1.0

v0.36

  • Crash / correctness fixes:
    • editor_find and editor_find_prevstart_line was not clamped before use — with a corrupted or uninitialized value it could make editor_get_line walk off the end of the buffer. Now clamped to [0, total-1].
    • editor_replace_at: added col > llen guard so an exact-end-of-line replacement can't produce a negative memcpy count.
    • we_eval_js: added !g_web_engine.loaded check — without it, a stale non-NULL js_ctx pointer left from a previous we_unload() call could be dereferenced.
    • draw_consolei < WJS_LOG_MAX_LINES guard added — a corrupted g_wjs_log_n could have caused a read past the log array bounds.
  • Compiler warning fixes:
    • (down & KEY_X) && ... — explicit parentheses added (GCC -Wall warning eliminated).
    • Two strcat() calls replaced with strncat().
    • LAYOUT_ED_H corrected to 178.0f (was 180.0f) — the 2px mismatch caused the cursor-to-line mapping to select the wrong line near the bottom of the editor panel.

v0.34

  • Slight UI changes
  • Bordered rendering for text & iframe
  • Memory usage fixes
  • More accurate CSS parsing
File Fixes/Changes
web_layout.c Body avail_w bug fixed: was 2×margin_left, now margin_left + margin_right.
web_layout.c Text node lay_w uses full available container width for alignment.
web_render.c Scale formula size/11.0f → size/30.0f (correct for system font at scale 1.0 ≈ 30px).
web_render.c TEXT nodes use parent container width for proper text alignment.
web_render.c Bottom border drawn on document viewport to frame the output area.
web_engine.c css_apply_ua_defaults() called after css_reset(), before parse — so user styles always win.
web_engine.c RUNNING bar cleaned up; conflicting title bar overlay removed.

v0.33.5

  • Hopefully fixed crashing issues

v0.33.4

  • MAYBE fixed crashing issues (untested, will update when tested)

v0.33.3

  • Fixed surface-level crashing issues

v0.33.2

  • Maybe fixed crashing issues
  • Stability fixes
  • Fixed errors while compiling

v0.33

  • Fixed scrolling
  • Fixed line truncation
  • Added more complete rendering capabilities
  • Added pointer lock integration
  • Added page interaction

v0.32

  • Fixed the HTML rendering engine
  • Slight UI changes

v0.31.1

  • Completely overhauled the UI (AI was used to help with this)
  • New frame buffer that minimizes the visual bug to almost unnoticeable proportions.

Pre-Release v0.30

  • Fixed app crashing on file explorer open (MAYBE FR THIS TIME)
  • Fixed the visual bug (kinda)

Credits

PocketCompiler project and idea by PlanetDogeCodes (me). Some browser runtime features, custom Canvas/WebGL Integration, and 3DS Optimizations were all made with help from GPT-5.5 (xhigh) and GLM 5.2 (max). Some UI elements and DOM-style event handling were made with help from Claude Sonnet 4.6

Built with:

  • Visual Studio Code
  • devkitPro
  • devkitARM
  • libctru
  • Citro2D
  • Citro3D

External links

Advertising: