<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: michel vilain</title>
    <description>The latest articles on DEV Community by michel vilain (@michel_vilain_f1f8e06dc47).</description>
    <link>https://dev.to/michel_vilain_f1f8e06dc47</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4035368%2Fbff610af-85a9-4e71-bcf7-d49e3ed33f63.jpg</url>
      <title>DEV Community: michel vilain</title>
      <link>https://dev.to/michel_vilain_f1f8e06dc47</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/michel_vilain_f1f8e06dc47"/>
    <language>en</language>
    <item>
      <title>Reviving a 20-year-old BASIC — and getting it to run in the browser</title>
      <dc:creator>michel vilain</dc:creator>
      <pubDate>Sat, 18 Jul 2026 13:47:15 +0000</pubDate>
      <link>https://dev.to/michel_vilain_f1f8e06dc47/reviving-a-20-year-old-basic-and-getting-it-to-run-in-the-browser-4mi7</link>
      <guid>https://dev.to/michel_vilain_f1f8e06dc47/reviving-a-20-year-old-basic-and-getting-it-to-run-in-the-browser-4mi7</guid>
      <description>&lt;h2&gt;
  
  
  First, go press a button
&lt;/h2&gt;

&lt;p&gt;Before the story, the thing itself. Open this in a browser tab:&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://uglymike17.github.io/basic256/" rel="noopener noreferrer"&gt;https://uglymike17.github.io/basic256/&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That's the full BASIC256 editor and interpreter — running entirely in your browser, no install, no plugin, no account. Type &lt;code&gt;PRINT "hello"&lt;/code&gt;, hit run. Or load a bundled example straight from the URL: &lt;a href="https://uglymike17.github.io/basic256/?run=mandelbrot" rel="noopener noreferrer"&gt;&lt;code&gt;?run=mandelbrot&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If that feels unremarkable, hang on — a year ago this program didn't build on a modern machine at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  What BASIC256 is
&lt;/h2&gt;

&lt;p&gt;BASIC256 (originally &lt;strong&gt;KidBASIC&lt;/strong&gt;) is an easy, graphical dialect of BASIC built to teach absolute beginners how to program. Three panes: a code editor, a text output console, and a graphics canvas. You write a couple of lines and &lt;em&gt;immediately&lt;/em&gt; see a circle, hear a beep, watch a sprite move. That instant feedback loop is the whole point — it's the on-ramp a lot of us had in the 80s and 90s, rebuilt for kids (and hobbyists) today.&lt;/p&gt;

&lt;p&gt;It had a good run on SourceForge, reached version 2.0.0.11… and then stopped. Development stalled, apparently after a failed attempt to port it to Qt6. A few people tried to pick it up. The code drifted further from what modern toolchains expect every year.&lt;/p&gt;

&lt;p&gt;I decided to have a go at bringing it back. I'll be honest about my qualifications up front, because it matters to the rest of this post: &lt;strong&gt;I'm a hobbyist, not a C++ developer.&lt;/strong&gt; I'm comfortable with project direction, build configuration, and reading code, but I do not write production C++ from scratch. I've leaned heavily on AI tooling to get through the parts that are over my head. If that disqualifies me in your eyes, fair enough — but the thing runs, and I had a lot of fun.&lt;/p&gt;

&lt;h2&gt;
  
  
  The revival, in layers
&lt;/h2&gt;

&lt;p&gt;The one lesson I'd pass on to anyone resurrecting an old codebase: &lt;strong&gt;do it in layers, and never try to modernize everything at once.&lt;/strong&gt; A giant "fix it all" branch becomes a multi-month swamp. Small, verifiable steps kept me sane.&lt;/p&gt;

