Close
0%
0%

Lunar Lander for the PDP-1

My PDP-1 Replica (PiDP-1) from Obsolescence Guaranteed has arrived and I want to do something cool with it.

Similar projects worth following
In his December 2024 newsletter Oscar Vermeulen of Obsolescence Guaranteed wrote, "With the PDP-1 team at the Computer History Museum, we plan to do an annual programming competition: the winner gets invited to run his [or her] code on the last working PDP-1 in the CHM in Mountain View." In 2026 I would like for that person to be me. This is the beginning of my journey.

I've been bitten by the PDP-1 bug.  When I saw that Obsolescence Guaranteed was shipping their PDP-1 Replica I knew that I wanted one so I placed my order. Due to some well deserved high demand I had to wait a while for my kit to ship,  so I had time to think about what I wanted to do with my PiDP-1 when it arrived (other than playing Spacewar!).

Hardware

My first instinct, given that I mostly make reproductions myself, was to create a DEC Precision CRT Display Type 30 Reproduction since the PDP-1 was already well in hand. I ended up making three reproductions of this unique Type 30 Display that was used with the PDP-1.  

Why three?

  1. DEC Precision CRT Display Type 30 Reproduction - When I made this first version I was under the impression that the PiDP-1 was a 2/3 scale Replica of the original.  I later found out that PiDP-1 is actually at 57% scale plus I had based my model on an invalid assumption w.r.t. the circular screen opening size. Long story short my reproduction was actually at 75% scale and it's big. Too big for my desktop but it will be great for Spacewar! games at my local retro computer meetings.
  2. Honey, I Shrunk the Type 30 Display Reproduction - I wanted to make a smaller display so I zeroed in on a 50% scale model. Why 50%? Because at that scale a Pimoroni PIM-372 8" 4:3 Display could be easily installed.  Later when I factored in my invalid circular screen opening size I realized that the scale was actually 56%, an almost perfect match to the PiDP-1.
  3. Another Type 30 Display Reproduction At 36% Scale - When I started my Type 30 reproduction project(s) I sent a request to the Computer History Museum (CHM) through their contact page asking if it would be possible to get some measurements of the Type 30 display. In mid-October 2025 I received a reply from a wonderful archivist at the CHM who kindly agreed to take some measurements for me. Based on those measurements I decided to make one last Type 30 display.  I chose 36% scale to accommodate a Waveshare 5 inch HDMI Circular Touch Display which other PiDP-1 enthusiasts were using. Because of the relatively small size I decided to model the whole display not just the front part. It was the CHM measurement that the circular screen opening was actually 14" that made me realize that my assumption of a 16" opening based on my misreading of the Precision CRT Display Type 30 manual was wrong, and I had to recalculate the scales of my first two attempts.

Software

With that out of my system I turned to the programming side of the PDP-1.  Since I have never written about a software only project before I am in new territory here. But I have a great role model.

Inspiration

I wanted to write some PDP-1 code but didn't know where to begin. The Obsolescence Guaranteed folks have a PROGRAMMING THE DEC PDP-1 - A QUICK WAY TO GET STARTED guide.  It's great, but it mostly focuses on using the tools they have provided as part of their distribution (lovingly recreated from original 60s source code) to build an assembly language program and run it on the PDP-1 using a simple circle program as an example. 

When I posed the "How do I get started?" question on the PiDP-1 Google Group Oscar pointed to this document, Retrochallenge 2016/10: Ironic Computer Space Simulator (ICSS). Boy was he right. This link documents Norbert Landsteiner's entry to Retrochallenge 2016/10, where he implements a version of Computer Space on the PDP-1. Computer Space was the very first coin operated video arcade game introduced by Nolan Bushnell in 1971.

After a short overview of the origins of the PDP-1 machine and the Computer Space game the ICSS document is broken up into Episodes (chapters).  Episode 1 has a brief description of the PDP-1 architecture, the characteristics of the Type 30 Display, an overview of Computer Space, and an outline of how Computer Space might be implemented...

