Initial public version of TX-0 for SIMH

Integrate TX-0 simulation into SIMH.
This commit is contained in:
Howard M. Harte 2012-11-07 20:47:26 -08:00
parent be1e1326b3
commit 35ef1c8d24
25 changed files with 11346 additions and 0 deletions

20
TX-0/resource.h Normal file
View file

@ -0,0 +1,20 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by tx0.rc
//
#define HTC_VERS_MIN 0
#define HTC_VERS_REV 0
#define HTC_VERS_MAJ 1
#define IDI_ICON1 106
#define HTC_VERS_BUILD 1746
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 108
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

BIN
TX-0/tx0.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

110
TX-0/tx0.rc Normal file
View file

@ -0,0 +1,110 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,0,1746
PRODUCTVERSION 1,0,0,1746
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x4L
FILETYPE 0x1L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "FileDescription", "SIMH TX-0 Simulator"
VALUE "FileVersion", "1.0.0.1746"
VALUE "InternalName", "TX-0"
VALUE "LegalCopyright", "Copyright (c) 2009-2012, Howard M. Harte"
VALUE "OriginalFilename", "TX0.exe"
VALUE "ProductName", " TX-0 Application"
VALUE "ProductVersion", "1.0.0.1746"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_ICON1 ICON "tx0.ico"
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

1476
TX-0/tx0_cpu.c Normal file

File diff suppressed because it is too large Load diff

93
TX-0/tx0_defs.h Normal file
View file

@ -0,0 +1,93 @@
/*************************************************************************
* *
* $Id: tx0_defs.h 2059 2009-02-23 05:59:14Z hharte $ *
* *
* Copyright (c) 2009 Howard M. Harte. *
* Based on pdp1_defs.h, Copyright (c) 1993-2006, Robert M. Supnik *
* *
* 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 HOWARD M. HARTE 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 name of Howard M. Harte shall *
* not be used in advertising or otherwise to promote the sale, use or *
* other dealings in this Software without prior written authorization *
* of Howard M. Harte. *
* *
* Module Description: *
* cpu TX-0 Central Processor *
* *
* Environment: *
* User mode only *
* *
*************************************************************************/
#ifndef _PDP1_DEFS_H_
#define _PDP1_DEFS_H_ 0
#include "sim_defs.h"
/* Simulator stop codes */
#define STOP_RSRV 1 /* must be 1 */
#define STOP_HALT 2 /* HALT */
#define STOP_IBKPT 3 /* breakpoint */
/* Memory */
#define ASIZE 16 /* address bits */
#define MAXMEMSIZE (1u << ASIZE) /* max mem size */
#define AMASK (MAXMEMSIZE - 1) /* address mask */
#define MEMSIZE (cpu_unit.capac) /* actual memory size */
#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE)
/* Architectural constants */
#define SIGN 0400000 /* sign */
#define DMASK 0777777 /* data mask */
#define YMASK 0017777 /* "Y" Mask for address calculation (13 bits) */
/* I/O status flags */
#define IOS_V_LPN 17 /* light pen */
#define IOS_V_PETR 16 /* paper tape reader */
#define IOS_V_TTO 15 /* typewriter out */
#define IOS_V_TTI 14 /* typewriter in */
#define IOS_V_PTP 13 /* paper tape punch */
#define IOS_V_DRM 12 /* drum */
#define IOS_V_SQB 11 /* sequence break */
#define IOS_V_PNT 3 /* print done */
#define IOS_V_SPC 2 /* space done */
#define IOS_V_DCS 1 /* data comm sys */
#define IOS_V_DRP 0 /* parallel drum busy */
#define IOS_LPN (1 << IOS_V_LPN)
#define IOS_PETR (1 << IOS_V_PETR)
#define IOS_TTO (1 << IOS_V_TTO)
#define IOS_TTI (1 << IOS_V_TTI)
#define IOS_PTP (1 << IOS_V_PTP)
#define IOS_DRM (1 << IOS_V_DRM)
#define IOS_SQB (1 << IOS_V_SQB)
#define IOS_PNT (1 << IOS_V_PNT)
#define IOS_SPC (1 << IOS_V_SPC)
#define IOS_DCS (1 << IOS_V_DCS)
#define IOS_DRP (1 << IOS_V_DRP)
#define UNIT_V_MODE (UNIT_V_UF + 0)
#define UNIT_MODE (3 << UNIT_V_MODE)
#define UNIT_MODE_READIN (3 << UNIT_V_MODE)
#define UNIT_MODE_TEST (1 << UNIT_V_MODE)
#endif

16
TX-0/tx0_diag.txt Normal file
View file

@ -0,0 +1,16 @@
Programs that are known to work well:
bin_tic-tac-toe_new_code_12-16-61.bin, seems to fully work:
sim> boot petr
sim> g (will halt with 205200 in LR)
sim> e lr
LR: 205200
sim> g (again to start game.)
bin_tstDisplay.bin, makes a diagonal line on the DPY
bin_lightGunTst.bin, can draw on screen with light pen.
bin_newMouse_3-22-66.bin - These kind of work, but mouse gives up easy
bin_newMouse_8-14-61.bin - and can crash on complex mazes. Sim bug
somewhere.

139
TX-0/tx0_dpy.c Normal file
View file

@ -0,0 +1,139 @@
/*************************************************************************
* *
* $Id: tx0_dpy.c 2060 2009-02-24 06:49:07Z hharte $ *
* *
* Copyright (c) 2009-2012, Howard M. Harte *
* Copyright (c) 2004, Philip L. Budne *
* Copyright (c) 1993-2003, Robert M. Supnik *
* *
* 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 HOWARD M. HARTE 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 name of Howard M. Harte shall *
* not be used in advertising or otherwise to promote the sale, use or *
* other dealings in this Software without prior written authorization *
* of Howard M. Harte. *
* *
* Module Description: *
* TX-0 display simulator *
* *
* Environment: *
* User mode only *
* *
*************************************************************************/
#ifdef USE_DISPLAY
#include "tx0_defs.h"
#include "display/display.h"
extern int32 ios, iosta, PF;
extern int32 stop_inst;
extern int32 PEN_HIT;
t_stat dpy_svc (UNIT *uptr);
t_stat dpy_reset (DEVICE *dptr);
/* DPY data structures
dpy_dev DPY device descriptor
dpy_unit DPY unit
dpy_reg DPY register list
*/
#define CYCLE_TIME 5 /* 5us memory cycle */
#define DPY_WAIT (50/CYCLE_TIME) /* 50us */
UNIT dpy_unit = {
UDATA (&dpy_svc, UNIT_ATTABLE, 0), DPY_WAIT };
DEVICE dpy_dev = {
"DPY", &dpy_unit, NULL, NULL,
1, 10, 31, 1, 8, 8,
NULL, NULL, &dpy_reset,
NULL, NULL, NULL,
NULL, DEV_DISABLE };
/* Display Routine */
int32 dpy (int32 ac)
{
int32 pen_hit;
int32 x, y;
int level;
if (dpy_dev.flags & DEV_DIS) /* disabled? */
return SCPE_UDIS;
x = (ac >> 9) & 0777; /* X = high nine bits of AC */
y = (ac & 0777); /* Y = low nine bits of AC */
/*
* convert one's complement -255..+255 center origin
* to 0..511 (lower left origin)
*/
if (x & 0400)
x ^= 0400;
else
x += 255;
if (y & 0400)
y ^= 0400;
else
y += 255;
level = DISPLAY_INT_MAX; /* Maximum intensity */
if (display_point(x,y,level,0)) {
/* here with light pen hit */
PF = PF | 010; /* set prog flag 3 */
pen_hit = 1;
} else {
pen_hit = 0;
}
sim_activate (&dpy_unit, dpy_unit.wait); /* activate */
return pen_hit;
}
/*
* Unit service routine
*
* Under X11 this includes polling for events, so it can't be
* call TOO infrequently...
*/
t_stat dpy_svc (UNIT *uptr)
{
display_age(dpy_unit.wait*CYCLE_TIME, 1);
sim_activate (&dpy_unit, dpy_unit.wait); /* requeue! */
return SCPE_OK;
}
/* Reset routine */
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 */
return SCPE_OK;
}
#else /* USE_DISPLAY not defined */
char tx0_dpy_unused; /* sometimes empty object modules cause problems */
#endif /* USE_DISPLAY not defined */

623
TX-0/tx0_stddev.c Normal file
View file