&lt;p&gt;Roughly the order it happened in:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Get it onto modern infrastructure.&lt;/strong&gt; Migrated the original SVN history to GitHub, then set up continuous integration so &lt;em&gt;every&lt;/em&gt; commit at least tries to build. You can't modernize what you can't build.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. qmake → CMake.&lt;/strong&gt; The old &lt;code&gt;.pro&lt;/code&gt; files were replaced with CMake. I kept qmake working in parallel for a while so I always had a fallback, then removed it once CI was green.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. MinGW → MSVC on Windows.&lt;/strong&gt; The classic "missing &lt;code&gt;libstdc++-6.dll&lt;/code&gt;" deployment pain went away once I moved to MSVC with &lt;code&gt;windeployqt&lt;/code&gt;. Fewer DLL surprises, better tooling.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. One pipeline, four platforms.&lt;/strong&gt; A single GitHub Actions workflow now builds Windows, Linux x86-64, Raspberry Pi (ARM64) and macOS, each gated behind the TestSuite so a broken build can't ship. The Raspberry Pi build was a highlight: GitHub now offers native ARM64 runners, so I could throw out the old QEMU-emulation approach entirely. Linux ships as an AppImage (built with &lt;code&gt;linuxdeploy&lt;/code&gt;), Windows as an NSIS installer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Qt5 → Qt6.&lt;/strong&gt; The big one. This is the migration that had killed the project before. &lt;code&gt;QRegExp&lt;/code&gt; became &lt;code&gt;QRegularExpression&lt;/code&gt;, the multimedia layer was rewritten, and I got bitten by silent traps like a &lt;code&gt;QAudioOutput&lt;/code&gt; that simply produced no sound because it was never explicitly attached to anything. But once it landed, Qt6 unlocked the payoff below.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. WebAssembly.&lt;/strong&gt; Because Qt6 supports WebAssembly, the &lt;em&gt;same&lt;/em&gt; Qt application can be compiled to run in a browser. That's how you get the demo you (hopefully) already clicked.&lt;/p&gt;

&lt;h2&gt;
  
  
  The WebAssembly part, honestly
&lt;/h2&gt;

