Screenshot of Linux in a PDF in a browser

Nice PDF, But Can It Run Linux? Yikes!

The days that PDFs were the granny-proof Swiss Army knives of document sharing are definitely over, according to [vk6]. He has managed to pull off the ultimate mind-bender: running Linux inside a PDF file. Yep, you read that right. A full Linux distro chugging along in a virtual machine all encapsulated within a document. Just when you thought running DOOM was the epitome of it. You can even try it out in your own browser, right here. Mind-boggling, or downright Pandora’s box?

Let’s unpack how this black magic works. The humble PDF file format supports JavaScript – with a limited standard library, mind you. By leveraging this, [vk6] managed to compile a RISC-V emulator (TinyEMU) into JavaScript using an old version of Emscripten targeting asm.js instead of WebAssembly. The emulator, embedded within the PDF, interfaces with virtual input through a keyboard and text box.

The graphical output is ingeniously rendered as ASCII characters – each line displayed in a separate text field. It’s a wild solution but works astonishingly well for something so unconventional.

Security-wise, this definitely raises eyebrows. PDFs have long been vectors for malware, but this pushes things further: PDFs with computational power. We know not to trust Word documents, whether they just capable of running Doom, or trash your entire system in a blink. This PDF anomaly unfolds a complete, powerful operating system in front of your very eyes. Should we think lightly, and hope it’ll lead to smarter, more interactive PDFs – or will it bring us innocent looking files weaponized for chaos?

Curious minds, go take a look for yourself. The project’s code is available on GitHub.

Continue reading “Nice PDF, But Can It Run Linux? Yikes!”

Writing And Running Atari 2600 Games In Your Browser

Here in 2024, writing new games for the venerable Atari 2600 game console is easier than ever, with plenty of emulators and toolchains to convert your code into ready-to-load ROMs. Yet what is easier than diving straight into 6502 assembly code without even having to download or set up a toolchain? That’s where [Henry Schmale]’s fully in-browser Atari IDE and associated emulator (using the Javatari project) comes into play.

As [Henry] explains in a blog post, the main goal was to get a project working in Emscripten, the LLVM-based toolchain to create WebAssembly binaries with. The target of this became DASM, the macro assembler for a range of 8-bit MPUs, including the 6502. In the blog post [Henry] describes the general procedure for how he compiled and integrated DASM, as part of creating the earlier linked Atari 2600.

In this IDE a number of example programs are provided, which can be selected, assembled and run in the integrated Javatari instance. Beyond this you can write your own custom 6502 ASM, of course, but at this point you may be interested in taking things further with the versatile Stella emulator that can even run on platforms which you’d be hard-pressed to get a browser running on, never mind Chromium.

Bringing Zelda Classic To The Browser

Finding a device or app that isn’t a web browser doesn’t seem easy. These days, it is either connected to the web (looking at you ESP32) or is just a web browser pretending to be something else (a la electron, PWAs, or React Native). So, of course, it is on us to create more and more exciting things to browse. [Connor Clark] is one of those people, and he brought Zelda Classic to the browser.

Zelda Classic (ZC) isn’t an official Zelda game. Instead, it’s an old engine designed to run the world in the OG Legend of Zelda and be easily modified to support hundreds of different games. To date, there are over 600 games submitted by a large community. ZC is an Allegro-based Windows-only game, so the first step was to bust out Emscripten to start tweaking the C++ code to support a web environment. Rather than completely port the huge codebase over from Allegro, [Connor] made the jump from Allegro 4 to 5. Allegro 5 has SDL as a backend and adds support for Emscripten.

Unfortunately, the 4 to 5 wasn’t as simple as changing the dependency. The API was wholly re-written, and there is a handy adapter known as Allegro Legacy to help transition a project from one to another. After squashing a multitude of bugs, it was a relatively painless procedure. After a quick detour getting music and level data working, [Connor] faced his next challenge: multi-threading. Efforts to move the main loop off of the browser thread and into a web worker ran into issues with having to yield in loops, deadlocks, and recursive mutexes. Finally, he added music and gamepad support after fixing several bugs in SDL and Allegro.

It’s an incredible journey with many tips and tricks for debugging seemingly intractable bugs. The code is up on GitHub, or jump in and start playing if you’re interested. Why not check out this browser-based OpenSCAD as well?

Hacked Punch-Out Controlled With Actual Punches

In a slightly safer departure away from jetpack roller-skating and flinging around bolts of lightning, [Ian Charnas] has been hacking retro video games. After a lot of hard work [Ian] has managed to add pose estimation to control the character in the NES boxing game “Punch-Out.” Surely he can’t get hurt doing that? No, but since it wasn’t fair to hurt the poor suffering characters, without taking any damage himself, he added electric-shock feedback to give the game a bit more, ahem, punch. See, you can get hurt playing video games!

By starting with Google MoveNet, which is a pre-baked skeletal tracking model which can run in a browser using TensorFlowJS, he defined some simple heuristics for the various boxing moves usually performed with the game controller. Next, he needed to get the game. Being a all-round good guy, [Ian] bought an original copy of the game cartridge to obtain the license, then using the USB CopyNES from RetroUSB, dumped out the game binary for the next step.

Emulation of the NES hardware was chosen, taken care of by FCEUX, in order to run the game and the posture model on the same machine. This simplified the control of the game, since it would be somewhat more work to have it run on the original NES. By using emscripten, FCEUX was cross-compiled to WebAssembly, and so both the game and control side are both in the land of JavaScript. To be honest, after playing the game a little, [Ian] found it far too fast to be playable with posture control, as opposed to much faster button pressing, so some game hacking was required. Emulation made this much easier.

It took [Ian] around two months of disassembling the game binary, and figuring out the game logic around the characters in order to slow them down enough to make it playable, but he did manage it. You can be the judge, since he bought a bunch more cartridges to unlock more license copies, you can play it too. Just don’t add the electric-shock part, nobody needs to be administered electric shock therapy from a two inch high bright orange Mike Tyson!

Continue reading “Hacked Punch-Out Controlled With Actual Punches”

SQLite On The Web: Absurd-sql

Love it or hate it, the capabilities of your modern web browser continuously grow in strange and wild ways. The ability for web apps to work offline requires a persistent local storage solution and for many, IndexedDB is the only choice as it works across most browsers and provides a database-like interface. However, as [James Long] found, IndexedDB is painfully slow on chrome and limited in querying ability. He set out to bring a tool he was familiar with, SQLite, and bring it to the web browser as absurd-sql.

Why absurd? Partially because most browsers (not chrome) implement IndexedDB on top of SQLite. So for many browsers, it is just SQLite on top of IndexedDB on top of SQLite. Luckily for [James] there already was a project known as sql.js that uses emscripten to compile the C-based SQLite into WebAssembly. However, sql.js uses an in-memory storage backing and all data is lost when refreshing the page. [James] tweaked SQLite’s method of reading and writing blocks. Instead of being memory backed, he added a layer to read and write blocks from IndexedDB. This means that only sections of the database need to be read in, bringing in huge performance gains.