@ -0,0 +1,623 @@
/*************************************************************************
* *
* $Id: tx0_stddev.c 2063 2009-02-25 07:37:57Z hharte $ *
* *
* Copyright (c) 2009-2012 Howard M. Harte. *
* Based on pdp1_stddev.c, Copyright (c) 1993-2006, Robert M. Supnik *
* *
* 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 HOWARD M. HARTE 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 name of Howard M. Harte shall *
* not be used in advertising or otherwise to promote the sale, use or *
* other dealings in this Software without prior written authorization *
* of Howard M. Harte. *
* *
* Module Description: *
* TX-0 Standard Devices *
* *
* Environment: *
* User mode only *
* *
*************************************************************************/
/*
petr paper tape reader
ptp paper tape punch
tti keyboard
tto teleprinter
Note: PTP timeout must be >10X faster than TTY output timeout for Macro
to work correctly!
*/
#include "tx0_defs.h"
#define FLEXO_STOP 061 /* stop code */
#define FLEXO_UC 071
#define FLEXO_LC 075
#define UC_V 6 /* upper case */
#define UC (1 << UC_V)
#define BOTH (1 << (UC_V + 1)) /* both cases */
#define CW (1 << (UC_V + 2)) /* char waiting */
#define TT_WIDTH 077
#define UNIT_V_ASCII (UNIT_V_UF + 0) /* ASCII/binary mode */
#define UNIT_ASCII (1 << UNIT_V_ASCII)
#define PETR_LEADER 20 /* ASCII leader chars */
#define TRACE_PRINT(dev, level, args) if(dev.dctrl & level) { \
printf args; \
}
int32 petr_state = 0;
int32 petr_wait = 0;
int32 petr_stopioe = 0;
int32 petr_uc = 0; /* upper/lower case */
int32 petr_hold = 0; /* holding buffer */
int32 petr_leader = PETR_LEADER; /* leader count */
int32 ptp_stopioe = 0;
int32 tti_hold = 0; /* tti hold buf */
int32 tty_buf = 0; /* tty buffer */
int32 tty_uc = 0; /* tty uc/lc */
int32 tto_sbs = 0;
extern int32 ios, iosta;
extern int32 PF, IR, PC, TA;
extern int32 M[];
t_stat petr_svc (UNIT *uptr);
t_stat ptp_svc (UNIT *uptr);
t_stat tti_svc (UNIT *uptr);
t_stat tto_svc (UNIT *uptr);
t_stat petr_reset (DEVICE *dptr);
t_stat ptp_reset (DEVICE *dptr);
t_stat tty_reset (DEVICE *dptr);
t_stat petr_boot (int32 unitno, DEVICE *dptr);
t_stat petr_attach (UNIT *uptr, char *cptr);
/* Character translation tables */
int32 flexo_to_ascii[128] = {
/*00*/ 0, 0, 'e', '8', 0, '|', 'a', '3', /* lower case */
/*10*/ ' ', '=', 's', '4', 'i', '+', 'u', '2',
/*20*/ 0, '.', 'd', '5', 'r', '1', 'j', '7',
/*30*/ 'n', ',', 'f', '6', 'c', '-', 'k', 0,
/*40*/ 't', 0, 'z', '\b','l', '\t','w', 0,
/*50*/ 'h', '\r','y', 0, 'p', 0, 'q', 0,
/*60*/ 'o', '*', 'b', 0, 'g', 0, '9', 0,
/*70*/ 'm', 0, 'x', 0, 'v', 0, '0', 0,
/*00*/ 0, 0, 'E', '8', 0, '_', 'A', '3', /* upper case */
/*10*/ ' ', ':', 'S', '4', 'I', '/', 'U', '2',
/*20*/ 0, ')', 'D', '5', 'R', '1', 'J', '7',
/*30*/ 'N', '(', 'F', '6', 'C', '-', 'K', 0,
/*40*/ 'T', 0, 'Z', '\b','L', '\t','W', 0,
/*50*/ 'H', '\r','Y', 0, 'P', 0, 'Q', 0,
/*60*/ 'O', '*', 'B', 0, 'G', 0, '9', 0,
/*70*/ 'M', 0, 'X', 0, 'V', 0, '0', 0,
};
int32 ascii_to_flexo[128] = {
/*00*/ 0, 0, 0, BOTH+061, 0, 0, 0, 0, /* STOP mapped to ^C */
/*10*/ BOTH+043, BOTH+045, 0, 0, 0, BOTH+051, 0, 0,
/*20*/ 0, 0, 0, 0, 0, 0, 0, 0,
/*30*/ 0, 0, 0, BOTH+020, 0, 0, 0, 0, /* Color Shift mapped to ESC */
/*40*/ BOTH+010, 0, 0, 0, 0, 0, 0, 0, /* " ", */
/*50*/ UC+021, UC+031, 021, 015, 031, UC+035, UC+011, UC+015, /* ()*+,-./ */
/*60*/ 076, 025, 017, 007, 013, 023, 033, 027, /* 0-7 */
/*70*/ 003, 066, 0, 0, 0, 011, 0, 0, /* 89:;<=>? */
/*00*/ 040, UC+006, UC+062, UC+034, UC+022, UC+002, UC+032, UC+064, /* A-G */
/*10*/ UC+050, UC+014, UC+026, UC+036, UC+044, UC+070, UC+030, UC+060, /* H-O */
/*20*/ UC+054, UC+056, UC+024, UC+012, 040, 016, 074, 046, /* P-W */
/*30*/ UC+072, UC+052, UC+042, 0, 0, 0, 0, UC+005, /* X-Z, */
/*40*/ 00, 006, 062, 034, 022, 002, 032, 064, /* a-g */
/*50*/ 050, 014, 026, 036, 044, 070, 030, 060, /* h-o */
/*60*/ 054, 056, 024, 012, 040, 016, 074, 046, /* p-w */
/*70*/ 072, 052, 042, 0, 005, 0, UC+035, BOTH+077 /* x-z, */
};
/* PETR data structures
petr_dev PETR device descriptor
petr_unit PETR unit
petr_reg PETR register list
*/
UNIT petr_unit = {
UDATA (&petr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0),
SERIAL_IN_WAIT
};
REG petr_reg[] = {
{ ORDATA (BUF, petr_unit.buf, 18) },
{ FLDATA (UC, petr_uc, UC_V) },
{ FLDATA (DONE, iosta, IOS_V_PETR) },
{ ORDATA (HOLD, petr_hold, 9), REG_HRO },
{ ORDATA (STATE, petr_state, 5), REG_HRO },
{ FLDATA (WAIT, petr_wait, 0), REG_HRO },
{ DRDATA (POS, petr_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, petr_unit.wait, 24), PV_LEFT },
{ DRDATA (LEADER, petr_leader, 6), REG_HRO },
{ FLDATA (STOP_IOE, petr_stopioe, 0) },
{ NULL }
};
MTAB petr_mod[] = {
{ UNIT_ASCII, UNIT_ASCII, "ASCII", "ASCII", NULL },
{ UNIT_ASCII, 0, "FLEXO", "FLEXO", NULL },
{ 0 }
};
/* Debug flags */
#define ERROR_MSG (1 << 0)
#define TRACE_MSG (1 << 1)
#define VERBOSE_MSG (1 << 2)
/* Debug Flags */
static DEBTAB petr_dt[] = {
{ "ERROR", ERROR_MSG },
{ "TRACE", TRACE_MSG },
{ "VERBOSE",VERBOSE_MSG },
{ NULL, 0 }
};
DEVICE petr_dev = {
"PETR", &petr_unit, petr_reg, petr_mod,
1, 10, 31, 1, 8, 8,
NULL, NULL, &petr_reset,
&petr_boot, &petr_attach, NULL,
NULL, DEV_DEBUG, (ERROR_MSG),
petr_dt, NULL
};
/* PTP data structures
ptp_dev PTP device descriptor
ptp_unit PTP unit
ptp_reg PTP register list
*/
UNIT ptp_unit = {
UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT
};
REG ptp_reg[] = {
{ ORDATA (BUF, ptp_unit.buf, 8) },
{ FLDATA (DONE, iosta, IOS_V_PTP) },
{ DRDATA (POS, ptp_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, ptp_unit.wait, 24), PV_LEFT },
{ FLDATA (STOP_IOE, ptp_stopioe, 0) },
{ NULL }
};
MTAB ptp_mod[] = {
{ 0 }
};
DEVICE ptp_dev = {
"PTP", &ptp_unit, ptp_reg, ptp_mod,
1, 10, 31, 1, 8, 8,
NULL, NULL, &ptp_reset,
NULL, NULL, NULL,
NULL, DEV_DEBUG, (ERROR_MSG|TRACE_MSG),
petr_dt, NULL
};
/* TTI data structures
tti_dev TTI device descriptor
tti_unit TTI unit
tti_reg TTI register list
*/
UNIT tti_unit = { UDATA (&tti_svc, 0, 0), KBD_POLL_WAIT };
REG tti_reg[] = {
{ ORDATA (BUF, tty_buf, 6) },
{ FLDATA (UC, tty_uc, UC_V) },
{ ORDATA (HOLD, tti_hold, 9), REG_HRO },
{ FLDATA (DONE, iosta, IOS_V_TTI) },
{ DRDATA (POS, tti_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, tti_unit.wait, 24), REG_NZ + PV_LEFT },
{ NULL }
};
MTAB tti_mod[] = {
{ 0 }
};
DEVICE tti_dev = {
"TTI", &tti_unit, tti_reg, tti_mod,
1, 10, 31, 1, 8, 8,
NULL, NULL, &tty_reset,
NULL, NULL, NULL,
NULL, DEV_DEBUG, (ERROR_MSG|TRACE_MSG),
petr_dt, NULL
};
/* TTO data structures
tto_dev TTO device descriptor
tto_unit TTO unit
tto_reg TTO register list
*/
UNIT tto_unit = { UDATA (&tto_svc, 0, 0), SERIAL_OUT_WAIT * 10 };
REG tto_reg[] = {
{ ORDATA (BUF, tty_buf, 6) },
{ FLDATA (UC, tty_uc, UC_V) },
{ FLDATA (DONE, iosta, IOS_V_TTO) },
{ DRDATA (POS, tto_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, tto_unit.wait, 24), PV_LEFT },
{ NULL }
};
MTAB tto_mod[] = {
{ 0 }
};
DEVICE tto_dev = {
"TTO", &tto_unit, tto_reg, tto_mod,
1, 10, 31, 1, 8, 8,
NULL, NULL, &tty_reset,
NULL, NULL, NULL,
NULL, DEV_DEBUG, (ERROR_MSG|TRACE_MSG),
petr_dt, NULL
};
/* Paper tape reader: IOT routine. Points to note:
- RPA (but not RPB) complements the reader clutch control. Thus,
if the reader is running, RPA will stop it.
- The status bit indicates data in the reader buffer that has not
been transfered to IR. It is cleared by any RB->IR operation,
including RRB and the completion pulse.
- A reader error on a wait mode operation could hang the simulator.
IOH is set; any retry (without RESET) will be NOP'd. Accordingly,
the PETR service routine clears IOH on any error during a rpa/rpb i.
*/
int32 petr (int32 inst, int32 dev, int32 dat)
{
int32 tmpAC = 0;
int i = 0;
t_stat result;
ios = 1;
for (i=0;i<inst;i++) {
do {
result = petr_svc(&petr_unit);
if (result != SCPE_OK) {
printf("PETR: Read error\n");
break;
}
} while ((petr_unit.buf & 0100) == 0); /* NOTE: Lines without seventh hole are ignored by PETR. */
petr_unit.buf &= 077; /* Mask to 6 bits. */
tmpAC |= ((petr_unit.buf & 001) >> 0) << 17; /* bit 0 */
tmpAC |= ((petr_unit.buf & 002) >> 1) << 14; /* bit 3 */
tmpAC |= ((petr_unit.buf & 004) >> 2) << 11; /* bit 6 */
tmpAC |= ((petr_unit.buf & 010) >> 3) << 8; /* bit 9 */
tmpAC |= ((petr_unit.buf & 020) >> 4) << 5; /* bit 12 */
tmpAC |= ((petr_unit.buf & 040) >> 5) << 2; /* bit 15 */
if (i < (inst-1)) {
uint32 bit0 = (tmpAC & 1) << 17;
TRACE_PRINT(petr_dev, TRACE_MSG, ("PETR read [%04x=0x%02x] %03o\n", petr_unit.pos-1, petr_unit.buf, petr_unit.buf));
tmpAC >>= 1;
tmpAC |= bit0;
} else {
TRACE_PRINT(petr_dev, TRACE_MSG, ("PETR read [%04x=0x%02x] %03o, tmpAC=%06o\n", petr_unit.pos-1, petr_unit.buf, petr_unit.buf, tmpAC));
}
}
return tmpAC;
/* sim_activate (&petr_unit, petr_unit.wait); */ /* start reader */
}
/* Unit service */
t_stat petr_svc (UNIT *uptr)
{
int32 temp;
if ((uptr->flags & UNIT_ATT) == 0) { /* attached? */
ios = 0;
return SCPE_OK;
}
if ((temp = getc (uptr->fileref)) != EOF) { /* no, get raw char */
uptr->pos = uptr->pos + 1; /* if not eof, count */
}
if (temp == EOF) { /* end of file? */
if (feof (uptr->fileref)) {
ios = 0;
return SCPE_IOERR;
}
else perror ("PETR I/O error");
clearerr (uptr->fileref);
ios = 0;
return SCPE_IOERR;
}
uptr->buf = temp;
ios = 0;
return SCPE_OK;
}
/* Reset routine */
t_stat petr_reset (DEVICE *dptr)
{
petr_state = 0; /* clear state */
petr_wait = 0;
petr_hold = 0;
petr_uc = 0;
petr_unit.buf = 0;
iosta = iosta & ~IOS_PETR; /* clear flag */
sim_cancel (&petr_unit); /* deactivate unit */
return SCPE_OK;
}
/* Attach routine */
t_stat petr_attach (UNIT *uptr, char *cptr)
{
petr_leader = PETR_LEADER; /* set up leader */
return attach_unit (uptr, cptr);
}
/* Bootstrap routine */
extern t_stat cpu_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc);
extern UNIT cpu_unit;
//#define SANITY_CHECK_TAPE
/* Switches the CPU to READIN mode and starts execution. */
t_stat petr_boot (int32 unitno, DEVICE *dptr)
{
t_stat reason = SCPE_OK;
#ifdef SANITY_CHECK_TAPE
int32 AC, MBR, MAR, IR = 0;
int32 blkcnt, chksum = 0, fa, la;
int32 addr, tdata;
#endif /* SANITY_CHECK_TAPE */
/* Switch to READIN mode. */
cpu_set_mode(&cpu_unit, UNIT_MODE_READIN, NULL, NULL);
#ifdef SANITY_CHECK_TAPE
for(;(IR != 2) && (IR != 1);) {
AC = petr(3,0,0); /* Read three chars from tape into AC */
MAR = AC & AMASK; /* Set memory address */
IR = AC >> 16;
if (!MEM_ADDR_OK(MAR)) {
TRACE_PRINT(petr_dev, ERROR_MSG, ("READIN: Tape address out of range.\n"));
reason = SCPE_FMT;
}
switch (IR) {
case 00: /* Storage (sto x) */
case 03: /* Storage (opr x) */
MBR = petr(3,0,0); /* Read three characters from tape. */
TRACE_PRINT(petr_dev, ERROR_MSG, ("READIN: sto @%06o = %06o\n", MAR, MBR));
printf("[%06o] = %06o\n", MAR, MBR);
break;
case 02: /* Transfer Control (trn x) Start Execution */
PC = MAR;
reason = SCPE_OK; /* let SIMH start execution. */
TRACE_PRINT(petr_dev, ERROR_MSG, ("READIN: trn %06o (Start Execution)\n", PC));
reason = cpu_set_mode(&cpu_unit, 0, NULL, NULL);
break;
case 01: /* Transfer (add x) - Halt */
PC = MAR;
reason = SCPE_STOP; /* let SIMH halt. */
TRACE_PRINT(petr_dev, ERROR_MSG, ("READIN: add %06o (Halt)\n", PC));
reason = cpu_set_mode(&cpu_unit, 0, NULL, NULL);
break;
default:
reason = SCPE_IERR;
break;
}
}
blkcnt = 0;
while (1) {
chksum = 0;
fa = petr(3,0,0); /* Read three characters from tape. */
if ((fa & 0400000) || (fa & 0200000)) {
break;
}
chksum += fa;
if (chksum > 0777777) {
chksum +=1;
}
chksum &= 0777777;
la = petr(3,0,0); /* Read three characters from tape. */
chksum += la;
if (chksum > 0777777) {
chksum +=1;
}
chksum &= 0777777;
la = (~la) & 0177777;
printf("First Address=%06o, Last Address=%06o\n", fa, la);
for(addr = fa; addr <= la; addr++) {
tdata = petr(3,0,0); /* Read three characters from tape. */
chksum += tdata;
if (chksum > 0777777) {
chksum +=1;
}
chksum &= 0777777;
}
chksum = (~chksum) & 0777777;
tdata = petr(3,0,0);
if (chksum != tdata) {
reason = SCPE_FMT;
}
printf("Block %d: Calculated checksum=%06o, real checksum=%06o, %s\n", blkcnt, chksum, tdata, chksum == tdata ? "OK" : "BAD Checksum!");
blkcnt++;
}
fseek (petr_dev.units[0].fileref, 0, SEEK_SET);
#endif /* SANITY_CHECK_TAPE */
/* Start Execution */
return (reason);
}
/* Paper tape punch: IOT routine */
int32 ptp (int32 inst, int32 dev, int32 dat)
{
iosta = iosta & ~IOS_PTP; /* clear flag */
ptp_unit.buf = dat & 0177;
ptp_svc (&ptp_unit);
/* sim_activate (&ptp_unit, ptp_unit.wait); */ /* start unit */
return dat;
}
/* Unit service */
t_stat ptp_svc (UNIT *uptr)
{
ios = 1; /* restart */
iosta = iosta | IOS_PTP; /* set flag */
if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */
return SCPE_UNATT;
if (putc (uptr->buf, uptr->fileref) == EOF) { /* I/O error? */
perror ("PTP I/O error");
clearerr (uptr->fileref);
return SCPE_IOERR;
}
uptr->pos = uptr->pos + 1;
return SCPE_OK;
}
/* Reset routine */
t_stat ptp_reset (DEVICE *dptr)
{
ptp_unit.buf = 0; /* clear state */
iosta = iosta & ~IOS_PTP; /* clear flag */
sim_cancel (&ptp_unit); /* deactivate unit */
return SCPE_OK;
}
/* Typewriter IOT routines */
int32 tti (int32 inst, int32 dev, int32 dat)
{
iosta = iosta & ~IOS_TTI; /* clear flag */
return tty_buf & 077;
}
int32 tto (int32 inst, int32 dev, int32 dat)
{
tty_buf = dat & TT_WIDTH; /* load buffer */
ios = 0;
tto_svc(&tto_unit);
/* sim_activate (&tto_unit, tto_unit.wait); */ /* activate unit */
return dat;
}
/* Unit service routines */
t_stat tti_svc (UNIT *uptr)
{
int32 in = 0, temp = 0;
sim_activate (uptr, uptr->wait); /* continue poll */
if (tti_hold & CW) { /* char waiting? */
tty_buf = tti_hold & TT_WIDTH; /* return char */
tti_hold = 0; /* not waiting */
} else {
if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp;
if (temp & SCPE_BREAK) return SCPE_OK; /* ignore break */
temp = temp & 0177;
if (temp == 0177) temp = '\b'; /* rubout? bs */
sim_putchar (temp); /* echo */
if (temp == '\r') sim_putchar ('\n'); /* cr? add nl */
in = ascii_to_flexo[temp]; /* translate char */
if (in == 0) return SCPE_OK; /* no xlation? */
if ((in & BOTH) || ((in & UC) == (tty_uc & UC))) {
tty_buf = in & TT_WIDTH;
} else { /* must shift */
tty_uc = in & UC; /* new case */
tty_buf = tty_uc? FLEXO_UC: FLEXO_LC;
tti_hold = in | CW; /* set 2nd waiting */
}
}
iosta = iosta | IOS_TTI; /* set flag */
TRACE_PRINT(tti_dev, TRACE_MSG, ("TTI read ASCII: %02x / FLEXO=%03o\n", temp, tty_buf));
uptr->pos = uptr->pos + 1;
return SCPE_OK;
}
t_stat tto_svc (UNIT *uptr)
{
int32 c = 0;
t_stat r;
if (tty_buf == FLEXO_UC) tty_uc = UC; /* upper case? */
else if (tty_buf == FLEXO_LC) tty_uc = 0; /* lower case? */
else {
c = flexo_to_ascii[tty_buf | tty_uc]; /* translate */
if (c && ((r = sim_putchar_s (c)) != SCPE_OK)) { /* output; error? */
sim_activate (uptr, uptr->wait); /* retry */
return ((r == SCPE_STALL)? SCPE_OK: r);
}
}
iosta = iosta | IOS_TTO; /* set flag */
uptr->pos = uptr->pos + 1;
if (c == '\r') { /* cr? add lf */
sim_putchar ('\n');
uptr->pos = uptr->pos + 1;
}
return SCPE_OK;
}
/* Reset routine */
t_stat tty_reset (DEVICE *dptr)
{
tty_buf = 0; /* clear buffer */
tty_uc = 0; /* clear case */
tti_hold = 0; /* clear hold buf */
iosta = (iosta & ~IOS_TTI) | IOS_TTO; /* clear flag */
sim_activate (&tti_unit, tti_unit.wait); /* activate keyboard */
sim_cancel (&tto_unit); /* stop printer */
return SCPE_OK;
}

439
TX-0/tx0_sys.c Normal file
View file

