/* * wrap, or clip? * skip vector points when scaling? * are scaled character sizes right?? */ /* * $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 * September 20, 2003 * from vt11.c * * First displayed PDP-6/10 SPCWAR Feb 2018! * * 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) * * This file simulates ONLY the 340 proper * and not CPU specific interfacing details * * see: * http://www.bitsavers.org/pdf/dec/graphics/H-340_Type_340_Precision_Incremental_CRT_System_Nov64.pdf * * Initial information from DECUS 7-13: * http://www.bitsavers.org/pdf/dec/graphics/7-13_340_Display_Programming_Manual.pdf * pre-bitsavers location(!!): * http://www.spies.com/~aek/pdf/dec/pdp7/7-13_340displayProgMan.pdf * * NOTE!!! The 340 is an async processor, with multiple control signals * running in parallel. No attempt has been made to simulate this. * And while it might be fun to try to implement it as a bit vector * of signals, and run code triggered by those signals in the next * service interval, BUT unless/until this is proven necessary, I'm * resisting that impulse (pun not intended). */ /* * Copyright (c) 2003-2018, 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 */ #include "type340.h" /* interface definitions */ #include "type340cmd.h" /* 340 command definitions */ /* * sub-options, under "#if" * (make runtime selectable????!) * TYPE342 character generator * TYPE343 slave display control * TYPE347 subroutine facility */ #ifndef TYPE342 #define TYPE342 1 /* default to character generation */ #endif #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 #include #define DEBUGF(X) printf X #else #define DEBUGF(X) #endif enum mode { PARAM=0, POINT, SLAVE, CHAR, VECTOR, VCONT, INCR, SUBR }; #define TY340_UNITS 1 enum jump_type { DJP=2, DJS=3, DDS=1 }; /* type 347 */ /* Codes for special characters. */ #define CH_LF 0001 /* Line feed. */ #define CH_CR 0002 /* Carriage return. */ #define CH_UC 0003 /* Shift in. */ #define CH_LC 0004 /* Shift out. */ #define CH_ESC 0005 /* Escape to parameter mode. */ #define CH_NSPC 0006 /* Non spacing. */ #define CH_D 0007 /* Descender. */ #define CH_BS 0010 /* Backspace. */ #define CH_SUB 0011 /* Subscript. */ #define CH_SUP 0012 /* Superscript. */ /* put all the state in a struct "just in case" */ static struct type340 { ty340word DAC; /* Display Address Counter */ ty340word status; /* see ST340_XXX in type340.h */ signed short xpos, ypos; /* 10 bits, signed (for OOB checks) */ char initialized; /* 0 before display_init */ /* only using (evil) bitfield syntax to limit enum size */ enum mode mode : 8; /* 3 bits */ unsigned char lp_ena; /* 1 bit */ unsigned char scale; /* multiplier: 1,2,4,8 */ unsigned char intensity; /* 3 bits */ #if TYPE342 unsigned char shift; /* 1 bit */ unsigned char width; /* character grid width */ unsigned char height; /* character grid height */ #endif #if TYPE347 ty340word ASR; /* Address Save Register */ unsigned char SAVE_FF; /* "save" flip-flop */ #endif } u340[TY340_UNITS]; #if TY340_UNITS == 1 #define UNIT(N) u340 #else #define UNIT(N) (u340+(N)) #endif /* NOT USED WITH PDP-6 Type 344 Interface!! */ void ty340_set_dac(ty340word addr) { struct type340 *u = UNIT(0); u->DAC = addr; DEBUGF(("set DAC %06o\r\n", u->DAC)); /* XXX only when reset? */ u->mode = PARAM; u->status = 0; /* XXX just clear stopped? */ ty340_rfd(); /* ready for data */ } void ty340_cycle(void) { struct type340 *u = UNIT(0); if (u->status == 0) { ty340word insn = ty340_fetch(u->DAC); u->status = ty340_instruction (insn); u->DAC = (u->DAC + 1) & 07777; } } ty340word ty340_get_dac(void) { struct type340 *u = UNIT(0); return u->DAC; } ty340word ty340_get_asr(void) { #if TYPE347 struct type340 *u = UNIT(0); return u->ASR; #else return 0; #endif } ty340word ty340_sense(ty340word flags) { struct type340 *u = UNIT(0); return u->status & flags; } void ty340_clear(ty340word flags) { struct type340 *u = UNIT(0); u->status &= ~flags; } ty340word ty340_reset(void *dptr) { struct type340 *u = UNIT(0); #ifndef TY340_NODISPLAY if (!u->initialized) { display_init(DIS_TYPE340, 1, dptr); /* XXX check return? */ u->initialized = 1; } #endif u->xpos = u->ypos = 0; u->mode = PARAM; u->status = 0; u->scale = 1; #if TYPE342 u->shift = 0; u->width = 6; u->height = 11; #endif #if TYPE347 u->SAVE_FF = 0; #endif ty340_rfd(); /* ready for data */ return u->status; } static int point(int x, int y, int seq) { struct type340 *u = UNIT(0); int i; #ifdef TYPE340_POINT DEBUGF(("type340 point %d %d %d\r\n", x, y, seq)); #endif i = DISPLAY_INT_MAX-7+u->intensity; if (i <= 0) i = 1; if (x < 0 || x > 1023) { /* XXX clip? wrap?? */ u->status |= ST340_VEDGE; return 0; } if (y < 0 || y > 1023) { /* XXX clip? wrap?? */ u->status |= ST340_HEDGE; return 0; } #ifndef TY340_NODISPLAY if (display_point(x, y, i, 0)) { /* * in real life: type340 pauses * until CPU reads coordinates */ u->status |= ST340_LPHIT; if (u->lp_ena) ty340_lp_int(x, y); } #endif return 1; } void lpoint(int x, int y) { #ifdef TYPE340_LPOINT DEBUGF(("type340 lpoint %d %d\r\n", x, y)); #endif point(x, y, 0); } /* * 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 -= stepx, 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 */ /* here in VECTOR & VCONT modes */ int vector(int i, int sy, int dy, int sx, int dx) { struct type340 *u = UNIT(0); int x0, y0, x1, y1; int flags = 0; DEBUGF(("v i%d y%c%d x%c%d\r\n", i, (sy ? '-' : '+'), dy, (sx ? '-' : '+'), dx)); x0 = u->xpos; y0 = u->ypos; if (sx) { x1 = x0 - dx * u->scale; if (x1 < 0) { x1 = 0; flags = ST340_HEDGE; } } else { x1 = x0 + dx * u->scale; if (x1 > 1023) { x1 = 1023; flags = ST340_HEDGE; } } if (sy) { y1 = y0 - dy * u->scale; if (y1 < 0) { y1 = 0; flags |= ST340_VEDGE; } } else { y1 = y0 + dy * u->scale; if (y1 > 1023) { y1 = 1023; flags |= ST340_VEDGE; } } DEBUGF(("vector i%d (%d,%d) to (%d,%d)\r\n", i, x0, y0, x1, y1)); if (i) /* XXX need OLD value??? */ lineTwoStep(x0, y0, x1, y1); u->xpos = x1; u->ypos = y1; u->status |= flags; /* ?? */ return flags; } /* * incremental vector * return true on raster violation * * i is intensify * n is subvector number * byte is 4 bits */ int ipoint(int i, int n, unsigned char byte) { struct type340 *u = UNIT(0); DEBUGF(("type340 ipoint i%d n%d %#o\r\n", i, n, byte)); if (byte & 010) { /* left/right */ if (byte & 04) { /* left */ u->xpos -= u->scale; if (u->xpos < 0) { u->xpos = 0; /* XXX wrap? */ u->status |= ST340_VEDGE; /* save flags & continue?? */ return 1; /* escape */ } } else { /* right */ u->xpos += u->scale; if (u->xpos > 1023) { u->xpos = 1023; /* XXX wrap? */ u->status |= ST340_VEDGE; return 1; } } } if (byte & 02) { /* up/down */ if (byte & 01) { /* down */ u->ypos -= u->scale; if (u->ypos < 0) { u->ypos = 0; /* XXX wrap? */ u->status |= ST340_HEDGE; return 1; } } else { u->ypos += u->scale; if (u->ypos > 1023) { u->ypos = 1023; /* XXX wrap? */ u->status |= ST340_HEDGE; return 1; } } } if (i) point(u->xpos, u->ypos, n); return 0; /* no escape */ } #if TYPE342 /* * 342 character generator - first 64 characters * 7-13_340_Display_Programming_Manual.pdf p.24 * each char contains a vertical stripe of the matrix. * highest bit is top, lowest bit is unused (what was I drinking? -PLB) * first char is leftmost */ static const unsigned char chars[128][6] = { { 0070, 0124, 0154, 0124, 0070, 0 }, /* 00 blob */ { 0176, 0220, 0220, 0220, 0176, 0 }, /* 01 A */ { 0376, 0222, 0222, 0222, 0154, 0 }, /* 02 B */ { 0174, 0202, 0202, 0202, 0104, 0 }, /* 03 C */ { 0376, 0202, 0202, 0202, 0174, 0 }, /* 04 D */ { 0376, 0222, 0222, 0222, 0222, 0 }, /* 05 E */ { 0376, 0220, 0220, 0220, 0220, 0 }, /* 06 F */ { 0174, 0202, 0222, 0222, 0134, 0 }, /* 07 G */ { 0376, 0020, 0020, 0020, 0376, 0 }, /* 10 H */ { 0000, 0202, 0376, 0202, 0000, 0 }, /* 11 I */ { 0004, 0002, 0002, 0002, 0374, 0 }, /* 12 J */ { 0376, 0020, 0050, 0104, 0202, 0 }, /* 13 K */ { 0376, 0002, 0002, 0002, 0002, 0 }, /* 14 L */ { 0376, 0100, 0040, 0100, 0376, 0 }, /* 15 M */ { 0376, 0100, 0040, 0020, 0376, 0 }, /* 16 N */ { 0174, 0202, 0202, 0202, 0174, 0 }, /* 17 O */ { 0376, 0220, 0220, 0220, 0140, 0 }, /* 20 P */ { 0174, 0202, 0212, 0206, 0176, 0 }, /* 21 Q */ { 0376, 0220, 0230, 0224, 0142, 0 }, /* 22 R */ { 0144, 0222, 0222, 0222, 0114, 0 }, /* 23 S */ { 0200, 0200, 0376, 0200, 0200, 0 }, /* 24 T */ { 0374, 0002, 0002, 0002, 0374, 0 }, /* 25 U */ { 0370, 0004, 0002, 0004, 0370, 0 }, /* 26 V */ { 0376, 0004, 0010, 0004, 0376, 0 }, /* 27 W */ { 0202, 0104, 0070, 0104, 0202, 0 }, /* 30 X */ { 0200, 0100, 0076, 0100, 0200, 0 }, /* 31 Y */ { 0226, 0232, 0222, 0262, 0322, 0 }, /* 32 Z */ { 0000, 0000, 0000, 0000, 0000, CH_LF }, /* 33 LF */ { 0000, 0000, 0000, 0000, 0000, CH_CR }, /* 34 CR */ { 0000, 0000, 0000, 0000, 0000, CH_UC }, /* 35 HORIZ */ { 0000, 0000, 0000, 0000, 0000, CH_LC }, /* 36 VERT */ { 0000, 0000, 0000, 0000, 0000, CH_ESC }, /* 37 ESC */ { 0000, 0000, 0000, 0000, 0000, 0 }, /* 40 space */ { 0000, 0000, 0372, 0000, 0000, 0 }, /* 41 ! */ { 0000, 0340, 0000, 0340, 0000, 0 }, /* 42 " */ { 0050, 0376, 0050, 0376, 0050, 0 }, /* 43 # */ { 0144, 0222, 0376, 0222, 0114, 0 }, /* 44 $ */ { 0306, 0310, 0220, 0246, 0306, 0 }, /* 45 % */ { 0154, 0222, 0156, 0004, 0012, 0 }, /* 46 & */ { 0000, 0000, 0300, 0340, 0000, 0 }, /* 47 ' */ { 0000, 0070, 0104, 0202, 0000, 0 }, /* 50 ( Source: AI film 104 */ { 0000, 0202, 0104, 0070, 0000, 0 }, /* 51 ) Source: AI film 104 */ { 0104, 0050, 0174, 0050, 0104, 0 }, /* 52 * Source: AI film */ { 0020, 0020, 0174, 0020, 0020, 0 }, /* 53 + */ { 0000, 0032, 0034, 0000, 0000, 0 }, /* 54 , Source: AI film 104 */ { 0020, 0020, 0020, 0020, 0020, 0 }, /* 55 - */ { 0000, 0006, 0006, 0000, 0000, 0 }, /* 56 . */ { 0004, 0010, 0020, 0040, 0100, 0 }, /* 57 / */ { 0174, 0212, 0222, 0242, 0174, 0 }, /* 60 0 */ { 0000, 0102, 0376, 0002, 0000, 0 }, /* 61 1 */ { 0116, 0222, 0222, 0222, 0142, 0 }, /* 62 2 */ { 0104, 0202, 0222, 0222, 0154, 0 }, /* 63 3 */ { 0020, 0060, 0120, 0376, 0020, 0 }, /* 64 4 */ { 0344, 0222, 0222, 0222, 0214, 0 }, /* 65 5 */ { 0174, 0222, 0222, 0222, 0114, 0 }, /* 66 6 */ { 0306, 0210, 0220, 0240, 0300, 0 }, /* 67 7 */ { 0154, 0222, 0222, 0222, 0154, 0 }, /* 70 8 */ { 0144, 0222, 0222, 0222, 0174, 0 }, /* 71 9 */ { 0000, 0066, 0066, 0000, 0000, 0 }, /* 72 : */ { 0000, 0332, 0334, 0000, 0000, 0 }, /* 73 ; Source: consistent with , */ { 0020, 0050, 0104, 0202, 0000, 0 }, /* 74 < */ { 0050, 0050, 0050, 0050, 0050, 0 }, /* 75 = */ { 0000, 0202, 0104, 0050, 0020, 0 }, /* 76 > */ { 0100, 0200, 0236, 0220, 0140, 0 }, /* 77 ? */ /* * NOT YET COMPLETE!!! * original letterforms not available, using * https://fontstruct.com/fontstructions/show/357807/5x7_monospaced_pixel_font * PLB: I wonder if VT52 was 5x7???? * * Lars Brinkhoff: I added new shapes from AI lab film footage, and * from the Knight TV font. */ { 0070, 0124, 0154, 0124, 0070, 0 }, /* 00 blob */ { 0034, 0042, 0042, 0074, 0002, 0 }, /* 01 a Source: AI film 75 */ { 0376, 0042, 0042, 0042, 0034, 0 }, /* 02 b Source: AI film 75 */ { 0034, 0042, 0042, 0042, 0024, 0 }, /* 03 c */ { 0034, 0042, 0042, 0042, 0376, 0 }, /* 04 d Source: AI film 75 */ { 0034, 0052, 0052, 0052, 0030, 0 }, /* 05 e Source: AI film 75 */ { 0020, 0176, 0220, 0200, 0100, 0 }, /* 06 f Source: Knight TV */ { 0160, 0212, 0212, 0212, 0174, CH_D },/* 07 g Source: AI film 75 */ { 0376, 0040, 0040, 0040, 0036, 0 }, /* 10 h Source: AI film 75 */ { 0000, 0042, 0276, 0002, 0000, 0 }, /* 11 i Source: AI film 75 */ { 0000, 0004, 0042, 0274, 0000, 0 }, /* 12 j */ { 0376, 0010, 0030, 0044, 0002, 0 }, /* 13 k Source: AI film 75 */ { 0000, 0202, 0376, 0002, 0000, 0 }, /* 14 l Source: AI film 75 */ { 0076, 0040, 0036, 0040, 0036, 0 }, /* 15 m */ { 0076, 0020, 0040, 0040, 0036, 0 }, /* 16 n Source: AI film 75 */ { 0034, 0042, 0042, 0042, 0034, 0 }, /* 17 o Source: AI film 75 */ { 0376, 0210, 0210, 0210, 0160, CH_D },/* 20 p Source: Knight TV */ { 0160, 0210, 0210, 0210, 0376, CH_D },/* 21 q Source: Knight TV */ { 0076, 0020, 0040, 0040, 0020, 0 }, /* 22 r Source: AI film 75 */ { 0022, 0052, 0052, 0052, 0044, 0 }, /* 23 s */ { 0040, 0374, 0042, 0002, 0004, 0 }, /* 24 t Source: AI film 75 */ { 0074, 0002, 0002, 0004, 0076, 0 }, /* 25 u Source: AI film 75 */ { 0070, 0004, 0002, 0004, 0070, 0 }, /* 26 v Source: Knight TV */ { 0074, 0002, 0034, 0002, 0074, 0 }, /* 27 w Source: AI film 75 */ { 0042, 0024, 0010, 0024, 0042, 0 }, /* 30 x */ { 0360, 0012, 0012, 0012, 0374, CH_D },/* 31 y Source: AI film 75 */ { 0042, 0056, 0052, 0072, 0042, 0 }, /* 32 z Source: Knight TV */ { 0000, 0000, 0000, 0000, 0000, CH_LF }, /* 33 LF */ { 0000, 0000, 0000, 0000, 0000, CH_CR }, /* 34 CR */ { 0000, 0000, 0000, 0000, 0000, CH_UC }, /* 35 HORIZ */ { 0000, 0000, 0000, 0000, 0000, CH_LC }, /* 36 VERT */ { 0000, 0000, 0000, 0000, 0000, CH_ESC }, /* 37 ESC */ { 0000, 0000, 0000, 0000, 0000, 0 }, /* 40 space */ { 0376, 0376, 0376, 0376, 0376, 0 }, /* 41 ??? */ { 0376, 0376, 0376, 0376, 0376, 0 }, /* 42 ??? */ { 0100, 0200, 0100, 0040, 0100, 0 }, /* 43 ~ */ { 0376, 0376, 0376, 0376, 0376, 0 }, /* 44 ??? */ { 0376, 0376, 0376, 0376, 0376, 0 }, /* 45 ??? */ { 0040, 0100, 0376, 0100, 0040, 0 }, /* 46 up arrow */ { 0020, 0020, 0124, 0070, 0020, 0 }, /* 47 left arrow */ { 0010, 0004, 0376, 0004, 0010, 0 }, /* 50 down arrow */ { 0020, 0070, 0124, 0020, 0020, 0 }, /* 51 right arrow */ { 0100, 0040, 0020, 0010, 0004, 0 }, /* 52 \ */ { 0000, 0376, 0202, 0202, 0000, 0 }, /* 53 [ */ { 0000, 0202, 0202, 0376, 0000, 0 }, /* 54 ] */ { 0000, 0020, 0154, 0202, 0000, 0 }, /* 55 { */ { 0000, 0202, 0154, 0020, 0000, 0 }, /* 56 } */ { 0376, 0376, 0376, 0376, 0376, 0 }, /* 57 ??? */ { 0002, 0002, 0002, 0002, 0002, 0 }, /* 60 _ */ { 0376, 0376, 0376, 0376, 0376, 0 }, /* 61 ??? */ { 0000, 0000, 0376, 0000, 0000, 0 }, /* 62 | */ { 0376, 0376, 0376, 0376, 0376, 0 }, /* 63 ??? */ { 0376, 0376, 0376, 0376, 0376, 0 }, /* 64 ??? */ { 0376, 0376, 0376, 0376, 0376, 0 }, /* 65 ??? */ { 0000, 0200, 0100, 0040, 0000, CH_NSPC }, /* 66 ` */ { 0040, 0100, 0200, 0100, 0040, CH_NSPC }, /* 67 ^ */ { 0376, 0376, 0376, 0376, 0376, 0 }, /* 70 ??? */ { 0376, 0376, 0376, 0376, 0376, 0 }, /* 71 block? */ { 0000, 0000, 0000, 0000, 0000, CH_BS }, /* 72 backspace */ { 0376, 0376, 0376, 0376, 0376, CH_SUB }, /* 73 subscript */ { 0376, 0376, 0376, 0376, 0376, 0 }, /* 74 ??? */ { 0376, 0376, 0376, 0376, 0376, 0 }, /* 75 ??? */ { 0376, 0376, 0376, 0376, 0376, 0 }, /* 76 ??? */ { 0376, 0376, 0376, 0376, 0376, CH_SUP } /* 77 superscript */ }; void ty342_set_grid(int w, int h) { struct type340 *u = UNIT(0); u->width = w; u->height = h; } /* * type 342 Character/Symbol generator for type 340 display * return true if ESCaped */ int character(int n, unsigned char c) { struct type340 *u = UNIT(0); int x, y; unsigned char s = u->scale; unsigned char flags; c |= u->shift; flags = chars[c][5]; if (flags == CH_LF) { /* LF */ u->ypos -= u->height*s; if (u->ypos < 0) { u->status |= ST340_HEDGE; u->ypos = 0; } return 0; } if (flags == CH_CR) { /* CR */ u->xpos = 0; return 0; } if (flags == CH_UC) { /* "SHIFT IN (HORIZ)" */ u->shift = 0; /* upper case in SPCWAR 163 */ return 0; } if (flags == CH_LC) { /* "SHIFT OUT (VERT)" */ u->shift = 0100; /* lower case in SPCWAR 163 */ return 0; } if (flags == CH_ESC) { /* escape */ return 1; } if ((flags == CH_NSPC) && u->xpos >= u->width*s) { u->xpos -= u->width*s; /* non spacing character */ } if (flags == CH_D) { /* descender */ u->ypos -= 2*s; } if (flags == CH_SUB) { /* subscript */ u->ypos -= u->width*s/2; return 0; } if (flags == CH_SUP) { /* superscript */ u->ypos += u->width*s/2; return 0; } /* plot character from character set selected by "shift" */ for (x = 0; x < 5; x++) { /* column: 0 to 4, left to right */ for (y = 0; y < 7; y++) { /* row: 0 to 6, bottom to top */ if (chars[c][x] & (2<xpos+x*s, u->ypos+y*s, n); } } } if (flags == CH_BS) { /* backspace */ u->xpos -= u->width*s; } else { u->xpos += u->width*s; } if (flags == CH_D) { /* undo descender */ u->ypos += 2*s; } if (u->xpos > 1023) { u->xpos = 1023; u->status |= ST340_VEDGE; } return 0; } #endif /* * execute one type340 instruction * returns status word * (could return number of microseconds) */ ty340word ty340_instruction(ty340word inst) { struct type340 *u = UNIT(0); int i, escape; #ifdef TYPE347 ty340word addr; #endif /* cleared by RFD */ u->status &= ~(ST340_HEDGE|ST340_VEDGE); DEBUGF(("type340 mode %#o status %#o\r\n", u->mode, u->status)); if (u->status & ST340_STOPPED) /* XXX LPINT as well??? */ return u->status; escape = 0; switch (u->mode) { case PARAM: if (inst & 0600600) { /* curious to see if MIT hacked theirs */ DEBUGF(("type340 reserved param bits set %#o\r\n", inst)); } /* READ TO MODE: */ u->mode = (enum mode)GETFIELD(inst, 2, 4); if (TESTBIT(inst, 5)) { /* load l.p. enable */ u->lp_ena = TESTBIT(inst,6); DEBUGF(("type340 lp_ena %d\r\n", u->lp_ena)); } /* PM PULSE: */ if (TESTBIT(inst, 14)) { /* STORE INTENSITY: */ u->intensity = GETFIELD(inst, 15, 17); DEBUGF(("type340 set intensity %d\r\n", u->intensity)); } if (TESTBIT(inst, 11)) { /* STORE SCALE: */ u->scale = 1<scale)); } if (TESTBIT(inst, 7)) { u->status |= ST340_STOPPED; DEBUGF(("type340 stop\r\n")); if (TESTBIT(inst, 8)) { DEBUGF(("type340 stop int\r\n")); u->status |= ST340_STOP_INT; } } break; case POINT: u->mode = (enum mode)GETFIELD(inst, 2, 4); if (TESTBIT(inst, 5)) { /* load l.p. enable */ u->lp_ena = TESTBIT(inst,6); DEBUGF(("type340 lp_ena %d\r\n", u->lp_ena)); } if (TESTBIT(inst, 1)) { u->ypos = GETFIELD(inst, 8, 17); DEBUGF(("type340 set u->ypos %d\r\n", u->ypos)); } else { u->xpos = GETFIELD(inst, 8, 17); DEBUGF(("type340 set xpos %d\r\n", u->xpos)); } if (TESTBIT(inst, 7)) { /* intensify */ DEBUGF(("type340 point (%d,%d)\r\n", u->ypos, u->xpos)); point(u->xpos, u->ypos, 0); } break; case SLAVE: DEBUGF(("type340 slave %06o\r\n", inst)); u->mode = (enum mode)GETFIELD(inst, 2, 4); #if TYPE343 /* control multiple windows???? */ #else /* ..set the mode register and halt without requesting a new data word */ u->status |= ST340_STOPPED; #endif break; case CHAR: DEBUGF(("type340 char %06o\r\n", inst)); #if TYPE342 escape = (character(0, GETFIELD(inst, 0, 5)) || character(1, GETFIELD(inst, 6, 11)) || character(2, GETFIELD(inst, 12, 17))); #else /* what other missing options do: */ u->status |= ST340_STOPPED; #endif break; case VECTOR: DEBUGF(("type340 vector %06o\r\n", inst)); 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? */ escape = 1; } break; case VCONT: DEBUGF(("type340 vcont %06o\r\n", inst)); while (!vector(TESTBIT(inst, 1), TESTBIT(inst, 2), GETFIELD(inst, 3, 9), TESTBIT(inst, 10), GETFIELD(inst, 11, 17))) ; escape = 1; /* XXX always???? */ /* NOTE: NO INTERRUPT!! Clear conditions???? */ break; case INCR: DEBUGF(("type340 incr %06o\r\n", inst)); i = TESTBIT(inst, 1); /* intensify bit */ 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))) escape = 1; else if (TESTBIT(inst, 0)) /* escape bit */ escape = 1; break; case SUBR: DEBUGF(("type340 subr %06o\r\n", inst)); #if TYPE347 /* type 347 Display Subroutine Option? */ u->mode = (enum mode)GETFIELD(inst, 2, 4); addr = GETFIELD(inst, 5, 17); switch (GETFIELD(inst, 0, 1)) { case DJS: /* display jump and save */ u->ASR = u->DAC; u->SAVE_FF = 1; /* set "save" flip-flop */ /* FALL */ case DJP: /* display jump */ u->DAC = addr; break; case DDS: /* display deposit save register */ ty340_store(addr, (DJP<<16) | u->ASR); /* clear SAVE_FF? */ break; default: /* XXX ??? */ break; } #else /* no 347 */ /* "halts without generating request for data or interrupt" */ u->status |= ST340_STOPPED; #endif break; } if (escape) { u->mode = PARAM; #if TYPE347 if (u->SAVE_FF) { /* return from subroutine */ u->DAC = u->ASR; u->SAVE_FF = 0; } #endif } if (!(u->status & ST340_STOPPED)) /* XXX LPINT as well??? */ ty340_rfd(); /* ready for data */ return u->status; } /* ty340_instruction */ ty340word ty340_status(void) { struct type340 *u = UNIT(0); return u->status; }