Graphics programming on the PiDP-10

192 views
Skip to first unread message

Francis King

unread,
Sep 28, 2025, 5:56:08 PMSep 28
to PiDP-10
Now that I have two working PiDP-10s in effect (one the PiDP10 console / Pi 5, one the x86 simulation running on a Lenovo 580 laptop), I'd like to have a go at graphics programming. I am not sure how best to do this.

As I understand it, graphics requires ITS rather than TOPS-10 or TOPS-20. Is this correct, please? If so, I am golden, since I have figured out how ITS works, reasonably well.

Is there a guide to programming graphics? Is there a programming language which is more practical than the others?

Advice please.

PS: When I ran pdpcontrol start 1 on the x86 simulation, I couldn't get pdp con to work, although pdp view worked well. This is odd, because the teletype appears to be part of the pdp view terminal.

dave avery

unread,
Sep 28, 2025, 7:13:15 PMSep 28
to Francis King, PiDP-10
There were graphics on tops 10 machines.  Model 340 displays and other vector displays

Sent from Gmail Mobile


--
You received this message because you are subscribed to the Google Groups "PiDP-10" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pidp-10+u...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/pidp-10/5e5930b0-c2cc-4f87-b024-46cb1e28de78n%40googlegroups.com.

Lars Brinkhoff

unread,
Sep 29, 2025, 12:34:02 AMSep 29
to PiDP-10
TVBROT is an example of a program that displays on both the Knight TV and the 340, subject to an assembly time switch.

The Type 340 is described here:

Francis King

unread,
Sep 29, 2025, 7:10:44 AMSep 29
to PiDP-10
Thanks, Lars.