@ -0,0 +1,439 @@
/*************************************************************************
* *
* $Id: tx0_sys.c 2061 2009-02-24 07:05:58Z hharte $ *
* *
* Copyright (c) 2009-2012 Howard M. Harte. *
* Based on pdp1_sys.c, Copyright (c) 1993-2007, Robert M. Supnik *
* *
* 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 HOWARD M. HARTE 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 name of Howard M. Harte shall *
* not be used in advertising or otherwise to promote the sale, use or *
* other dealings in this Software without prior written authorization *
* of Howard M. Harte. *
* *
* Module Description: *
* TX-0 simulator interface *
* *
* Environment: *
* User mode only *
* *
*************************************************************************/
#include "tx0_defs.h"
#include <ctype.h>
extern DEVICE cpu_dev;
extern DEVICE petr_dev;
extern DEVICE tto_dev;
extern DEVICE tti_dev;
extern DEVICE ptp_dev;
#ifdef USE_DISPLAY
extern DEVICE dpy_dev;
#endif /* USE_DISPLAY */
#ifdef USE_FPC
extern DEVICE fpc_dev;
#endif /* USE_FPC */
extern UNIT cpu_unit;
extern REG cpu_reg[];
extern int32 M[];
extern int32 PC;
extern int32 ascii_to_flexo[], flexo_to_ascii[];
extern int32 sc_map[];
extern int32 sim_switches;
/* SCP data structures and interface routines
sim_name simulator name string
sim_PC pointer to saved PC register descriptor
sim_emax number of words for examine
sim_devices array of pointers to simulated devices
sim_stop_messages array of pointers to stop messages
sim_load binary loader
*/
char sim_name[] = "TX-0";
REG *sim_PC = &cpu_reg[0];
int32 sim_emax = 1;
DEVICE *sim_devices[] = {
&cpu_dev,
&petr_dev,
&tti_dev,
&tto_dev,
&ptp_dev,
#ifdef USE_DISPLAY
&dpy_dev,
#endif/* USE_DISPLAY */
#ifdef USE_FPC
&fpc_dev,
#endif /* USE_FPC */
NULL
};
const char *sim_stop_messages[] = {
"Unknown error",
"Undefined instruction",
"HALT instruction",
"Breakpoint",
"Nested XCT's",
"Nested indirect addresses",
"Infinite I/O wait state",
"DECtape off reel"
};
int32 tx0_getw (FILE *inf)
{
int32 i, tmp, word;
word = 0;
for (i = 0; i < 3;) {
if ((tmp = getc (inf)) == EOF) return -1;
if (tmp & 0200) {
word = (word << 6) | (tmp & 077);
i++;
}
}
return word;
}
/* Symbol tables */
typedef struct {
int32 opr;
char *mnemonic;
char *desc;
} OPMAP;
typedef struct {
char *mnemonic;
char *desc;
} INSTMAP;
const INSTMAP instmap[] = {
/* Store Class */
{ "sto", "Store AC" },
{ "stx", "Store AC, Indexed" },
{ "sxa", "Store XR in Address" },
{ "ado", "Add One" },
{ "slr", "Store LR" },
{ "slx", "Store LR, Indexed" },
{ "stz", "Store Zero" },
{ "[!sto-nop]", "NOP" },
/* Add Class */
{ "add", "Add" },
{ "adx", "Add, Indexed" },
{ "ldx", "Load XR" },
{ "aux", "Augment XR" },
{ "llr", "Load LR" },
{ "llx", "Load LR, Indexed" },
{ "lda", "Load AC" },
{ "lax", "Load AC, Indexed" },
/* Transfer Class */
{ "trn", "Transfer Negative" },
{ "trz", "Transfer +/- Zero" },
{ "tsx", "Transfer and set Index" },
{ "tix", "Transfer and Index" },
{ "tra", "Transfer" },
{ "trx", "Transfer Indexed" },
{ "tlv", "Transfer on external Level" },
{ "[!tra-nop]", "NOP" }
};
const OPMAP opmap [] = {
{ 0600000, "opr", "No operation" },
{ 0600001, "xro", "Clear XR to +0" },
{ 0600003, "lxr", "Place LR in XR" },
{ 0600012, "cry", "Carry the contents of AC according to bits of LR" },
{ 0600022, "lpd", "Logical exclusive or of AC is placed in AC (partial add)" },
{ 0600032, "lad", "Add LR to AC" },
{ 0600040, "com", "Compliment the AC" },
{ 0600072, "lcd", "Contents of LR minus those of AC are placed in AC" },
{ 0600130, "xad", "Add index register to accumulator" },
{ 0600170, "xcd", "Contents of XR minus those of AC are placed in AC" },
{ 0600200, "lro", "Clear LR to +0" },
{ 0600300, "xlr", "Place XR in LR" },
{ 0600303, "ixl", "Interchange XR and LR" },
{ 0600400, "shr", "Shift accumulator right one place, bit 0 remains unchanged" },
{ 0600600, "cyr", "Cycle AC right one place" },
{ 0603000, "pen", "Contents of light pen and light cannon flip-flops replace contents of AC bits 0 and 1. The flip-flops are cleared." },
{ 0604000, "bsr", "Backspace tape unit by one record" },
{ 0604004, "rtb", "Read tape binary (odd parity)" },
{ 0604004, "rds", "Select tape unit for reading a record" },
{ 0604010, "rew", "Rewind tape unit" },
{ 0604014, "wtb", "Write tape binary (odd parity)" },
{ 0604014, "wrs", "Select tape unit for writing a record" },
{ 0604024, "rtd", "Read tape decimal (even parity)" },
{ 0604034, "wtd", "Write tape decimal (even parity)" },
{ 0607000, "cpf", "The program flag is cleared" },
{ 0620000, "cpy", "Transmit information between the live register and selected input-output unit" },
{ 0622000, "dis", "Display point on CRT corresponding to contents of AC" },
{ 0624000, "prt", "Print one on-line flexo character from bits 2, 5, etc." },
{ 0624600, "pnt", "PRT, then cycle AC right once to set up another character" },
{ 0625000, "typ", "Read one character from on-line flexowriter into LR bits 12-17" },
{ 0626600, "p6h", "Punch one line of paper tape; 6 holes from bits 2, 5, etc. of AC then cycle right once." },
{ 0627600, "p7h", "Same as p6h, but punch 7th hole" },
{ 0630000, "hlt", "Stops computer" },
{ 0631000, "cll", "Clear left half of AC to zero" },
{ 0632000, "clr", "Clear right half of AC" },
{ 0632022, "---", "CLR+PAD+LMB" },
{ 0640001, "axr", "Place AC contents in XR" },
{ 0640021, "axo", "AXR, then set AC to +0" },
{ 0640030, "cyl", "Cycle AC left one place" },
{ 0640031, "alx", "AXR, then cycle AC left once" },
{ 0640040, "amz", "Add minus zero to AC" },
{ 0640061, "axc", "AXR, then set AC to -0" },
{ 0640200, "alr", "Place accumulator contents in live register" },
{ 0640201, "---", "ALR+MBX, Place accumulator contents in live register, Transfer MBR to XR." },
{ 0640203, "rax", "Place LR in XR, then place AC in LR" },
{ 0640205, "orl", "Logical or of AC and LR is placed in LR" },
{ 0640207, "anl", "Logical and of AC and LR is placed in LR" },
{ 0640220, "alo", "ALR, then set AC to +0" },
{ 0640230, "all", "ALR, then cycle left once" },
{ 0640231, "---", "AMB+MBL+PAD+CRY+MBX" },
{ 0640232, "iad", "Interchange and add AC contents are placed in the LR and the previous contents of the LR ar added to AC" },
{ 0640260, "alc", "ALR, then set AC to -0" },
{ 0640601, "arx", "AXR, then cycle AC right once" },
{ 0647000, "spf", "Place AC in program flag register" },
{ 0662020, "dso", "DIS, then clear AC" },
{ 0664020, "pno", "PRT, then clear AC" },
{ 0664060, "pnc", "PRT, then clear AC to -0" },
{ 0666020, "p6o", "p6h then clear AC" },
{ 0667020, "p7o", "p7h then clear AC" },
{ 0700000, "cla", "Clear entire AC to +0" },
{ 0700001, "cax", "Clear AC and XR to +0" },
{ 0700012, "lal", "Place LR in AC cycled left once" },
{ 0700022, "lac", "Place LR in AC" },
{ 0700040, "clc", "Clear and complement: set AC to -0" },
{ 0700062, "lcc", "Place complement of LR in AC" },
{ 0700072, "laz", "Add LR to minus zero in AC" },
{ 0700110, "xal", "XAC, then cycle AC left once" },
{ 0700120, "xac", "Place index register in accumulator" },
{ 0700160, "xcc", "Place complement of XR in accumulator" },
{ 0700200, "cal", "Clear AC and LR to +0" },
{ 0700322, "rxe", "Place LR in AC, then place XR in LR" },
{ 0700622, "lar", "Place LR in AC cycled right once" },
{ 0701000, "tac", "Contents of test accumulator are placed in AC" },
{ 0702020, "tbr", "Contents of test buffer register are placed in AC" },
{ 0703000, "---", "Clear AC and read light pen" },
{ 0706020, "rpf", "The program flag register is placed in AC" },
{ 0721000, "rlc", "Read one line paper tape into AC bits 0, 3, etc." },
{ 0721600, "rlr", "rlc, then cycle AC right once" },
{ 0723000, "r3c", "Read three lines of paper tape" },
{ 0723032, "---", "R3C+LMB+PAD+CRY" },
{ 0726000, "p6a", "Clear AC and punch a line of blank tape" },
{ 0740025, "ora", "Logical or of AC and LR is placed in AC" },
{ 0740027, "ana", "Logical and of AC and LR is placed in AC" },
{ 0740207, "anc", "ANL, then clear AC" },
{ 0740205, "oro", "ORL, then clear AC" },
{ 0740222, "ial", "Interchange AC and LR" },
{ 0763232, "---", "AMB+CLA+R3L+MBL+LMB+PAD+CRY" },
{ 0766020, "p6b", "Punch a line of blank tape, but save AC" },
{ 0000000, NULL, NULL }
};
/* Symbolic decode
Inputs:
*of = output stream
addr = current PC
*val = pointer to values
*uptr = pointer to unit
sw = switches
Outputs:
return = status code
*/
#define FMTASC(x) ((x) < 040)? "<%03o>": "%c", (x)
#define SIXTOASC(x) flexo_to_ascii[x]
#define ASCTOSIX(x) (ascii_to_flexo[x] & 077)
extern int32 cpu_get_mode (void);
extern t_stat fprint_sym_orig (FILE *of, t_addr addr, t_value *val,
UNIT *uptr, int32 sw);
t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,
UNIT *uptr, int32 sw)
{
int32 cflag, i, inst, op;
if(!cpu_get_mode()) {
return fprint_sym_orig (of, addr, val, uptr, sw);
}
inst = val[0];
cflag = (uptr == NULL) || (uptr == &cpu_unit);
if (sw & SWMASK ('A')) { /* ASCII? */
if (inst > 0377) return SCPE_ARG;
fprintf (of, FMTASC (inst & 0177));
return SCPE_OK;
}
if (sw & SWMASK ('F')) {
fputc (flexo_to_ascii[inst & 077], of);
return SCPE_OK;
}
if (sw & SWMASK ('C')) { /* character? */
fprintf (of, "%c", SIXTOASC ((inst >> 12) & 077));
fprintf (of, "%c", SIXTOASC ((inst >> 6) & 077));
fprintf (of, "%c", SIXTOASC (inst & 077));
return SCPE_OK;
}
if (!(sw & SWMASK ('M'))) return SCPE_ARG;
/* Instruction decode */
op = (inst >> 13) & 037;
if ((op & 030) != 030) /* sto, add, trn (not an opr) */
{
fprintf (of, "%s %05o (%s)", instmap[op].mnemonic, inst & 017777, instmap[op].desc);
} else { /* opr */
for(i=0;opmap[i].opr != 0;i++) {
if(inst == opmap[i].opr) {
fprintf (of, "opr %s (%s)", opmap[i].mnemonic, opmap[i].desc);
}
}
}
return SCPE_OK;
}
/* Get 18b signed number
Inputs:
*cptr = pointer to input string
*sign = pointer to sign
*status = pointer to error status
Outputs:
val = output value
*/
t_value get_sint (char *cptr, int32 *sign, t_stat *status)
{
*sign = 1;
if (*cptr == '+') {
*sign = 0;
cptr++;
}
else if (*cptr == '-') {
*sign = -1;
cptr++;
}
return get_uint (cptr, 8, DMASK, status);
}
/* Symbolic input
Inputs:
*cptr = pointer to input string
addr = current PC
uptr = pointer to unit
*val = pointer to output values
sw = switches
Outputs:
status = error status
*/
t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw)
{
#if 0
int32 cflag, d, i, j, k, sign;
t_stat r;
static int32 sc_enc[10] = { 0, 01, 03, 07, 017, 037, 077, 0177, 0377, 0777 };
char gbuf[CBUFSIZE];
cflag = (uptr == NULL) || (uptr == &cpu_unit);
while (isspace (*cptr)) cptr++;
for (i = 1; (i < 3) && (cptr[i] != 0); i++)
if (cptr[i] == 0) for (j = i + 1; j <= 3; j++) cptr[j] = 0;
if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */
if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
val[0] = (t_value) cptr[0];
return SCPE_OK;
}
if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* sixbit string? */
if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
val[0] = ((ASCTOSIX (cptr[0]) & 077) << 12) |
((ASCTOSIX (cptr[1]) & 077) << 6) |
(ASCTOSIX (cptr[2]) & 077);
return SCPE_OK;
}
cptr = get_glyph (cptr, gbuf, 0); /* get opcode */
for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ;
if (opcode[i] == NULL) return SCPE_ARG;
val[0] = opc_val[i] & DMASK; /* get value */
j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */
switch (j) { /* case on class */
case I_V_LAW: /* LAW */
cflag = 0; /* fall through */
case I_V_MRF: case I_V_MRI: /* mem ref */
cptr = get_glyph (cptr, gbuf, 0); /* get next field */
if ((j != I_V_MRI) && strcmp (gbuf, "I") == 0) { /* indirect? */
val[0] = val[0] | IA;
cptr = get_glyph (cptr, gbuf, 0);
}
d = get_uint (gbuf, 8, AMASK, &r);
if (r != SCPE_OK) return SCPE_ARG;
if (d <= DAMASK) val[0] = val[0] | d;
else if (cflag && (((addr ^ d) & EPCMASK) == 0))
val[0] = val[0] | (d & DAMASK);
else return SCPE_ARG;
break;
case I_V_SHF: /* shift */
cptr = get_glyph (cptr, gbuf, 0);
d = get_uint (gbuf, 10, 9, &r);
if (r != SCPE_OK) return SCPE_ARG;
val[0] = val[0] | sc_enc[d];
break;
case I_V_NPN: case I_V_IOT:
case I_V_OPR: case I_V_SKP: case I_V_SPC:
for (cptr = get_glyph (cptr, gbuf, 0); gbuf[0] != 0;
cptr = get_glyph (cptr, gbuf, 0)) {
for (i = 0; (opcode[i] != NULL) &&
(strcmp (opcode[i], gbuf) != 0); i++) ;
if (opcode[i] != NULL) {
k = opc_val[i] & DMASK;
if ((k != IA) && (((k ^ val[0]) & 0760000) != 0))
return SCPE_ARG;
val[0] = val[0] | k;
}
else {
d = get_sint (gbuf, &sign, &r);
if (r != SCPE_OK) return SCPE_ARG;
if (sign == 0) val[0] = val[0] + d;
else if (sign < 0) val[0] = val[0] - d;
else val[0] = val[0] | d;
}
}
break;
} /* end case */
if (*cptr != 0) return SCPE_ARG; /* junk at end? */
#endif
return SCPE_ARG;
}

133
TX-0/tx0_sys_orig.c Normal file
View file

@ -0,0 +1,133 @@
/*************************************************************************
* *
* $Id: tx0_sys_orig.c 2065 2009-02-25 15:05:00Z hharte $ *
* *
* Copyright (c) 2009-2012 Howard M. Harte. *
* *
* 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 HOWARD M. HARTE 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 name of Howard M. Harte shall *
* not be used in advertising or otherwise to promote the sale, use or *
* other dealings in this Software without prior written authorization *
* of Howard M. Harte. *
* *
* Module Description: *
* TX-0 simulator interface *
* *
* Environment: *
* User mode only *
* *
*************************************************************************/
#include "tx0_defs.h"
#include <ctype.h>
typedef struct {
int32 opr;
char *mnemonic;
char *desc;
} OPMAP;
const OPMAP opmap_orig [] = {
{ 0700000, "cll", "Clear the left nine digital positions of the AC" },
{ 0640000, "clr", "Clear the right nine digital positions of the AC" },
{ 0620000, "ios", "In-Out Stop" },
{ 0630000, "hlt", "Halt the computer" },
{ 0607000, "p7h", "Punch holes 1-6 in flexo tape Also punch a 7th hole on tape" },
{ 0606000, "p6h", "Punch holes 1-6 in flexo tape" },
{ 0604000, "pnt", "Print one flexowrite charater" },
{ 0601000, "r1c", "Read one line of flexo tape" },
{ 0603000, "r3c", "Read three lines of flexo tape" },
{ 0602000, "dis", "Intesnsify a point on the scope from x,y in AC" },
{ 0600400, "shr", "Shift the AC right one place" },
{ 0600600, "cyr", "Cycle the AC right one digital position (AC17 -> AC0)" },
{ 0600200, "mlr", "Store the contents of the MBR in the LR" },
{ 0600100, "pen", "Read the light pen flip flops 1 and 2 into AC0 and AC1" },
{ 0600004, "tac", "Insert a one in each digital position of the AC whereever there is a one in the corresponding digital position of the TAC" },
{ 0600040, "com", "Complement every digit in the accumulator" },
{ 0600020, "pad", "Partial add AC to MBR" },
{ 0600010, "cry", "Partial add the 18 digits of the AC to the corresponding 18 digits of the carry" },
{ 0600001, "amb", "Store the contents of the AC in the MBR" },
{ 0600003, "tbr", "Store the contents of the TBR in the MBR" },
{ 0600002, "lmb", "Store the contents of the LR in the MBR" },
/* Combined Operate Class Commands */
{ 0740000, "cla", "Clear the AC" },
{ 0600031, "cyl", "Cycle the AC left one digital position" },
{ 0740040, "clc", "Clear and complement AC" },
{ 0622000, "dis", "Display (note IOS must be included for in-out cmds)" },
{ 0760000, "ios+cll+clr", "In out stop with AC cleared" },
{ 0627600, "ios+p7h+cyr", "Punch 7 holes and cycle AC right" },
{ 0626600, "ios+p6h+cyr", "Punch 6 holes and cycle AC right" },
{ 0766000, "ios+cll+clr+p6h", "Clear the AC and punch a blank space on tape" },
{ 0624600, "ios+pnt+cyr", "Print and cycle AC right" },
{ 0627021, "ios+p7h+amb+pad", "Punch 7 holes and leave AC cleared" },
{ 0626021, "ios+p6h+amb+pad", "Punch 6 holes and leave AC cleared" },
{ 0624021, "ios+pnt+amb+pad", "Print and leave AC cleared" },
{ 0741000, "cll+clr+ric", "Clear AC and start PETR running (note computer hasn't stopped to wait for information" },
{ 0601031, "ric+amb+pad+cry", "Start PETR running and cycle AC left" },
{ 0601600, "ric+cyr", "Start PETR running and cycle right" },
{ 0763000, "cll+clr+ios+r3c", "Clear AC and read 3 lines of tape" },
{ 0761000, "cll+clr+ios+ric", "Clear AC and read one line of tape" },
{ 0761031, "cll+clr+ios+ric+pad+cry", "Read 1 line of tape and cycle AC left" },
{ 0761600, "cll+clr+ios+ric+cyr", "Read 1 line of tape and cycle right" },
{ 0740004, "cll+clr+tac", "Put contents of TAC in AC" },
{ 0600030, "pad+cry", "Full-add the MBR and AC and leave sum in AC" },
{ 0740022, "cll+clr+lmb+pad", "Clear the AC - store LR contents in memory buffer register add memory buffer to AC - i.e., store live reg. contents in AC (LAC)" },
{ 0600201, "amb+mlr", "Store contents of AC in MBR, store contents of MBR in LR i.e., store contents of AC in LR. (ALR)" },
{ 0600022, "lmb+pad", "Store the contents of LR in MBR, partial add AC and MBR i.e., partial add LR to AC. (LPD)" },
/* { 0600200, "mlr", "Since MLR alone will ahve a clear MBR, this is really clear LR (LRO)" }, */
{ 0600032, "lmb+pad+cry", "Full-add the LR to the AC (LAD)" },
{ 0740023, "cll+clr+tbr+pad", "Store contents of TBR in AC" },
{ 0000000, NULL, NULL }
};
t_stat fprint_sym_orig (FILE *of, t_addr addr, t_value *val,
UNIT *uptr, int32 sw)
{
int32 i, inst, op;
inst = val[0];
/* Instruction decode */
op = (inst >> 16) & 3;
switch (op) {
case 0:
fprintf (of, "sto %06o", inst & 0177777); /* opcode */
break;
case 1:
fprintf (of, "add %06o", inst & 0177777); /* opcode */
break;
case 2:
fprintf (of, "trn %06o", inst & 0177777); /* opcode */
break;
case 3:
for(i=0;opmap_orig[i].opr != 0;i++) {
if(inst == opmap_orig[i].opr) {
fprintf (of, "opr %s (%s)", opmap_orig[i].mnemonic, opmap_orig[i].desc); /* opcode */
}
}
break;
}
return SCPE_OK;
}

