diff --git a/PDP1/pdp1_dpy.c b/PDP1/pdp1_dpy.c index 805de2f5..9c21606b 100644 --- a/PDP1/pdp1_dpy.c +++ b/PDP1/pdp1_dpy.c @@ -35,6 +35,7 @@ #ifdef USE_DISPLAY #include "pdp1_defs.h" #include "display/display.h" +#include "sim_video.h" extern int32 ios, cpls, iosta, PF; extern int32 stop_inst; @@ -55,12 +56,33 @@ t_stat dpy_reset (DEVICE *dptr); UNIT dpy_unit = { UDATA (&dpy_svc, UNIT_ATTABLE, 0), DPY_WAIT }; +static t_bool dpy_stop_flag = FALSE; + +static void dpy_quit_callback (void) +{ +dpy_stop_flag = TRUE; +} + +#define DEB_VMOU SIM_VID_DBG_MOUSE /* Video mouse */ +#define DEB_VKEY SIM_VID_DBG_KEY /* Video key */ +#define DEB_VCUR SIM_VID_DBG_CURSOR /* Video cursor */ +#define DEB_VVID SIM_VID_DBG_VIDEO /* Video */ + +DEBTAB dpy_deb[] = { + { "VMOU", DEB_VMOU, "Video Mouse" }, + { "VKEY", DEB_VKEY, "Video Key" }, + { "VCUR", DEB_VCUR, "Video Cursor" }, + { "VVID", DEB_VVID, "Video Video" }, + { NULL, 0 } + }; + DEVICE dpy_dev = { "DPY", &dpy_unit, NULL, NULL, 1, 10, 31, 1, 8, 8, NULL, NULL, &dpy_reset, NULL, NULL, NULL, - NULL, DEV_DIS | DEV_DISABLE }; + NULL, DEV_DIS | DEV_DISABLE | DEV_DEBUG, + 0, dpy_deb}; /* Display IOT routine */ @@ -115,8 +137,6 @@ return io; /* * Unit service routine * - * Under X11 this includes polling for events, so it can't be - * call TOO infrequently... */ t_stat dpy_svc (UNIT *uptr) { @@ -124,8 +144,12 @@ t_stat dpy_svc (UNIT *uptr) ios = 1; /* restart */ cpls = cpls & ~CPLS_DPY; } /* clr pulse pending */ - display_age(dpy_unit.wait*CYCLE_TIME, 1); - sim_activate (&dpy_unit, dpy_unit.wait); /* requeue! */ + display_age(dpy_unit.wait*CYCLE_TIME, 0); + sim_activate_after (&dpy_unit, dpy_unit.wait*CYCLE_TIME); /* requeue! */ + if (dpy_stop_flag) { + dpy_stop_flag = FALSE; /* reset flag after we notice it */ + return SCPE_STOP; + } return SCPE_OK; } @@ -134,7 +158,9 @@ t_stat dpy_svc (UNIT *uptr) t_stat dpy_reset (DEVICE *dptr) { if (!(dptr->flags & DEV_DIS)) { + display_init(DISPLAY_TYPE, PIX_SCALE, dptr); display_reset(); + vid_register_quit_callback (&dpy_quit_callback); cpls = cpls & ~CPLS_DPY; iosta = iosta & ~(IOS_PNT | IOS_SPC); /* clear flags */ } diff --git a/PDP11/pdp11_defs.h b/PDP11/pdp11_defs.h index 40633823..e809d5e7 100644 --- a/PDP11/pdp11_defs.h +++ b/PDP11/pdp11_defs.h @@ -636,9 +636,8 @@ typedef struct pdp_dib DIB; #define INT_V_DCO 12 /* VT simulation is sequential, so only one interrupt is posted at a time. */ -#define INT_V_VTLP 13 /* XXX - Manual says VTLP, VTST have opposite */ -#define INT_V_VTST 14 /* XXX precedence, but that breaks LUNAR! */ - /* XXX How this happens is an utter mystery. */ +#define INT_V_VTST 13 +#define INT_V_VTLP 14 #define INT_V_VTCH 15 #define INT_V_VTNM 16 #define INT_V_LK 17 @@ -784,6 +783,7 @@ typedef struct pdp_dib DIB; #define IREQ(dv) int_req[IPL_##dv] #define SET_INT(dv) int_req[IPL_##dv] = int_req[IPL_##dv] | (INT_##dv) #define CLR_INT(dv) int_req[IPL_##dv] = int_req[IPL_##dv] & ~(INT_##dv) +#define INT_IS_SET(dv) (int_req[IPL_##dv] & (INT_##dv)) /* Massbus definitions */ diff --git a/PDP11/pdp11_io_lib.c b/PDP11/pdp11_io_lib.c index c29c46a5..18e37a83 100644 --- a/PDP11/pdp11_io_lib.c +++ b/PDP11/pdp11_io_lib.c @@ -657,6 +657,8 @@ AUTO_CON auto_tab[] = {/*c #v am vm fxa fxv */ { { NULL }, 1, 2, 16, 8 }, /* DH11 */ { { "VT" }, 1, 4, 0, 8, {012000, 012010, 012020, 012030} }, /* VT11/GT40 - fx CSRs */ + { { "VS60" }, 1, 4, 0, 8, + {012000} }, /* VS60/GT48 - fx CSRs */ { { NULL }, 1, 2, 0, 8, {010400} }, /* LPS11 */ { { NULL }, 1, 2, 8, 8 }, /* DQ11 */ diff --git a/PDP11/pdp11_vt.c b/PDP11/pdp11_vt.c index 433347e4..157dcac5 100644 --- a/PDP11/pdp11_vt.c +++ b/PDP11/pdp11_vt.c @@ -47,6 +47,7 @@ #include "display/display.h" #include "display/vt11.h" +#include "sim_video.h" /* * Timing parameters. Should allow some runtime adjustment, @@ -61,8 +62,9 @@ /* * run a VT11/VS60 cycle every this many PDP-11 "cycle" times; * - * Under the X Window System (X11), this includes polling - * for events (mouse movement)! + * this includes phosphor aging and polling for events (mouse movement) + * every refresh_interval (determined internally while processing the + * VT11/VS60 cycle). */ #define VT11_DELAY 1 @@ -109,43 +111,106 @@ const char *vt_description (DEVICE *dptr); #define IOLN_VT11 010 /* VT11 */ #define IOLN_VS60 040 /* VS60 */ DIB vt_dib = { IOBA_AUTO, IOLN_VT11, &vt_rd, &vt_wr, - 4, IVCL(VTST), VEC_AUTO, {NULL} }; + 4, IVCL(VTST), VEC_AUTO, {NULL}, IOLN_VT11 }; /* (VT11 uses only the first 3 interrupt vectors) */ UNIT vt_unit = { - UDATA (&vt_svc, UNIT_SEQ, 0), VT11_DELAY}; + UDATA (&vt_svc, UNIT_SEQ, 0), VT11_DELAY}; REG vt_reg[] = { + { DRDATAD (CYCLE, vt_unit.wait, 24, "VT11/VS60 cycle"), REG_NZ + PV_LEFT }, { GRDATA (DEVADDR, vt_dib.ba, DEV_RDX, 32, 0), REG_HRO }, { GRDATA (DEVVEC, vt_dib.vec, DEV_RDX, 16, 0), REG_HRO }, { NULL } }; MTAB vt_mod[] = { - { MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "CRT", "CRT={VR14|VR17|VR48}", - &vt_set_crt, &vt_show_crt, NULL, "CRT Type" }, - { MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "SCALE", "SCALE={1|2|4|8}", - &vt_set_scale, &vt_show_scale, NULL, "Pixel Scale Factor" }, - { MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "HSPACE", "HSPACE={NARROW|NORMAL}", + { MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "CRT", "CRT={VR14|VR17|VR48}", + &vt_set_crt, &vt_show_crt, NULL, "CRT Type" }, + { MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "SCALE", "SCALE={1|2|4|8}", + &vt_set_scale, &vt_show_scale, NULL, "Pixel Scale Factor" }, + { MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "HSPACE", "HSPACE={NARROW|NORMAL}", &vt_set_hspace, &vt_show_hspace, NULL, "Horizontal Spacing" }, - { MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "VSPACE", "VSPACE={TALL|NORMAL}", + { MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "VSPACE", "VSPACE={TALL|NORMAL}", &vt_set_vspace, &vt_show_vspace, NULL, "Vertical Spacing" }, { MTAB_XTD|MTAB_VDV|MTAB_VALR, 020, "ADDRESS", "ADDRESS", - &set_addr, &show_addr, NULL, "Bus address" }, - { MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "VECTOR", "VECTOR", - &set_vec, &show_vec, NULL, "Interrupt vector" }, - { MTAB_XTD|MTAB_VDV, 0, NULL, "AUTOCONFIGURE", - &set_addr_flt, NULL, NULL, "Enable autoconfiguration of address & vector" }, + &set_addr, &show_addr, NULL, "Bus address" }, + { MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "VECTOR", "VECTOR", + &set_vec, &show_vec, NULL, "Interrupt vector" }, + { MTAB_XTD|MTAB_VDV, 0, NULL, "AUTOCONFIGURE", + &set_addr_flt, NULL, NULL, "Enable autoconfiguration of address & vector" }, { 0 } }; + +static t_bool vt_stop_flag = FALSE; + +static void vt_quit_callback (void) +{ +vt_stop_flag = TRUE; +} + +/* Debug detail levels */ + +#define DEB_OPS 0001 /* transactions */ +#define DEB_RRD 0002 /* reg reads */ +#define DEB_RWR 0004 /* reg writes */ +#define DEB_TRC 0010 /* trace */ +#define DEB_STINT 0020 /* STOP interrupts */ +#define DEB_LPINT 0040 /* Light Pen interrupts */ +#define DEB_CHINT 0100 /* CHAR interrupts */ +#define DEB_NMINT 0200 /* NAME interrupts */ +#define DEB_INT 0360 /* All Interrupts */ +#define DEB_VT11 0400 /* VT11 activities */ +#define DEB_VMOU SIM_VID_DBG_MOUSE /* Video mouse */ +#define DEB_VKEY SIM_VID_DBG_KEY /* Video key */ +#define DEB_VCUR SIM_VID_DBG_CURSOR /* Video cursor */ +#define DEB_VVID SIM_VID_DBG_VIDEO /* Video */ + +DEBTAB vt_deb[] = { + { "OPS", DEB_OPS, "transactions" }, + { "RRD", DEB_RRD, "register reads" }, + { "RWR", DEB_RWR, "register writes" }, + { "INT", DEB_INT, "All Interrupts" }, + { "STOP", DEB_STINT, "STOP interrupts" }, + { "LPEN", DEB_LPINT, "Light Pen interrupts" }, + { "CHAR", DEB_CHINT, "CHAR interrupts" }, + { "NAME", DEB_NMINT, "NAME interrupts" }, + { "VT11", DEB_VT11, "VT11 activities" }, + { "TRACE", DEB_TRC, "trace" }, + { "VMOU", DEB_VMOU, "Video Mouse" }, + { "VKEY", DEB_VKEY, "Video Key" }, + { "VCUR", DEB_VCUR, "Video Cursor" }, + { "VVID", DEB_VVID, "Video Video" }, + { NULL, 0 } + }; + DEVICE vt_dev = { "VT", &vt_unit, vt_reg, vt_mod, 1, 8, 31, 1, DEV_RDX, 16, NULL, NULL, &vt_reset, &vt_boot, NULL, NULL, - &vt_dib, DEV_DIS | DEV_DISABLE | DEV_UBUS | DEV_Q18, - 0, 0, NULL, NULL, NULL, NULL, NULL, + &vt_dib, DEV_DIS | DEV_DISABLE | DEV_UBUS | DEV_Q18 | DEV_DEBUG, + 0, vt_deb, NULL, NULL, NULL, NULL, NULL, &vt_description }; + +char *vt_regnam[] = { + "DPC", + "MPR", + "XPR", + "YPR", + "RR", + "SPR", + "XOR", + "YOR", + "ANR", + "SCR", + "NR", + "SDR", + "STR", + "SAR", + "ZPR", + "ZOR", + }; /* VT11/VS60 routines @@ -159,45 +224,67 @@ DEVICE vt_dev = { t_stat vt_rd(int32 *data, int32 PA, int32 access) { + t_stat stat = SCPE_OK; + switch (PA & 036) { - case 000: *data = vt11_get_dpc(); return SCPE_OK; - case 002: *data = vt11_get_mpr(); return SCPE_OK; - case 004: *data = vt11_get_xpr(); return SCPE_OK; - case 006: *data = vt11_get_ypr(); return SCPE_OK; - case 010: if (!VS60) break; *data = vt11_get_rr(); return SCPE_OK; - case 012: if (!VS60) break; *data = vt11_get_spr(); return SCPE_OK; - case 014: if (!VS60) break; *data = vt11_get_xor(); return SCPE_OK; - case 016: if (!VS60) break; *data = vt11_get_yor(); return SCPE_OK; - case 020: if (!VS60) break; *data = vt11_get_anr(); return SCPE_OK; - case 022: if (!VS60) break; *data = vt11_get_scr(); return SCPE_OK; - case 024: if (!VS60) break; *data = vt11_get_nr(); return SCPE_OK; - case 026: if (!VS60) break; *data = vt11_get_sdr(); return SCPE_OK; - case 030: if (!VS60) break; *data = vt11_get_str(); return SCPE_OK; - case 032: if (!VS60) break; *data = vt11_get_sar(); return SCPE_OK; - case 034: if (!VS60) break; *data = vt11_get_zpr(); return SCPE_OK; - case 036: if (!VS60) break; *data = vt11_get_zor(); return SCPE_OK; + case 000: *data = vt11_get_dpc(); break; + case 002: *data = vt11_get_mpr(); break; + case 004: *data = vt11_get_xpr(); break; + case 006: *data = vt11_get_ypr(); break; + case 010: if (VS60) *data = vt11_get_rr(); else stat = SCPE_NXM; break; + case 012: if (VS60) *data = vt11_get_spr(); else stat = SCPE_NXM; break; + case 014: if (VS60) *data = vt11_get_xor(); else stat = SCPE_NXM; break; + case 016: if (VS60) *data = vt11_get_yor(); else stat = SCPE_NXM; break; + case 020: if (VS60) *data = vt11_get_anr(); else stat = SCPE_NXM; break; + case 022: if (VS60) *data = vt11_get_scr(); else stat = SCPE_NXM; break; + case 024: if (VS60) *data = vt11_get_nr(); else stat = SCPE_NXM; break; + case 026: if (VS60) *data = vt11_get_sdr(); else stat = SCPE_NXM; break; + case 030: if (VS60) *data = vt11_get_str(); else stat = SCPE_NXM; break; + case 032: if (VS60) *data = vt11_get_sar(); else stat = SCPE_NXM; break; + case 034: if (VS60) *data = vt11_get_zpr(); else stat = SCPE_NXM; break; + case 036: if (VS60) *data = vt11_get_zor(); else stat = SCPE_NXM; break; + default: stat = SCPE_NXM; } - return SCPE_NXM; + sim_debug (DEB_RRD, &vt_dev, "vt_rd(%s-PA=0%o,data=0x%X(0%o),access=%d)\n", vt_regnam[(PA & 036)>>1], (int)PA, (int)*data, (int)*data, (int)access); + return stat; } t_stat vt_wr(int32 data, int32 PA, int32 access) { uint16 d = data & 0177777; /* mask just in case */ + + sim_debug (DEB_RWR, &vt_dev, "vt_wr(%s-PA=0%o,data=0x%X(0%o),access=%d)\n", vt_regnam[(PA & 036)>>1], (int)PA, (int)data, (int)data, (int)access); switch (PA & 037) { case 000: /* DPC */ /* set the simulator PC */ vt11_set_dpc(d); - /* clear interrupt request (only one will be simulated at a time) */ - CLR_INT (VTST); - CLR_INT (VTLP); - CLR_INT (VTCH); - CLR_INT (VTNM); + /* Interrupt requests are cleared as each vector is dispatched, + so in general, no need to clear interrupt requests here. + However, if software is running at high IPL (diagnostics maybe) + clearing them here does no harm */ + if (INT_IS_SET(VTST)) { + sim_debug (DEB_STINT, &vt_dev, "CLR_INT(all)\n"); + CLR_INT (VTST); + } + if (INT_IS_SET(VTLP)) { + sim_debug (DEB_LPINT, &vt_dev, "CLR_INT(all)\n"); + CLR_INT (VTLP); + } + if (INT_IS_SET(VTCH)) { + sim_debug (DEB_CHINT, &vt_dev, "CLR_INT(all)\n"); + CLR_INT (VTCH); + } + if (INT_IS_SET(VTNM)) { + sim_debug (DEB_NMINT, &vt_dev, "CLR_INT(all)\n"); + CLR_INT (VTNM); + } /* start the display processor by running a cycle */ - return vt_svc(&vt_unit); + vt_svc (&vt_unit); + return SCPE_OK; case 002: vt11_set_mpr(d); return SCPE_OK; case 004: vt11_set_xpr(d); return SCPE_OK; @@ -221,15 +308,17 @@ vt_wr(int32 data, int32 PA, int32 access) /* * here to run a display processor cycle, called as a SIMH * "device service routine". - * - * Under X11 this includes polling for events, so it can't be - * call TOO infrequently... */ t_stat vt_svc(UNIT *uptr) { - if (vt11_cycle(CYCLE_US, 1)) - sim_activate (&vt_unit, vt_unit.wait); /* running; reschedule */ + sim_debug (DEB_TRC, &vt_dev, "vt_svc(wait=%d,DPC=0%o)\n", uptr->wait, vt11_get_dpc()); + if (vt11_cycle(uptr->wait, 0)) + sim_activate_after (uptr, uptr->wait); /* running; reschedule */ + if (vt_stop_flag) { + vt_stop_flag = FALSE; /* reset flag after we notice it */ + return SCPE_STOP; + } return SCPE_OK; } @@ -237,12 +326,14 @@ t_stat vt_reset(DEVICE *dptr) { if (!(dptr->flags & DEV_DIS)) - vt11_reset(); + vt11_reset(dptr, DEB_VT11); + vid_register_quit_callback (&vt_quit_callback); + sim_debug (DEB_INT, &vt_dev, "CLR_INT(all)\n"); CLR_INT (VTST); CLR_INT (VTLP); CLR_INT (VTCH); CLR_INT (VTNM); - sim_cancel (&vt_unit); /* deactivate unit */ + sim_cancel (dptr->units); /* deactivate unit */ return auto_config ("VT", (dptr->flags & DEV_DIS) ? 0 : 1); } @@ -256,6 +347,7 @@ t_stat vt_boot(int32 unit, DEVICE *dptr) { t_stat r; + char stability[32]; extern int32 saved_PC; extern uint16 *M; @@ -266,15 +358,23 @@ vt_boot(int32 unit, DEVICE *dptr) sim_set_memory_load_file (BOOT_CODE_ARRAY, BOOT_CODE_SIZE); r = load_cmd (0, BOOT_CODE_FILENAME); sim_set_memory_load_file (NULL, 0); - /* Lunar Lander presumes a VT device vector of 320 */ - if (0320 != vt_dib.vec) { /* If that is not the case, then copy the 320 vector to */ - M[vt_dib.vec >> 1] = M[0320 >> 1]; + /* Lunar Lander presumes a VT device vector base of 320 */ + if (0320 != vt_dib.vec) { /* If that is not the case, then copy the 320 vectors to the right place */ + M[(vt_dib.vec >> 1) + 0] = M[(0320 >> 1) + 0]; M[(vt_dib.vec >> 1) + 1] = M[(0320 >> 1) + 1]; + M[(vt_dib.vec >> 1) + 2] = M[(0324 >> 1) + 0]; + M[(vt_dib.vec >> 1) + 3] = M[(0324 >> 1) + 1]; + M[(vt_dib.vec >> 1) + 4] = M[(0330 >> 1) + 0]; + M[(vt_dib.vec >> 1) + 5] = M[(0330 >> 1) + 1]; + M[(vt_dib.vec >> 1) + 6] = M[(0334 >> 1) + 0]; + M[(vt_dib.vec >> 1) + 7] = M[(0334 >> 1) + 1]; } - M[032530>>1] = 1; cpu_set_boot (saved_PC); set_cmd (0, "VT SCALE=1"); set_cmd (0, "VT CRT=VR14"); + sprintf (stability, "%d", SIM_IDLE_STMIN); + sim_set_idle (NULL, 0, stability, NULL); /* force minimum calibration stability */ + sim_clr_idle (NULL, 0, stability, NULL); return r; } @@ -284,6 +384,7 @@ t_stat vt_set_crt(UNIT *uptr, int32 val, char *cptr, void *desc) { char gbuf[CBUFSIZE]; + if (vt11_init) return SCPE_ALATT; /* should be "changes locked out" */ if (cptr == NULL) @@ -298,6 +399,9 @@ vt_set_crt(UNIT *uptr, int32 val, char *cptr, void *desc) else return SCPE_ARG; vt_dib.lnt = (VS60) ? IOLN_VS60 : IOLN_VT11; + deassign_device (&vt_dev); + if (VS60) + assign_device (&vt_dev, "VS60"); return SCPE_OK; } @@ -388,24 +492,28 @@ vt_show_vspace(FILE *st, UNIT *uptr, int32 val, void *desc) void vt_stop_intr(void) { + sim_debug (DEB_STINT, &vt_dev, "SET_INT (VTST)\n"); SET_INT (VTST); } void vt_lpen_intr(void) { + sim_debug (DEB_LPINT, &vt_dev, "SET_INT (VTLP)\n"); SET_INT (VTLP); } void vt_char_intr(void) { + sim_debug (DEB_CHINT, &vt_dev, "SET_INT (CHAR)\n"); SET_INT (VTCH); } void vt_name_intr(void) { + sim_debug (DEB_NMINT, &vt_dev, "SET_INT (VTNM)\n"); SET_INT (VTNM); } diff --git a/TX-0/mouse.simh b/TX-0/mouse.simh index 0ff6814a..ab207534 100644 --- a/TX-0/mouse.simh +++ b/TX-0/mouse.simh @@ -1,4 +1,5 @@ ; TX-0 Initialization file for the Mouse Maze Game +set dpy enable att petr bin_newMouse_3-22-66.bin ; The mouse maze game mode is manipulated under TAC control. diff --git a/TX-0/tic.simh b/TX-0/tic.simh index 47636aff..b5a634c7 100644 --- a/TX-0/tic.simh +++ b/TX-0/tic.simh @@ -1,4 +1,5 @@ ; TX-0 Initialization file for the tic-tac-toe game +set dpy enable att petr bin_tic-tac-toe_new_code_12-16-61.bin boot petr g diff --git a/TX-0/tx0_dpy.c b/TX-0/tx0_dpy.c index 40e92819..6ace879b 100644 --- a/TX-0/tx0_dpy.c +++ b/TX-0/tx0_dpy.c @@ -41,6 +41,7 @@ #ifdef USE_DISPLAY #include "tx0_defs.h" #include "display/display.h" +#include "sim_video.h" extern int32 ios, iosta, PF; extern int32 stop_inst; @@ -61,12 +62,32 @@ t_stat dpy_reset (DEVICE *dptr); UNIT dpy_unit = { UDATA (&dpy_svc, UNIT_ATTABLE, 0), DPY_WAIT }; +static t_bool dpy_stop_flag = FALSE; + +static void dpy_quit_callback (void) +{ +dpy_stop_flag = TRUE; +} + +#define DEB_VMOU SIM_VID_DBG_MOUSE /* Video mouse */ +#define DEB_VKEY SIM_VID_DBG_KEY /* Video key */ +#define DEB_VCUR SIM_VID_DBG_CURSOR /* Video cursor */ +#define DEB_VVID SIM_VID_DBG_VIDEO /* Video */ + +DEBTAB dpy_deb[] = { + { "VMOU", DEB_VMOU, "Video Mouse" }, + { "VKEY", DEB_VKEY, "Video Key" }, + { "VCUR", DEB_VCUR, "Video Cursor" }, + { "VVID", DEB_VVID, "Video Video" }, + { NULL, 0 } + }; + DEVICE dpy_dev = { "DPY", &dpy_unit, NULL, NULL, 1, 10, 31, 1, 8, 8, NULL, NULL, &dpy_reset, NULL, NULL, NULL, - NULL, DEV_DISABLE }; + NULL, DEV_DISABLE | DEV_DIS | DEV_DEBUG, 0, dpy_deb }; /* Display Routine */ int32 dpy (int32 ac) @@ -120,6 +141,10 @@ t_stat dpy_svc (UNIT *uptr) { display_age(dpy_unit.wait*CYCLE_TIME, 1); sim_activate (&dpy_unit, dpy_unit.wait); /* requeue! */ + if (dpy_stop_flag) { + dpy_stop_flag = FALSE; /* reset flag after we notice it */ + return SCPE_STOP; + } return SCPE_OK; } @@ -127,10 +152,13 @@ t_stat dpy_svc (UNIT *uptr) t_stat dpy_reset (DEVICE *dptr) { - display_init(DIS_TX0, RES_FULL); - display_reset(); - iosta = iosta & ~(IOS_PNT | IOS_SPC); /* clear flags */ sim_cancel (&dpy_unit); /* deactivate unit */ + if (dpy_dev.flags & DEV_DIS) /* disabled? */ + return SCPE_OK; + display_init(DIS_TX0, RES_FULL, dptr); + display_reset(); + vid_register_quit_callback (&dpy_quit_callback); + iosta = iosta & ~(IOS_PNT | IOS_SPC); /* clear flags */ return SCPE_OK; } diff --git a/Visual Studio Projects/PDP1.vcproj b/Visual Studio Projects/PDP1.vcproj index bf9bb91b..ef20bc82 100644 --- a/Visual Studio Projects/PDP1.vcproj +++ b/Visual Studio Projects/PDP1.vcproj @@ -41,8 +41,8 @@ diff --git a/Visual Studio Projects/PDP11.vcproj b/Visual Studio Projects/PDP11.vcproj index 4447dd38..40d852bd 100644 --- a/Visual Studio Projects/PDP11.vcproj +++ b/Visual Studio Projects/PDP11.vcproj @@ -427,11 +427,11 @@ > + + @@ -254,10 +258,6 @@ RelativePath="..\TX-0\tx0_sys_orig.c" > - - = refresh_interval) { + display_sync (); + refresh_elapsed = 0; + } + while ((p = head->next) != head) { int x, y; @@ -717,7 +725,7 @@ display_point(int x, /* 0..xpixels (unscaled) */ { long lx, ly; - if (!initialized && !display_init(DISPLAY_TYPE, PIX_SCALE)) + if (!initialized && !display_init(DISPLAY_TYPE, PIX_SCALE, NULL)) return 0; /* scale x and y to the displayed number of pixels */ @@ -828,7 +836,7 @@ find_type(enum display_type type) } int -display_init(enum display_type type, int sf) +display_init(enum display_type type, int sf, void *dptr) { static int init_failed = 0; struct display *dp; @@ -924,7 +932,7 @@ display_init(enum display_type type, int sf) if (!points) goto failed; - if (!ws_init(dp->name, xpixels, ypixels, ncolors)) + if (!ws_init(dp->name, xpixels, ypixels, ncolors, dptr)) goto failed; phosphor_init(dp->color0->phosphors, dp->color0->nphosphors, 0); @@ -950,7 +958,8 @@ display_reset(void) void display_sync(void) { - ws_sync(); + ws_poll (NULL, 0); + ws_sync (); } void diff --git a/display/display.h b/display/display.h index 850e0c20..96bcc07b 100644 --- a/display/display.h +++ b/display/display.h @@ -58,7 +58,7 @@ enum display_type { * must be called before first call to display_age() * (but called implicitly by display_point()) */ -extern int display_init(enum display_type, int scale); +extern int display_init(enum display_type, int scale, void *dptr); /* return size of virtual display */ extern int display_xpoints(void); @@ -97,6 +97,7 @@ extern int display_point(int,int,int,int); /* * force window system to output bits to screen; * call after adding points, or aging the screen + * collect any window system input (mouse or keyboard) */ extern void display_sync(void); diff --git a/display/sim_ws.c b/display/sim_ws.c new file mode 100644 index 00000000..67905330 --- /dev/null +++ b/display/sim_ws.c @@ -0,0 +1,422 @@ +/* + * simh sim_video support for XY display simulator + * Mark Pizzolato + * January 2016 + * Based on win32.c module by Phil Budne + */ + +/* + * Copyright (c) 2016, Mark Pizzolato + * + * 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. + */ + +/* + * BUGS: + * Does not allow you to close display window; + * would need to tear down both system, and system independent data. + * + */ + +#include "sim_video.h" +#include +#include +#include "ws.h" +#include "xy.h" + +#ifndef PIX_SIZE +#define PIX_SIZE 1 +#endif + +/* + * light pen location + * see ws.h for full description + */ +int ws_lp_x = -1; +int ws_lp_y = -1; + +static int xpixels, ypixels; +static int pix_size = PIX_SIZE; +static char *window_name; +static uint32 *colors = NULL; +static uint32 ncolors = 0, size_colors = 0; +static uint32 *surface = NULL; +typedef struct cursor { + Uint8 *data; + Uint8 *mask; + int width; + int height; + int hot_x; + int hot_y; + } CURSOR; + +static CURSOR *arrow_cursor; +static CURSOR *cross_cursor; + + +static int +map_key(int k) +{ + switch (k) { + case SIM_KEY_0: return '0'; + case SIM_KEY_1: return '1'; + case SIM_KEY_2: return '2'; + case SIM_KEY_3: return '3'; + case SIM_KEY_4: return '4'; + case SIM_KEY_5: return '5'; + case SIM_KEY_6: return '6'; + case SIM_KEY_7: return '7'; + case SIM_KEY_8: return '8'; + case SIM_KEY_9: return '9'; + case SIM_KEY_A: return 'a'; + case SIM_KEY_B: return 'b'; + case SIM_KEY_C: return 'c'; + case SIM_KEY_D: return 'd'; + case SIM_KEY_E: return 'e'; + case SIM_KEY_F: return 'f'; + case SIM_KEY_G: return 'g'; + case SIM_KEY_H: return 'h'; + case SIM_KEY_I: return 'i'; + case SIM_KEY_J: return 'j'; + case SIM_KEY_K: return 'k'; + case SIM_KEY_L: return 'l'; + case SIM_KEY_M: return 'm'; + case SIM_KEY_N: return 'n'; + case SIM_KEY_O: return 'o'; + case SIM_KEY_P: return 'p'; + case SIM_KEY_Q: return 'q'; + case SIM_KEY_R: return 'r'; + case SIM_KEY_S: return 's'; + case SIM_KEY_T: return 't'; + case SIM_KEY_U: return 'u'; + case SIM_KEY_V: return 'v'; + case SIM_KEY_W: return 'w'; + case SIM_KEY_X: return 'x'; + case SIM_KEY_Y: return 'y'; + case SIM_KEY_Z: return 'z'; + case SIM_KEY_BACKQUOTE: return '`'; + case SIM_KEY_MINUS: return '-'; + case SIM_KEY_EQUALS: return '='; + case SIM_KEY_LEFT_BRACKET: return '['; + case SIM_KEY_RIGHT_BRACKET: return ']'; + case SIM_KEY_SEMICOLON: return ';'; + case SIM_KEY_SINGLE_QUOTE: return '\''; + case SIM_KEY_BACKSLASH: return '\\'; + case SIM_KEY_LEFT_BACKSLASH: return '\\'; + case SIM_KEY_COMMA: return ','; + case SIM_KEY_PERIOD: return '.'; + case SIM_KEY_SLASH: return '/'; + case SIM_KEY_BACKSPACE: return '\b'; + case SIM_KEY_TAB: return '\t'; + case SIM_KEY_ENTER: return '\r'; + case SIM_KEY_SPACE: return ' '; + } + return k; +} + +int +ws_poll(int *valp, int maxus) +{ + SIM_MOUSE_EVENT mev; + SIM_KEY_EVENT kev; + + if (maxus > 1000) + sim_os_ms_sleep (maxus/1000); + + if (SCPE_OK == vid_poll_mouse (&mev)) { + unsigned char old_lp_sw = display_lp_sw; + + if (display_lp_sw = mev.b1_state) { + ws_lp_x = mev.x_pos; + ws_lp_y = (ypixels - 1) - mev.y_pos; /* range 0 - (ypixels-1) */ + /* convert to display coordinates */ + ws_lp_x /= pix_size; + ws_lp_y /= pix_size; + if (!old_lp_sw && !display_tablet) + vid_set_cursor (1, cross_cursor->width, cross_cursor->height, cross_cursor->data, cross_cursor->mask, cross_cursor->hot_x, cross_cursor->hot_y); + } + else { + ws_lp_x = ws_lp_y = -1; + if (old_lp_sw && !display_tablet) + vid_set_cursor (1, arrow_cursor->width, arrow_cursor->height, arrow_cursor->data, arrow_cursor->mask, arrow_cursor->hot_x, arrow_cursor->hot_y); + } + vid_set_cursor_position (mev.x_pos, mev.y_pos); + } + if (SCPE_OK == vid_poll_kb (&kev)) { + switch (kev.state) { + case SIM_KEYPRESS_DOWN: + case SIM_KEYPRESS_REPEAT: + display_keydown(map_key(kev.key)); + break; + case SIM_KEYPRESS_UP: + display_keyup(map_key(kev.key)); + break; + } + } + return 1; +} + +/* XPM */ +static const char *arrow[] = { + /* width height num_colors chars_per_pixel */ + " 16 16 3 1", + /* colors */ + "X c #000000", /* black */ + ". c #ffffff", /* white */ + " c None", + /* pixels */ + "X ", + "XX ", + "X.X ", + "X..X ", + "X...X ", + "X....X ", + "X.....X ", + "X......X ", + "X.......X ", + "X........X ", + "X.....XXXXX ", + "X..X..X ", + "X.X X..X ", + "XX X..X ", + "X X..X ", + " XX ", +}; + +/* XPM */ +static const char *cross[] = { + /* width height num_colors chars_per_pixel hot_x hot_y*/ + " 16 16 3 1 7 7", + /* colors */ + "X c #000000", /* black */ + ". c #ffffff", /* white */ + " c None", + /* pixels */ + " XXXX ", + " X..X ", + " X..X ", + " X..X ", + " X..X ", + " X..X ", + "XXXXXXX..XXXXXXX", + "X..............X", + "X..............X", + "XXXXXXX..XXXXXXX", + " X..X ", + " X..X ", + " X..X ", + " X..X ", + " X..X ", + " XXXX ", + "7,7" +}; + +static CURSOR *ws_create_cursor(const char *image[]) +{ +int byte, bit, row, col; +Uint8 *data = NULL; +Uint8 *mask = NULL; +char black, white, transparent; +CURSOR *result = NULL; +int width, height, colors, cpp; +int hot_x = 0, hot_y = 0; + +if (4 > sscanf(image[0], "%d %d %d %d %d %d", + &width, &height, &colors, &cpp, &hot_x, &hot_y)) + return result; +if ((cpp != 1) || (0 != width%8) || (colors != 3)) + return result; +black = image[1][0]; +white = image[2][0]; +transparent = image[3][0]; +data = (Uint8 *)calloc (1, (width / 8) * height); +mask = (Uint8 *)calloc (1, (width / 8) * height); +if (!data || !mask) { + free (data); + free (mask); + return result; + } +bit = 7; +byte = 0; +for (row=0; rowdata = data; + result->mask = mask; + result->width = width; + result->height = height; + result->hot_x = hot_x; + result->hot_y = hot_y; + } +else { + free (data); + free (mask); + } +return result; +} + +static void ws_free_cursor (CURSOR *cursor) +{ +if (!cursor) + return; +free (cursor->data); +free (cursor->mask); +free (cursor); +} + +/* called from display layer on first display op */ +int +ws_init(char *name, int xp, int yp, int colors, void *dptr) +{ + int i; + int ret; + + arrow_cursor = ws_create_cursor (arrow); + cross_cursor = ws_create_cursor (cross); + xpixels = xp; + ypixels = yp; + window_name = name; + surface = realloc (surface, xpixels*ypixels*sizeof(*surface)); + for (i=0; iwidth, arrow_cursor->height, arrow_cursor->data, arrow_cursor->mask, arrow_cursor->hot_x, arrow_cursor->hot_y); + return ret; +} + +void +ws_shutdown(void) +{ +ws_free_cursor(arrow_cursor); +ws_free_cursor(cross_cursor); +vid_close(); +} + +void * +ws_color_rgb(int r, int g, int b) +{ + uint32 color, i; + + color = sim_end ? (0xFF000000 | ((r & 0xFF00) << 8) | (g & 0xFF00) | ((b & 0xFF00) >> 8)) : (0x000000FF | (r & 0xFF00) | ((g & 0xFF00) << 8) | ((b & 0xFF00) << 16)); + for (i=0; i xpixels || y > ypixels) + return; + + y = ypixels - 1 - y; /* invert y, top left origin */ + + if (brush == NULL) + brush = ws_color_black (); + if (pix_size > 1) { + int i, j; + + for (i=0; i= 0; x--) { for (y = 0; y < 20; y++) { ws_display_point(x*4, y, x, 0); @@ -160,7 +160,7 @@ void t3(void) { int x, y; - display_init(TEST_DIS, TEST_RES); + display_init(TEST_DIS, TEST_RES, NULL); for (x = DISPLAY_INT_MAX; x >= 0; x--) { for (y = 0; y < 20; y++) { display_point(x*2, y*2, x, 0); @@ -175,7 +175,7 @@ t3(void) { int main(void) { - if (!display_init(TEST_DIS, TEST_RES)) + if (!display_init(TEST_DIS, TEST_RES, NULL)) exit(EXIT_FAILURE); cpu_set_switches(04000UL); /* classic starting value */ diff --git a/display/vt11.c b/display/vt11.c index 20b3f11c..627bc2ff 100644 --- a/display/vt11.c +++ b/display/vt11.c @@ -128,10 +128,26 @@ /* extract a 1-bit field */ #define TESTBIT(W,B) (((W) & BITMASK(B)) != 0) +static void *vt11_dptr; +static int vt11_dbit; + #ifdef DEBUG_VT11 -#define DEBUGF(X) do { printf X; fflush(stdout); } while (0) + +#include + +#define DEVICE void + +#define DBG_CALL 1 +int vt11_debug; + +extern void _sim_debug (int dbits, DEVICE* dptr, const char* fmt, ...); + +#define DEBUGF(...) do {if (vt11_debug & DBG_CALL) { _sim_debug (vt11_dbit, vt11_dptr, ## __VA_ARGS__); };} while (0) + #else -#define DEBUGF(X) + +#define DEBUGF(...) + #endif /* @@ -194,8 +210,8 @@ enum display_type vt11_display = DISPLAY_TYPE; /* DIS_VR{14,17,48} */ int vt11_scale = PIX_SCALE; /* RES_{FULL,HALF,QUARTER,EIGHTH} */ unsigned char vt11_init = 0; /* set after display_init() called */ -#define INIT { if (!vt11_init) { display_init(vt11_display, vt11_scale); \ - vt11_init = 1; vt11_reset(); } } +#define INIT { if (!vt11_init) { display_init(vt11_display, vt11_scale, vt11_dptr); \ + vt11_init = 1; vt11_reset(vt11_dptr, vt11_dbit); } } /* state visible to host */ @@ -638,7 +654,7 @@ void vt11_set_dpc(uint16 d) { INIT bdb = d; /* save all bits in case maint1 used */ - DEBUGF(("set DPC 0%06o\r\n", (unsigned)d)); + DEBUGF("set DPC 0%06o\r\n", (unsigned)d); /* Stack level is unaffected, except that stack_sel==037 goes to 040; this fudge is necessary to pass DZVSC test 3, which misleadingly calls it setting top-of-stack upon START (vt11_set_dpc(even)). If one instead @@ -728,7 +744,7 @@ vt11_get_xpr(void) void vt11_set_xpr(uint16 d) { INIT - DEBUGF(("set XPR: no effect\r\n")); + DEBUGF("set XPR: no effect\r\n"); } int32 @@ -743,7 +759,7 @@ vt11_get_ypr(void) void vt11_set_ypr(uint16 d) { INIT - DEBUGF(("set YPR: no effect\r\n")); + DEBUGF("set YPR: no effect\r\n"); } /* All the remaining registers pertain to the VS60 only. */ @@ -820,7 +836,7 @@ vt11_set_yor(uint16 d) int32 vt11_get_anr(void) { INIT - DEBUGF(("get ANR: no effect\r\n")); + DEBUGF("get ANR: no effect\r\n"); return (search << 12) | assoc_name; /* [garbage] */ } @@ -896,7 +912,7 @@ vt11_get_nr(void) void vt11_set_nr(uint16 d) { INIT - DEBUGF(("set NR: no effect\r\n")); + DEBUGF("set NR: no effect\r\n"); } int32 @@ -932,7 +948,7 @@ vt11_get_sdr(void) void vt11_set_sdr(uint16 d) { INIT - DEBUGF(("set SDR: no effect\r\n")); + DEBUGF("set SDR: no effect\r\n"); } int32 @@ -1010,7 +1026,7 @@ vt11_get_zpr(void) void vt11_set_zpr(uint16 d) { INIT - DEBUGF(("set ZPR: no effect\r\n")); + DEBUGF("set ZPR: no effect\r\n"); } int32 @@ -1039,8 +1055,13 @@ vt11_set_zor(uint16 d) } void -vt11_reset(void) +vt11_reset(void *dev, int debug) { + if (dev) { + vt11_dptr = dev; + vt11_dbit = debug; + } + /* make sure display code has been initialized */ if (!vt11_init) /* (SIMH invokes before display type is set) */ return; /* wait until last moment */ @@ -2021,7 +2042,7 @@ vector3(int i, int32 dx, int32 dy, int32 dz) /* unscaled display-file units */ xpos = 010000L * adx / ady + 1; /* truncates */ ypos = ady; /* according to DZVSC test 100 */ } - DEBUGF(("delta=0%o, tangent=0%o\r\n", xpos, ypos)); + DEBUGF("delta=0%o, tangent=0%o\r\n", xpos, ypos); xpos = PSCALE(xpos); /* compensates for eventual PNORM */ ypos = PSCALE(ypos); /* compensates for eventual PNORM */ } @@ -2078,7 +2099,7 @@ vector3(int i, int32 dx, int32 dy, int32 dz) /* unscaled display-file units */ case 0: /* invisible */ return; default: - DEBUGF(("clip() bad return: %d\n", clip_vect)); + DEBUGF("clip() bad return: %d\n", clip_vect); case -1: /* visible, not clipped */ clip_vect = 0; break; /* draw immediately */ @@ -2174,10 +2195,10 @@ basic_vector(int i, int dir, int len) /* unscaled display-file units */ dy = -len; break; default: /* "can't happen" */ - DEBUGF(("BUG: basic vector: illegal direction %d\r\n", dir)); + DEBUGF("BUG: basic vector: illegal direction %d\r\n", dir); return; } - DEBUGF(("basic ")); + DEBUGF("basic "); vector2(i, dx, dy); } @@ -3120,7 +3141,7 @@ vt11_cycle(int us, int slowdown) /*FALLTHRU*/ case 010: /* Set Graphic Mode 1000 */ if (VT11) { - DEBUGF(("SGM 1000 IGNORED\r\n")); + DEBUGF("SGM 1000 IGNORED\r\n"); break; } /*FALLTHRU*/ @@ -3131,34 +3152,34 @@ vt11_cycle(int us, int slowdown) case 4: /* Set Graphic Mode 0100 */ case 5: /* Set Graphic Mode 0101 */ case 6: /* Set Graphic Mode 0110 */ - DEBUGF(("Set Graphic Mode %u", (unsigned)mode_field)); + DEBUGF("Set Graphic Mode %u", (unsigned)mode_field); graphic_mode = mode_field; offset = 0; shift_out = 0; /* seems to be right */ if (TESTBIT(inst,10)) { intensity = GETFIELD(inst,9,7); - DEBUGF((" intensity=%d", (int)intensity)); + DEBUGF(" intensity=%d", (int)intensity); } if (TESTBIT(inst,6)) { lp0_intr_ena = TESTBIT(inst,5); - DEBUGF((" lp0_intr_ena=%d", (int)lp0_intr_ena)); + DEBUGF(" lp0_intr_ena=%d", (int)lp0_intr_ena); } if (TESTBIT(inst,4)) { blink_ena = TESTBIT(inst,3); - DEBUGF((" blink=%d", (int)blink_ena)); + DEBUGF(" blink=%d", (int)blink_ena); } if (TESTBIT(inst,2)) { line_type = GETFIELD(inst,1,0); - DEBUGF((" line_type=%d", (int)line_type)); + DEBUGF(" line_type=%d", (int)line_type); } - DEBUGF(("\r\n")); + DEBUGF("\r\n"); break; case 012: /* 1010: Load Name Register */ if (VT11) goto bad_ins; name = GETFIELD(inst,10,0); - DEBUGF(("Load Name Register name=0%o\r\n", name)); + DEBUGF("Load Name Register name=0%o\r\n", name); { static unsigned nmask[4] = { 0, 03777, 03770, 03600 }; if (search != 0 && ((name^assoc_name) & nmask[search]) == 0) @@ -3169,21 +3190,21 @@ vt11_cycle(int us, int slowdown) case 013: /* 1011: Load Status C */ if (VT11) goto bad_ins; - DEBUGF(("Load Status C")); + DEBUGF("Load Status C"); if (TESTBIT(inst,9)) { char_rotate = TESTBIT(inst,8); - DEBUGF((" char_rotate=d", (int)char_rotate)); + DEBUGF(" char_rotate=d", (int)char_rotate); } if (TESTBIT(inst,7)) { cs_index = GETFIELD(inst,6,5); /* 0, 1, 2, 3 */ char_scale = csi2csf[cs_index]; /* for faster CSCALE macro */ - DEBUGF((" cs_index=%d(x%d/4)", (int)cs_index, (int)char_scale)); + DEBUGF(" cs_index=%d(x%d/4)", (int)cs_index, (int)char_scale); } if (TESTBIT(inst,4)) { vector_scale = GETFIELD(inst,3,0); - DEBUGF((" vector_scale=%d/4", (int)vector_scale)); + DEBUGF(" vector_scale=%d/4", (int)vector_scale); } - DEBUGF(("\r\n")); + DEBUGF("\r\n"); break; case 014: /* 1100__ */ @@ -3199,7 +3220,7 @@ vt11_cycle(int us, int slowdown) jmpa: finish_jmpa = 0; DPC = inst & ~1; - DEBUGF(("Display Jump Absolute 0%06o\r\n", (unsigned)inst)); + DEBUGF("Display Jump Absolute 0%06o\r\n", (unsigned)inst); break; case 1: /* 110001: Display Jump Relative */ @@ -3264,19 +3285,19 @@ vt11_cycle(int us, int slowdown) case 015: /* 1101__ */ if (VT11) - DEBUGF(("Display NOP\r\n")); + DEBUGF("Display NOP\r\n"); else { op = GETFIELD(inst,10,9); switch (op) { case 0: /* 110100: Load Scope Selection */ /* also used as Display NOP */ - DEBUGF(("Load Scope Selection")); + DEBUGF("Load Scope Selection"); c = TESTBIT(inst,8); - DEBUGF((" console=%d", c)); + DEBUGF(" console=%d", c); if (TESTBIT(inst,7)) { ez = TESTBIT(inst,6); - DEBUGF((" blank=%d", (int)!ez)); + DEBUGF(" blank=%d", (int)!ez); if (c) int1_scope = (unsigned char)(ez & 0xFF); else @@ -3284,7 +3305,7 @@ vt11_cycle(int us, int slowdown) } if (TESTBIT(inst,5)) { ez = TESTBIT(inst,4); - DEBUGF((" lp_intr_ena=%d", (int)ez)); + DEBUGF(" lp_intr_ena=%d", (int)ez); if (c) lp1_intr_ena = (unsigned char)(ez & 0xFF); else @@ -3292,52 +3313,54 @@ vt11_cycle(int us, int slowdown) } if (TESTBIT(inst,3)) { ez = TESTBIT(inst,2); - DEBUGF((" lp_sw_intr_ena=%d", (int)ez)); + DEBUGF(" lp_sw_intr_ena=%d", (int)ez); if (c) lp1_sw_intr_ena = (unsigned char)(ez & 0xFF); else lp0_sw_intr_ena = (unsigned char)(ez & 0xFF); } - DEBUGF(("\r\n")); + DEBUGF("\r\n"); break; case 1: /* 110101: Display POP Not Restore */ - DEBUGF(("Display POP Not Restore\r\n")); + DEBUGF("Display POP Not Restore\r\n"); pop(0); /* sets new DPC as side effect */ break; case 2: /* 110110: Display POP Restore */ - DEBUGF(("Display POP Restore\r\n")); + DEBUGF("Display POP Restore\r\n"); pop(1); /* sets new DPC as side effect */ break; default: /* 110111: undocumented -- ignored? */ - DEBUGF(("Display NOP?\r\n")); + DEBUGF("Display NOP?\r\n"); } } break; case 016: /* 1110: Load Status A */ - DEBUGF(("Load Status A")); + DEBUGF("Load Status A"); internal_stop = TESTBIT(inst,10); /* 11101 Display Stop */ if (internal_stop) { stopped = 1; /* (synchronous with display cycle) */ - DEBUGF((" stop")); + DEBUGF(" stop"); } if (TESTBIT(inst,9)) { stop_intr_ena = TESTBIT(inst,8); - DEBUGF((" stop_intr_ena=%d", (int)stop_intr_ena)); + DEBUGF(" stop_intr_ena=%d", (int)stop_intr_ena); } if (TESTBIT(inst,7)) { lp_intensify = !TESTBIT(inst,6); - DEBUGF((" lp_intensify=%d", (int)lp_intensify)); + DEBUGF(" lp_intensify=%d", (int)lp_intensify); } if (TESTBIT(inst,5)) { italics = TESTBIT(inst,4); - DEBUGF((" italics=%d", (int)italics)); + DEBUGF(" italics=%d", (int)italics); } refresh_rate = GETFIELD(inst,VS60?3:2,2); - DEBUGF((" refresh=%d", refresh_rate)); + DEBUGF(" refresh=%d", refresh_rate); + if (sync_period != refresh_rate) + DEBUGF("old sync_period=%d, new refresh=%d", sync_period, refresh_rate); switch (refresh_rate) { case 0: /* continuous */ sync_period = 0; @@ -3357,46 +3380,46 @@ vt11_cycle(int us, int slowdown) } if (VS60 && TESTBIT(inst,1)) { menu = TESTBIT(inst,0); - DEBUGF((" menu=%d", (int)menu)); + DEBUGF(" menu=%d", (int)menu); } - DEBUGF(("\r\n")); + DEBUGF("\r\n"); break; case 017: /* 1111_ */ if (VS60 && TESTBIT(inst,10)) { /* 11111: Load Status BB */ - DEBUGF(("Load Status BB")); + DEBUGF("Load Status BB"); if (TESTBIT(inst,7)) { depth_cue_proc = TESTBIT(inst,6); - DEBUGF((" depth_cue_proc=%d", (int)depth_cue_proc)); + DEBUGF(" depth_cue_proc=%d", (int)depth_cue_proc); } if (TESTBIT(inst,5)) { edge_intr_ena = TESTBIT(inst,4); - DEBUGF((" edge_intr_ena=%d", (int)edge_intr_ena)); + DEBUGF(" edge_intr_ena=%d", (int)edge_intr_ena); } if (TESTBIT(inst,3)) { file_z_data = TESTBIT(inst,2); - DEBUGF((" file_z_data=%d", (int)file_z_data)); + DEBUGF(" file_z_data=%d", (int)file_z_data); } if (TESTBIT(inst,1)) { char_escape = TESTBIT(inst,0); - DEBUGF((" char_escape=%d", (int)char_escape)); + DEBUGF(" char_escape=%d", (int)char_escape); } } else { /* 11110: Load Status B */ - DEBUGF(("Load Status B")); + DEBUGF("Load Status B"); if (VS60 && TESTBIT(inst,9)) { color = GETFIELD(inst,8,7); - DEBUGF((" color=%d", (int)color)); + DEBUGF(" color=%d", (int)color); } if (TESTBIT(inst,6)) { graphplot_step = GETFIELD(inst,5,0); - DEBUGF((" graphplot_step=%d", (int)graphplot_step)); + DEBUGF(" graphplot_step=%d", (int)graphplot_step); } } - DEBUGF(("\r\n")); + DEBUGF("\r\n"); break; default: - bad_ins: DEBUGF(("SPARE COMMAND 0%o\r\n", mode_field)); + bad_ins: DEBUGF("SPARE COMMAND 0%o\r\n", mode_field); /* "display processor hangs" */ DPC -= 2; /* hang around scene of crime */ break; @@ -3423,17 +3446,17 @@ vt11_cycle(int us, int slowdown) word_number = 0; if (word_number == 0) { c = GETFIELD(inst,6,0); - DEBUGF(("char1 %d (", c)); - DEBUGF((040 <= c && c < 0177 ? "'%c'" : "0%o", c)); - DEBUGF((")\r\n")); + DEBUGF("char1 %d (", c); + DEBUGF(040 <= c && c < 0177 ? "'%c'" : "0%o", c); + DEBUGF(")\r\n"); if (character(c)) /* POPR was done; end chars */ break; MORE_DATA /* post any intrs now */ } c = GETFIELD(inst,15,8); - DEBUGF(("char2 %d (", c)); - DEBUGF((040 <= c && c < 0177 ? "'%c'" : "0%o", c)); - DEBUGF((")\r\n")); + DEBUGF("char2 %d (", c); + DEBUGF(040 <= c && c < 0177 ? "'%c'" : "0%o", c); + DEBUGF(")\r\n"); (void)character(c); break; @@ -3459,7 +3482,7 @@ vt11_cycle(int us, int slowdown) i, (int)x, (int)y, (int)z)); vector3(i, x, y, z); } else { - DEBUGF(("short vector i%d (%d,%d)\r\n", i, (int)x, (int)y)); + DEBUGF("short vector i%d (%d,%d)\r\n", i, (int)x, (int)y); vector2(i, x, y); } break; @@ -3494,9 +3517,9 @@ vt11_cycle(int us, int slowdown) } else { if (ex) norot: /* undocumented and probably nonfunctional */ - DEBUGF(("ROTATE NOT SUPPORTED\r\n")); + DEBUGF("ROTATE NOT SUPPORTED\r\n"); else { - DEBUGF(("long vector i%d (%d,%d)\r\n", i, (int)x, (int)y)); + DEBUGF("long vector i%d (%d,%d)\r\n", i, (int)x, (int)y); vector2(i, x, y); } } @@ -3535,7 +3558,7 @@ vt11_cycle(int us, int slowdown) if (szo) ez = -ez; if (offset) { /* OFFSET rather than POINT */ - DEBUGF(("offset (%d,%d,%d)\r\n", (int)ex,(int)ey,(int)ez)); + DEBUGF("offset (%d,%d,%d)\r\n", (int)ex,(int)ey,(int)ez); xoff = PSCALE(ex); yoff = PSCALE(ey); zoff = PSCALE(ez * 4); /* XXX include bits 1:0 ? */ @@ -3550,13 +3573,13 @@ vt11_cycle(int us, int slowdown) } } else { if (offset) { /* (VS60) OFFSET rather than POINT */ - DEBUGF(("offset (%d,%d)\r\n", (int)ex, (int)ey)); + DEBUGF("offset (%d,%d)\r\n", (int)ex, (int)ey); xoff = PSCALE(ex); yoff = PSCALE(ey); s_xoff = (unsigned char)(sxo & 0xFF); s_yoff = (unsigned char)(syo & 0xFF); } else { - DEBUGF(("point i%d (%d,%d)\r\n", i, (int)ex, (int)ey)); + DEBUGF("point i%d (%d,%d)\r\n", i, (int)ex, (int)ey); point2(i, VSCALE(ex) + xoff, VSCALE(ey) + yoff, VS60); } } @@ -3569,7 +3592,7 @@ vt11_cycle(int us, int slowdown) goto blv; /* (VS60) BLVECT rather than GRAPHX */ else { ex = GETFIELD(inst,9,0); - DEBUGF(("graphplot x (%d) i%d\r\n", (int)ex, i)); + DEBUGF("graphplot x (%d) i%d\r\n", (int)ex, i); ey = ypos + VSCALE(graphplot_step); /* VT48 ES says first datum doesn't increment Y; that's wrong */ /* diagnostic DZVSD shows that "i" bit is ignored! */ @@ -3589,7 +3612,7 @@ vt11_cycle(int us, int slowdown) basic_vector(i, (int)x, (int)y); } else { ey = GETFIELD(inst,9,0); - DEBUGF(("graphplot y (%d) i%d\r\n", (int)ey, i)); + DEBUGF("graphplot y (%d) i%d\r\n", (int)ey, i); ex = xpos + VSCALE(graphplot_step); /* VT48 ES says first datum doesn't increment X; that's wrong */ /* diagnostic DZVSD shows that "i" bit is ignored! */ @@ -3620,7 +3643,7 @@ vt11_cycle(int us, int slowdown) point3(i, xpos + VSCALE(ex), ypos + VSCALE(ey), zpos + VSCALE(ez * 4), 1); } else { - DEBUGF(("relative point i%d (%d,%d)\r\n", i, (int)ex, (int)ey)); + DEBUGF("relative point i%d (%d,%d)\r\n", i, (int)ex, (int)ey); point2(i, xpos + VSCALE(ex), ypos + VSCALE(ey), 1); } break; @@ -3643,7 +3666,7 @@ vt11_cycle(int us, int slowdown) vt_lpen_intr(); /* post graphic interrupt to host */ MORE_DATA } - DEBUGF(("basic short vector2 i%d d%d l%d\r\n", i, (int)ex,(int)ey)); + DEBUGF("basic short vector2 i%d d%d l%d\r\n", i, (int)ex,(int)ey); basic_vector(i, (int)ex, (int)ey); break; @@ -3678,7 +3701,7 @@ vt11_cycle(int us, int slowdown) PNORM(ez - zpos) / 4); /* approx. */ zpos = ez; /* more precise, if PSCALEF > 1 */ } else { - DEBUGF(("absolute vector i%d (%d,%d)\r\n", i, (int)x, (int)y)); + DEBUGF("absolute vector i%d (%d,%d)\r\n", i, (int)x, (int)y); ex = VSCALE(x) + xoff; ey = VSCALE(y) + yoff; vector2(i, PNORM(ex - xpos), PNORM(ey - ypos)); /* approx. */ @@ -3753,7 +3776,7 @@ vt11_cycle(int us, int slowdown) goto check; bus_timeout: - DEBUGF(("TIMEOUT\r\n")); + DEBUGF("TIMEOUT\r\n"); /* fall through to check (time_out has already been set) */ check: @@ -3788,4 +3811,3 @@ vt11_cycle(int us, int slowdown) display_age(us, slowdown); return !maint1 && !maint2 && busy; } /* vt11_cycle */ - diff --git a/display/vt11.h b/display/vt11.h index d5833ebc..91d21acc 100644 --- a/display/vt11.h +++ b/display/vt11.h @@ -124,8 +124,8 @@ extern void vt11_set_sar(uint16); /* write stack address/maint register */ extern void vt11_set_zpr(uint16); /* write Z position register */ extern void vt11_set_zor(uint16); /* write Z offset register */ -extern void vt11_reset(void); /* reset the display processor */ -extern int vt11_cycle(int,int); /* perform a display processor cycle */ +extern void vt11_reset(void *, int); /* reset the display processor */ +extern int vt11_cycle(int, int); /* perform a display processor cycle */ /* * callbacks from VT11/VS60 simulator (to SIMH PDP-11 VT driver, for example) diff --git a/display/win32.c b/display/win32.c index 670d6ecb..0fee54f4 100644 --- a/display/win32.c +++ b/display/win32.c @@ -317,7 +317,7 @@ ws_thread_init(void) /* called from display layer on first display op */ int -ws_init(char *name, int xp, int yp, int colors) +ws_init(char *name, int xp, int yp, int colors, void *dptr) { xpixels = xp; ypixels = yp; @@ -331,6 +331,10 @@ ws_init(char *name, int xp, int yp, int colors) return 1; /* XXX return errors!! */ } +void ws_shutdown (void) +{ +} + void * ws_color_rgb(int r, int g, int b) { diff --git a/display/ws.h b/display/ws.h index 87d67869..21c83a85 100644 --- a/display/ws.h +++ b/display/ws.h @@ -31,13 +31,13 @@ /* unless you're writing a new driver, you shouldn't be looking here! */ -extern int ws_init(char *, int, int, int); +extern int ws_init(char *, int, int, int, void *); +void ws_shutdown(void); extern void *ws_color_rgb(int, int, int); extern void *ws_color_black(void); extern void *ws_color_white(void); extern void ws_display_point(int, int, void *); extern void ws_sync(void); -extern int ws_loop(void (*)(void *), void *); extern int ws_poll(int *, int); extern void ws_beep(void); diff --git a/display/x11.c b/display/x11.c index d68ad65f..68796b5d 100644 --- a/display/x11.c +++ b/display/x11.c @@ -207,7 +207,8 @@ handle_exposure(w, d, e, b) int ws_init(char *crtname, /* crt type name */ int xp, int yp, /* screen size in pixels */ - int colors) /* colors to support (not used) */ + int colors, /* colors to support (not used) */ + void *dptr) { Arg arg[25]; XGCValues gcvalues; @@ -298,6 +299,10 @@ ws_init(char *crtname, /* crt type name */ return 1; } /* ws_init */ +void ws_shutdown (void) +{ +} + void * ws_color_black(void) { diff --git a/display/xy.h b/display/xy.h index 7fc87328..b99de0a2 100644 --- a/display/xy.h +++ b/display/xy.h @@ -57,7 +57,7 @@ enum display_type { * must be called before first call to display_age() * (but called implicitly by display_point()) */ -extern int display_init(enum display_type, int scale); +extern int display_init(enum display_type, int scale, void *dptr); /* return size of virtual display */ extern int display_xpoints(void); diff --git a/doc/tx0_doc.doc b/doc/tx0_doc.doc index 87794940..7c74e045 100644 Binary files a/doc/tx0_doc.doc and b/doc/tx0_doc.doc differ diff --git a/makefile b/makefile index 58a5a790..894fe08a 100644 --- a/makefile +++ b/makefile @@ -56,35 +56,32 @@ ifeq (old,$(shell gmake --version /dev/null 2>&1 | grep 'GNU Make' | awk '{ if ( $(warning *** Warning *** GNU Make Version $(GMAKE_VERSION) is too old to) $(warning *** Warning *** fully process this makefile) endif -# building the pdp11, or any vax simulator could use networking support BUILD_SINGLE := $(MAKECMDGOALS) $(BLANK_SUFFIX) +# building the pdp1, pdp11, tx-0, or any microvax simulator could use video support +ifneq (,$(or $(findstring XXpdp1XX,$(addsuffix XX,$(addprefix XX,$(MAKECMDGOALS)))),$(findstring pdp11,$(MAKECMDGOALS)),$(findstring tx-0,$(MAKECMDGOALS)),$(findstring microvax1,$(MAKECMDGOALS)),$(findstring microvax2,$(MAKECMDGOALS)),$(findstring microvax3900,$(MAKECMDGOALS)),$(findstring XXvaxXX,$(addsuffix XX,$(addprefix XX,$(MAKECMDGOALS)))))) + VIDEO_USEFUL = true +endif +# building the besm6 needs both video support and fontfile support +ifneq (,$(findstring besm6,$(MAKECMDGOALS))) + VIDEO_USEFUL = true + BESM6_BUILD = true +endif +# building the pdp11, or any vax simulator could use networking support ifneq (,$(or $(findstring pdp11,$(MAKECMDGOALS)),$(findstring vax,$(MAKECMDGOALS)),$(findstring all,$(MAKECMDGOALS)))) NETWORK_USEFUL = true - ifneq (,$(or $(findstring microvax1,$(MAKECMDGOALS)),$(findstring microvax2,$(MAKECMDGOALS)),$(findstring microvax3900,$(MAKECMDGOALS)),$(findstring XXvaxXX,$(addsuffix XX,$(addprefix XX,$(MAKECMDGOALS)))))) - VIDEO_USEFUL = true - endif ifneq (,$(findstring all,$(MAKECMDGOALS))$(word 2,$(MAKECMDGOALS))) BUILD_MULTIPLE = s VIDEO_USEFUL = true + BESM6_BUILD = true endif - ifneq (,$(findstring pdp11,$(MAKECMDGOALS))$(findstring all,$(MAKECMDGOALS))) - DISPLAY_USEFUL = true - endif -else ifneq (,$(findstring besm6,$(MAKECMDGOALS))) - VIDEO_USEFUL = true - BESM6_BUILD = true else ifeq ($(MAKECMDGOALS),) # default target is all NETWORK_USEFUL = true VIDEO_USEFUL = true - DISPLAY_USEFUL = true BUILD_MULTIPLE = s BUILD_SINGLE := all $(BUILD_SINGLE) - else - ifneq (,$(or $(or $(findstring pdp1,$(MAKECMDGOALS)),$(findstring pdp11,$(MAKECMDGOALS))),$(findstring tx-0,$(MAKECMDGOALS)))) - DISPLAY_USEFUL = true - endif + BESM6_BUILD = true endif endif find_lib = $(abspath $(strip $(firstword $(foreach dir,$(strip $(LIBPATH)),$(wildcard $(dir)/lib$(1).$(LIBEXT)))))) @@ -427,9 +424,12 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin) endif ifneq (,$(call find_include,SDL2/SDL)) ifneq (,$(call find_lib,SDL2)) - VIDEO_CCDEFS += -DHAVE_LIBSDL -I$(dir $(call find_include,SDL2/SDL)) + VIDEO_CCDEFS += -DHAVE_LIBSDL -DUSE_SIM_VIDEO -I$(dir $(call find_include,SDL2/SDL)) VIDEO_LDFLAGS += -lSDL2 VIDEO_FEATURES = - video capabilities provided by libSDL2 (Simple Directmedia Layer) + DISPLAYL = ${DISPLAYD}/display.c $(DISPLAYD)/sim_ws.c + DISPLAYVT = ${DISPLAYD}/vt11.c + DISPLAY_OPT += -DUSE_DISPLAY $(VIDEO_CCDEFS) $(VIDEO_LDFLAGS) $(info using libSDL2: $(call find_lib,SDL2) $(call find_include,SDL2/SDL)) ifeq (Darwin,$(OSTYPE)) VIDEO_LDFLAGS += -lobjc -framework cocoa -DSDL_MAIN_AVAILABLE @@ -438,9 +438,12 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin) else ifneq (,$(call find_include,SDL/SDL)) ifneq (,$(call find_lib,SDL)) - VIDEO_CCDEFS += -DHAVE_LIBSDL -I$(dir $(call find_include,SDL/SDL)) + VIDEO_CCDEFS += -DHAVE_LIBSDL -DUSE_SIM_VIDEO -I$(dir $(call find_include,SDL/SDL)) VIDEO_LDFLAGS += -lSDL VIDEO_FEATURES = - video capabilities provided by libSDL (Simple Directmedia Layer) + DISPLAYL = ${DISPLAYD}/display.c $(DISPLAYD)/sim_ws.c + DISPLAYVT = ${DISPLAYD}/vt11.c + DISPLAY_OPT += -DUSE_DISPLAY $(VIDEO_CCDEFS) $(VIDEO_LDFLAGS) $(info using libSDL: $(call find_lib,SDL) $(call find_include,SDL/SDL)) ifeq (Darwin,$(OSTYPE)) VIDEO_LDFLAGS += -lobjc -framework cocoa -DSDL_MAIN_AVAILABLE @@ -461,27 +464,6 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin) $(info *** Info ***) endif endif - ifneq (,$(DISPLAY_USEFUL)) - ifeq (,$(WIN32)) - ifneq (,$(call find_include,X11/Intrinsic)) - ifneq (,$(call find_lib,Xt)) - DISPLAYL = ${DISPLAYD}/display.c $(DISPLAYD)/x11.c - DISPLAYVT = ${DISPLAYD}/vt11.c - DISPLAY_OPT += -DUSE_DISPLAY -I$(dir $(call find_include,X11/Intrinsic))/include -lXt -lX11 -lm - $(info using display: $(call find_lib,Xt) $(call find_include,X11/Intrinsic)) - endif - ifneq (,$(GCC_WARNINGS_CMD)$(CLANG_VERSION)) - ifneq (,$(CLANG_VERSION)$(findstring -Wdeprecated-declarations,$(shell $(GCC_WARNINGS_CMD)))) - DISPLAY_OPT += -Wno-deprecated-declarations - endif - endif - endif - else - DISPLAYL = ${DISPLAYD}/display.c $(DISPLAYD)/win32.c - DISPLAYVT = ${DISPLAYD}/vt11.c - DISPLAY_OPT = -DUSE_DISPLAY -lgdi32 - endif - endif ifneq (,$(NETWORK_USEFUL)) ifneq (,$(call find_include,pcap)) ifneq (,$(shell grep 'pcap/pcap.h' $(call find_include,pcap) | grep include)) @@ -926,10 +908,13 @@ DISPLAYD = display # Emulator source files and compile time options # PDP1D = PDP1 +ifneq (,$(DISPLAY_OPT)) + PDP1_DISPLAY_OPT = -DDISPLAY_TYPE=DIS_TYPE30 -DPIX_SCALE=RES_HALF +endif PDP1 = ${PDP1D}/pdp1_lp.c ${PDP1D}/pdp1_cpu.c ${PDP1D}/pdp1_stddev.c \ ${PDP1D}/pdp1_sys.c ${PDP1D}/pdp1_dt.c ${PDP1D}/pdp1_drm.c \ ${PDP1D}/pdp1_clk.c ${PDP1D}/pdp1_dcs.c ${PDP1D}/pdp1_dpy.c ${DISPLAYL} -PDP1_OPT = -I ${PDP1D} $(DISPLAY_OPT) +PDP1_OPT = -I ${PDP1D} $(DISPLAY_OPT) $(PDP1_DISPLAY_OPT) NOVAD = NOVA