Read more »

lunar_lander.txt

Lunar Lander as of Mar. 14, 2026

text/plain - 52.07 kB - 12/15/2025 at 15:25

Download

  • Less Boring Bonus

    Michael Gardi03/28/2026 at 17:07 0 comments

    Upon a sixth successful landing on the last unique target, after the normal score and fuel animations, the player will see the following screen counting up the score with 1,000 additional points.

    That's OK I guess but it feels a little underwhelming for such a monumental achievement right? After a little thought I realized that this was a fireworks moment.  So I began playing around with a fireworks effect. Here is what I came up with.

    Still a work in progress but at this point I decided to try and incorporate the code into Lunar Lander. 

    Much to my disappointment the additional code will not fit into the 4K memory limit of the PDP-1 without using the paged memory system (which I do not want to do for this project).  

    Sigh. I might at some point continue to work on fireworks as a stand alone demo. Lots of room for improvement.

  • No Hyperspace (Yet)

    Michael Gardi03/14/2026 at 18:16 0 comments

    I was doing a some testing and noticed that the Hyperspace button on the game pad (right below) would cause the LEM to rotate first in one direction then the other on each press.  That is because by convention the Hyperspace button on the original game controllers (left below) caused the left and right bits in the Test Word to be on at the same time.  Since the left/right contacts on the original controllers were on opposite sides of a toggle switch, this could never happen by accident.

    Since there is no Hyperspace feature in Lunar Lander and probably never will be I added a bit of coded to ignore the input if the left and right bits were set at the same time.

    / Input bits in AC.
      and (600000         / Check for hyperspace, left and right on.
      sad (600000         / Are left and right on?
      jmp pix             /  Yes - Ignore this input.
                          /   No - Process input.

  • Restart

    Michael Gardi03/13/2026 at 18:47 0 comments

    I added a mechanism for restarting Lunar Lander at any point while the game is running. It won't work from the GAME OVER screen (you can just click any button on the game controller) or the NEW GAME screen (game is already restarted). 

    To restart Lunar Lander to the NEW GAME screen while playing, simply change the state of Sense Switch 1.  So if it's ON turn it OFF and vice-versa. 

    The PDP-1 has a single instruction for determining the state of a Sense Switch.

    Instruction   Code #            Explanation
    ~~~~~~~~~~~   ~~~~~~            ~~~~~~~~~~~
        szs       6400s0      Skip on ZERO Sense Switch.

    Where  s  in the code is the switch number 1-6.

    I added the following code in the New Game setup section.

    sw1, 0         / Value of Sense Switch 1 at the start of a game.
    
    / Get the current state of Sense Switch 1.
        dzm sw1    / Default sw1 to 'off'.
        lac (1     / Value to set if Sense Switch 1 is "on".
        szs 10     / Skip if Sense Switch 1 is already off.
        dac sw1    / Set sw1 to "on".

    Then at the start of the main game loop I added the following.

    / Check for restart signal.
        lac (0     / Default to Sense Switch 1 "off"
        szs 10     / Skip if Sense Switch 1 is off.
        lac (1     / Set to Sense Switch 1 "on".
        sas sw1    / Is Sense Switch 1 still in the same state?
        jmp ngm    /   No - Restart the game.
                   /  Yes - Keep playing.

    I did not want to tie the reset signal to a specific state of the sense switch (ON or OFF)  so that the game would start correctly no matter what the initial state was. 

  • Where Did I Land Again?

    Michael Gardi03/11/2026 at 19:52 0 comments

    I added a 1000 point bonus for safely landing on all six zones in a single game. If you are meticulous like me you will probably attempt the zones from one side to the other in order and thus never lose track of which zones have been successfully conquered. On the other hand a better strategy might be to try the zones you find easiest first and might then forget which zones you have completed.

    I have repurposed the Program Flags to light up upon each successful landing. The six lamps are now mapped to the six landing zones (from left to right) in the order they appear on the screen.  I was using the Program Flags to keep track of some internal bookkeeping but now think that this is a better use of the feature.

    So the player above is one safe landing (in the fifth zone from the left) from getting a 1000 point bonus. Let's wish them luck because at this point they are for sure running low on fuel.

    I wasn't expecting this, but it turns out that there is something very satisfying about seeing a physical "contact light" turn on when you have successfully landed. Who knew.

    The contact light on the Apollo Lunar Excursion Module (LEM) was an indicator in the cockpit that illuminated when one or more of the 67.2-inch probes extending from the footpads touched the lunar surface.

    I posted the updated code to the Files section above. 

  • A Bonus Log

    Michael Gardi02/15/2026 at 22:37 0 comments

    After a few successful landings, one thing that I noticed all of my play testers doing was to pick one of the two 5x landing zones and repeatedly attempt to land only there. Makes sense. This will maximize the score and also minimize fuel consumption as both of those zones are not as deep into the "gravity well" as the lesser valued targets.

    To discourage this behavior I have introduced a 1,000 point bonus to the score when a player lands successfully on all six targets in a single game. This dovetails nicely with the increase in initial fuel allotment to 1,999 units and the doubling the fuel bonus for a successful landing to 100.

    Upon a sixth successful landing on the last unique target, after the normal score and fuel animations, the player will see the following screen counting up the score with 1,000 additional points.

    I have updated the Files section with the latest source code.

  • Sometimes Coding Can Be Exhausting

    Michael Gardi02/13/2026 at 21:08 0 comments

    I was having a discussion of my Lunar Lander game with someone in the PiDP-1 Google Group, and they asked if my version had a McDonalds? I was a little confused so I did a bit of research. It turns out there was a 1973 version of Lunar Lander (called Moonlander)  for the DEC GT40 (in essence an all-in-one PDP-11 with a VT11 graphics system and a display) that featured a McDonalds as an Easter egg.  You had to "fly" to the right-most edge of the scrolling moon terrain to find the McDonalds (with golden arches).  If you inadvertently (or purposefully) crashed into the McDonalds the game displayed the following message:

    Upon successfully landing near the McDonalds, an astronaut would debark the LEM, go into the restaurant, and order..

    then walk back to the LEM, get in, and fly away. Hilarious. 

    No, I did not immediately jump into my code and add a McDonalds. What caught my eye was the Moonlander LEM's exhaust. 

    I thought it was a pretty funky "straw broom like" look that matched the overall vibe of the game.  Now obviously that version of Moonlander had way more pixels and horsepower available on the DEC GT40 to create that effect than I do on the PDP-1, but to me the animation signaled that something was definitely going on when the engine was firing.

    I played around with the idea a bit and came up with a two pixel implementation that I'm pretty happy with.

    Actually the video above masks the fact that the two pixels at the tip of the exhaust spike are randomly blinking. It's more pronounced on the actual screen. Worth part of an afternoon in IMHO.

    I have updated the Files section with the latest source code.

  • Update 02/12/2026

    Michael Gardi02/12/2026 at 23:52 0 comments

    I posted updated code to the Files section above. This release incorporates some of the suggestions made last Sunday at the Retro Computer meetup.

    1. Increase the initial allotment of fuel from 999 to 1,999. Correspondingly the fuel bonus for a successful landing and penalty for a crash have been increased from 50 to 100 in both cases. 
    2. Changed the scoring so that if you crash inside a landing zone, the multiplier for that zone is applied to the 5 points already being added.  This corresponds to the "hard landing" bonus awarded in the original arcade but without the velocity check. It also encourages an end game strategy of trying to hit landing zones when there is not enough fuel left for a safe landing.
    3. A small change to show the multiplier label for a landing zone upon a successful landing while the score and fuel are being updated.
    4. Increased the moon’s "gravity" and "thrust" of the LEM engine. This does seem to add more tension to the game and increase the skill required to successfully land. At the very least it changes the mechanics enough throw someone off who has been playing at different settings (like me ;-)  Definitely a candidate for having optional easy and hard modes of play.

  • Play Testing

    Michael Gardi02/09/2026 at 16:49 0 comments

    Local retro computer enthusiasts meet on the second Sunday of each month at Kwartzlab, my treasured makerspace.  Yesterday I brought my PiDP-1 and largest Type 30 display reproduction to the "lab" and enlisted some of the participants to try out my Lunar Lander game. 

    Meeting in the Kwartzlab Event Space.  I'm in the orange plaid lower right photo 1. 

    I received a lot of great suggestions which I would like to share.

    • Increase the initial fuel allotment. The current 999 "units" is enough fuel for about 2.5 safe landings. This is sort of a carryover from the original arcade version which wanted more quarters to be inserted for more fuel. While there needs to be some limit to encourage skillful play, the current allotment seems too small. 1,300, 1,500, and 2,000 units were all suggested.
    • On a similar note, increase the bonus fuel allotment awarded for a safe landing. The thought was that a skillful player could possibly achieve continuous play.  Cool idea.
    • Increase the pace of the game. The time it takes to get from "orbit" to ground feels a bit long. This could be a simple matter of increasing the "gravity" and corresponding LEM "thrust" variables. I think this might also require better reaction time from the player. A related suggestion was to have the "gravity" increase after each successful landing.
    • Vary the point values of the landing zones. My initial landing zone "multipliers" were based on having higher values for smaller zones that were presumably harder to get to being on the sides or tops of the mountains. This is consistent with the arcade version. It was pointed out that the easier less valued landing zones were also deeper in the "gravity well" requiring more fuel. So my play testers quickly gravitated (see what I did there) to landing on the two 5x zones at or near the peaks of the mountains.
      One thought is to have an increased fuel "bonus" based on the fuel cost of landing on that target. Maybe that could be combined with a "big" bonus score for landing at all six zones?  Or what about a random 6x (or more) multiplier replacing one of the exiting zones for the current landing only. Lots to digest here.
    • Rather than having the LEM appear on the left top travelling right at 400 horizontal "units", randomize this. Different entry heights, velocities, positions, and even direction all suggested.

    • Right now the game only ends when the LEM is out of fuel and crashes. At some point in the game there is not enough fuel for even the most skillful player to land safely. The only recourse in that case is to expend the remaining fuel and wait "patiently" for the crash. One thought here is to apply 5 x the multiplier to the score if the LEM "crashes" into a landing zone.  This could also act as the "hard" landing bonus of the original arcade version. The player would then be encouraged to use their remaining fuel to try and "hit" a high value landing zone, still in the game to the bitter end.

    A lot of good ideas here. Lunar Lander is closing in on the 4K word memory limit of the PDP-1 so I appreciate that all of these suggestions are fairly easily implemented with minimal increases in code.  Things like scrolling/random terrain or zooming into the landing zone on close approach, like the arcade version does, are a little out of reach now without diving into page swapping.

    Some of these suggestion like increasing the initial fuel allotment,  faster game pace, and applying the multiplier (x 5) when crashing into a landing zone I think will be applied to the "core" game. These are all in line with my arcade game reproduction "target".

    The PDP-1 has a series of six "sense" switches on the Console that can be read from within a program.  I will use these switches to implement some of the other variants listed above as "options" to the game play. 

    There are not many opportunities for me to have people test my Lunar Lander implementation, so I appreciate all of my fellow retro...

    Read more »

  • Update 01/25/2026

    Michael Gardi01/25/2026 at 17:40 0 comments

    I posted updated code to the Files section above. Not much is new except that I have been cleaning up the code and doing some optimizations. 

    One big change is that I have implemented a 50 "gallon" penalty for each crash. I walked away in the middle of a game once for a couple of hours and came back to find that I had racked up a pretty good score (2000+) because the LEM was in a crashing loop and received 5 points for each crash.  The penalty limits a score achieved this way to about 40 points. 

  • Cleanup And Optomization

    Michael Gardi01/17/2026 at 19:21 0 comments

    I wanted to review the code I had written. When I started this project I was a complete noob to both the PDP-1 machine and it's assembly language (I had written 6502 and x86 assembly code before but not PDP-1). After about a month's effort I felt that I was beginning to "get it".

    So I went back and reviewed an early piece of code, drawing the LEM, and sure enough there were a number of improvements to be had.

    / Draw the LEM based on an 18-bit by 18 word bitmap.
       
       
            OLD                                NEW
            ===                                ===    
    
                                               lac (400000 
                                               dac bit
                                                
                                               lac bsx
                                               dac tmp     [+40]
    
    lbn,    lac .                      lbn,    lac .       
            sza i                              sza i       
            jmp lt1                            jmp lt1     
    
            dac bmr                            dac bmr     [-20]
            lac (400000         
            dac bit                        
                                           
    nb0,    lac bit                    nb0,    lac bit     [0]
            and bmr                            and bmr     
            sza i                              sza i       
            jmp nb1                            jmp nb1     
                                           
            lac bsx                            lac bsx     
            lio bsy                            lio bsy
            dpy-i 4700                         dpy-i 4700
                                               
    nb1,    lac bit                    nb1,    lac bit     [-10]
            sad (1                             rar 1s      
            jmp nrw                            dac bit 
                                               sad (400000 
            lac bit                            jmp nrw     
            rar 1s                         
            dac bit                                  
                                                  
            lac bsx                            lac bsx  
            add scl                            add scl   
            dac bsx                            dac bsx
            jmp nb0                            jmp nb0  
                                           
    nrw,    lac lbn                    nrw,    idx lbn     [-50]  
            add (1                         
            dac lbn                                
                                                   
            lac bsy                            lac bsy    
            sub scl                            sub scl
            dac bsy                            dac bsy 
                                                   
            lac scx                            lac tmp 
            sub (4400                          dac bsx 
            dac bsx 
                                              
            lac (400000         
            dac bit
            jmp lbn                           jmp lbn  

    I'm not going to go into detail on the code above (comments were removed to get everything to fit). Suffice it to say that I'm pretty happy with the improvements. The important thing here is the numbers off to the right. They represent the number of microseconds I was able to eliminate from the OLD code when creating the NEW. Both of course do exactly the same thing.

    PDP-1 instructions have the following performance characteristics:

    • Memory Cycle Time: The fundamental memory cycle time of the PDP-1 is 5 microseconds.
    • Instruction Speed: The jmp instruction, along with other single-cycle instructions, requires only one memory reference and completes within that 5-microsecond cycle.
    • Indirect Addressing: If a jmp instruction uses indirect addressing (indicated by a 1 in the defer bit), it requires an additional 5 microseconds for each level of redirection.
    • Comparison: Unlike jmp, two-cycle instructions (such as add, sub, deposit, or load) take 10 microseconds to complete. 

    In the above code comparison the numbers on the right indicate the how many "microseconds" were removed from that block of the code (demarked by the labels). Another thing to consider is how any times that block of code will be executed when drawing the LEM.  The stuff above lbn executes only once, both the lbn and nrw blocks execute once per row of the bitmap, while the nb1 code executes once per pixel. The total savings for optimizing this code is:

    One time only code =             -40 microseconds
    (20 + 50) x 18 rows =          1,260 microseconds
    10 x 18 columns x 18 rows =    3,240 microseconds
                                   ==================
                                   4,460 microseconds
                                 

    or about 4.5 ms every time the LEM is drawn which is about 10 times per second.  That doesn't sound like much but it leaves more time to draw the other pixels and thus reduce flicker (say).

View all 25 project logs

Enjoy this project?

Share

Discussions

Oscarv wrote 03/14/2026 at 02:22 point

An absolute masterpiece in many ways. That this runs on 1959 hardware is nothing short of amazing. Let's get it on the real PDP-1 at CHM! (Which will also be the ultimate acid test for the PiDP-1 simulator). Thank you!!

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates