Tachibana

Astéroric — detailed features

A study clone of Asteroids for the Oric-1 48K · C + 6502 assembly (cc65) · EUPL 1.2 licence

This page lists Astéroric's features with, for each, what it does and how. The GitHub repository (README, ROADMAP, CHANGELOG) remains the up-to-date reference; the manual covers usage.

Contents

1. HIRES vector rendering

Astéroric draws everything — ship, asteroids, saucers, torpedoes, letters, digits — with line segments, like the vector-screen arcade cabinet, but on the Oric's bitmap HIRES screen.

Monochrome HIRES mode

240 × 200 pixels, PAPER 0 / INK 7. The character set is copied from $B400 to $9800 and the three bottom text lines are cleaned. The video attribute set at init is $1E (HIRES 50 Hz, PAL): with $1C (60 Hz) an RGB2HDMI would not lock onto the signal on a real Oric-1.

XOR Bresenham

Every segment is drawn in XOR: drawing it again erases it, with no background save. The draw_line_xor routine (src/asm/line.s) is self-modifying assembly, with a dedicated path for pure verticals and per-byte processing on the horizontal axis. Vertices shared between segments are drawn only once (half-open Bresenham), otherwise the XOR would cancel them.

Pre-rendered sprites

Shapes that do not rotate (asteroids, saucers, digits) are pre-rendered and XOR-blitted instead of being redrawn segment by segment — phase 26, which raised idle CPU time to 39.8%.

Anti-flicker

Erase and redraw of each entity are kept tight in the loop (erase → tick → draw per entity, previous positions remembered) to shorten the window during which an object is missing from the screen.

Sub-pixel motion

Ship and asteroids in 8.8 fixed point: fractional speeds and smooth trajectories despite the 240 × 200 grid. The ship rotates through 32 angles (11.25°) with precomputed tables.

2. Arcade fidelity

The game logic is transposed from the disassembly of the arcade ROM rev 4 (6502disassembly.com): same CPU as the Oric, and the original variable names are kept for traceability.

Authentic asteroids

