onsoku advance is sonic advance, the game boy advance game from 2001, built again for a browser. there is no emulator in it. the game's rules are written again in javascript, and everything on the screen and in the speakers is read from the player's own copy of the game, on their machine, when they open the page. the first act, neo green hill zone act 1, plays whole, and the game was checked against the original a frame at a time. onsoku is japanese for the speed of sound.
it can be played at nahuelgenchi.github.io/onsoku-advance, with a copy of the game, and its code is on github. every frame in this article was drawn by it.1
the repository holds no sprite, no tile, no note of music and no line of the original's code. the page asks for the game's ROM, the file a cartridge is copied into, reads it in the browser and never sends it anywhere. it can keep it on the device, so the next visit starts at once.
reading a ROM means knowing where things are in it. the tested copy, the american one, is known by its checksum, and its tables sit at fixed places: the sprites at 0x0D868C, the act's tilemaps at 0x4A6C40, its collision at 0x4A6DA4, the songs at 0x6D76AC. the formats come from SAT-R, the community's decompilation of the game, which names its functions and its data. none of its code or data is in the repository either.
another version of the game keeps the same tables in other places, so the extractor also looks for them by their shape. the tilemap table is the one where act 2 repeats act 1's background in each of the first five zones, so five pairs of its entries match. the collision table is the one whose first entry points at the same tiles and maps as the tilemaps' first two. the spin dash's speeds are nine numbers from 6.0 to 9.0, 0.375 apart.
the act is drawn in tiles of 8 × 8 pixels, and its ground is kept with the same tiles. each of the act's 982 tiles has a height for each of its eight columns and each of its eight rows, half a byte each, an angle, from 0 to 255 for a whole turn, and two bits of flags, one of which makes it a ledge that can be jumped through from below. a tile drawn mirrored is solid mirrored too. so a pixel of ground is found by asking which tile is drawn there, and which way round.
a loop needs one more thing. where it closes, the ground that leads into it crosses the ground that leads out, so the two halves of a loop are on different layers, and he collides with one layer at a time. thirty-one invisible boxes at the loops move him from one to the other: 11 to the front layer and 20 to the back.
the original runs everything as tasks in one list, sorted by a number each task carries, and so does onsoku advance, with the same numbers. the order is not a detail. the objects run before sonic, so a spring or an enemy tests where he was at the end of the frame before, and a frame later he is where the original would have him.
| priority | what runs |
|---|---|
0x0900 | the ends of the grind rails |
0x0F00 | the camera |
0x1000 | the forced slide |
0x2000 | the rings, what spawns, the two palette animations, and every object and enemy in the order it was made |
0x2001 | rings sonic has dropped, and the sparks off a rail |
0x2100 | the title card, while it plays |
0x2180 | the rings, score, time and lives in the corners |
0x3000 | sonic |
0x4000 | the music |
0xFF00 | the stage's clock |
sonic's own step follows the original's player code, and its numbers are the original's. a spin dash starts from a crouch with a press of jump. each further press adds 2.0 to a charge, which loses a thirty-second of itself every frame, and letting go of down looks the speed up in a table in the ROM.
the table has nine speeds, and the original never checks the charge against it. revved fast enough, the charge reads past the ninth into the table stored after it, which runs from 8.25 to 11.25. so a quick player can leave faster than any speed the first table holds, or slower than the one before it. onsoku advance reads both tables, as the game does, and stops at the end of the second, where the original goes on into bytes that are not speeds at all.
nothing was judged by eye. the reference is mGBA 0.10.5, an emulator, running the original ROM with no window and writing out the game's memory after every frame: sonic, the camera, the rings, every task. each recording is a short piece of play, the same inputs given to both, and the engine passes when its state is the original's on every frame.
| recordings | |
|---|---|
| wall poles | 40 |
| the ramp, the half-pipe and the slide | 40 |
| turning sprites | 38 |
| grind rails | 25 |
| item boxes | 21 |
| waterfalls and ledges | 16 |
| platforms | 14 |
| boosters | 14 |
| enemies | 13 |
| checkpoints and the restart | 12 |
| the title card | 12 |
| getting hurt and dying | 10 |
| boulders | 7 |
a comparison that strict brings the original's quirks along with its rules, and they are kept. the rings are searched for by regions of 256 pixels, and the search stops 16 pixels short of the bottom of sonic's box, so a ring just inside the next region down is missed for a frame. a thing whose spawn point is on the very first pixel of a region appears a frame late. the forced slide, once the camera has been near it, never leaves the list of tasks: it may only go on a frame with nobody in it, and the second player's empty place always counts as someone.
the title card is checked as pictures. it slides in over the act while the screen fades up from black, and the engine's frames match mGBA's screenshots pixel for pixel on every frame of it, in twelve runs, ten of them pressing a button at different moments of it. to get there the fade had to darken colours the way the emulator does, from its eight bits a channel, rather than from the five the console has.
the music is checked the same way. sonic advance plays its songs on nintendo's standard sound engine, which many game boy advance games use, and onsoku advance carries a port of it that reads the songs, voices and samples from the ROM. it mixes 176 samples a frame, at 10,512 a second, as the game sets it to. loaded with the original's state and run one frame, it matches mGBA's byte for byte in 3,657 of 3,659 frames of the act's music. the two that do not are frames where the game itself starts a song or changes its pitch or volume, outside the engine. the four channels the console makes in hardware, two squares, a wave and noise, are emulated, and match in pitch, level and envelope, but not sample for sample: where a wave starts depends on the exact cycle the game writes to them, which nothing here counts.
sonic's walking and running frames tilt with the ground. the console does that with hardware: a sprite gets a matrix, and every pixel on the screen is looked up in the sprite through it, nearest pixel, line by line. the first version of the renderer turned his frames with the canvas instead, which smooths and places pixels its own way. his position was right, and the pictures were not.
now the renderer builds the matrix from his angle as the game's TransformSprite does, moves him so his anchor stays put, and samples each piece of the sprite the way mGBA's renderer does, with its rounding and the places it skips. in the run that dies on spikes and starts the act again, 603 frames differed from the emulator's screenshots around sonic. afterwards none did. the other 37 recordings of that bar, three of them whole loops, turn him through the whole circle facing left, and through the angles act 1 gives him facing right.
the game is checked against the original screen, so anything added has to leave it alone, and both extras are switched off until a player asks for them.
the first is a widescreen view, up to 368 × 208, which shows more of the act around the original screen. only the drawing changes. the camera, and the tests of what is near enough to spawn or far enough to vanish, still work on the 240 × 160 screen, so the game plays exactly as it does without it. the price is honest: a shot from an enemy still disappears at the edge of the original screen, which is now inside the view.
the second is not sonic advance's at all. it is the boost from sonic rush, the 2005 game for the nintendo DS, its rules read from that game and checked against melonDS, an emulator of the DS. it needs the player's copy of sonic rush too, read the same way, and nothing of it is in the repository. held, it sends sonic at 12 pixels a frame, the camera falls behind him for eight frames and then runs up to 88 pixels ahead, and enemies in a box 64 pixels square around him burst. the trail behind him is drawn as the DS draws its own, as translucent 3D polygons, and the sound is played by a port of the DS's sound engine. switched off, every frame is what it was without it, which was checked over about 140,000 frames.


the repository was made just after midnight on 23 october 2026, and the boost went in late on the 24th. everything in between came one change at a time, each with its own issue and its own pull request.
what is left is most of the game. the act has no end yet, and losing the last life does not end it. the other zones, the bosses and the special stages are not there yet, and the boost has no gauge to run down. the other way round from this, a real game run inside another by an emulator, is inside kirby super star ultra.