&lt;p&gt;This is the bit people ask about, so here's what it actually took — including the ugly parts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Keep Qt, keep &lt;code&gt;QString&lt;/code&gt;.&lt;/strong&gt; I didn't rewrite the app for the web. It's Qt-for-WebAssembly: the real interpreter, the real IDE, compiled with Emscripten. No parallel "web version" to maintain.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The interpreter blocks a thread — on purpose.&lt;/strong&gt; BASIC256's interpreter runs on its own &lt;code&gt;QThread&lt;/code&gt; and blocks (a running program should be able to sit in a loop). The browser hates blocking the main thread. The multithreaded Qt WASM build, which needs &lt;code&gt;SharedArrayBuffer&lt;/code&gt;, is what makes this model survive the move.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;SharedArrayBuffer&lt;/code&gt; means COOP/COEP headers — which GitHub Pages won't send.&lt;/strong&gt; To use those threads the page has to be "cross-origin isolated," which requires specific HTTP headers. GitHub Pages doesn't let you set them. The workaround is a service-worker shim (&lt;code&gt;coi-serviceworker&lt;/code&gt;) that injects the headers client-side. Slightly cursed, completely functional.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Some things just can't exist in a browser.&lt;/strong&gt; Six subsystems have no meaning in a sandbox — launching external processes, serial ports, an embedded SQL database, printing, running a TCP server, and OS text-to-speech. Rather than crash, each is stubbed to raise a clean runtime error in the web build, so a program that hits one gets a message instead of a white screen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Audio fought back.&lt;/strong&gt; Getting sound working in the WASM build meant a genuinely annoying &lt;code&gt;makeDynCall&lt;/code&gt; problem, which I ended up solving with direct &lt;code&gt;KEEPALIVE&lt;/code&gt; exports so the audio sink's callbacks survive Emscripten's optimizer. I will not pretend I found that elegant. It works.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Run programs from a link.&lt;/strong&gt; Because "no install" is the superpower, I made programs shareable by URL:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;parameter&lt;/th&gt;
&lt;th&gt;what it runs&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;?run=&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;a bundled Example (e.g. &lt;code&gt;?run=mandelbrot&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;?url=&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;a &lt;code&gt;.kbs&lt;/code&gt; file hosted on the same site&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;?src=&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;the source itself, base64-encoded into the link&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Add &lt;code&gt;&amp;amp;mode=&lt;/code&gt; to pick the window layout (these mirror the desktop command-line switches). &lt;code&gt;?url=&lt;/code&gt; is deliberately restricted to the page's own site, so a link can't point the app at somebody else's server.&lt;/p&gt;

&lt;h2&gt;
  
  
  The reason I actually did this
&lt;/h2&gt;

&lt;p&gt;Underneath the build-system archaeology, I have a soft spot for &lt;strong&gt;creative coding&lt;/strong&gt; — fractals and generative art. BASIC256's immediate canvas is a lovely little playground for it, and being able to hand someone a &lt;em&gt;link&lt;/em&gt; that runs a Julia set in their browser, no setup, is exactly the kind of low-friction magic that got me into programming in the first place.&lt;/p&gt;

&lt;p&gt;So a chunk of the examples lean that way — Julia sets, Strange attractors, Slime-mold simulations, Quiverbloom. Try one, then open the source and change a number. That "change a number, watch the whole picture change" loop is BASIC256 doing what it was always for.&lt;/p&gt;

&lt;h2&gt;
  
  
  Documentation, rebuilt
&lt;/h2&gt;

&lt;p&gt;The original help lived on a DokuWiki I don't control. So I rebuilt it as a Docusaurus site: &lt;strong&gt;&lt;a href="https://uglymike17.github.io/Basic256-Docs" rel="noopener noreferrer"&gt;https://uglymike17.github.io/Basic256-Docs&lt;/a&gt;&lt;/strong&gt;. It's now the in-app online help, and pressing &lt;strong&gt;F1&lt;/strong&gt; on any keyword jumps straight to its page. Migrating hundreds of wiki pages into MDX was its own small adventure of encoding bugs and namespace collisions, but it's a real, searchable docs site now.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's rough (it's a Beta, and I mean it)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;browser build&lt;/strong&gt; can't do the OS-level things listed above; they'll report an error rather than work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;macOS builds currently target Apple Silicon (arm64)&lt;/strong&gt; only.&lt;/li&gt;
&lt;li&gt;It's a Beta. Some behaviour will change before 2.1 final, and there are surely bugs I haven't hit.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's the deal, stated plainly, so nobody feels misled.&lt;/p&gt;

&lt;h2&gt;
  
  
  A note on building this with AI
&lt;/h2&gt;

&lt;p&gt;Since I'm not a C++ developer, this revival simply wouldn't exist without AI assistance — for the Qt6 API changes, the CMake and CI plumbing, and especially the WASM edge cases. I don't think that's something to hide. It's a real example of a non-specialist shipping something non-trivial by pairing domain interest with these tools, and then &lt;em&gt;verifying&lt;/em&gt; the results by actually building and running them across five targets. I learned an enormous amount in the process, which was half the point.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it, break it, tell me
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Run it in your browser:&lt;/strong&gt; &lt;a href="https://uglymike17.github.io/basic256/" rel="noopener noreferrer"&gt;https://uglymike17.github.io/basic256/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Download&lt;/strong&gt; (Windows / Linux x86-64 / Raspberry Pi ARM64 / macOS): &lt;a href="https://github.com/uglymike17/basic256/releases" rel="noopener noreferrer"&gt;https://github.com/uglymike17/basic256/releases&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docs:&lt;/strong&gt; &lt;a href="https://uglymike17.github.io/Basic256-Docs" rel="noopener noreferrer"&gt;https://uglymike17.github.io/Basic256-Docs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Source &amp;amp; issues:&lt;/strong&gt; &lt;a href="https://github.com/uglymike17/basic256" rel="noopener noreferrer"&gt;https://github.com/uglymike17/basic256&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you teach beginners, tinker with retro BASIC, or just want to make a fractal appear in a browser tab in four lines of code, I'd love for you to kick the tyres — and I &lt;em&gt;especially&lt;/em&gt; want to hear what breaks.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>webassembly</category>
      <category>qt</category>
      <category>basic</category>
    </item>
  </channel>
</rss>
