Peter and George Phillips explain how to move old software onto new hardware when the shipped binary is the best specification left. Their 2003 ACM Queue essay draws on game preservation, where small behavioral differences can ruin a faithful port.

  • Choose the boundary you can reproduce precisely. Hardware instructions and I/O behavior often have firmer specifications than a program’s undocumented internal interfaces.
  • Budget for the whole machine. Emulation pays for instruction decoding, address mapping, arithmetic flags, timing, and devices. Faster host hardware has to cover those costs.
  • Move repeated work into translation. Converting instructions ahead of time removes runtime decoding and lets a host compiler eliminate redundant operations.
  • Check coverage explicitly. Indirect jumps, jump tables, and generated code complicate static analysis. Translating every byte position buys coverage at a steep cost in executable size, with generated code still needing separate treatment.
  • Keep expectations for generated C realistic. Functionally equivalent output can still look like assembly written in C. Familiar syntax alone does little for maintainability.
  • Use a hybrid when it fits. Translate expensive paths and fall back to an emulator elsewhere, accepting the extra memory needed to keep the original program.

Phantasy Star III supplies the concrete case. The Genesis and Game Boy Advance CPUs were too close in performance for straightforward emulation. The team reconciled available source with the shipped ROM, translated assembly into C macros, and adapted graphics and sound.

Compatibility depends on the behavior you preserve and the cost of reproducing it. Recovering execution and recovering maintainable source are separate projects; this essay keeps that distinction honest.