1
0
mirror of https://github.com/simh/simh.git synced 2026-01-25 11:46:37 +00:00

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

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;
}