POM1 Apple-1 Emulator: A cycle-accurate C++ rewrite for the 50th Anniversary and modern development

2 posts / 0 new
Last post
Offline
Last seen: 16 hours 14 min ago
Joined: Apr 22 2026 - 13:54
Posts: 1
POM1 Apple-1 Emulator: A cycle-accurate C++ rewrite for the 50th Anniversary and modern development
AttachmentSize
Package icon POM1 1.8.6 for Windows5.41 MB

Hello everyone, Arnaud here,

As we hit April 2026 and celebrate the 50th anniversary of the Apple-1, I wanted to share a major architectural update to the POM1 emulator (v1.8.6).

Some of the veterans here might remember the older Java iterations of POM1 from years ago. While it served its purpose, I have closely followed the feedback on this forum before starting to write the new version and realized the old architecture was creating bottlenecks for serious software archaeology and hardware cross-development.

Before diving into the new specs, I want to explicitly thank Uncle Bernie and Jeff Jetton. Uncle Bernie, your work on Codebreaker highlighted a severe limitation in the old POM1's keyboard entry. Pasting large .apl hex dumps was painfully slow and prone to dropping characters because the emulator couldn't properly bypass the PIA polling limits in real-time. Jeff Jetton, your early tests with your 15 Puzzle ASM code exposed execution bugs where the emulator would fail specific branch executions.

These historical failures drove this complete rewrite. The new POM1 is built from scratch in modern C++ with a focus on determinism, low-level accuracy, and large hardware extension support.

1. The Core: Cycle-Accurate 6502 & Clock Math

The engine is no longer a naive state machine. The CPU (M6502.cpp) is now cycle-accurate, executing memory fetches and addressing modes with strict clock cycle penalties.

The system clock is mathematically derived from the NTSC color subcarrier frequency.

              f {CPU} = 14.31818 MHz /14 = 1.022727 MHz

This ensures that tight timing loops in native ASM should run exactly as they would on original silicon.

2. Resolving the Keyboard & ACI Bottlenecks

To fix the pasting issue, the KeyboardController now features a direct-injection clipboard buffer. You can paste modern code from your host OS, and the emulator will feed it to the Wozmon deterministically without overflowing the simulated PIA. You can use "telnet localhost 6502" too with P-LAB Terminal to feed POM1 if you want to have a full history of your interaction.

For the Apple Cassette Interface (ACI), CassetteDevice.cpp now features pulse-mode playback logic. It decodes .wav, .mp3, and .aci audio files asynchronously, feeding the analog wave simulation directly into the ROM reading routine. 

3. Hardware Extensions & Memory Topography

The original 4K/8K memory map is fully supported, but POM1 now acts as a comprehensive Apple-1 development chassis. The PeripheralBus.cpp handles dynamic dispatching for an array of community hardware. You can toggle these via UI presets or CLI flags:

  • Storage: Rich Dreher's CFFA1 and the Parmegiani's P-LAB microSD interface (virtualizing a FAT32 file system directly mapped to a local host directory for easy drag-and-drop compilation).

  • Video: Uncle Bernie's GEN2 Color Graphics Card (simulating NTSC chroma artifacts for color generation) and the TMS9918 VDP.

  • Audio & Comms: P-LAB A1-SID (with libresidfp integration for the 6581/8580) and a 65C51 ACIA-based Wi-Fi Modem bridging to host TCP/Telnet sockets.

The Fantasy Multiplexing Memory Map :

4. Lock-Free UI & Debugging

The UI is built on Dear ImGui. To prevent the GUI from choking the 1 MHz emulation thread, they are decoupled using lock-free atomic variables (SnapshotPublisher.cpp). This allows you to inspect the full 64K memory map, watch the Program Counter (PC) and Stack Pointer (SP), and edit hex dumps in real-time without introducing micro-stutters to the CPU execution.

Access & Call to Action

POM1 is fully open-source (GPLv3). It is true free software, as it was in the beginning.

I invite you to subject this build to your most demanding stress tests. Fork it, adapt it, or use it to bridge your modern dev environment with your physical Apple-1 builds.

Happy 50th, everyone.

— Arnaud.

 

Offline
Last seen: 2 days 12 hours ago
Joined: Apr 1 2020 - 16:46
Posts: 1337
Some praise and some hints !