I have read some of the PDF that you recommended. The documentation provides an example in the MACRO programming language. The questions that I have relate to where I start my exploration of graphics on the PDP-10. Does the following seem reasonable?

  • MACRO-10
  • TOPS-10 (according to the PiDP-10 book, p.244, MACRO-10 doesn't work properly on ITS)

Lars Brinkhoff

unread,
Sep 29, 2025, 7:28:51 AMSep 29
to PiDP-10
Francis wrote:
The questions that I have relate to where I start my exploration of graphics on the PDP-10. Does the following seem reasonable?
  • MACRO-10
  • TOPS-10 (according to the PiDP-10 book, p.244, MACRO-10 doesn't work properly on ITS)

If you're going with TOPS-10, MACRO-10 should be your best choice.  But I don't know how to do graphics programming on TOPS-10, so I can't say whether it's advisable or not.  It would probably only have the Type 340 (or the mostly equivalent VB10C).

If you're going with ITS, you should use MIDAS.  But it's simliar to MACRO-10, so no big deal.  ITS also has the Knight TV monochrome raster, color scope, IMLAC, and GT40 available for graphics programming of various flavours.

MACRO-10 does work on ITS.  There may be some edge cases that don't work.  It can assemble itself.

Francis King

unread,
Oct 1, 2025, 5:58:15 PMOct 1
to PiDP-10
I've just worked through the Macro-10 Disassembly Language Handbook. I'm coming at this from the viewpoint of Z80A programming. Some questions please.

Am I correct in my understanding that the PDP-10 doesn't have a stack? If so, how do you call a subroutine?

Francis.

Eric Swenson

unread,
Oct 1, 2025, 6:52:50 PMOct 1
to Francis King, PiDP-10
I’m most definitely not the best person to answer this — and I’m sure someone will provide a better answer.  But….

There is not “a stack” for the PDP-10.  However, any application can allocate some stack space (array or 36-bit words) and initialize a PDP-10 register to hold an AOBJN pointer (see later) to the base of the stack.  Then, stack-based calls can be done with the PUSHP SP, instructor and returns can be done with the POPJ SP, instruction, where SP is defined as the register that points to the stack.  Register 17 is frequently used as the stack pointer for an application (although this is not required).  There is nothing stopping a PDP-10 program from having more than one stack and using more than one register for stack pointers.

One of the first things a PDP-10 program that uses a stack must do is set up the stack.  Assuming you have allocate some space in your program for the stack, frequently called a “PDL” (push down list), and assuming that this location is memory is located at the symbol PDL and that the stack length you allocated is defined by the constant PDLLEN, then you do this to initialize your stack pointer:

MOVE SP,[-PDLLEN,,PDL]

This sets up an AOBJN pointer, where the negative length (-PDLLEN) is in the left half (LH) of a word, and the top-of-stack is located in the right half (RH).

Now, you can call your subroutines with:

PUSHJ SP, FOO

Where FOO is the subroutine.  That subroutine can return with:

POPJ SP,

The PUSHJ SP, FOO instruction will first add 000001000001 (base 8)  to the memory referenced by SP.  If the LH of SP goes to zero, the Pushdown Overflow flag will be set.  Then PUSHJ will place the address of the next instruction (the return address), into the RH of SP.  If will then JUMP to the address of FOO.

The increment of both halves of SP will set things up for the next PUSHJ or POPJ.

The POPJ SP, instruction will take the return address from the location addressed by the RH of SP (and hang onto it until the stack is adjusted).  Then it will subtract 000001000001 from the memory addressed by SP.  If this causes the LH of SP to go to -1, the Pushdown Overflow flag will be set.  Then the POPJ instruction will cause a transfer to the address retrieved prior to the decrement.

I’ve written the above from memory and haven’t programmed in assembly on a PDP-10 for many months, so I may have messed up the description in some way.  I’m sure someone else will correct me if I did.

The main takeways are that there isn’t a single stack, but any program is free to define one or more stacks (usually one), and then use the PUSHJ and POPJ instructions to “call” and “return” from subroutines.

Oh, I forgot to give an example of allocation stack space in the program:

pdllen==100.   ;this is how deep the stack should be
pdl: block pdllen

100 words are allocated at the address specified by PDL.

— Eric

--
You received this message because you are subscribed to the Google Groups "PiDP-10" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pidp-10+u...@googlegroups.com.

Lars Brinkhoff

unread,
Oct 2, 2025, 12:37:52 AMOct 2
to Eric Swenson, Francis King, PiDP-10
Eric Swenson wrote:
There is not “a stack” for the PDP-10.  However, any application can allocate some stack space (array or 36-bit words) and initialize a PDP-10 register to hold an AOBJN pointer (see later) to the base of the stack.  Then, stack-based calls can be done with the PUSHP SP, instructor and returns can be done with the POPJ SP, instruction, where SP is defined as the register that points to the stack.  Register 17 is frequently used as the stack pointer

Minor additional notes.  The "stack" is often called the "pushdown list", aka PDL.  The stack pointer is usually called P.  Maybe it's best to stick to this convention. 

Lars Brinkhoff

unread,
Oct 2, 2025, 12:57:10 AMOct 2
to PiDP-10
Eric Swenson wrote:
then you do this to initialize your stack pointer:

MOVE SP,[-PDLLEN,,PDL]

One more thing.  You can do MOVE P,[-PDLLEN,PDL-1]
The stack grows up, and when a word is pushed, the pointer is incremented before writing to memory. 

Eric Swenson

unread,
Oct 2, 2025, 1:14:06 AMOct 2
to Lars Brinkhoff, PiDP-10
I think Lars meant to use a ,, rather than a single comma in his example. FOO,,BAR is the standard way of writing two half-words with a LF and RH.

On Oct 1, 2025, at 21:57, Lars Brinkhoff <lars.br...@gmail.com> wrote:


--
You received this message because you are subscribed to the Google Groups "PiDP-10" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pidp-10+u...@googlegroups.com.

Ric Werme

unread,
Oct 2, 2025, 1:49:37 AMOct 2
to PiDP-10
I think Lars meant to use a ,, rather than a single comma in his example.

To init a stack pointer, use [iowd len,addr] where addr is the start of the stack.  It generates [-len,,addr-1].

I started a new topic - this goes way beyond graphics programming.

Lars Brinkhoff

unread,
Oct 2, 2025, 2:02:37 AMOct 2
to Ric Werme, PiDP-10
Ric Werme wrote:
To init a stack pointer, use [iowd len,addr] where addr is the start of the stack.  It generates [-len,,addr-1].

That's a MACRO thing.  IOWD doesn't exist in MIDAS.  You can define one yourself, of course.  But the convention in ITS is to spell it out -len,,addr-1. 

Ric Werme

unread,
Oct 2, 2025, 7:52:46 AMOct 2
to PiDP-10
Francis wrote:
I've just worked through the Macro-10 Disassembly Language Handbook.

Disassembly?  I don't see that mentioned here or on Google.  Typo?  Or something I've missed?

I went from PDP-10 to Z80.  The loss of all those general purpose registers was the hardest transition.  Learning hexadecimal addition and multiplication tables was annoying - octal is much much easier.  AOBJN is a wonderful instruction.  I was positively impressed with the PIO, SIO, and DMA support chips from Zilog - each replaced a cabinet, more or less, on the KA10 (think LPT, DC10, DF10).

Francis King

unread,
Dec 13, 2025, 1:03:11 PM (12 days ago) Dec 13
to PiDP-10
I have made some progress with the Type 340 display, but have some questions about why it doesn't work.

The basic idea is the example from the Type 340 display manual, page 2-17: https://bitsavers.org/pdf/dec/graphics/H-340_Type_340_Precision_Incremental_CRT_System_Nov64.pdf

I have written a minimal example, in file "Point Mid": 

          Title Point

DIS=130
PI=004

; handle error conditions
LOC 54
          JSR, WHY
          BLOCK 1

; set data to display
LOC 56
          BLKO DIS, TABLE
          JSR , RESTART

;  set up interrupts, devices PI and DIS
START:    CONO PI, 2203
                 CONO DIS, 167

LOOP:     JUMPA LOOP

TABLE:    XWD -1, TABLE
         XWD 022100, 222100

POINT:    XWD -1, TABLE

RESTART:  BLOCK 1
                    MOVE 0, POINT
                    MOVEM 0, TABLE
                   JRST 12, @.-3

WHY:      BLOCK 1
        JRST 12, @WHY

END       START

Comments:

  1. In the original code, the assembler knows what DIS and PI are. I have had to define them myself
  2. In the original code, the interrupt locations are given as LOC 54:, but here the MIDAS assembler wants LOC 54 instead
  3. I create a loop at LOOP:, waiting for an interrupt
  4. The original code had a reserved word using Z, but midas doesn't seem to have this, so I've used BLOCK 1
  5. The original label was REPEAT: but midas said this is macro name already, so now it's RESTART:
  6. This code assembles OK, :midas ts point_point
  7. When run it has an ILOPR response: ILOPR; 60>>CONO PI,2203      2203/     ??
Thoughts please.

Eric Swenson

unread,
Dec 13, 2025, 4:23:55 PM (12 days ago) Dec 13
to Francis King, PiDP-10
I don’t know the answer off the top of my head and I’m on a phone without access to ITS now. However, if you are trying to run this as a logged in user of ITS under time sharing, the ILOPR fault is due to not being able to access I/O ports from user processes. 

Are you trying to run standalone from DSKDMP or as a TS XXXXXX program under timesharing?

If you are using timesharing, then I think you need to use a slave interface that calls ITS (which switches to monitor mode where I/o instructions are allowed). I can remember the details off the top of my head.

Lars will surely know exactly what you need to do here and will likely respond to your message soon.

I know that SHRDLU, written in LISP, uses a SLAVE FASL to talk to the slave device that allows calls into ITS to talk to the GT40). But the details escape me now.

— Eric

On Dec 13, 2025, at 10:03, Francis King <francis...@gmail.com> wrote:

I have made some progress with the Type 340 display, but have some questions about why it doesn't work.
--
You received this message because you are subscribed to the Google Groups "PiDP-10" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pidp-10+u...@googlegroups.com.

Lars Brinkhoff

unread,
Dec 14, 2025, 12:35:41 AM (12 days ago) Dec 14
to Francis King, PiDP-10
Francis King wrote:
> 1. In the original code, the assembler knows what DIS and PI are. I have had to define them myself
> 2. In the original code, the interrupt locations are given as LOC 54:, but here the MIDAS assembler wants LOC 54 instead

These, and 4, 5 below, I believe are  because the original code was for MACRO, not MIDAS.

3. I create a loop at LOOP:, waiting for an interrupt
4. The original code had a reserved word using Z, but midas doesn't seem to have this, so I've used BLOCK 1
5. The original label was REPEAT: but midas said this is macro name already, so now it's RESTART:
6. This code assembles OK, :midas ts point_point 
7. When run it has an ILOPR response: ILOPR; 60>>CONO PI,2203

7 is probably because you're running from user mode, and then CONO and other IOTs are not allowed.  You would need to enter IOTLSR mode.  See SYSDOC;UUOS. 

Francis King

unread,
Dec 14, 2025, 3:17:53 PM (11 days ago) Dec 14
to PiDP-10
Thank you for that. I've read the Lorenz code and SYSDOC; UUOS

While reading the UUOS text for IOTLSR, I came across the following:

If bit 4.9 (the sign bit) of accumulator <ac> is zero,
.IOTLSR mode is relinquished, even if it was not formerly
possessed by the job.
If bit 4.9 is one, then the executing job is granted .IOTLSR
mode, and the system job prints a message on the system
console to document the fact.

I'm confused by the notation bit x.y What does this mean please? I've done computers for 40 years, and I've never seen that before.

Chuck McManis

unread,
Dec 14, 2025, 7:28:53 PM (11 days ago) Dec 14
to dave avery, Francis King, PiDP-10
On Sun, Sep 28, 2025 at 4:13 PM dave avery <daveave...@gmail.com> wrote:
There were graphics on tops 10 machines.  Model 340 displays and other vector displays

This is correct AND if you have an Xterm compiled with sixel graphics, you can run those programs and see all the pretty colors :-)

