Pravetz 82
An in-browser Pravetz 82 emulator for emulators.org. The Pravetz 82 (Правец 82) is a 1980s Bulgarian Apple ][ clone built by the Pravetz plant, faithful to the Apple II at the chip level with a Cyrillic character generator and a Latin/Cyrillic keyboard switch. This emulator reuses the object-oriented apple2js Apple II core with the Pravetz system ROM and Cyrillic character ROM, so it boots straight to the Cyrillic ПРАВЕЦ banner and the Applesoft-compatible BASIC prompt with no downloads. Because the 6502, memory and I/O are ordinary JavaScript objects, the whole machine steps and inspects live in the shared debugger.
Runs on: Web browser
Pravetz 82 Online Emulator
Play Pravetz 82 using JavaScript directly in your browser.
Controls
Configurations
| Configuration | Emulator | Machine | OS | Legal | |
|---|---|---|---|---|---|
| Pravetz 82 · БЕЙСИК (BASIC) | Pravetz 82 | Pravetz 82 | grey | Open ⛶ | |
| Pravetz 82 · Integer BASIC | Pravetz 82 | Pravetz 82 | grey | Open ⛶ | |
| Pravetz 82 · Applesoft BASIC | Pravetz 82 | Pravetz 82 | grey | Open ⛶ |
Machines emulated
Chips
Notes
Embedding
The Pravetz 82 is an Apple II clone, so rather than write a new machine we reuse the apple2js core (Will Scullin's Apple II, MIT) vendored here as apple2js-boot.js, and point it at the Pravetz ROMs that apple2js already carries: the system ROM pravetz82 and the Cyrillic character ROM pravetz82_char. We load the bundle as one plain <script> and drive the machine from a loop we control, so it can be paused and single-stepped for the debugger.
Boot. A tiny global picks the ROM pair; the bundle constructs the core Apple2 class (not its React UI), points it at a <canvas>, resets the 6502, then runs a loop on cpu.stepCycles():
// choose the Pravetz ROM + Cyrillic character ROM
window.__APPLE2JS_CFG = { rom: "pravetz82", characterRom: "pravetz82_char" };
const apple2 = new Apple2({
canvas: document.querySelector("#screen"),
rom: "pravetz82", characterRom: "pravetz82_char",
e: false, enhanced: false, gl: false, tick: ()=>{}
});
await apple2.ready;
const cpu = apple2.getCPU(), io = apple2.getIO();
cpu.reset(); // reset vector → Autostart ROM → ПРАВЕЦ / BASIC
The whole machine is plain objects. apple2js exposes everything the debugger needs as ordinary methods — no wasm heap to reach into:
| Member | Kind | What it does |
|---|---|---|
cpu.step() | method | Execute exactly one 6502 instruction. The single-step primitive. |
cpu.stepCycles(n) | method | Run for n clocks — the fast run-at-speed path. |
cpu.getState() / setState(s) | methods | Read / write all registers at once: {a,x,y,s,pc,sp} (s = the status byte). |
cpu.getPC() | method | The live program counter — what the breakpoint check and follow-PC read. |
cpu.read(addr) / write(addr,v) | methods | Banked CPU-bus read / write; write pokes memory live. |
io.keyDown(ascii) / io.keyUp() | methods | Feed the keyboard latch a 7-bit code — Latin upper case, or lower case for a Cyrillic glyph. |
Because the CPU, bus and I/O are ordinary JavaScript objects, the debugger single-steps with cpu.step(), reads and writes registers through getState/setState, disassembles from cpu.read, and implements breakpoints and watchpoints as host-side checks — with no changes to the emulator core.
Debugger integration
Wiring the Pravetz into the shared in-browser debugger reused the apple2js integration and added a Cyrillic keyboard.
1 · A boot shim we can pause. apple2js's normal entry builds a React UI and owns an internal requestAnimationFrame loop that cannot be single-stepped from outside. So the bundled boot constructs just the core Apple2 machine and drives it from a loop we control. When no breakpoints are armed it runs a whole frame fast with cpu.stepCycles(); when a breakpoint or watchpoint is set it steps one instruction at a time:
function runCycles(target){
if (!bps.size && !wps.size){ cpu.stepCycles(target); return false; }
for (let done=0; done<target; ){
if (bps.has(cpu.getPC())) return true; // execution breakpoint
const pre = watchSnapshot(), c0 = cpu.getCycles();
cpu.step(); done += cpu.getCycles() - c0;
if (watchChanged(pre)) return true; // value-change watchpoint
}
}
2 · One self-contained script. apple2js loads its ROMs with dynamic import(); the bundle is built with webpack's dynamicImportMode: 'eager', so every ROM — including pravetz82 and pravetz82_char — is inlined. Nothing is fetched at runtime.
3 · A Cyrillic keyboard. On the Pravetz the character ROM holds the Cyrillic glyphs in the lower-case code range ($61–$7A), and the machine's Latin/Cyrillic switch chooses whether a letter key emits its upper-case (Latin) or lower-case (Cyrillic) code. The plug-in reproduces that with a ЛАТ/КИР toggle: in КИР mode a letter is sent as base+0x20, which pravetz82_char renders as the phonetic Cyrillic letter (a→А, b→Б, c→Ц). The same toggle also re-routes the physical keyboard via a capture-phase key handler.
Techniques for deeper access. The plug-in reaches into the running machine through apple2js's own surfaces — no fork of the core:
- Side-effect-free reads. The hex and disassembly views read the bus with a wrapper that skips the
$C000–$C0FFsoft-switch window, so auto-polling the view can never flip a display page or clear the keyboard strobe. - Direct state. Registers are read and written through
cpu.getState()/setState(); the status flags are the bits ofstate.s. - Single instruction step.
cpu.step()runs exactly one instruction — the primitive under Step and under the breakpoint loop. - Breakpoints & watchpoints. Execution breakpoints compare
cpu.getPC()before each instruction; memory watchpoints compare the watched addresses' values after each instruction — both host-side.
Architecture
The Pravetz 82 (Правец 82, 1982+) is a Bulgarian Apple II clone built by the Pravetz plant. It is faithful to the Apple ][ at the chip level, with a Cyrillic character generator and a Latin/Cyrillic keyboard switch as the main additions. Emulated here through the object-oriented apple2js core, every block is an ordinary JavaScript class hanging off Apple2:
CPU6502(from@whscullin/cpu6502) — the MOS 6502 interpreter. Memory is reached through page handlers registered withaddPageHandler.Apple2IO— the$C0xxI/O space: keyboard latch, speaker, annunciators, game paddles and the peripheral-card slots.VideoModeswithLoresPage/HiresPage— the text, lo-res and hi-res display, rastered to a 560×384 canvas. Text uses thepravetz82_chargenerator, which carries Latin upper case plus the Cyrillic set.RAMandROMpage handlers — 48K of main RAM plus thepravetz82system ROM (the Pravetz monitor + an Applesoft-compatible BASIC); aLanguageCardadds the upper 16K.
Each frame steps the 6502 for a slice of time and blits the video. Because every component is an ordinary object with getState/setState, the whole machine is inspectable — which is what the debugger reads each refresh.