166
display/README Normal file
View file

@ -0,0 +1,166 @@
$Id: README,v 1.15 2004/02/09 07:20:18 phil Exp $
XY Display Simulation
Simulates XY plotting displays used on DEC PDP systems.
Copyright (c) 2003-2004, Philip L. Budne and Douglas A. Gwyn
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.
Phil Budne <phil@ultimate.com>
Douglas A Gwyn <gwyn@arl.army.mil>
February 5, 2004
Designed for use with Bob Supnik's SIMH, but the code should be easily
portable, and usable standalone (see vttest.c for an example).
Display code is provided for X11 (Unix/VMS) and Win32.
We're not GUI programmers, so the code is PRIMITIVE!!
Started from VC8E simulator by Douglas W. Jones
(distribution 5, of Feb 4, 1997);
This PDP8 Emulator was written by Douglas W. Jones at the
University of Iowa. It is distributed as freeware, of
uncertain function and uncertain utility.
Original phosphor decay constants for Type 30 display from XMame 0.72.1
VT11 support GREATLY enhanced (and VT48 support added) and
other general improvements from Douglas A Gwyn.
In the interest of fair play we have supplied two makefiles (neither
of which is named Makefile nor makefile), one which works under all
flavors of "make" (after necessary editing, in the traditional manner),
and one which functions only under the GNU version of make (sometimes
installed as "gmake", but the default "make" on many systems). We have
not added a third flavor which uses BSD make enhancements, because our
deeply held roots (over 40 combined years of Unix experience by the
authors) demand that things should work on all platforms. Both the
Linux and Windows worlds violate this simple credo (everything works so
long as you use OUR preferred software), and many current users may not
even realize that editing Makefiles used to be de rigeur. Since the
GNU environment is widely available and "gmake" has features that
support automatic configuration for multiple platforms, we have
supplied thr GNU-specific variant with the expectation that many users
will find it more convenient. You can copy or link whichever flavor of
makefile suits your taste to whichever spelling of "makefile" suits
your fancy, or invoke "make" with the -f flag specifying the desired
makefile.
To compile test programs:
========================
On Unix:
# edit smakefile to match your environment
make -f smakefile
or
gmake -f gmakefile
On Win32 (using Cygwin);
make -f gmakefile WIN32=1
On Win32 (using MINGW):
# edit smakefile to match your environment
make -f smakefile
or
mingw32-make -f gmakefile WIN32=1
or
execute build-mingw.bat in a DOS command window
creates:
munch: standalone simulation of PDP-1 munching squares;
examines console "test switches" (see next section)
vt11: sequences through VT11/VS60 simulator test displays;
shows how the diplay-processor simulator can be used
from applications other than PDP-11 simulators
Console switches:
================
Upto 18 simulated console switches, toggled by hitting keys:
123 456 789 qwe rty uio
space bar clears all switches.
Spacewar Switches:
=================
Key presses for simulated Spacewar control box switches;
action player
1 2
rotate clockwise a k
rotate counter clockwise s l
fire engines d ;
launch torpedo f '
hyperspace (both at once) as kl
Light pen:
=========
The light pen is active when any mouse button is held down.
Mouse button 1 acts as a "tip switch" for models so equipped (VS60).
The light pen may be dragged while active.
Too many compile time parameters:
================================
Read the comments in display.c for more explanations!!
DISPLAY_TYPE default display type, one of:
DIS_VR14, DIS_VR17, DIS_VR20, DIS_VR48, DIS_TYPE30, DIS_TYPE340
selects screen characteristics (phosphor, dimensions).
Only affects programs which do not make an expicit
display_init() call.
PIX_SCALE one of RES_FULL, RES_HALF, RES_QUARTER, RES_EIGHTH
selects default display scaling factor.
PEN_RADIUS default radius of light pen in (scaled) pixels
MAXELAPSED Upper limit in real microseconds between polls/delays
MINELAPSED Lower limit in real microseconds between polls/delays
MINDELAY Lower limit in real microseconds for attempted delay
MAXDELAY Upper limit in real microseconds for attempted delay
GAINSHIFT delay_check increment/decrement gain factor
In display system support (x11.c, win32.c);
PIX_SIZE selects displayed pixel size (default 1)
makes screen larger, useful when display scaled to small size
Programming interface:
=====================
see display.h
Source repository:
=================
Up-to-date Sources are available by anonymous CVS.
See http://www.ultimate.com/phil/xy/

12
display/build_mingw.bat Normal file
View file

@ -0,0 +1,12 @@
@echo off
rem $Id: build_mingw.bat,v 1.1 2004/01/25 17:48:03 phil Exp $
rem Compile all test programs using MINGW make and gcc environment
rem
rem If needed, define the path for the MINGW bin directory.
rem (this should already be set if MINGW was installed correctly)
rem
gcc -v 1>NUL 2>NUL
if ERRORLEVEL 1 path C:\MinGW\bin;D:\MinGW\bin;E:\MinGW\bin;%path%
gcc -v 1>NUL 2>NUL
if ERRORLEVEL 1 echo "MinGW Environment Unavailable"
mingw32-make WIN32=1 -f gmakefile %1 %2 %3 %4

1053
display/display.c Normal file

File diff suppressed because it is too large Load diff

143
display/display.h Normal file
View file

@ -0,0 +1,143 @@
/*
* $Id: display.h,v 1.13 2004/01/24 08:34:33 phil Exp $
* interface to O/S independent layer of XY display simulator
* Phil Budne <phil@ultimate.com>
* September 2003
*
* Changes from Douglas A. Gwyn, Jan 12, 2004
*/
/*
* Copyright (c) 2003-2004, Philip L. Budne
*
* 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.
*/
/*
* known display types
*/
enum display_type {
DIS_VR14 = 14,
DIS_VR17 = 17,
DIS_VR20 = 20,
DIS_TYPE30 = 30,
DIS_TX0 = 33,
DIS_VR48 = 48,
DIS_TYPE340 = 340
};
/*
* display scale factors
*/
#define RES_FULL 1
#define RES_HALF 2
#define RES_QUARTER 4
#define RES_EIGHTH 8
/*
* must be called before first call to display_age()
* (but called implicitly by display_point())
*/
extern int display_init(enum display_type, int scale);
/* return size of virtual display */
extern int display_xpoints(void);
extern int display_ypoints(void);
/* virtual points between display and menu sections */
#define VR48_GUTTER 8 /* just a guess */
/* conversion factor from virtual points and displayed pixels */
extern int display_scale(void);
/*
* simulate passage of time; first argument is simulated microseconds elapsed,
* second argument is flag to slow down simulated speed
* see comments in display.c for why you should call it often!!
* Under X11 polls for window events!!
*/
extern int display_age(int,int);
/*
* display intensity levels.
* always at least 8 (for VT11/VS60) -- may be mapped internally
*/
#define DISPLAY_INT_MAX 7
#define DISPLAY_INT_MIN 0 /* lowest "on" level */
/*
* plot a point; argumen ts are x, y, intensity, color (0/1)
* returns true if light pen active (mouse button down)
* at (or very near) this location.
*
* Display initialized on first call.
*/
extern int display_point(int,int,int,int);
/*
* force window system to output bits to screen;
* call after adding points, or aging the screen
*/
extern void display_sync(void);
/*
* currently a noop
*/
extern void display_reset(void);
/*
* ring the bell
*/
extern void display_beep(void);
/*
* Set light-pen radius; maximum radius in display coordinates
* from a "lit" location that the light pen will see.
*/
extern void display_lp_radius(int);
/*
* set by simulated spacewar switch box switches
* 18 bits (only high 4 and low 4 used)
*/
extern unsigned long spacewar_switches;
/*
* light pen "tip switch" activated (for VS60 emulation etc.)
* should only be set from "driver" (window system layer)
*/
extern unsigned char display_lp_sw;
/*
* deactivates light pen
* (SIMH DR11-C simulation when initialized sets this and
* then reports mouse coordinates as Talos digitizer data)
*/
extern unsigned char display_tablet;
/*
* users of this library are expected to provide these calls.
* simulator will set 18 simulated switches.
*/
extern unsigned long cpu_get_switches(void); /* get current switch state */
extern void cpu_set_switches(unsigned long); /* set switches */

77
display/gmakefile Normal file
View file

@ -0,0 +1,77 @@
# $Id: gmakefile,v 1.17 2004/01/24 08:31:56 phil Exp - revised by DAG
# (GNU) Makefile for test programs under Unix/X11 and Win32
#
# Unix:
# edit Unix defs to fit your compiler/library environment, then
# gmake -f gmakefile
# or if GNU make is the default:
# make -f gmakefile
#
# Win32 (Cygwin)
# make WIN32=1
#
# Win32 (MINGW):
# mingw32-make -f gmakefile WIN32=1
DISP_DEFS=-DTEST_DIS=DIS_VR48 -DTEST_RES=RES_HALF # -DDEBUG_VT11
ifeq ($(WIN32),)
#Unix environments
X11BASE=/usr/X11R6
X11LIBDIR=$(X11BASE)/lib
X11INCDIR=$(X11BASE)/include
LIBS=-L$(X11LIBDIR) -lXt -lX11 -lm
OSFLAGS=-I$(X11INCDIR)
DRIVER=x11.o
EXT=
else
#Win32 environments
LIBS=-lgdi32
OSFLAGS=
DRIVER=win32.o
EXT=.exe
endif
#PROF=-g # -pg
OPT=-O2
CFLAGS=$(OPT) $(PROF) $(OSFLAGS) $(DISP_DEFS)
CC=gcc -Wunused
LDFLAGS=$(PROF)
ALL= munch$(EXT) vt11$(EXT)
ALL: $(ALL)
# munching squares; see README file for
# how to use console switches
MUNCH=$(DRIVER) display.o test.o
munch$(EXT): $(MUNCH)
$(CC) $(LDFLAGS) -o munch$(EXT) $(MUNCH) $(LIBS)
VT11=$(DRIVER) vt11.o vttest.o display.o
vt11$(EXT): $(VT11)
$(CC) $(LDFLAGS) -o vt11$(EXT) $(VT11) $(LIBS)
display.o: display.h ws.h
vt11.o: display.h vt11.h
x11.o: ws.h display.h
win32.o: ws.h
test.o: display.h vt11.h
vttest.o: display.h vt11.h vtmacs.h
clean:
ifeq ($(WIN32),)
rm -f *.o *~ .#*
else
if exist *.o del /q *.o
if exist *~ del /q *~
if exist .#* del /q .#*
endif
clobber: clean
ifeq ($(WIN32),)
rm -f $(ALL)
else
if exist *.exe del /q *.exe
endif

75
display/smakefile Normal file
View file

@ -0,0 +1,75 @@
# $Id: smakefile,v 1.17 2004/01/24 08:31:56 phil Exp - revised by DAG
# Makefile for test programs (standard Unix "make" version)
# Unix:
# comment out Windows defs, uncomment Unix defs,
# edit Unix defs to fit your compiler/library environment, then
# (g)make
#
# Win32 (Cygwin)
# comment out Unix defs, uncomment Windows defs, then
# make
#
# Win32 (MINGW)
# comment out Unix defs, uncomment Windows defs, then
# mingw32-make
DISP_DEFS=-DTEST_DIS=DIS_VR48 -DTEST_RES=RES_HALF # -DDEBUG_VT11
#Unix environments
CC=cc # gcc -Wunused
#X11BASE=/usr/X11R6
#X11LIBDIR=$(X11BASE)/lib
#X11INCDIR=$(X11BASE)/include
LIBS=-lXt -lX11 -lm # -L$(X11LIBDIR)
OSFLAGS=-I$(X11INCDIR)
DRIVER=x11.o
EXT=
PROF=-g # -pg
OPT=-O # -O2
CFLAGS=$(OPT) $(PROF) $(OSFLAGS) $(DISP_DEFS)
CC=cc # gcc -Wunused
LDFLAGS=$(PROF)
##Win32 environments
#LIBS=-lgdi32
#OSFLAGS=
#DRIVER=win32.o
#EXT=.exe
#PROF=-g # -pg
#OPT=-O2
#CFLAGS=$(OPT) $(PROF) $(OSFLAGS) $(DISP_DEFS)
#CC=gcc -Wunused
LDFLAGS=$(PROF)
ALL= munch$(EXT) vt11$(EXT)
ALL: $(ALL)
# munching squares; see README file for
# how to use console switches
MUNCH=$(DRIVER) display.o test.o
munch$(EXT): $(MUNCH)
$(CC) $(LDFLAGS) -o munch$(EXT) $(MUNCH) $(LIBS)
VT11=$(DRIVER) vt11.o vttest.o display.o
vt11$(EXT): $(VT11)
$(CC) $(LDFLAGS) -o vt11$(EXT) $(VT11) $(LIBS)
display.o: display.h ws.h
vt11.o: display.h vt11.h
x11.o: ws.h display.h
win32.o: ws.h
test.o: display.h vt11.h
vttest.o: display.h vt11.h vtmacs.h
clean:
rm -f *.o *~ .#* # Unix
# if exist *.o del /q *.o # Win32
# if exist *~ del /q *~ # Win32
# if exist .#* del /q .#* # Win32
clobber: clean
rm -f $(ALL) # Unix
# if exist *.exe del /q *.exe # Win32

192
display/test.c Normal file
View file