Hi Arnaud,

 

thanks for this work ! I appreciate this contribution of yours very much !

 

An updated POM-1 emulator with the support for my Apple-1 color graphics card will help me greatly to develop some software for the card. So far I did all the development work for the graphics function library using an Apple II emulator (Linapple). And these do not feature the dual video output of an Apple-1 equipped with my graphics card, but this is a nice feature I want to use with my software. It has advantages ... games could show text on the Apple-1 native "terminal section" and then could show graphics from the graphics card on a second (color) monitor.

 

There are, however, a few changes which I had to put into the planned "release" version of the color graphics card, which you could not know about. Even I did not know about these changes until I had the PCB layout 80% finished. I ran into routing channel congestion and hence could not route all address lines as planned to the address decoder for the soft switches. I had to drop some and this would have caused the ACI operation to interfere with the soft switches, which in the original Apple II are in the address range $Co50-$C057. I had to drop A6 from the decoder and this mirrors the soft switches to $C010-$C017. Alas, the wicked code Woz wrote to write to cassette toggles the TAPE OUT flipflop by using a LDY FLIP,X command (on location $C1EA in the PROM space). Where X is the double bit counter initialized to $10 and FLIP is $C000. Which means that any cassette write operation using the firmware will touch soft switch SS_TEXT and clear it, turning off the TEXT mode. Not good !

 

The deeper reason for this is that on this side of the layout, I do only have address lines A9 and A11 available and all the other address bits must be taken from the multiplexed address bus for the DRAMs, which is available in that side of the layout, as the video scanner resides there. Alas, A6 is not available in the ROW address of the DRAM. Where it ought to be because the soft switches are clocked at the end of the ROW address gate time. There is no way to change this. Initially, I had A6 routed to the left side of the layout, but then  had to use this trace for some other, more important signal.

 

All this can't be investigated with the wire wrapped "lab rat" as it occupies the sole slot, so there is no ACI which could cause trouble with the soft switches. I found out about the problem when pondering over the consequences from dropping A6 from the decoder.

 

The solution to avoid all that trouble with ACI conflicts was to move the soft switches of the graphics card to $C250-$C257. So to adapt Apple II software to this graphics card, a little bit of additional rework is required to change all the $C0 of the graphics mode soft switches to $C2. All the text and graphics modes and the screen buffer addresses as such stay the same as in the Apple II.

 

There is one benefit from this last minute change of the soft switch addresses, though: now, access of the soft switches does not toggle TAPE OUT of the ACI. This means TAPE OUT can be hooked to an audio amplifier driving a loudspeaker and the sound effects of Apple II games can be heard ! There is a caveat, though: all the accesses to all other soft switches in the address range $C000-$C0FF (where the ACI reacts and toggles TAPE OUT) in the software must be knocked out. Only the accesses to $C03X (the "official" SPEAKER toggle soft switch of the Apple II) should stay as is. Then, the ACI will faithfully reproduce the same sound as coded into the original Apple II game.

 

There is another change from the original concept, I found out that "vaporlock" code from original Apple II games would not work in any case ... again, because the ACI spits us into the soup. "Vaporlock" works by reading "bit vapors" from soft switch addresses which do not drive anything onto the data bus. In the original Apple II, this is how lingering "bit vapors" from the video scanner accesses can be read and if special byte codes which make no sense for HIRES graphics are put into certain screen buffer locations, the "vaporlock" technique can deduce whether the electron beam is in the vertical blank period or not, and this info is then used to control screen page flipping or rendering small objects at times where the electron beam does not write them. An important technique for smooth animation without objects breaking up on the screen or "jerking" in weird ways the human eye can perceive and finds to be annoying. Alas, the presence of the ACI card foils this scheme. Despite I put considerable effort designing in "vaporlock" support. This was before I saw the issues with the ACI itself.

 

So I added a hardware flag which appears in the MSB whenever a graphics card soft switch is read. This can be used to discern horizontal and vertical blank periods using trivial and short software routines. It's a more powerful scheme than the VBL flag available from the IOU custom chip in the Apple IIc and IIe.

 

This said, it would be nice if these features would be implemented in the update POM-1 emulator. So people could start porting games from the Apple II to the Apple-1 ;-)

 

Comments invited !

 

- Uncle Bernie

Log in or register to post comments