Four shapes × three sizes, vertices extracted from the ROM (Nick Mikstas's work), 11 to 13 vertices per shape without decimation. Up to six asteroids at once (performance limit).

Waves and fragmentation

Progressive wave spawning with positions and velocities drawn from the arcade's pseudo-random generator; a large asteroid that is hit yields three fragments, the parent shrinks; fragment speed retuned (phase 29) and overall speed reduced (phase 37) after playtesting.

Cylinder and torus

Wrapping from one edge to the other is done by instance duplication (an object straddling the edge is drawn on both sides); collisions are computed in toroidal topology.

Ship, shots, hyperspace

Arcade-faithful 5-segment ship (cockpit bar, notches), thrust flame, 2 × 2 px torpedoes with arcade range and wraparound, rapid fire when SPACE is held, hyperspace with a 25% chance of death. Extra life every 10,000 points, capped at 60,000; at most four life icons displayed.

Explosions

The ship breaks into five debris pieces (rev 4 ShipExpVelTbl/ShipExpPtrTbl tables); asteroids explode into short-lived dots with the arcade's exact shrapnel pattern.

Game over and scores

Three-step sequence (explosion → GAME OVER → HIGH SCORES table), 5 s lock, top-five scores kept in RAM for the session.

3. Saucers

Large and small

Two saucers with firing AI transposed from the arcade: 8-way shots or aiming at the ship, accuracy indexed on the score, the small one alone above 35,000 points.

End-of-wave pressure

ScrSpeedup: the saucer returns faster when only a few asteroids are left; AstBreakTimer blocks its appearance right after an asteroid is hit.

4. AY-3-8912 sound

The original arcade used discrete analogue oscillators; Astéroric's effects are an original recreation on the Oric's PSG (no Atari audio data reused).

Interrupt-driven player

Sound is played by a routine under the VIA Timer 1 IRQ at 50 Hz (every other update at 25 Hz), which frees the main loop. PSG access is protected (sei, dedicated scratch) — two IRQ corruption bugs were found and fixed.

Three independent channels

Channel A: effects (fire, S/M/L explosions, thrust, hyperspace, extra life); channel B: the thump-thump heartbeat that speeds up with the asteroid count; channel C: the saucer's continuous beeping. Hardware envelopes (R11-R13) for natural decays.

Title jingle

On entering the title screen, “In the Hall of the Mountain King” (Grieg, public domain), accelerando, legato, with an octave doubling on channel B.

5. Title screen and display

A-Z vector font

Since phase 40, a complete vector font (src/font.c) renders “ASTERORIC”, “GAME OVER”, “PRESS SPACE”, “HIGH SCORES”, “WAVE” and the CONTROLS screen through a generic text_draw function.

Attract demo

As on the cabinet, asteroids drift behind the title; “PRESS SPACE” blinks; the game really waits for SPACE (no timed start).

HUD

7-segment score digits, life icons, two-digit wave number.

6. Keyboard and joystick

Direct keyboard scan

The keyboard is read through the VIA and PSG register 14, column by column, without the ROM keyboard buffer — the game does not depend on the Atmos ROM $0265. The full 64-position matrix (src/keys_tab.h) is documented from the ROM tables and validated on hardware.

Configurable keys

On the title screen, K opens CONTROLS: LEFT, RIGHT, THRUST, FIRE, HYPER are entered in turn, duplicates and unknown positions refused, ESC cancels and restores. The mapping lives in RAM (defaults on reload).

IJK joystick

The IJK interface is read on the printer port (VIA port A directly, PB4 strobe) with a presence bit: without an interface, the read is ignored. The first protocol (reading through the PSG) reproduced a wrong emulator model and was fixed after feedback on a physical interface; Phosphoric was fixed alongside. Not remappable.

7. Performance

The budget is about 40,000 cycles per frame at 25 Hz on a 1 MHz 6502.

Fixed-step scheduler

Phase 28: fixed step with catch-up, paced by the VIA Timer 1 (20 ms) — no more 60 ms stalls, constant 25 Hz. An adaptive 50 Hz mode was tried and rejected.

Measurements

Initial drawing at ~97 cycles/pixel (phase 2), since reduced by self-modification, byte batching and pre-rendered sprites; idle CPU time in play raised from 17.9% to 39.8% (phases 24-26). make bench profile over 25 million cycles.

Video synchronisation

The CB1 line (VSync) is not wired on a real Oric-1: timing comes from the free-running Timer 1, not from the video signal.

8. Specifications

ItemValue
Target machineOric-1 48K, BASIC 1.0 ROM
ScreenHIRES 240 × 200 monochrome, 50 Hz (attribute $1E)
Frame rateConstant 25 Hz (VIA Timer 1, 20 ms)
SoundAY-3-8912, 3 channels, IRQ-driven player at 50 Hz
InputKeyboard (direct VIA scan, remappable), IJK joystick (printer port)
Loadingasteroric.tap (~23 KB) with autorun flag, code at $0500
LanguagesC (cc65) + 6502 assembly (ca65)
LicenceEUPL 1.2 (original code); Atari-derived elements not covered

9. Build and tests

Prerequisites

cc65 ≥ 2.19 (cc65, ca65, ld65), Python 3 for the table generators (ship_verts.s, shapes.s), and Phosphoric to run, capture and profile (path to adjust in the Makefile).

Make targets

make produces build/asteroric.tap; make run / make run-joy launch under Phosphoric (keyboard / emulated IJK); make test captures the screen headless; make check compares bit for bit against the versioned reference capture; make host-test builds and runs the x86 host tests; make bench profiles 25 M cycles.

Tests

Portable host tests on the pseudo-random generator and the shared key table (8 assertions), a title-screen reference capture compared bit for bit, scripted firing scenarios under Phosphoric (--type-keys) for keyboard/joystick non-regression.

10. Known limits

Oric Atmos

The .tap does not work with the Atmos ROM (BASIC 1.1), under Phosphoric or Oricutron. The nominal target remains the Oric-1; Atmos compatibility is a separate sprint.

Non-persistent high scores

The top-five scores and the key mapping live in RAM: everything is lost on reload. Tape/disk saving is on the roadmap.

Six asteroids at most

A limit set to hold 25 Hz; the arcade shows more.

Torpedoes

On real hardware, torpedoes remain hard to see at high speed despite the move to 2 × 2 px.

← Astéroric · Manual →