苹果II的微软SoftCard:让两个处理器共享内存
The Microsoft SoftCard for the Apple II: Getting two processors to share memory

原始链接: https://devblogs.microsoft.com/oldnewthing/20251104-00/?p=111758

## 微软Z-80软卡:将CP/M带到Apple II 微软Z-80软卡是Apple II的一款开创性扩展卡,值得注意的是,它是微软的第一款硬件产品,也是1980年的一项重要收入来源。它允许Apple II用户运行为CP/M操作系统设计的软件,该操作系统运行在8080处理器上——与Apple II的原生6502处理器不同。 该软卡通过包含自己的Z80处理器来实现这一功能,该处理器与8080兼容。然而,仅仅添加一个处理器是不够的。该卡巧妙地通过欺骗6502进入暂停状态(模拟DMA)来管理与6502的共存,同时Z80运行,并定期“唤醒”6502以防止寄存器退化。 一个重要的挑战是内存映射。两种处理器对初始内存地址都有冲突的使用,并且CP/M期望特定的加载位置,这与Apple II系统功能冲突。软卡通过地址转换电路解决了这个问题,重新映射Z80的内存视图以避免冲突并提供连续的RAM访问。这种复杂的交互使Apple II用户能够体验CP/M软件的世界。

Hacker News 新闻 | 过去 | 评论 | 提问 | 展示 | 招聘 | 提交 登录 微软为Apple II推出的SoftCard:让两个处理器共享内存 (microsoft.com) 14点赞 zdw 4小时前 | 隐藏 | 过去 | 收藏 | 讨论 考虑申请YC冬季2026批次!申请截止至11月10日 指南 | 常见问题 | 列表 | API | 安全 | 法律 | 申请YC | 联系 搜索:
相关文章

原文

The Microsoft Z-80 SoftCard was a plug-in expansion card for the Apple II that added the ability to run CP/M software. According to Wikipedia, it was Microsoft’s first hardware product and in 1980 was the single largest revenue source for the company.

CP/M runs on an 8080 processor, but the Apple II has a 6502 processor. So how can you run CP/M on an Apple II? Answer: The card comes with its own 8080-compatible processor, the Zilog Z80, which was arguable better than the 8080 for a bunch of reasons given on its Wikipedia page

Great, you now have a processor. But what happens to the old 6502 processor? Ideally, you would just shut it off, but you can’t go cold turkey because some things still had to be handled by the 6502.² Nicole Branagan digs deeper into the story of how the two processors coexist. The idea is that the SoftCard tells the 6502 that it’s doing DMA, so the 6502 pauses and waits for the DMA to complete. However, you can’t leave the 6502 paused for too long or its internal registers degrade and lose their values.

The solution is to take advantage of the Z80’s REFRESH line, which the processor uses to signal that it’s not accessing memory right now (because it’s decoding an instruction). This tells external memory refresh circuitry that it can run and keep the RAM values refreshed so that they don’t degrade and lose their values.

On the Apple II, memory refreshing is done by the video circuitry, so there is need for a dedicated REFRESH signal. The SoftCard uses this signal to allow the 6502 to execute a tiny little bit. (Presumably it is sitting in a spin loop waiting to be woken.) This keeps the 6502’s registers refreshed.

When the SoftCard needs the 6502 to do actual work, it can update some memory to tell the 6502, “Break out of your spin loop and do something for me, then let me know the answer and go back to the spin loop.” The Z80 then goes to sleep until it gets an answer from the 6502.

Another wrinkle in the way that the 6502 and Z80 shared memory is in the memory map. Both the Z80 and 6502 consider the first 256 bytes of memory to be special and want to use it for different things. Furthermore, CP/M programs expect to be loaded at $0100, but the 6502 hard-codes its CPU stack to live in the range $0100–$01FF. There are other obstacles in the low part of the Apple II memory map: The Apple II system monitor uses $0200–$02FF as its keyboard input buffer, the bytes in the range $03F0–$03FF are used to hold interrupt vectors, and the text video frame buffer goes from $0400–$07FF. (There is a second text video frame buffer from $0800–$0BFF, but almost nobody uses it.) Other big obstacles are the memory range from $C000–$CFFF, which is used by peripheral devices, and the memory range from $D000–$FFFF, which holds the Apple II monitor ROM, but can be replaced by RAM if you have the Language Card (a 16KB memory expansion card), except that the last few bytes $FFFA–$FFFF are used by the CPU as interrupt vectors.

The solution is to remap the memory by putting address translation circuitry on the SoftCard, so that when the Z80 asks for memory address $0000, say, it actually gets physical memory $1000. The remapping is carefully arranged so that all of the Apple II’s special reserved addresses get shuffled to the end of the Z80 memory map, and all of the Apple II’s normal RAM occupies contiguous address space in the Z80 memory map starting at $0000.³

  6502   Physical   Z80
Special use $0000–$0FFF $1000–$1FFF   $0000–$0FFF normal RAM
(contiguous,
up to
installed RAM)
normal RAM
(contiguous,
up to
installed RAM)
$1000–$1FFF $2000–$2FFF   $1000–$1FFF
$2000–$2FFF $3000–$3FFF   $2000–$2FFF
$3000–$3FFF $4000–$4FFF   $3000–$3FFF
$4000–$4FFF $5000–$5FFF   $4000–$4FFF
$5000–$5FFF $6000–$6FFF   $5000–$5FFF
$6000–$6FFF $7000–$7FFF   $6000–$6FFF
$7000–$7FFF $8000–$8FFF   $7000–$7FFF
$8000–$8FFF $9000–$9FFF   $8000–$8FFF
$9000–$9FFF $A000–$AFFF   $9000–$9FFF
$A000–$AFFF $B000–$BFFF   $A000–$AFFF
$B000–$BFFF $D000–$DFFF   $B000–$BFFF expansion RAM
(except for
last 6 bytes)
I/O space $C000–$CFFF $E000–$EFFF   $C000–$CFFF
expansion RAM
(except for
last 6 bytes)
$D000–$DFFF $F000–$FFFF   $D000–$DFFF
$E000–$EFFF $C000–$CFFF   $E000–$EFFF I/O space
$F000–$FFFF $0000–$0FFF   $F000–$FFFF Special use

The SoftCard manual contained lots of details on how to write code for it. For example, it included instructions on how to call into a 6502 subroutine from Z80 and had a chart showing how the memory was remapped for the Z80. It even included the Z80 processor reference manual, listing all the instructions. This will come in handy in a future story.

¹ I don’t know where the hyphen in Z-80 came from.

² In many places, I/O was handled by timing loops, so if you wanted to access, say, the game paddles, you had to let the 6502 do the I/O with its precise software timing loops.

³ There were also two high resolution graphics frame buffers, one at $2000–$3FFF, and another at $4000–$5FFF. These were right in the middle of the Z80 memory map, but in practice it wasn’t a problem because CP/M was a text-mode operating system, so the programs you were running didn’t try to do graphics anyway.

联系我们 contact @ memedata.com