--Chuck
 

Lars Brinkhoff

unread,
Dec 15, 2025, 12:38:25 AM (11 days ago) Dec 15
to Francis King, PiDP-10
Francis King wrote:
I'm confused by the notation bit x.y What does this mean please? I've done computers for 40 years, and I've never seen that before.

That notation is unique to MIT and ITS.  I think it's documented in at least as early as the ITS 1.4 Reference Manual.  X is the word "quadrant" with 1 being the least significant, and 4 the most.  Y is the bit in side the quadrant, again 1 being least significant.  So 4.9 means the most significant bit in the word. 

Francis King

unread,
Dec 18, 2025, 9:24:56 AM (7 days ago) Dec 18
to PiDP-10
I am making incremental progress:

         Title Point

DIS=130
PI=004
X=1                                                   ;  new item


; handle error conditions
LOC 54
          JSR, WHY
          BLOCK 1

; set data to display
LOC 56
          BLKO DIS, TABLE
          JSR , RESTART

;  set up interrupts, devices PI and DIS
LOC 100                                      ; new item

START:    SETO X,                      ; new item
                 .IOTLSR X,                 ; new item

                 CONO PI, 2203
                 CONO DIS, 167

LOOP:     JUMPA LOOP

TABLE:    XWD -2, TABLE            ; changed item
         XWD 020016, 022100
                 XWD 222100, 000000