@ -0,0 +1,192 @@
/*
* $Id: test.c,v 1.23 2004/02/07 06:31:20 phil Exp $
* XY Display simulator test program (PDP-1 Munching Squares)
* Phil Budne <phil@ultimate.com>
* September 2003
*
* Updates from Douglas A. Gwyn, 12 Jan. 2004
*
* With thanks to Daniel Smith for his web page:
* http://world.std.com/~dpbsmith/munch.html
*/
/*
* Copyright (c) 2003-2004, Philip L. Budne
*
* 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.
*/
#ifndef TEST_DIS
#define TEST_DIS DIS_TYPE30
#endif
#ifndef TEST_RES
#define TEST_RES RES_HALF
#endif
#include <stdio.h>
#include <stdlib.h>
#ifndef EXIT_FAILURE
/* SunOS4 <stdlib.h> doesn't define this */
#define EXIT_FAILURE 1
#endif
#include "display.h"
static unsigned long test_switches = 0;
/* called from display code: */
unsigned long
cpu_get_switches(void) {
return test_switches;
}
/* called from display code: */
void
cpu_set_switches(bits)
unsigned long bits;
{
printf("switches: %06lo\n", bits);
test_switches = bits;
}
void
munch(void) {
static long us = 0;
static long io = 0, v = 0;
long ac;
int x, y;
ac = test_switches;
ac += v; /* add v */
if (ac & ~0777777) {
ac++;
ac &= 0777777;
}
v = ac; /* dac v */
ac <<= 9; /* rcl 9s */
io <<= 9;
io |= ac>>18;
ac &= 0777777;
ac |= io>>18;
io &= 0777777;
ac ^= v; /* xor v */
/* convert +/-512 one's complement to 0..1022, origin in lower left */
y = (io >> 8) & 01777; /* hi 10 */
if (y & 01000)
y ^= 01000;
else
y += 511;
x = (ac >> 8) & 01777; /* hi 10 */
if (x & 01000) /* negative */
x ^= 01000;
else
x += 511;
if (display_point(x, y, DISPLAY_INT_MAX, 0))
printf("light pen hit at (%d,%d)\n", x, y);
/*#define US 100000 /* 100ms (10/sec) */
/*#define US 50000 /* 50ms (20/sec) */
/*#define US 20000 /* 20ms (50/sec) */
/*#define US 10000 /* 10ms (100/sec) */
#define US 0
us += 50; /* 10 5us PDP-1 memory cycles */
if (us >= US) {
display_age(us, 1);
us = 0;
}
display_sync(); /* XXX push down */
}
#ifdef T2
/* display all window system level intensities;
* must be compiled with -DINTENSITIES=<n> -DT2
*/
void
t2(void) {
int x, y;
display_init(TEST_DIS, TEST_RES);
for (x = INTENSITIES-1; x >= 0; x--) {
for (y = 0; y < 20; y++) {
ws_display_point(x*4, y, x, 0);
ws_display_point(x*4+1, y, x, 0);
ws_display_point(x*4+2, y, x, 0);
ws_display_point(x*4+3, y, x, 0);
}
display_sync();
}
fflush(stdout);
for (;;)
/* wait */ ;
}
#endif
#ifdef T3
/* display all "user" level intensities;
* must be compiled with -DINTENSITIES=<n> -DT3
*
* skip every other virtual point on both axes
* default scaling maps adjacent pixels and
* causes re-intensification!
*/
void
t3(void) {
int x, y;
display_init(TEST_DIS, TEST_RES);
for (x = DISPLAY_INT_MAX; x >= 0; x--) {
for (y = 0; y < 20; y++) {
display_point(x*2, y*2, x, 0);
}
display_sync();
}
fflush(stdout);
for (;;)
/* wait */ ;
}
#endif
int
main(void) {
if (!display_init(TEST_DIS, TEST_RES))
exit(EXIT_FAILURE);
cpu_set_switches(04000UL); /* classic starting value */
for (;;) {
#ifdef T2
t2();
#endif
#ifdef T3
t3();
#endif
munch();
}
/*NOTREACHED*/
}

706
display/type340.c Normal file
View file

@ -0,0 +1,706 @@
/*
* $Id: type340.c,v 1.5 2004/01/24 20:52:16 phil Exp $
* Simulator Independent DEC Type 340 Graphic Display Processor Simulation
* Phil Budne <phil@ultimate.com>
* September 20, 2003
* from vt11.c
*
* Information from DECUS 7-13
* http://www.spies.com/~aek/pdf/dec/pdp7/7-13_340displayProgMan.pdf
*/
/*
* Copyright (c) 2003-2004, Philip L. Budne
*
* 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 name of the author 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 "display.h" /* XY plot interface */
/*
* The Type 340 was used on the PDP-{4,6,7,9,10}
* and used 18-bit words, with bits numbered 0 thru 17
* (most significant to least)
*/
#define BITMASK(N) (1<<(17-(N)))
/* mask for a field */
#define FIELDMASK(START,END) ((1<<((END)-(START)+1))-1)
/* extract a field */
#define GETFIELD(W,START,END) (((W)>>(17-(END)))&FIELDMASK(START,END))
/* extract a 1-bit field */
#define TESTBIT(W,B) (((W) & BITMASK(B)) != 0)
#ifdef DEBUG_TY340
#define DEBUGF(X) printf X
#else
#define DEBUGF(X)
#endif
typedef long ty340word;
static ty340word DAC; /* Display Address Counter */
static unsigned char shift; /* 1 bit */
static enum mode mode; /* 3 bits */
static int scale; /* 2 bits */
enum mode { PARAM=0, POINT, SLAVE, CHAR, VECTOR, VCONT, INCR, SUBR };
enum jump_type { DJP=2, DJS=3, DDS=1 };
static ty340word ASR; /* Address Save Register */
static unsigned char save_ff; /* "save" flip-flop */
static unsigned char intensity; /* 3 bits */
static unsigned char lp_ena; /* 1 bit */
/* kept signed for raster violation checking */
static short xpos, ypos; /* 10 bits, signed */
static unsigned char sequence; /* 2 bits */
/* XXX make defines public for 340_cycle return */
#define STOPPED 01
#define LPHIT 02
#define VEDGE 04
#define HEDGE 010
static unsigned char status = STOPPED;
/*
* callbacks into PDP-6/10 simulator
*/
extern ty340word ty340_fetch(ty340word);
extern void ty340_store(ty340word, ty340word);
extern void ty340_stop_int(void);
extern void ty340_lp_int(void);
void
ty340_set_dac(ty340word addr)
{
DAC = addr;
mode = 0;
DEBUGF(("set DAC %06\r\n", DAC));
status = 0; /* XXX just clear stopped? */
/* XXX clear other stuff? save_ff? */
}
void
ty340_reset(void)
{
/* XXX call display layer? destroy window? */
xpos = ypos = 0;
status = STOPPED;
}
static int
point(int x, int y, int seq)
{
int i;
/* XXX apply scale? */
i = DISPLAY_INT_MAX-7+intensity;
if (i <= 0)
i = 1;
if (x < 0 || x > 1023) {
status |= VEDGE;
return 0;
}
if (y < 0 || y > 1023) {
status |= HEDGE;
return 0;
}
if (display_point(x, y, i, 0)) {
if (lp_ena) {
/* XXX save location? */
status |= LPHIT;
sequence = seq;
}
}
}
/*
* two-step algorithm, developed by Xiaolin Wu
* from http://graphics.lcs.mit.edu/~mcmillan/comp136/Lecture6/Lines.html
*/
/*
* The two-step algorithm takes the interesting approach of treating
* line drawing as a automaton, or finite state machine. If one looks
* at the possible configurations for the next two pixels of a line,
* it is easy to see that only a finite set of possibilities exist.
* The two-step algorithm shown here also exploits the symmetry of
* line-drawing by simultaneously drawn from both ends towards the
* midpoint.
*/
static void
lineTwoStep(int x0, int y0, int x1, int y1)
{
int dy = y1 - y0;
int dx = x1 - x0;
int stepx, stepy;
if (dy < 0) { dy = -dy; stepy = -1; } else { stepy = 1; }
if (dx < 0) { dx = -dx; stepx = -1; } else { stepx = 1; }
lpoint(x0,y0);
if (dx == 0 && dy == 0) /* following algorithm won't work */
return; /* just the one dot */
lpoint(x1, y1);
if (dx > dy) {
int length = (dx - 1) >> 2;
int extras = (dx - 1) & 3;
int incr2 = (dy << 2) - (dx << 1);
if (incr2 < 0) {
int c = dy << 1;
int incr1 = c << 1;
int d = incr1 - dx;
int i;
for (i = 0; i < length; i++) {
x0 += stepx;
x1 -= stepx;
if (d < 0) { /* Pattern: */
lpoint(x0, y0);
lpoint(x0 += stepx, y0); /* x o o */
lpoint(x1, y1);
lpoint(x1 -= stepx, y1);
d += incr1;
}
else {
if (d < c) { /* Pattern: */
lpoint(x0, y0); /* o */
lpoint(x0 += stepx, y0 += stepy); /* x o */
lpoint(x1, y1);
lpoint(x1 -= stepx, y1 -= stepy);
} else {
lpoint(x0, y0 += stepy); /* Pattern: */
lpoint(x0 += stepx, y0); /* o o */
lpoint(x1, y1 -= stepy); /* x */
lpoint(x1 -= stepx, y1);
}
d += incr2;
}
}
if (extras > 0) {
if (d < 0) {
lpoint(x0 += stepx, y0);
if (extras > 1) lpoint(x0 += stepx, y0);
if (extras > 2) lpoint(x1 -= stepx, y1);
} else
if (d < c) {
lpoint(x0 += stepx, y0);
if (extras > 1) lpoint(x0 += stepx, y0 += stepy);
if (extras > 2) lpoint(x1 -= stepx, y1);
} else {
lpoint(x0 += stepx, y0 += stepy);
if (extras > 1) lpoint(x0 += stepx, y0);
if (extras > 2) lpoint(x1 -= stepx, y1 -= stepy);
}
}
} else {
int c = (dy - dx) << 1;
int incr1 = c << 1;
int d = incr1 + dx;
int i;
for (i = 0; i < length; i++) {
x0 += stepx;
x1 -= stepx;
if (d > 0) {
lpoint(x0, y0 += stepy); /* Pattern: */
lpoint(x0 += stepx, y0 += stepy); /* o */
lpoint(x1, y1 -= stepy); /* o */
lpoint(x1 -= stepx, y1 -= stepy); /* x */
d += incr1;
} else {
if (d < c) {
lpoint(x0, y0); /* Pattern: */
lpoint(x0 += stepx, y0 += stepy); /* o */
lpoint(x1, y1); /* x o */
lpoint(x1 -= stepx, y1 -= stepy);
} else {
lpoint(x0, y0 += stepy); /* Pattern: */
lpoint(x0 += stepx, y0); /* o o */
lpoint(x1, y1 -= stepy); /* x */
lpoint(x1 -= stepx, y1);
}
d += incr2;
}
}
if (extras > 0) {
if (d > 0) {
lpoint(x0 += stepx, y0 += stepy);
if (extras > 1) lpoint(x0 += stepx, y0 += stepy);
if (extras > 2) lpoint(x1 -= stepx, y1 -= stepy);
} else if (d < c) {
lpoint(x0 += stepx, y0);
if (extras > 1) lpoint(x0 += stepx, y0 += stepy);
if (extras > 2) lpoint(x1 -= stepx, y1);
} else {
lpoint(x0 += stepx, y0 += stepy);
if (extras > 1) lpoint(x0 += stepx, y0);
if (extras > 2) {
if (d > c)
lpoint(x1 -= stepx, y1 -= stepy);
else
lpoint(x1 -= stepx, y1);
}
}
}
}
} else {
int length = (dy - 1) >> 2;
int extras = (dy - 1) & 3;
int incr2 = (dx << 2) - (dy << 1);
if (incr2 < 0) {
int c = dx << 1;
int incr1 = c << 1;
int d = incr1 - dy;
int i;
for (i = 0; i < length; i++) {
y0 += stepy;
y1 -= stepy;
if (d < 0) {
lpoint(x0, y0);
lpoint(x0, y0 += stepy);
lpoint(x1, y1);
lpoint(x1, y1 -= stepy);
d += incr1;
} else {
if (d < c) {
lpoint(x0, y0);
lpoint(x0 += stepx, y0 += stepy);
lpoint(x1, y1);
lpoint(x1 -= stepx, y1 -= stepy);
} else {
lpoint(x0 += stepx, y0);
lpoint(x0, y0 += stepy);
lpoint(x1 -= stepx, y1);
lpoint(x1, y1 -= stepy);
}
d += incr2;
}
}
if (extras > 0) {
if (d < 0) {
lpoint(x0, y0 += stepy);
if (extras > 1) lpoint(x0, y0 += stepy);
if (extras > 2) lpoint(x1, y1 -= stepy);
} else
if (d < c) {
lpoint(x0, y0 += stepy);
if (extras > 1) lpoint(x0 += stepx, y0 += stepy);
if (extras > 2) lpoint(x1, y1 -= stepy);
} else {
lpoint(x0 += stepx, y0 += stepy);
if (extras > 1) lpoint(x0, y0 += stepy);
if (extras > 2) lpoint(x1 -= stepx, y1 -= stepy);
}
}
} else {
int c = (dx - dy) << 1;
int incr1 = c << 1;
int d = incr1 + dy;
int i;
for (i = 0; i < length; i++) {
y0 += stepy;
y1 -= stepy;
if (d > 0) {
lpoint(x0 += stepx, y0);
lpoint(x0 += stepx, y0 += stepy);
lpoint(x1 -= stepy, y1);
lpoint(x1 -= stepx, y1 -= stepy);
d += incr1;
} else {
if (d < c) {
lpoint(x0, y0);
lpoint(x0 += stepx, y0 += stepy);
lpoint(x1, y1);
lpoint(x1 -= stepx, y1 -= stepy);
} else {
lpoint(x0 += stepx, y0);
lpoint(x0, y0 += stepy);
lpoint(x1 -= stepx, y1);
lpoint(x1, y1 -= stepy);
}
d += incr2;
}
}
if (extras > 0) {
if (d > 0) {
lpoint(x0 += stepx, y0 += stepy);
if (extras > 1) lpoint(x0 += stepx, y0 += stepy);
if (extras > 2) lpoint(x1 -= stepx, y1 -= stepy);
} else if (d < c) {
lpoint(x0, y0 += stepy);
if (extras > 1) lpoint(x0 += stepx, y0 += stepy);
if (extras > 2) lpoint(x1, y1 -= stepy);
} else {
lpoint(x0 += stepx, y0 += stepy);
if (extras > 1) lpoint(x0, y0 += stepy);
if (extras > 2) {
if (d > c)
lpoint(x1 -= stepx, y1 -= stepy);
else
lpoint(x1, y1 -= stepy);
}
}
}
}
}
} /* lineTwoStep */
static int
vector(int i, int sx, int dx, int sy, int dy)
{
int x0, y0, x1, y1;
x0 = xpos;
y0 = ypos;
if (sx) {
x1 = x0 - dx;
if (x1 < 0) /* XXX TEMP? */
x1 = 0;
}
else {
x1 = x0 + dx;
if (x1 > 1023) /* XXX TEMP? */
x1 = 1023;
}
if (sy) {
y1 = y0 - dy;
if (y1 < 0) /* XXX TEMP? */
y1 = 0;
}
else {
y1 = y0 + dy; /* XXX TEMP? */
if (y1 > 1023)
y1 = 1023;
}
DEBUGF(("vector i%d (%d,%d) to (%d,%d)\r\n", i, x0, y0, x1, y1));
if (i)
lineTwoStep(x0, y0, x1, y1);
xpos = x1;
ypos = y1;
return 0;
}
/* return true on raster violation */
int
ipoint(int i, int n, unsigned char byte)
{
if (byte & 010) { /* left/right */
if (byte & 04) {
if (xpos == 0) {
status |= VEDGE;
return 1;
}
xpos--;
}
else {
if (xpos == 1023) {
status |= VEDGE;
return 1;
}
xpos++;
}
}
if (byte & 02) { /* up/down */
if (byte & 04) {
if (ypos == 0) {
status |= HEDGE;
return 1;
}
ypos--;
}
else {
if (ypos == 1023) {
status |= HEDGE;
return 1;
}
ypos++;
}
}
if (i)
point(xpos, ypos, n);
return 0;
}
/*
* 342 character generator - first 64 characters (from manual)
*/
static const unsigned char chars[64][5] = {
{ 0070, 0124, 0154, 0124, 0070 }, /* 00 */
{ 0174, 0240, 0240, 0240, 0174 }, /* 01 A */
{ 0376, 0222, 0222, 0222, 0154 }, /* 02 B */
{ 0174, 0202, 0202, 0202, 0104 }, /* 03 C */
{ 0376, 0202, 0202, 0202, 0174 }, /* 04 D */
{ 0376, 0222, 0222, 0222, 0222 }, /* 05 E */
{ 0376, 0220, 0220, 0220, 0220 }, /* 06 F */
{ 0174, 0202, 0222, 0222, 0134 }, /* 07 G */
{ 0376, 0020, 0020, 0020, 0376 }, /* 10 H */
{ 0000, 0202, 0376, 0202, 0000 }, /* 11 I */
{ 0004, 0002, 0002, 0002, 0374 }, /* 12 J */
{ 0376, 0020, 0050, 0104, 0202 }, /* 13 K */
{ 0376, 0002, 0002, 0002, 0002 }, /* 14 K */
{ 0374, 0100, 0040, 0100, 0374 }, /* 15 M */
{ 0376, 0100, 0040, 0020, 0376 }, /* 16 N */
{ 0174, 0202, 0202, 0202, 0174 }, /* 17 O */
{ 0376, 0220, 0220, 0220, 0140 }, /* 20 P */
{ 0174, 0202, 0212, 0206, 0176 }, /* 21 Q */
{ 0376, 0220, 0230, 0224, 0142 }, /* 22 R */
{ 0144, 0222, 0222, 0222, 0114 }, /* 23 S */
{ 0200, 0200, 0376, 0200, 0200 }, /* 24 T */
{ 0374, 0002, 0002, 0002, 0374 }, /* 25 U */
{ 0370, 0004, 0002, 0004, 0370 }, /* 26 V */
{ 0376, 0004, 0010, 0004, 0376 }, /* 27 W */
{ 0202, 0104, 0070, 0104, 0202 }, /* 30 X */
{ 0200, 0100, 0076, 0100, 0200 }, /* 31 Y */
{ 0226, 0232, 0222, 0262, 0322 }, /* 32 Z */
{ 0000, 0000, 0000, 0000, 0000 }, /* 33 LF */
{ 0000, 0000, 0000, 0000, 0000 }, /* 34 CR */
{ 0000, 0000, 0000, 0000, 0000 }, /* 35 HORIZ */
{ 0000, 0000, 0000, 0000, 0000 }, /* 36 VERT */
{ 0000, 0000, 0000, 0000, 0000 }, /* 37 ESC */
{ 0000, 0000, 0000, 0000, 0000 }, /* 40 space */
{ 0000, 0000, 0372, 0000, 0000 }, /* 41 ! */
{ 0000, 0340, 0000, 0340, 0000 }, /* 42 " */
{ 0050, 0376, 0050, 0376, 0050 }, /* 43 # */
{ 0144, 0222, 0376, 0222, 0114 }, /* 44 $ */
{ 0306, 0310, 0220, 0246, 0306 }, /* 45 % */
{ 0154, 0222, 0156, 0004, 0012 }, /* 46 & */
{ 0000, 0000, 0300, 0340, 0000 }, /* 47 ' */
{ 0070, 0104, 0202, 0000, 0000 }, /* 50 ( */
{ 0000, 0000, 0202, 0104, 0070 }, /* 51 ) */
{ 0124, 0070, 0174, 0070, 0124 }, /* 52 * */
{ 0020, 0020, 0174, 0020, 0020 }, /* 53 + */
{ 0000, 0014, 0016, 0000, 0000 }, /* 54 , */
{ 0020, 0020, 0020, 0020, 0020 }, /* 55 - */
{ 0000, 0006, 0006, 0000, 0000 }, /* 56 . */
{ 0004, 0010, 0020, 0040, 0100 }, /* 57 / */
{ 0174, 0212, 0222, 0242, 0174 }, /* 60 0 */
{ 0000, 0102, 0376, 0002, 0000 }, /* 61 1 */
{ 0116, 0222, 0222, 0222, 0142 }, /* 62 2 */
{ 0104, 0202, 0222, 0222, 0154 }, /* 63 3 */
{ 0020, 0060, 0120, 0376, 0020 }, /* 64 4 */
{ 0344, 0222, 0222, 0222, 0214 }, /* 65 5 */
{ 0174, 0222, 0222, 0222, 0114 }, /* 66 6 */
{ 0306, 0210, 0220, 0240, 0300 }, /* 67 7 */
{ 0154, 0222, 0222, 0222, 0154 }, /* 70 8 */
{ 0144, 0222, 0222, 0222, 0174 }, /* 71 9 */
{ 0000, 0066, 0066, 0000, 0000 }, /* 72 : */
{ 0000, 0154, 0156, 0000, 0000 }, /* 73 ; */
{ 0020, 0050, 0104, 0202, 0000 }, /* 74 < */
{ 0050, 0050, 0050, 0050, 0050 }, /* 75 = */
{ 0000, 0202, 0104, 0050, 0020 }, /* 76 > */
{ 0100, 0200, 0236, 0220, 0140 } /* 77 ? */
};
/*
* type 342 Character/Symbol generator for type 340 display
* return true if ESCaped
*/
static int
character(int n, char c)
{
int x, y;
switch (c) {
case 033: /* LF */
if (ypos < 12) {
status |= HEDGE;
ypos = 0;
}
else
ypos -= 12; /* XXX scale? */
return 0;
case 034: /* CR */
xpos = 0;
return 0;
case 035: /* shift in */
shift = 1;
return 0;
case 036: /* shift out */
shift = 0;
return 0;
case 037: /* escape */
sequence = n;
return 1;
}
/* XXX plot character from character set selected by "shift"
* (offset index by 64?)
*/
for (x = 0; x < 5; x++) {
for (y = 0; y < 7; y++) {
if (chars[c][x] & (1<<y)) {
/* XXX check for raster violation? */
point(xpos+x, ypos+y, n); /* XXX scale? */
}
}
}
xpos += 7; /* XXX scale? */
if (xpos > 1023) {
xpos = 1023;
status |= VEDGE;
}
return 0;
}
int
ty340_cycle(int us, int slowdown)
{
ty340word inst, addr;
int i, escape, stopped;
if (status & STOPPED)
return 0; /* XXX age display? */
inst = ty340_fetch(DAC);
DEBUGF(("%06o: %06o\r\n", DAC, inst));
DAC++;
escape = 0;
switch (mode) {
case PARAM:
mode = GETFIELD(inst, 2, 4);
if (TESTBIT(inst, 5)) { /* load l.p. enable */
lp_ena = TESTBIT(inst,6);
DEBUGF(("lp_ena %d\r\n", lp_ena));
}
if (TESTBIT(inst, 7)) {
status |= STOPPED;
if (TESTBIT(inst, 8))
ty340_stop_int(); /* set stop_int_end? */
}
if (TESTBIT(inst, 11))
scale = GETFIELD(inst, 12, 13);
if (TESTBIT(inst, 14))
intensity = GETFIELD(inst, 15, 17);
break;
case POINT:
mode = GETFIELD(inst, 2, 4);
if (TESTBIT(inst, 5)) /* load l.p. enable */
lp_ena = TESTBIT(inst,6);
if (TESTBIT(inst, 1))
ypos = GETFIELD(inst, 8, 17);
else
xpos = GETFIELD(inst, 8, 17);
if (TESTBIT(inst, 7))
point(xpos, ypos, 0);
break;
case SLAVE:
mode = GETFIELD(inst, 2, 4);
break;
case CHAR:
escape = (character(0, GETFIELD(inst, 0, 5)) ||
character(1, GETFIELD(inst, 6, 11)) ||
character(2, GETFIELD(inst, 12, 17)));
break;
case VECTOR:
escape = TESTBIT(inst, 0);
if (vector(TESTBIT(inst, 1),
TESTBIT(inst, 2), GETFIELD(inst, 3, 9),
TESTBIT(inst, 10), GETFIELD(inst, 11, 17))) {
/* XXX interrupt? */
}
break;
case VCONT:
escape = TESTBIT(inst, 0);
if (vector(TESTBIT(inst, 1),
TESTBIT(inst, 2), GETFIELD(inst, 3, 9),
TESTBIT(inst, 10), GETFIELD(inst, 11, 17))) {
/* XXX set escape? */
mode = PARAM; /* raster violation */
}
break;
case INCR:
escape = TESTBIT(inst, 0); /* escape bit */
i = TESTBIT(inst, 1);
if (ipoint(i, 0, GETFIELD(inst, 2, 5)) ||
ipoint(i, 1, GETFIELD(inst, 6, 9)) ||
ipoint(i, 2, GETFIELD(inst, 10, 13)) ||
ipoint(i, 3, GETFIELD(inst, 14, 17)))
/* XXX set escape? */
mode = PARAM; /* raster violation */
break;
case SUBR:
/* type 347 Display Subroutine Option? */
mode = GETFIELD(inst, 2, 4);
/* XXX take high bits of current DAC? */
addr = GETFIELD(inst, 5, 17);
switch (GETFIELD(inst, 0, 1)) {
case DJS: /* display jump and save */
ASR = DAC;
save_ff = 1; /* set "save" flip-flop */
/* FALL */
case DJP: /* display jump */
DAC = addr;
break;
case DDS: /* display deposit save register */
ty340_deposit(addr, (DJP<<16) | ASR);
save_ff = 0; /* ?? */
break;
default:
/* XXX ??? */
break;
}
break;
}
if (escape) {
mode = PARAM;
if (save_ff) {
/* return from subroutine */
DAC = ASR;
save_ff = 0;
}
}
return status;
} /* ty340_cycle */

