/* | |
* $Id: type340.c,v 1.6 2005/01/14 18:58:00 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 "xy.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 */ |