POINT:    XWD -2, TABLE             ; changed item


RESTART:  BLOCK 1
                    MOVE 0, POINT
                    MOVEM 0, TABLE
                   JRST 12, @.-3

WHY:      BLOCK 1
        JRST 12, @WHY

END       START

I have made the following changes:
  1. I have added .IOTLSR to the code. The teletype says that I have enabled this, as promised in the documentation
  2. The code runs without complaint now, no more illegal instructions
  3. I have added LOC 100, missing before    :)
  4. I have expanded the table to include an 18-bit parameter word
So, it should do something. And it does. It does the wrong things.

  1.  It draws to the Knight terminal, rather than the Type 340, a thin green bit of activity at the bottom of the terminal 
  2. It locks the Knight terminal up. F1 doesn't work, neither does Ctrl-Z. I can't start a parallel terminal, and I have to use pdpcontrol stop / pdpcontrol start 1 to continue
 

Lars Brinkhoff

unread,
Dec 19, 2025, 1:45:12 AM (7 days ago) Dec 19
to Francis King, PiDP-10
Francis King wrote:
So, it should do something. And it does. It does the wrong things.
  1.  It draws to the Knight terminal, rather than the Type 340, a thin green bit of activity at the bottom of the terminal 
This is because your program is running at full speed, due to the tight JUMPA LOOP.  You should instead do this to pause your program and only execute the interrupts.

JFCL
 .HANG

Second, the thin green line (idea for a movie, eh?) is a CPU indicator light drawn by ITS.  Usually if you run a program it will flicker on and off.

Third, you need to trigger a 340 interrupt to get to the BLKO.  Er, I don't remember how right now!

Fourth, and I apologize for not mentioning this earlier, if you want to output a display list (340 program) there is a better way: the .DSTART uuo.  You should do something like .DSTART [-2,,TABLE-1], dropping the XWD, and then ITS will handle the interrupts, the BLKO pointer, the restarting, etc.
  1. It locks the Knight terminal up. F1 doesn't work, neither does Ctrl-Z. I can't start a parallel terminal, and I have to use pdpcontrol stop / pdpcontrol start 1 to continue
There is a problem somewhere in the emulators when "too much" is drawn on a Knight TV.  It will hang the system.

Francis King

unread,
Dec 19, 2025, 9:54:28 AM (6 days ago) Dec 19
to PiDP-10
Thanks for your continued support and advice.

I tried a few things:
  1. Replacing LOOP: JUMPA LOOP with LOOP: JFCL  .HANG, but this uses just as much CPU. Terminal locks, nothing on Type 340 display. 
  2. Replacing LOOP: JFCL . HANG with CONO DIS, 100 .HANG. But this gives an illegal instruction error
  3. I tried .DSTART [-N,,TABLE-1], but it doesn't appear to loop, handle restarts, etc. It just seems to open the display and move to the next instruction, so reports illegal operation when the code execution moves to the table
With my original program, I agree that we are missing something with the interrupts.  If the worst comes to the worst, we could use polling, as most/all of the examples do.

Lars Brinkhoff

unread,
Dec 19, 2025, 10:41:22 AM (6 days ago) Dec 19
to Francis King, PiDP-10
Francis King wrote:
> Replacing LOOP: JUMPA LOOP with LOOP: JFCL  .HANG, but this uses just as much CPU. Terminal locks, nothing on Type 340 display. \\

It looks like you have JFCL and .HANG on the same line.  That will not work.  Read about .HANG in SYSDOC;UUOS.

> I tried .DSTART [-N,,TABLE-1], but it doesn't appear to loop, handle restarts, etc. It just seems to open the display and move to the next instruction, so reports illegal operation when the code execution moves to the table

Read about .DSTART in SYSDOC;UUOS.
Reply all
Reply to author
Forward
0 new messages