3148
display/vt11.c Normal file

File diff suppressed because it is too large Load diff

137
display/vt11.h Normal file
View file

@ -0,0 +1,137 @@
/*
* $Id: vt11.h,v 1.7 2004/01/25 17:20:51 phil Exp $
* interface to VT11 simulator
* Phil Budne <phil@ultimate.com>
* September 16, 2003
* Substantially revised by Douglas A. Gwyn, 14 Jan. 2004
*
* prerequisite: display.h
*/
/*
* Copyright (c) 2003-2004, Philip L. Budne and Douglas A. Gwyn
*
* 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.
*/
#ifndef _SIM_DEFS_H_
typedef unsigned short uint16;
typedef long int32;
typedef unsigned long uint32;
#endif /* _SIM_DEFS_H_ */
/*
* VT11 jumpers control character spacing; VS60 always uses VT11 normal.
* The VT11_CSP_{W,H} #defines establish the initial default character
* spacing; to change the VT11 simulation from these default values,
* set vt11_csp_{w,h} before calling any function named vt11_*.
*/
extern unsigned char vt11_csp_w; /* horizontal character spacing */
#ifdef VT11_NARROW_OPT /* W3 or W6 installed */
#define VT11_CSP_W 12
#else /* VT11 normal; W4 or W5 installed */
#define VT11_CSP_W 14
#endif
extern unsigned char vt11_csp_h; /* vertical character spacing */
#ifdef VT11_TALL_OPT /* W3 or W4 installed */
#define VT11_CSP_H 26
#else /* VT11 normal; W5 or W6 installed */
#define VT11_CSP_H 24
#endif
/*
* The DISPLAY_TYPE #define establishes the initial default display
* type; to change from the default display type, set vt11_display
* before calling any function named vt11_* (other than vt11_reset()).
*/
#ifndef DISPLAY_TYPE
#define DISPLAY_TYPE DIS_VR17 /* default display type */
#endif
extern enum display_type vt11_display; /* DIS_VR{14,17,48} */
/*
* The PIX_SCALE #define establishes the initial default display scale
* factor; to change from the default scale factor, set vt11_scale
* before calling any function named vt11_* (other than vt11_reset()).
*/
#ifndef PIX_SCALE
#define PIX_SCALE RES_HALF /* default display scale factor */
#endif
extern int vt11_scale; /* RES_{FULL,HALF,QUARTER,EIGHTH} */
/*
* When vt11_init (READONLY) is nonzero, it indicates that it is too late
* to change display parameters (type, scale, character spacing, etc.).
*/
extern unsigned char vt11_init; /* set after display_init() called */
/* vt11.c simulates either a VT11 or a VT48(VS60), according to display type: */
#define VS60 (vt11_display == DIS_VR48)
#define VT11 (!VS60)
/* The display file is an array of 16-bit words. */
typedef uint16 vt11word;
extern int32 vt11_get_dpc(void); /* read Display PC */
extern int32 vt11_get_mpr(void); /* read mode parameter register */
extern int32 vt11_get_xpr(void); /* read graphplot incr/X pos register */
extern int32 vt11_get_ypr(void); /* read char code/Y pos register */
extern int32 vt11_get_rr(void); /* read relocate register */
extern int32 vt11_get_spr(void); /* read status parameter register */
extern int32 vt11_get_xor(void); /* read X offset register */
extern int32 vt11_get_yor(void); /* read Y offset register */
extern int32 vt11_get_anr(void); /* read associative name register */
extern int32 vt11_get_scr(void); /* read slave console/color register */
extern int32 vt11_get_nr(void); /* read name register */
extern int32 vt11_get_sdr(void); /* read stack data register */
extern int32 vt11_get_str(void); /* read char string term register */
extern int32 vt11_get_sar(void); /* read stack address/maint register */
extern int32 vt11_get_zpr(void); /* read Z position register */
extern int32 vt11_get_zor(void); /* read Z offset register */
extern void vt11_set_dpc(uint16); /* write Display PC */
extern void vt11_set_mpr(uint16); /* write mode parameter register */
extern void vt11_set_xpr(uint16); /* write graphplot inc/X pos register */
extern void vt11_set_ypr(uint16); /* write char code/Y pos register */
extern void vt11_set_rr(uint16); /* write relocate register */
extern void vt11_set_spr(uint16); /* write status parameter register */
extern void vt11_set_xor(uint16); /* write X offset register */
extern void vt11_set_yor(uint16); /* write Y offset register */
extern void vt11_set_anr(uint16); /* write associative name register */
extern void vt11_set_scr(uint16); /* write slave console/color register */
extern void vt11_set_nr(uint16); /* write name register */
extern void vt11_set_sdr(uint16); /* write stack data register */
extern void vt11_set_str(uint16); /* write char string term register */
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 */
/*
* callbacks from VT11/VS60 simulator (to SIMH PDP-11 VT driver, for example)
*/
extern int vt_fetch(uint32, vt11word *); /* get a display-file word */
extern void vt_stop_intr(void); /* post a display-stop interrupt */
extern void vt_lpen_intr(void); /* post a surface-related interrupt */
extern void vt_char_intr(void); /* post a bad-char./timeout interrupt */
extern void vt_name_intr(void); /* post a name-match interrupt */

291
display/vtmacs.h Normal file
View file

