diff --git a/PDP8/pdp8_defs.h b/PDP8/pdp8_defs.h
index 3cc84227..71ceb4a7 100644
--- a/PDP8/pdp8_defs.h
+++ b/PDP8/pdp8_defs.h
@@ -107,6 +107,7 @@ typedef struct {
#define DEV_PTP 002 /* paper tape punch */
#define DEV_TTI 003 /* console input */
#define DEV_TTO 004 /* console output */
+#define DEV_DPY 005 /* Type 34 display */
#define DEV_CLK 013 /* clock */
#define DEV_TSC 036
#define DEV_KJ8 040 /* extra terminals */
diff --git a/PDP8/pdp8_dpy.c b/PDP8/pdp8_dpy.c
new file mode 100644
index 00000000..3c019ee6
--- /dev/null
+++ b/PDP8/pdp8_dpy.c
@@ -0,0 +1,153 @@
+#ifdef USE_DISPLAY
+/* pdp8_dpy.c: Type 34 point-plotting display
+
+ Copyright (c) 2025, Lars Brinkhoff
+
+ Permission is hereby granted, free of charge, to any person obtaining a
+ copy of this software and associated documentation files (the "Software"),
+ to deal in the Software without restriction, including without limitation
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ and/or sell copies of the Software, and to permit persons to whom the
+ Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ Except as contained in this notice, the names of the authors shall not be
+ used in advertising or otherwise to promote the sale, use or other dealings
+ in this Software without prior written authorization from the authors.
+*/
+
+#include "pdp8_defs.h"
+#include "display/display.h"
+#include "sim_video.h"
+
+/* Run a Type 34 cycle every this many PDP-8 "cycle" times. */
+#define DPY_DELAY 1
+
+/* Memory cycle time. */
+#define MEMORY_CYCLE 1
+
+#define CYCLE_US (MEMORY_CYCLE*(DPY_DELAY*2+1))
+
+t_stat dpy_svc(UNIT *uptr);
+int32 dpy_iot (int32 IR, int32 AC);
+t_stat dpy_reset(DEVICE *dptr);
+t_stat dpy_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr);
+const char *dpy_description (DEVICE *dptr);
+
+DIB dpy_dib = { DEV_DPY, 2, { &dpy_iot, &dpy_iot } };
+
+UNIT dpy_unit = {
+ UDATA (&dpy_svc, UNIT_IDLE, 0), 0
+};
+
+static t_bool dpy_quit = FALSE;
+static uint16 dpy_x, dpy_y;
+
+static void dpy_quit_callback (void)
+{
+ dpy_quit = TRUE;
+}
+
+DEVICE dpy_dev = {
+ "DPY", &dpy_unit, NULL, NULL,
+ 1, 8, 16, 1, 8, 16,
+ NULL, NULL, &dpy_reset,
+ NULL, NULL, NULL,
+ &dpy_dib, DEV_DIS | DEV_DISABLE, 0,
+ NULL, NULL, NULL, NULL, NULL, NULL,
+ &dpy_description
+};
+
+t_stat
+dpy_svc(UNIT *uptr)
+{
+#ifdef USE_DISPLAY
+ display_age (100, 0);
+ sim_activate_after (uptr, 100);
+ if (dpy_quit) {
+ dpy_quit = FALSE;
+ return SCPE_STOP;
+ }
+#endif
+ return SCPE_OK;
+}
+
+/* Type 34: IOT routine */
+
+int32 dpy_iot (int32 IR, int32 AC)
+{
+ switch (IR & 071) {
+ case 051: /* DCX */
+ dpy_x = 0;
+ break;
+ case 061: /* DCY */
+ dpy_y = 0;
+ break;
+ }
+
+ switch (IR & 072) {
+ case 052: /* DXL */
+ dpy_x |= AC & 01777;
+ break;
+ case 062: /* DYL */
+ dpy_y |= AC & 01777;
+ break;
+ }
+
+ switch (IR & 004) {
+ case 004: /* DIX, DIY */
+#ifdef USE_DISPLAY
+ if (dpy_dev.flags & DEV_DIS)
+ break;
+ display_point (dpy_x, dpy_y, DISPLAY_INT_MAX, 0);
+#endif
+ break;
+ }
+
+ return AC;
+}
+
+t_stat
+dpy_reset(DEVICE *dptr)
+{
+#ifdef USE_DISPLAY
+ if (dptr->flags & DEV_DIS || (sim_switches & SWMASK('P')) != 0) {
+ display_close (dptr);
+ sim_cancel (&dpy_unit);
+ } else {
+ display_reset ();
+ display_init (DIS_TYPE30, 1, dptr);
+ vid_register_quit_callback (&dpy_quit_callback);
+ sim_activate_abs (&dpy_unit, 0);
+ }
+#endif
+ return SCPE_OK;
+}
+
+const char *dpy_description (DEVICE *dptr)
+{
+ return "Type 34 vector display controller";
+}
+
+void
+cpu_get_switches(unsigned long *p1, unsigned long *p2)
+{
+}
+
+void
+cpu_set_switches(unsigned long w1, unsigned long w2)
+{
+}
+
+#else /* USE_DISPLAY not defined */
+char pdp8_dpy_unused; /* sometimes empty object modules cause problems */
+#endif /* USE_DISPLAY not defined */
diff --git a/PDP8/pdp8_sys.c b/PDP8/pdp8_sys.c
index 55962b80..69d4c82f 100644
--- a/PDP8/pdp8_sys.c
+++ b/PDP8/pdp8_sys.c
@@ -67,6 +67,9 @@ extern DEVICE df_dev, rf_dev;
extern DEVICE dt_dev, td_dev;
extern DEVICE mt_dev, ct_dev;
extern DEVICE ttix_dev, ttox_dev;
+#ifdef USE_DISPLAY
+extern DEVICE dpy_dev;
+#endif
extern REG cpu_reg[];
extern uint16 M[];
@@ -114,6 +117,10 @@ DEVICE *sim_devices[] = {
&td_dev,
&mt_dev,
&ct_dev,
+ &ct_dev,
+#ifdef USE_DISPLAY
+ &dpy_dev,
+#endif
NULL
};
@@ -332,6 +339,8 @@ static const char *opcode[] = {
"PCE", "PSF", "PCF", "PPC", "PLS",
"KCF", "KSF", "KCC", "KRS", "KIE", "KRB", /* console */
"TLF", "TSF", "TCF", "TPC", "SPI", "TLS",
+ "DCX", "DXL", "DIX", "DXS",
+ "DCY", "DYL", "DIY", "DYS",
"SBE", "SPL", "CAL", /* power fail */
"CLEI", "CLDI", "CLSC", "CLLE", "CLCL", "CLSK", /* clock */
"CINT", "RDF", "RIF", "RIB", /* mem mmgt */
@@ -400,6 +409,8 @@ static const int32 opc_val[] = {
06020+I_NPN, 06021+I_NPN, 06022+I_NPN, 06024+I_NPN, 06026+I_NPN,
06030+I_NPN, 06031+I_NPN, 06032+I_NPN, 06034+I_NPN, 06035+I_NPN, 06036+I_NPN,
06040+I_NPN, 06041+I_NPN, 06042+I_NPN, 06044+I_NPN, 06045+I_NPN, 06046+I_NPN,
+ 06051+I_NPN, 06053+I_NPN, 06054+I_NPN, 06057+I_NPN,
+ 06061+I_NPN, 06063+I_NPN, 06064+I_NPN, 06067+I_NPN,
06101+I_NPN, 06102+I_NPN, 06103+I_NPN,
06131+I_NPN, 06132+I_NPN, 06133+I_NPN, 06135+I_NPN, 06136+I_NPN, 06137+I_NPN,
06204+I_NPN, 06214+I_NPN, 06224+I_NPN, 06234+I_NPN,
diff --git a/PDP8/tests/dpy_test.do b/PDP8/tests/dpy_test.do
new file mode 100644
index 00000000..9b1b6328
--- /dev/null
+++ b/PDP8/tests/dpy_test.do
@@ -0,0 +1,14 @@
+DEPOSIT 200 CLA
+DEPOSIT 201 TAD 207
+;Display one point in the center: (1000,1000)
+DEPOSIT 202 DXL
+DEPOSIT 203 DYS
+DEPOSIT 204 TAD 210
+;Display another point mid-way to the right: (1400,1000)
+DEPOSIT 205 DXS
+DEPOSIT 206 JMP 200
+DEPOSIT 207 1000
+DEPOSIT 210 400
+
+SET DPY ENABLED
+GO 200
diff --git a/Visual Studio Projects/PDP8.vcproj b/Visual Studio Projects/PDP8.vcproj
index 0f52ab0c..cb10d4a7 100644
--- a/Visual Studio Projects/PDP8.vcproj
+++ b/Visual Studio Projects/PDP8.vcproj
@@ -34,6 +34,9 @@
+
@@ -41,7 +44,7 @@
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../PDP8/;./;../;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/include;;../../windows-build/include/SDL2"
- PreprocessorDefinitions="_CRT_NONSTDC_NO_WARNINGS;SIM_BUILD_TOOL=simh-Visual-Studio-Project;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCRE_H;PCRE_STATIC;HAVE_LIBEDIT"
+ PreprocessorDefinitions="USE_DISPLAY;USE_SIM_VIDEO;_CRT_NONSTDC_NO_WARNINGS;SIM_BUILD_TOOL=simh-Visual-Studio-Project;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCRE_H;PCRE_STATIC;HAVE_LIBSDL;HAVE_LIBPNG;HAVE_LIBEDIT"
KeepComments="false"
BasicRuntimeChecks="0"
RuntimeLibrary="1"
@@ -117,6 +120,9 @@
+
@@ -127,7 +133,7 @@
OmitFramePointers="true"
WholeProgramOptimization="true"
AdditionalIncludeDirectories="../PDP8/;./;../;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/include;;../../windows-build/include/SDL2"
- PreprocessorDefinitions="_CRT_NONSTDC_NO_WARNINGS;SIM_BUILD_TOOL=simh-Visual-Studio-Project;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCRE_H;PCRE_STATIC;HAVE_LIBEDIT"
+ PreprocessorDefinitions="USE_DISPLAY;USE_SIM_VIDEO;_CRT_NONSTDC_NO_WARNINGS;SIM_BUILD_TOOL=simh-Visual-Studio-Project;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCRE_H;PCRE_STATIC;HAVE_LIBSDL;HAVE_LIBPNG;HAVE_LIBEDIT"
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
@@ -195,6 +201,10 @@
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"
>
+
+
@@ -211,6 +221,10 @@
RelativePath="..\PDP8\pdp8_df.c"
>
+
+
@@ -311,11 +325,19 @@
RelativePath="..\sim_video.c"
>
+
+
+
+
@@ -372,6 +394,10 @@
RelativePath="..\sim_video.h"
>
+
+