{"id":1854,"date":"2026-05-01T13:51:35","date_gmt":"2026-05-01T11:51:35","guid":{"rendered":"https:\/\/www.pagetable.com\/?p=1854"},"modified":"2026-05-01T15:04:54","modified_gmt":"2026-05-01T13:04:54","slug":"running-adobes-1991-postscript-interpreter-in-the-browser","status":"publish","type":"post","link":"https:\/\/www.pagetable.com\/?p=1854","title":{"rendered":"Running Adobe&#8217;s 1991 PostScript Interpreter in the Browser"},"content":{"rendered":"<p>The <a href=\"https:\/\/www.pagetable.com\/?p=1673\">HP C2089A &ldquo;PostScript Cartridge Plus&rdquo;<\/a>, a 1991 add-on for the LaserJet II\/III, adds PostScript Level 2 support through Adobe&rsquo;s own reference interpreter (version 2010.118) on a 2 MB ROM.<\/p>\n<p>Thirty-five years on, that ROM is still a current PostScript implementation: it renders the language correctly, and the language hasn&rsquo;t changed. We have Ghostscript today, but this is Adobe&rsquo;s own reference implementation! Old code is not always retro code: Why not use it productively today?<\/p>\n<p><a href=\"https:\/\/github.com\/mist64\/retro-ps\">retro-ps<\/a> takes that ROM, emulates the M68K it ran on, fakes the LaserJet mainboard around it, and runs the result on the command line \u2014 or in the browser at <a href=\"https:\/\/www.pagetable.com\/retro-ps\/\">pagetable.com\/retro-ps<\/a>. Drop a <code>.ps<\/code> file onto the page; the cart&rsquo;s own rasterizer renders it client-side. There is no server.<\/p>\n<p><a href=\"https:\/\/www.pagetable.com\/retro-ps\/\"><img decoding=\"async\" src=\"docs\/retro-ps\/retro-ps.png\" alt=\"retro-ps in the browser, rendering the cart's own test page\" \/><\/a><\/p>\n<h2 id=\"hardware-details\">Hardware details<\/h2>\n<p>The LaserJet III is the host. Its formatter board has a Motorola 68000 at 8 MHz, 1 MB of system RAM (expandable to 4 MB), a cartridge port that maps an external ROM into the CPU&rsquo;s address space, and memory-mapped registers for talking to the print engine. The C2089A &ldquo;PostScript Cartridge Plus&rdquo; plugs into that cartridge. The PostScript interpreter, fonts, halftone, and banding all run from cart ROM, working out of formatter RAM.<\/p>\n<h2 id=\"emulator-internals\">Emulator Internals<\/h2>\n<p>The cart was built to drive a LaserJet III: 300 DPI, fixed paper sizes, 0.25&#8243; hardware margin. The PostScript interpreter inside is general \u2014 those constraints are the printer&rsquo;s, not the language&rsquo;s. retro-ps lifts them: any DPI up to the cart&rsquo;s clip cap, any paper size, any halftone frequency, no margin. (<code>--lj3<\/code> puts the original constraints back.) A few things made that work:<\/p>\n<ul>\n<li><strong>CPU and RAM.<\/strong> The emulator&rsquo;s 68020 sees more memory than the original 68000 could address. 16 MB of RAM here. That headroom is what lets the cart render high-DPI pages without rewriting its allocator.<\/li>\n<li><strong>No mainboard, no engine.<\/strong> We have the cart ROM, not the LaserJet&rsquo;s mainboard ROM, and no print engine. The emulator stands in for the soft-traps the mainboard provides (printer-model byte, IPC byte stream, engine-status polling) and fakes the engine-done interrupt so the cart&rsquo;s state machine moves on.<\/li>\n<li><strong>Halftone scaling.<\/strong> Adobe hand-tuned the cart&rsquo;s halftone cell for 300 DPI; above that the default cell renders too sparse and grayscale fills look chalky. We inject a DPI-scaled <code>setscreen<\/code> prolog.<\/li>\n<li><strong>Pixel ceiling.<\/strong> The PS interpreter&rsquo;s <code>clip<\/code> operator caps content at about 16,000 device pixels per axis. This is a limit in Adobe&#8217;s code; the practical DPI max scales with paper size (\u2248 1450 DPI on Letter).<\/li>\n<\/ul>\n<h2 id=\"future-work\">Future Work<\/h2>\n<ul>\n<li>Other cartridge ROMs. <a href=\"https:\/\/www.pagetable.com\/?p=1850\">Pacific Page P\u00b7E<\/a> would be the obvious next target.<\/li>\n<li>LaserJet 4M and later. Same Adobe code, different CPU: the 4-series formatter is Intel i960-based with PostScript Level 2 baked into the formatter ROM \u2014 no cartridge.<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>The HP C2089A &ldquo;PostScript Cartridge Plus&rdquo;, a 1991 add-on for the LaserJet II\/III, adds PostScript Level 2 support through Adobe&rsquo;s own reference interpreter (version 2010.118) on a 2 MB ROM. Thirty-five years on, that ROM is still a current PostScript implementation: it renders the language correctly, and the language hasn&rsquo;t changed. We have Ghostscript today, &#8230; <a title=\"Running Adobe&#8217;s 1991 PostScript Interpreter in the Browser\" class=\"read-more\" href=\"https:\/\/www.pagetable.com\/?p=1854\" aria-label=\"Read more about Running Adobe&#8217;s 1991 PostScript Interpreter in the Browser\">Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5,24],"tags":[],"class_list":["post-1854","post","type-post","status-publish","format-standard","hentry","category-archeology","category-postscript"],"_links":{"self":[{"href":"https:\/\/www.pagetable.com\/index.php?rest_route=\/wp\/v2\/posts\/1854","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.pagetable.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.pagetable.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.pagetable.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.pagetable.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1854"}],"version-history":[{"count":4,"href":"https:\/\/www.pagetable.com\/index.php?rest_route=\/wp\/v2\/posts\/1854\/revisions"}],"predecessor-version":[{"id":1858,"href":"https:\/\/www.pagetable.com\/index.php?rest_route=\/wp\/v2\/posts\/1854\/revisions\/1858"}],"wp:attachment":[{"href":"https:\/\/www.pagetable.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1854"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.pagetable.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1854"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.pagetable.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1854"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}