@ -0,0 +1,291 @@
/*
* $Id: vtmacs.h,v 1.4 2004/02/07 06:26:47 phil Exp $
* macros for coding a VT11/VS60 display file (instructions and data)
* Douglas A. Gwyn <gwyn@arl.army.mil>
* January 31, 2004
*
* XXX -- assumes ASCII host character set
*/
/* helper macros (not for use outside this header): */
#define SGN_(x) ((x) < 0)
#define MAG_(x) ((x) >= 0 ? (x) : -(x)) /* -0 not expressible directly in C */
/* control instructions: */
/* load status register A: */
#define LSRA(stop,stop_intr,lp_hit_chg,ital,refresh,menu) \
0170000 | stop | stop_intr | lp_hit_chg | ital | refresh | menu
/* display stop: */
#define ST_SAME 00000 /* don't stop display */
#define ST_STOP 02000 /* stop display */
/* stop interrupt: */
#define SI_SAME 00000 /* no change */
#define SI_INHIBIT 01000 /* inhibit interrupt on stop */
#define SI_GENERATE 01400 /* generate interrupt on stop */
/* light pen hit intensify (bright-down on VS60): */
#define LI_SAME 0000 /* no change */
#define LI_INTENSIFY 0200 /* enable intensify on hit (VT11) */
#define LI_BRIGHTDOWN 0200 /* enable bright down on hit (VS60) */
#define LI_NOINTENSIFY 0300 /* inhibit intensify on hit (VT11) */
#define LI_NOBRIGHTDOWN 0300 /* inhibit bright down on hit (VS60) */
/* italic font: */
#define IT_SAME 000 /* no change */
#define IT_NORMAL 040 /* normal font */
#define IT_ITALIC 060 /* italic font */
/* refresh rate: */
#define RF_UNSYNC 000 /* unsynchronized */
#define RF_SAME 000 /* (happens to work like that) */
#define RF_LINE 004 /* sync with line (VT11) */
#define RF_30 004 /* 30 frames/sec (VS60) */
#define RF_40 010 /* 40 frames/sec (VS60) */
#define RF_EXT 014 /* external sync (VS60) */
/* menu/main area (VS60): */
#define MN_SAME 0 /* no change */
#define MN_MAIN 2 /* major screen area */
#define MN_MENU 3 /* menu area */
/* load status register B: */
#define LSRB(color,set_step,step) \
0174000 | color | set_step | (step)
/* color select (VS60): */
#define CL_SAME 00000 /* no change */
#define CL_GREEN 01000 /* green */
#define CL_YELLOW 01200 /* yellow */
#define CL_ORANGE 01400 /* orange */
#define CL_RED 01600 /* red */
/* graphplot increment register change enable: */
#define SS_SAME 0000 /* no change (step value ignored) */
#define SS_CHANGE 0100 /* write step value into register */
/* load status register BB (VS60): */
#define LSRBB(z_data,edge_intr,depth_cue,char_esc) \
0176000 | z_data | edge_intr | depth_cue | char_esc
/* file Z data: */
#define ZD_SAME 000 /* no change */
#define ZD_NO 010 /* d.file does not contain Z coords. */
#define ZD_YES 014 /* d.file contains Z coordinates */
/* edge interrupts enable: */
#define ED_SAME 000 /* no change */
#define ED_DIS 040 /* disable intr. on edge transition */
#define ED_ENA 060 /* enable intr. on edge transition */
/* depth cue processing: */
#define DQ_SAME 0000 /* no change */
#define DQ_OFF 0200 /* disable depth cueing (Z intensity) */
#define DQ_ON 0300 /* enable depth cueing (Z intensity) */
/* escape on terminating character: */
#define ES_SAME 0 /* no change */
#define ES_NO 2 /* disable POPR on terminating char. */
#define ES_YES 3 /* enable POPR on terminating char. */
/* load status register C (VS60): */
#define LSRC(rotate,cs_change,cscale,vs_change,vscale) \
0154000 | rotate | cs_change | ((cscale)<<5) | \
vs_change | (vscale)
/* character rotation: */
#define RO_SAME 00000 /* no change */
#define RO_HORIZONTAL 01000 /* no text rotation */
#define RO_VERTICAL 01400 /* rotate text 90 degrees CCW */
/* character scale change enable: */
#define CS_SAME 0000 /* no change (cscale value ignored) */
#define CS_CHANGE 0200 /* set character scale */
/* vector scale change enable: */
#define VS_SAME 000 /* no change (vscale value ignored) */
#define VS_CHANGE 020 /* set vector scale */
/* load scope selection register (VS60): */
#define LSSR(console,disp,lp_intr,sw_intr) \
0164000 | console | disp | lp_intr | sw_intr
/* console to which this instruction applies: */
#define CN_0 0000 /* console # 0 */
#define CN_1 0400 /* console # 1 */
/* display enable: */
#define DS_SAME 0000 /* no change */
#define DS_DIS 0200 /* disable display (blank CRT) */
#define DS_ENA 0300 /* enable display (use CRT) */
/* light-pen hit interrupt enable: */
#define LH_SAME 0000 /* no change */
#define LH_DIS 0040 /* light-pen hit interrupt disabled */
#define LH_ENA 0060 /* light-pen hit interrupt enabled */
/* tip-switch transition interrupt enable: */
#define SW_SAME 0000 /* no change */
#define SW_DIS 0010 /* tip-switch interrupt disabled */
#define SW_ENA 0014 /* tip-switch hit interrupt enabled */
/* load name register (VS60): */
#define LNR(name) \
0150000 | (name)
/* set graphic mode: */
#define SGM(mode,intens,lp_intr,blink,line_type) \
0100000 | mode | intens | lp_intr | blink | line_type
/* graphic mode: */
#define GM_CHAR 000000 /* character */
#define GM_SVECT 004000 /* short vector */
#define GM_LVECT 010000 /* long vector */
#define GM_APOINT 014000 /* absolute point, or offset */
#define GM_GRAPHX 020000 /* graphplot X, or basic long vector */
#define GM_GRAPHY 024000 /* graphplot Y, or basic long vector */
#define GM_RPOINT 030000 /* relative point */
#define GM_BSVECT 034000 /* basic short vector */
#define GM_ARC 040000 /* circle/arc */
#define GM_AVECT 044000 /* absolute vector */
/* intensity: */
#define IN_SAME 00000 /* no change */
#define IN_0 02000 /* intensity level 0 (dimmest) */
#define IN_1 02200 /* intensity level 1 */
#define IN_2 02400 /* intensity level 2 */
#define IN_3 02600 /* intensity level 3 */
#define IN_4 03000 /* intensity level 4 */
#define IN_5 03200 /* intensity level 5 */
#define IN_6 03400 /* intensity level 6 */
#define IN_7 03600 /* intensity level 7 (brightest) */
/* light pen interrupt: */
#define LP_SAME 0000 /* no change */
#define LP_DIS 0100 /* light-pen hit interrupt disabled */
#define LP_ENA 0140 /* light-pen hit interrupt enabled */
/* blink: */
#define BL_SAME 000 /* no change */
#define BL_OFF 020 /* blink off */
#define BL_ON 030 /* blink on */
/* line type: */
#define LT_SAME 00 /* no change */
#define LT_SOLID 04 /* solid */
#define LT_LDASH 05 /* long dash */
#define LT_SDASH 06 /* short dash */
#define LT_DDASH 07 /* dot dash */
/* display jump absolute: */
#define DJMP_ABS(addr) \
0160000, \
(addr) & ~1
/* display jump relative (VS60): */
#define DJMP_REL(raddr) \
0161000 | (SGN_(raddr) << 8) | MAG_(raddr)
/* display jump to subroutine absolute (VS60): */
#define DJSR_ABS(addr) \
0162000, \
(addr) & ~1
/* display jump to subroutine relative (VS60): */
#define DJSR_REL(raddr) \
0163000 | (SGN_(raddr) << 8) | MAG_(raddr)
/* display no-op: */
#define DNOP \
0164000
/* display pop, no restore (VS60): */
#define DPOP_NR \
0165000
/* display pop, restore (VS60): */
#define DPOP_R \
0165000
/* display stop: */
#define DSTOP LSRA(ST_STOP,SI_SAME,LI_SAME,IT_SAME,RF_UNSYNC,MN_SAME)
/* graphic data: */
/* intensify enable (common to all modes exept CHAR and OFFSET): */
#define I_OFF 000000 /* beam off */
#define I_ON 040000 /* beam on */
/* Note: when VS60 "file Z data" is enabled,
use the *3() macros instead of the corresponding normal ones. */
/* character data: */
#define CHAR(c1,c2) \
((c2) << 8) | (c1) /* 7-bit ASCII assumed */
/* short vector data: */
#define SVECT(i,dx,dy) \
i | (SGN_(dx) << 13) | (MAG_(dx) << 7) | (SGN_(dy) << 6) | MAG_(dy)
#define SVECT3(i,dx,dy,dz) \
i | (SGN_(dx) << 13) | (MAG_(dx) << 7) | (SGN_(dy) << 6) | MAG_(dy), \
(SGN_(dz) << 13) | (MAG_(dz) << 2)
/* long vector data: */
#define LVECT(i,dx,dy) \
i | (SGN_(dx) << 13) | MAG_(dx), \
(SGN_(dy) << 13) | MAG_(dy)
#define LVECT3(i,dx,dy,dz) \
i | (SGN_(dx) << 13) | MAG_(dx), \
(SGN_(dy) << 13) | MAG_(dy), \
(SGN_(dz) << 13) | (MAG_(dz) << 2)
/* rotation data (VS60, probably unimplemented): */
#define ROTATE(i,a,b) \
i | (SGN_(a) << 13) | 010000 | MAG_(a), \
(SGN_(b) << 13) | MAG_(b)
#define ROTATE3(i,a,b,c) \
i | (SGN_(a) << 13) | 010000 | MAG_(a), \
(SGN_(b) << 13) | MAG_(b), \
(SGN_(c) << 13) | (MAG_(c) << 2)
/* absolute point data: */
#define APOINT(i,x,y) \
i | (SGN_(x) << 13) | MAG_(x), \
(SGN_(y) << 13) | MAG_(y)
#define APOINT3(i,x,y,z) \
i | (SGN_(x) << 13) | MAG_(x), \
(SGN_(y) << 13) | MAG_(y), \
(SGN_(z) << 13) | (MAG_(z) << 2)
/* offset data (VS60): */
#define OFFSET(x,y) \
(SGN_(x) << 13) | 010000 | MAG_(x), \
(SGN_(y) << 13) | 010000 | MAG_(y)
#define OFFSET3(x,y,z) \
(SGN_(x) << 13) | 010000 | MAG_(x), \
(SGN_(y) << 13) | 010000 | MAG_(y), \
(SGN_(z) << 13) | 010000 | (MAG_(z) << 2)
/* graphplot X data: */
#define GRAPHX(i,x) \
i | (x)
/* graphplot Y data: */
#define GRAPHY(i,y) \
i | (y)
/* basic long vector data (VS60): */
#define BLVECT(i,dir,len) \
i | ((dir) << 11) | 02000 | (len)
/* relative point data: */
#define RPOINT(i,dx,dy) \
i | (SGN_(dx) << 13) | (MAG_(dx) << 7) | (SGN_(dy) << 6) | MAG_(dy)
#define RPOINT3(i,dx,dy,dz) \
i | (SGN_(dx) << 13) | (MAG_(dx) << 7) | (SGN_(dy) << 6) | MAG_(dy), \
(SGN_(dz) << 13) | (MAG_(dz) << 2)
/* basic short vector data (VS60): */
#define BSVECT(i,dir1,len1,dir2,len2) \
i | ((dir2) << 11) | ((len2) << 7) | ((dir1) << 4) | (len1)
/* circle/arc data (VS60, option): */
#define ARC(i,dcx,dcy,dex,dey) \
i | (SGN_(dcx) << 13) | MAG_(dcx), \
(SGN_(dcy) << 13) | MAG_(dcy), \
(SGN_(dex) << 13) | MAG_(dex), \
(SGN_(dey) << 13) | MAG_(dey)
#define ARC3(i,dcx,dcy,cz,dex,dey,ez) \
i | (SGN_(dcx) << 13) | MAG_(dcx), \
(SGN_(dcy) << 13) | MAG_(dcy), \
(SGN_(cz) << 13) | (MAG_(cz) << 2), \
(SGN_(dex) << 13) | MAG_(dex), \
(SGN_(dey) << 13) | MAG_(dey), \
(SGN_(ez) << 13) | (MAG_(ez) << 2)
/* absolute vector data (VS60): */
#define AVECT(i,x,y) \
i | (SGN_(x) << 13) | MAG_(x), \
(SGN_(y) << 13) | MAG_(y)
#define AVECT3(i,x,y,z) \
i | (SGN_(x) << 13) | MAG_(x), \
(SGN_(y) << 13) | MAG_(y), \
(SGN_(z) << 13) | (MAG_(z) << 2)

1301
display/vttest.c Normal file

File diff suppressed because it is too large Load diff

418
display/win32.c Normal file
View file

@ -0,0 +1,418 @@
/*
* $Id: win32.c,v 1.38 2004/02/07 06:32:01 phil Exp $
* Win32 support for XY display simulator
* Phil Budne <phil@ultimate.com>
* September 2003
* Revised by Douglas A. Gwyn, 05 Feb. 2004
*/
/*
* Copyright (c) 2003-2004, Philip L. Budne
*
* 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.
*/
/* use a thread to handle windows messages; */
#define THREADS
/*
* BUGS:
* Does not allow you to close display window;
* would need to tear down both system, and system independent data.
*
* now tries to handle PAINT message, as yet untested!!
*/
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include "ws.h"
#include "display.h"
#ifndef PIX_SIZE
#define PIX_SIZE 1
#endif
#define APP_CLASS "XYAppClass"
#define APP_MENU "XYAppMenu" /* ?? */
/*
* light pen location
* see ws.h for full description
*/
int ws_lp_x = -1;
int ws_lp_y = -1;
static HWND static_wh;
static HINSTANCE static_inst;
static int xpixels, ypixels;
static char *window_name;
static HBRUSH white_brush;
static HBRUSH black_brush;
#ifdef SWITCH_CURSORS
static HCURSOR cross, arrow;
#endif
static __inline int
map_key(int k)
{
switch (k) {
case 186: return ';'; /* VK_OEM_1? */
case 222: return '\''; /* VK_OEM_7? */
}
return k;
}
static void
keydown(int k)
{
display_keydown(map_key(k));
}
static void
keyup(int k)
{
display_keyup(map_key(k));
}
/*
* here on any button click, or if mouse dragged while a button down
*/
static void
mousepos(DWORD lp)
{
int x, y;
x = LOWORD(lp);
y = HIWORD(lp);
/* convert to display coordinates */
#if PIX_SIZE > 1
x /= PIX_SIZE;
y /= PIX_SIZE;
#endif
y = ypixels - 1 - y;
/* if window has been stretched, can get out of range bits!! */
if (x >= 0 && x < xpixels && y >= 0 && y < ypixels) {
/* checked by display_add_point() */
ws_lp_x = x;
ws_lp_y = y;
}
}
/* thoingggg!! "message for you sir!!!" */
static LRESULT CALLBACK
patsy(HWND wh, UINT msg, WPARAM wp, LPARAM lp) /* "WndProc" */
{
/* printf("msg %d\n", msg); */
switch (msg) {
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_MOUSEMOVE:
if (wp & (MK_LBUTTON|MK_MBUTTON|MK_RBUTTON)) {
#ifdef SWITCH_CURSORS
if (ws_lp_x == -1 && !display_tablet)
SetCursor(cross);
#endif
mousepos(lp);
}
#ifdef SWITCH_CURSORS
else if (ws_lp_x != -1 && !display_tablet)
SetCursor(arrow);
#endif
break; /* return?? */
case WM_LBUTTONDOWN:
display_lp_sw = 1;
case WM_MBUTTONDOWN:
case WM_RBUTTONDOWN:
#ifdef SWITCH_CURSORS
if (!display_tablet)
SetCursor(cross);
#endif
mousepos(lp);
break; /* return?? */
case WM_LBUTTONUP:
display_lp_sw = 0;
case WM_MBUTTONUP:
case WM_RBUTTONUP:
#ifdef SWITCH_CURSORS
if (!display_tablet)
SetCursor(arrow);
#endif
ws_lp_x = ws_lp_y = -1;
break; /* return?? */
case WM_KEYDOWN:
keydown(wp);
break;
case WM_KEYUP:
keyup(wp);
break;
case WM_PAINT:
display_repaint();
break; /* return?? */
}
return DefWindowProc(wh, msg, wp, lp);
}
int
ws_poll(int *valp, int maxus)
{
#ifdef THREADS
/* msgthread handles window events; just delay simulator */
if (maxus > 0)
Sleep((maxus+999)/1000);
#else
MSG msg;
DWORD start;
int maxms = (maxus + 999) / 1000;
for (start = GetTickCount(); GetTickCount() - start < maxms; Sleep(1)) {
/* empty message queue without blocking */
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
#endif
return 1;
}
/* called from non-threaded main program */
int
ws_loop(void (*func)(void *), void *arg)
{
int val;
while (ws_poll(&val, 0))
(*func)(arg);
return val;
}
/* worker for display init */
static void
ws_init2(void) {
WNDCLASS wc;
int h, w;
#ifdef SWITCH_CURSORS
if (!display_tablet) {
arrow = LoadCursor(NULL, IDC_ARROW);
cross = LoadCursor(NULL, IDC_CROSS);
}
#endif
black_brush = GetStockObject(BLACK_BRUSH);
white_brush = GetStockObject(WHITE_BRUSH);
wc.lpszClassName = APP_CLASS;
wc.lpfnWndProc = patsy;
wc.style = CS_OWNDC | CS_VREDRAW | CS_HREDRAW;
/* also CS_NOCLOSE? CS_SAVEBITS? */
wc.hInstance = static_inst = GetModuleHandleA(0);
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
#ifdef SWITCH_CURSORS
wc.hCursor = NULL;
#else
wc.hCursor = display_tablet ? NULL : LoadCursor(NULL, IDC_CROSS);
#endif
wc.hbrBackground = black_brush;
wc.lpszMenuName = APP_MENU;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
/* WNDCLASSEX/RegisterClassEx include hIconSm (small icon) */
RegisterClass(&wc);
/*
* WS_OVERLAPPEDWINDOW=>
* WS_OVERLAPPED, WS_CAPTION, WS_SYSMENU, WS_THICKFRAME,
* WS_MINIMIZEBOX, WS_MAXIMIZEBOX
*
* WS_CHILD (no menu bar), WS_POPUP (mutually exclusive)
*/
/* empirical crocks to get entire screen; */
w = (xpixels*PIX_SIZE)+6;
h = (ypixels*PIX_SIZE)+32;
/* XXX -- above values work with XP; Phil had +10,+30 */
static_wh = CreateWindow(APP_CLASS, /* registered class name */
window_name, /* window name */
WS_OVERLAPPED, /* style */
CW_USEDEFAULT, CW_USEDEFAULT, /* X,Y */
w, h,
NULL, /* HWND hWndParent */
NULL, /* HMENU hMenu */
static_inst, /* application instance */
NULL); /* lpParam */
ShowWindow(static_wh, SW_SHOW);
UpdateWindow(static_wh);
}
#ifdef THREADS
static volatile init_done;
static DWORD msgthread_id;
static DWORD WINAPI
msgthread(LPVOID arg)
{
MSG msg;
ws_init2();
/* XXX use a mutex? */
init_done = 1;
while (GetMessage(&msg, NULL, 0, 0) > 0) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
static void
ws_thread_init(void)
{
HANDLE th = CreateThread(NULL, /* sec. attr. */
0, /* stack size */
msgthread,
NULL, /* param */
0, /* flags */
&msgthread_id);
CloseHandle(th);
/* XXX use a mutex; don't wait forever!! */
while (!init_done)
;
}
#endif /* THREADS */
/* called from display layer on first display op */
int
ws_init(char *name, int xp, int yp, int colors)
{
xpixels = xp;
ypixels = yp;
window_name = name;
#ifdef THREADS
ws_thread_init();
#else
ws_init2();
#endif
return 1; /* XXX return errors!! */
}
void *
ws_color_rgb(int r, int g, int b)
{
/* XXX check for failure??? try GetNearestColor??? */
return CreateSolidBrush(RGB(r/256, g/256, b/256));
}
void *
ws_color_black(void)
{
return black_brush;
}
void *
ws_color_white(void)
{
return white_brush;
}
void
ws_display_point(int x, int y, void *color)
{
HDC dc;
RECT r;
HBRUSH brush = color;
if (x > xpixels || y > ypixels)
return;
y = ypixels - 1 - y; /* invert y, top left origin */
/* top left corner */
r.left = x*PIX_SIZE;
r.top = y*PIX_SIZE;
/* bottom right corner, non-inclusive */
r.right = (x+1)*PIX_SIZE;
r.bottom = (y+1)*PIX_SIZE;
if (brush == NULL)
brush = black_brush;
dc = GetDC(static_wh);
FillRect(dc, &r, brush);
ReleaseDC(static_wh, dc);
}
void
ws_sync(void) {
/* noop */
}
void
ws_beep(void) {
#if 0
/* play SystemDefault sound; does not work over terminal service */
MessageBeep(MB_OK);
#else
/* works over terminal service? Plays default sound/beep on Win9x/ME */
Beep(440, 500); /* Hz, ms. */
#endif
}
unsigned long
os_elapsed(void)
{
static int new;
unsigned long ret;
static DWORD t[2];
/*
* only returns milliseconds, but Sleep()
* only takes milliseconds.
*
* wraps after 49.7 days of uptime.
* DWORD is an unsigned long, so this should be OK
*/
t[new] = GetTickCount();
if (t[!new] == 0)
ret = ~0L; /* +INF */
else
ret = (t[new] - t[!new]) * 1000;
new = !new; /* Ecclesiastes III */
return ret;
}

66
display/ws.h Normal file
View file

@ -0,0 +1,66 @@
/*
* $Id: ws.h,v 1.17 2004/02/03 21:23:51 phil Exp $
* Interfaces to window-system specific code for XY display simulation
*/
/*
* Copyright (c) 2003-2004, Philip L. Budne
*
* 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.
*/
/* unless you're writing a new driver, you shouldn't be looking here! */
extern int ws_init(char *, int, int, int);
extern void ws_close(void); // 2006-07-19 SAI
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);
/* entries into display.c from below: */
extern void display_keyup(int);
extern void display_keydown(int);
extern void display_repaint(void);
/*
* Globals set by O/S display level to SCALED location in display
* coordinate system in order to save an upcall on every mouse
* movement.
*
* *NOT* for consumption by clients of display.c; although display
* clients can now get the scaling factor, real displays only give you
* a light pen "hit" when the beam passes under the light pen.
*/
extern int ws_lp_x, ws_lp_y;
/*
* O/S services in theory independent of window system,
* but in (current) practice not!
*/
extern unsigned long os_elapsed(void);

512
display/x11.c Normal file
View file

@ -0,0 +1,512 @@
/*
* $Id: x11.c,v 1.29 2004/02/03 21:23:51 phil Exp $
* X11 support for XY display simulator
* Phil Budne <phil@ultimate.com>
* September 2003
*
* Changes from Douglas A. Gwyn, Jan 8, 2004
*
* started from PDP-8/E simulator (vc8e.c & kc8e.c);
* This PDP8 Emulator was written by Douglas W. Jones at the
* University of Iowa. It is distributed as freeware, of
* uncertain function and uncertain utility.
*/
/*
* Copyright (c) 2003-2004, Philip L. Budne
*
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ws.h"
#include "display.h"
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/Core.h>
#include <X11/Shell.h>
#include <X11/cursorfont.h>
#include <sys/types.h>
#include <sys/time.h>
#ifndef PIX_SIZE
#define PIX_SIZE 1
#endif
//#define FULL_SCREEN 1
#define NO_CURSOR 1
#define NO_BORDER 1
/*
* light pen location
* see ws.h for full description
*/
int ws_lp_x = -1;
int ws_lp_y = -1;
static XtAppContext app_context; /* the topmost context for everything */
static Display* dpy; /* its display */
static int scr; /* its screen */
static Colormap cmap; /* its colormap */
static Widget crtshell; /* the X window shell */
static Widget crt; /* the X window in which output will plot */
static int xpixels, ypixels;
#ifdef FULL_SCREEN
/* occupy entire screen for vintage computer fan Sellam Ismail */
static int xoffset, yoffset;
#endif
static GC whiteGC; /* gc with white foreground */
static GC blackGC; /* gc with black foreground */
static int buttons = 0; /* tracks state of all buttons */
static int os_pollfd(int, int); /* forward */
/* here on any mouse button down, AND movement when any button down */
static void
handle_button_press(w, d, e, b)
Widget w;
XtPointer d;
XEvent *e;
Boolean *b;
{
int x, y;
x = e->xbutton.x;
y = e->xbutton.y;
#ifdef FULL_SCREEN
x -= xoffset;
y -= yoffset;
#endif
#if PIX_SIZE > 1
x *= PIX_SIZE;
y *= PIX_SIZE;
#endif
#ifndef NO_CURSUR
if (!display_tablet)
/* crosshair cursor to indicate tip of active pen */
XDefineCursor(dpy, XtWindow(crt),
(Cursor) XCreateFontCursor(dpy, XC_crosshair));
#endif
y = ypixels - y - 1;
/*printf("lightpen at %d,%d\n", x, y); fflush(stdout);*/
ws_lp_x = x;
ws_lp_y = y;
if (e->type == ButtonPress) {
buttons |= e->xbutton.button;
if (e->xbutton.button == 1) {
display_lp_sw = 1;
/*printf("tip switch activated\n"); fflush(stdout);*/
}
}
if (b)
*b = TRUE;
}
static void
handle_button_release(w, d, e, b)
Widget w;
XtPointer d;
XEvent *e;
Boolean *b;
{
if ((buttons &= ~e->xbutton.button) == 0) { /* all buttons released */
#ifndef NO_CURSOR
if (!display_tablet)
/* pencil cursor (close to a pen!) to indicate inactive pen posn */
XDefineCursor(dpy, XtWindow(crt),
(Cursor) XCreateFontCursor(dpy, XC_pencil));
#endif
/* XXX change cursor back?? */
ws_lp_x = ws_lp_y = -1;
}
if (e->xbutton.button == 1) {
display_lp_sw = 0;
/*printf("tip switch deactivated\n"); fflush(stdout);*/
}
if (b)
*b = TRUE;
}
static void
handle_key_press(w, d, e, b)
Widget w;
XtPointer d;
XEvent *e;
Boolean *b;
{
int shift = (ShiftMask & e->xkey.state) != 0;
KeySym key = XKeycodeToKeysym( dpy, e->xkey.keycode, shift );
/*printf("key %d down\n", key); fflush(stdout);*/
if ((key & 0xff00) == 0)
display_keydown(key);
if (b)
*b = TRUE;
}
static void
handle_key_release(w, d, e, b)
Widget w;
XtPointer d;
XEvent *e;
Boolean *b;
{
int shift = (ShiftMask & e->xkey.state) != 0;
KeySym key = XKeycodeToKeysym( dpy, e->xkey.keycode, shift );
/*printf("key %d up\n", key); fflush(stdout);*/
if ((key & 0xff00) == 0)
display_keyup(key);
if (b)
*b = TRUE;
}
static void
handle_exposure(w, d, e, b)
Widget w;
XtPointer d;
XEvent *e;
Boolean *b;
{
display_repaint();
if (b)
*b = TRUE;
}
int
ws_init(char *crtname, /* crt type name */
int xp, int yp, /* screen size in pixels */
int colors) /* colors to support (not used) */
{
Arg arg[25];
XGCValues gcvalues;
unsigned int n;
int argc;
char *argv[1];
int height, width;
xpixels = xp; /* save screen size */
ypixels = yp;
XtToolkitInitialize();
app_context = XtCreateApplicationContext();
argc = 0;
argv[0] = NULL;
dpy = XtOpenDisplay( app_context, NULL, NULL, crtname, NULL, 0,
&argc, argv);
scr = DefaultScreen(dpy);
crtshell = XtAppCreateShell( crtname, /* app name */
crtname, /* app class */
#ifdef NO_BORDER
overrideShellWidgetClass,
#else
applicationShellWidgetClass, /* wclass */
#endif
dpy, /* display */
NULL, /* arglist */
0); /* nargs */
cmap = DefaultColormap(dpy, scr);
/*
* Create a drawing area
*/
n = 0;
#ifdef FULL_SCREEN
/* center raster in full-screen black window */
width = DisplayWidth(dpy,scr);
height = DisplayHeight(dpy,scr);
xoffset = (width - xpixels*PIX_SIZE)/2;
yoffset = (height - ypixels*PIX_SIZE)/2;
#else
width = xpixels*PIX_SIZE;
height = ypixels*PIX_SIZE;
#endif
XtSetArg(arg[n], XtNwidth, width); n++;
XtSetArg(arg[n], XtNheight, height); n++;
XtSetArg(arg[n], XtNbackground, BlackPixel( dpy, scr )); n++;
crt = XtCreateWidget( crtname, widgetClass, crtshell, arg, n);
XtManageChild(crt);
XtPopup(crtshell, XtGrabNonexclusive);
/*
* Create black and white Graphics Contexts
*/
gcvalues.foreground = BlackPixel( dpy, scr );
gcvalues.background = BlackPixel( dpy, scr );
blackGC = XCreateGC(dpy, XtWindow(crt),
GCForeground | GCBackground, &gcvalues);
gcvalues.foreground = WhitePixel( dpy, scr );
whiteGC = XCreateGC(dpy, XtWindow(crt),
GCForeground | GCBackground, &gcvalues);
#ifndef NO_CURSOR
if (!display_tablet) {
/* pencil cursor */
XDefineCursor(dpy, XtWindow(crt),
(Cursor) XCreateFontCursor(dpy, XC_pencil));
}
#endif
/*
* Setup to handle events
*/
XtAddEventHandler(crt, ButtonPressMask|ButtonMotionMask, FALSE,
handle_button_press, NULL);
XtAddEventHandler(crt, ButtonReleaseMask, FALSE,
handle_button_release, NULL);
XtAddEventHandler(crt, KeyPressMask, FALSE,
handle_key_press, NULL);
XtAddEventHandler(crt, KeyReleaseMask, FALSE,
handle_key_release, NULL);
XtAddEventHandler(crt, ExposureMask, FALSE,
handle_exposure, NULL);
return 1;
} /* ws_init */
/* Added 2006-07-19 SAI */
void ws_close(void)
{
XtCloseDisplay(dpy);
}
void *
ws_color_black(void)
{
return blackGC;
}
void *
ws_color_white(void)
{
return whiteGC;
}
void *
ws_color_rgb(int r, int g, int b)
{
XColor color;
color.red = r;
color.green = g;
color.blue = b;
/* ignores flags */
if (XAllocColor(dpy, cmap, &color)) {
XGCValues gcvalues;
memset(&gcvalues, 0, sizeof(gcvalues));
gcvalues.foreground = gcvalues.background = color.pixel;
return XCreateGC(dpy, XtWindow(crt),
GCForeground | GCBackground,
&gcvalues);
}
/* allocation failed */
return NULL;
}
/* put a point on the screen */
void
ws_display_point(int x, int y, void *color)
{
GC gc = (GC) color;
if (x > xpixels || y > ypixels)
return;
y = ypixels - y - 1; /* X11 coordinate system */
#ifdef FULL_SCREEN
x += xoffset;
y += yoffset;
#endif
if (gc == NULL)
gc = blackGC; /* default to off */
#if PIX_SIZE == 1
XDrawPoint(dpy, XtWindow(crt), gc, x, y);
#else
XFillRectangle(dpy, XtWindow(crt), gc,
x*PIX_SIZE, y*PIX_SIZE, PIX_SIZE, PIX_SIZE);
#endif
}
void
ws_sync(void)
{
XFlush(dpy);
}
/*
* elapsed wall clock time since last call
* +INF on first call
*/
struct elapsed_state {
struct timeval tvs[2];
int new;
};
static unsigned long
elapsed(struct elapsed_state *ep)
{
unsigned long val;
gettimeofday(&ep->tvs[ep->new], NULL);
if (ep->tvs[!ep->new].tv_sec == 0)
val = ~0L;
else
val = ((ep->tvs[ep->new].tv_sec - ep->tvs[!ep->new].tv_sec) * 1000000 +
(ep->tvs[ep->new].tv_usec - ep->tvs[!ep->new].tv_usec));
ep->new = !ep->new;
return val;
}
/* called periodically */
int
ws_poll(int *valp, int maxusec)
{
static struct elapsed_state es; /* static to avoid clearing! */
#ifdef WS_POLL_DEBUG
printf("ws_poll %d\n", maxusec);
fflush(stdout);
#endif
elapsed(&es); /* start clock */
do {
unsigned long e;
/* tried checking return, but lost on TCP connections? */
os_pollfd(ConnectionNumber(dpy), maxusec);
while (XtAppPending(app_context)) {
XEvent event;
/* XXX check for connection loss; set *valp? return 0 */
XtAppNextEvent(app_context, &event );
XtDispatchEvent( &event );
}
e = elapsed(&es);
#ifdef WS_POLL_DEBUG
printf(" maxusec %d e %d\r\n", maxusec, e);
fflush(stdout);
#endif
maxusec -= e;
} while (maxusec > 10000); /* 10ms */
return 1;
}
/* utility: can be called from main program
* which is willing to cede control
*/
int
ws_loop(void (*func)(void *), void *arg)
{
int val;
/* XXX use XtAppAddWorkProc & XtAppMainLoop? */
while (ws_poll(&val,0))
(*func)(arg);
return val;
}
void
ws_beep(void)
{
XBell(dpy, 0); /* ring at base volume */
XFlush(dpy);
}
/****************
* could move these to unix.c, if VMS versions needed
* (or just (GASP!) ifdef)
*/
/* public version, used by delay code */
unsigned long
os_elapsed(void)
{
static struct elapsed_state es;
return elapsed(&es);
}
/*
* select/DisplayNumber works on VMS 7.0+?
* could move to "unix.c"
* (I have some nasty VMS code that's supposed to to the job
* for older systems)
*/
/*
* sleep for maxus microseconds, returning TRUE sooner if fd is readable
* used by X11 driver
*/
static int
os_pollfd(int fd, int maxus)
{
/* use trusty old select (most portable) */
fd_set rfds;
struct timeval tv;
if (maxus >= 1000000) { /* not bloody likely, avoid divide */
tv.tv_sec = maxus / 1000000;
tv.tv_usec = maxus % 1000000;
}
else {
tv.tv_sec = 0;
tv.tv_usec = maxus;
}
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
return select(fd+1, &rfds, NULL, NULL, &tv) > 0;
}