669 lines
29 KiB
C
669 lines
29 KiB
C
/* ka10_iii.c: Triple III display processor.
|
|
|
|
Copyright (c) 2019-2020, Richard Cornwell
|
|
|
|
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
|
|
RICHARD CORNWELL 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 Richard Cornwell shall not be
|
|
used in advertising or otherwise to promote the sale, use or other dealings
|
|
in this Software without prior written authorization from Richard Cornwell
|
|
|
|
*/
|
|
|
|
#include "kx10_defs.h"
|
|
#ifndef NUM_DEVS_III
|
|
#define NUM_DEVS_III 0
|
|
#endif
|
|
|
|
#if NUM_DEVS_III > 0
|
|
#include "display/display.h"
|
|
#include "display/iii.h"
|
|
|
|
#define III_DEVNUM 0430
|
|
|
|
#define STATUS u3
|
|
#define MAR u4
|
|
#define PIA u5
|
|
#define POS u6
|
|
|
|
/* CONO Bits */
|
|
#define SET_PIA 000000010 /* Set if this bit is zero */
|
|
#define STOP 000000020 /* Stop processor after instruction */
|
|
#define CONT 000000040 /* Start execution at address */
|
|
#define F 000000100 /* Clear flags */
|
|
#define SET_MSK 000360000 /* Set mask */
|
|
#define RST_MSK 007400000 /* Reset mask */
|
|
|
|
/* CONI Bits */
|
|
#define PIA_MSK 000000007
|
|
#define INST_HLT 000000010 /* 32 - Halt instruction */
|
|
#define WRAP_ENB 000000020 /* 31 - Wrap around mask */
|
|
#define EDGE_ENB 000000040 /* 30 - Edge interrupt mask */
|
|
#define LIGH_ENB 000000100 /* 29 - Light pen enable mask */
|
|
#define CLK_STOP 000000200 /* 28 - Clock stop */
|
|
/* 27 - Not used */
|
|
#define CLK_BIT 000001000 /* 26 - Clock */
|
|
#define NXM_BIT 000002000 /* 25 - Non-existent memory */
|
|
#define IRQ_BIT 000004000 /* 24 - Interrupt pending */
|
|
#define DATAO_LK 000010000 /* 23 - PDP10 gave DATAO when running */
|
|
#define CONT_BIT 000020000 /* 22 - Control bit */
|
|
#define LIGHT_FLG 000040000 /* 21 - Light pen flag */
|
|
#define WRAP_FLG 000100000 /* 20 - Wrap around flag */
|
|
#define EDGE_FLG 000200000 /* 19 - Edge overflow */
|
|
#define HLT_FLG 000400000 /* 18 - Not running */
|
|
|
|
#define WRAP_MSK 00001
|
|
#define EDGE_MSK 00002
|
|
#define LIGH_MSK 00004
|
|
#define HLT_MSK 00010
|
|
#define WRP_FBIT 00020
|
|
#define EDG_FBIT 00040
|
|
#define LIT_FBIT 00100
|
|
#define CTL_FBIT 00200
|
|
#define HLT_FBIT 00400
|
|
#define NXM_FLG 01000
|
|
#define DATA_FLG 02000
|
|
#define RUN_FLG 04000
|
|
|
|
#define TSS_INST 012 /* Test */
|
|
#define LVW_INST 006 /* Long Vector */
|
|
#define SVW_INST 002 /* Short vector */
|
|
#define JMP_INST 000 /* Jump or Halt */
|
|
#define JSR_INST 004 /* JSR(1) or JMS(0), SAVE(3) */
|
|
#define RES_INST 014 /* Restore */
|
|
#define SEL_INST 010 /* Select instruction */
|
|
|
|
#define POS_X 01777400000
|
|
#define POS_Y 00000377700
|
|
#define CBRT 00000000070 /* Current brightness */
|
|
#define CSIZE 00000000007 /* Current char size */
|
|
#define POS_X_V 17
|
|
#define POS_Y_V 6
|
|
#define CBRT_V 3
|
|
#define CSIZE_V 0
|
|
|
|
/*
|
|
* Character map.
|
|
* M(x,y) moves pointer to x,y.
|
|
* V(x,y) draws a vector between current pointer and x,y.
|
|
* All characters start at 0,6 and end at 8,6.
|
|
* In the map there are up to 18 points per character. For a character a M(0,0) indicates
|
|
* that drawing is done and a move to 8,6 should be done.
|
|
*/
|
|
#define M(x,y) (x << 4)|y|0000
|
|
#define V(x,y) (x << 4)|y|0200
|
|
|
|
uint8 map[128][18] = {
|
|
/* Blank */ { 0 },
|
|
/* Down */ { M(0,9), V(3,6), V(3,14), M(3,6), V(6,9) },
|
|
/* Alpha */ { M(6,6), V(3,9), V(1,9), V(0,8), V(0,7), V(1,6), V(3,6), V(6,9) },
|
|
/* Beta */ { V(2,8), V(2,13), V(3,14), V(5,14), V(6,13), V(6,12), V(5,11),
|
|
V(2,11), M(5,11), V(6,10), V(6,9), V(5,8), V(3,8), V(2,9) },
|
|
/* ^ */ { M(0,8), V(3,11), V(6,8) },
|
|
/* Not */ { M(0,10), V(6,10), V(6,7) },
|
|
/* Epsilon */ { M(3,9), V(2,10), V(1,10), V(0,9), V(0,7), V(1,6), V(2,6), V(3,7),
|
|
M(2,8), V(0,8) },
|
|
/* Pi */ { M(0,10), V(6,10), M(4,10), V(4,6), M(2,6), V(2,10) },
|
|
/* Lambda */ { V(3,9), M(0,11), V(1,11), V(6,6) },
|
|
/* ?? */ { M(0,11), V(1,12), V(2,12), V(5,9), V(5,7), V(4,6), V(3,6), V(2,7),
|
|
V(2,8), V(6,12) },
|
|
/* Delta */ { M(2,10), V(1,10), V(0,9), V(0,7), V(1,6), V(3,6), V(4,7), V(4,9),
|
|
V(3,10), V(2,10), V(2,12), V(4,12) },
|
|
/* Integ */ { M(0,7), V(1,6), V(2,6), V(3,7), V(3,12), V(4,13), V(5,13), V(6,12) },
|
|
/* PlusMinus */{ M(0,9), V(4,9), M(2,11), V(2,7), M(0,7), V(4,7) },
|
|
/* Circross */ { M(0,8), V(0,7), V(1,6), V(3,6), V(4,7), V(4,9), V(3,10), V(1,10),
|
|
V(0,9), V(0,8), V(4,8), M(2,10), V(2,6) },
|
|
/* Sigma */ { M(0,10), V(1,9), V(2,9), V(4,11), V(5,11), V(6,10), V(5,9), V(4,9),
|
|
V(2,11), V(1,11), V(0,10) },
|
|
/* Union */ { M(4,8), V(3,9), V(1,9), V(0,8), V(0,7), V(1,6), V(3,6), V(4,7),
|
|
V(4,10), V(2,12), V(1,12) },
|
|
/* Intersect */{ M(3,11), V(1,11), V(0,10), V(0,8), V(1,7), V(3,7) },
|
|
/* Cap */ { M(0,11), V(2,11), V(3,10), V(3,8), V(2,7), V(0,7) },
|
|
/* Cup */ { M(0,7), V(0,9), V(1,10), V(3,10), V(4,9), V(4,7) },
|
|
/* A */ { M(0,10), V(0,8), V(1,7), V(3,7), V(4,8), V(4,10) },
|
|
/* E */ { M(0,13), V(0,8), V(2,6), V(4,6), V(6,8), V(6,13), M(0,10), V(6,10) },
|
|
/* cx */ { V(6,6), V(6,14), V(0,14), M(2,10), V(6,10) },
|
|
{ V(4,10), M(0,10), V(4,6), M(3,6), V(1,6), V(0,7), V(0,9), V(1,10),
|
|
V(3,10), V(4,9), V(4,7), V(3,6) },
|
|
/* Dbl arrow */{ M(2,8), V(0,10), V(2,12), M(0,10), V(6,10), M(4,12), V(6,10),
|
|
V(4,8)},
|
|
/* Under */ { M(0,5), V(6,5) },
|
|
{ M(0,10), V(6,10), M(3,13), V(6,10), V(3,7) },
|
|
{ M(0,12), V(2,14), V(4,12), V(6,14) },
|
|
{ V(6,12), M(0,10), V(6,10), M(0,8), V(6,8) },
|
|
{ V(3,6), M(3,7), V(0,10), V(3,13) },
|
|
{ V(3,6), M(0,7), V(3,10), V(0,13) },
|
|
{ M(0,7), V(6,7), M(6,9), V(0,9), M(0,11), V(6,11) },
|
|
{ M(0,11), V(3,8), V(6,11) },
|
|
/* Blank */ { 0, },
|
|
/* ! */ { M(2,6), V(2,7), M(2,8), V(2,13) },
|
|
/* " */ { M(2,12), V(2,14), M(4,14), V(4,12) },
|
|
/* # */ { M(2,7), V(2,13), M(4,13), V(4,7), M(6,9), V(0,9), M(0,11), V(6,11) },
|
|
/* $ */ { M(0,8), V(2,6), V(4,6), V(6,8), V(4,10), V(2,10), V(0,12), V(2,14),
|
|
V(4,14), V(6,12), M(4,14), V(4,6), M(2,6), V(2,14) },
|
|
/* % */ { V(6,12), V(1,12), V(0,11), V(0,10), V(1,9), V(2,9), V(3,10), V(3,11),
|
|
V(2,12), M(4,9), V(3,8), V(3,7), V(4,6), V(5,6), V(6,7), V(6,8),
|
|
V(5,9), V(4,9) },
|
|
/* & */ { M(6,6), V(1,11), V(1,13), V(2,14), V(3,14), V(4,13), V(0,9), V(0,7),
|
|
V(1,6), V(3,6), V(5,8) },
|
|
/* ' */ { M(2,12), V(4,14) },
|
|
/* ( */ { M(2,6), V(0,8), V(0,12), V(2,14) },
|
|
/* ) */ { V(2,8), V(2,12), V(0,14) },
|
|
/* * */ { M(1,8), V(5,12), M(3,13), V(3,7), M(5,8), V(1,12), M(0,10),
|
|
V(6,10) },
|
|
/* + */ { M(2,7), V(2,11), M(0,9), V(4,9) },
|
|
/* , */ { M(0,7), V(1,6), V(1,5), V(0,4) },
|
|
/* - */ { M(0,9), V(4,9) },
|
|
/* . */ { M(2,6), V(3,6), V(3,7), V(2,7), V(2,6) },
|
|
/* / */ { V(6,12) },
|
|
/* 0 */ { M(0,7), V(6,13), M(6,12), V(4,14), V(2,14), V(0,12), V(0,8), V(2,6),
|
|
V(4,6), V(6,8), V(6,12) },
|
|
/* 1 */ { M(1,12), V(3,14), V(3,6) },
|
|
/* 2 */ { M(0,13), V(1,14), V(4,14), V(6,12), V(6,11), V(5,10), V(2,10),
|
|
V(0,8), V(0,6), V(6,6) },
|
|
/* 3 */ { M(0,14), V(6,14), V(6,12), V(4,10), V(5,10), V(6,9), V(6,7), V(5,6),
|
|
V(0,6) },
|
|
/* 4 */ { M(5,6), V(5,14), V(0,9), V(6,9) },
|
|
/* 5 */ { M(0,7), V(1,6), V(4,6), V(6,8), V(6,9), V(5,10), V(1,10), V(0,9),
|
|
V(0,14), V(6,14) },
|
|
/* 6 */ { M(0,9), V(1,10), V(5,10), V(6,9), V(6,7), V(5,6), V(1,6), V(0,7),
|
|
V(0,10), V(4,14) },
|
|
/* 7 */ { V(6,12), V(6,14), V(0,14) },
|
|
/* 8 */ { M(1,10), V(0,9), V(0,7), V(1,6), V(5,6), V(6,7), V(6,9), V(5,10),
|
|
V(6,11), V(6,13), V(5,14), V(1,14), V(0,13), V(0,11), V(1,10),
|
|
V(5,10) },
|
|
/* 9 */ { M(2,6), V(6,10), V(6,13), V(5,14), V(1,14), V(0,13), V(0,11),
|
|
V(1,10), V(5,10), V(6,11) },
|
|
/* : */ { M(2,6), V(3,6), V(3,7), V(2,7), V(2,6), M(2,10), V(3,10), V(3,11),
|
|
V(2,11), V(2,10) },
|
|
/* ; */ { M(2,7), V(3,6), V(3,5), V(2,4), M(2,10), V(3,10), V(3,11), V(2,11),
|
|
V(2,10) },
|
|
/* < */ { M(3,7), V(0,10), V(3,13) },
|
|
/* = */ { M(0,8), V(6,8), M(6,10), V(0,10) },
|
|
/* > */ { M(0,7), V(3,10), V(0,13) },
|
|
/* ? */ { M(0,13), V(1,14), V(2,13), V(2,12), V(1,11), V(1,8), M(1,7),
|
|
V(1,6) },
|
|
/* @ */ { M(1,6), V(0,7), V(0,11), V(1,12), V(5,12), V(6,11), V(6,8), V(5,7),
|
|
V(4,8), V(4,11), M(4,10), V(3,11), V(2,11), V(1,10), V(1,9), V(2,8),
|
|
V(3,8), V(4,9) },
|
|
/* A */ { V(0,12), V(2,14), V(4,14), V(6,12), V(6,9), V(0,9), V(6,9), V(6,6) },
|
|
/* B */ { V(0,14), V(5,14), V(6,13), V(6,11), V(5,10), V(0,10), V(5,10),
|
|
V(6,9), V(6,7), V(5,6), V(0,6) },
|
|
/* C */ { M(6,13), V(5,14), V(2,14), V(0,12), V(0,8), V(2,6), V(5,6), V(6,7) },
|
|
/* D */ { V(0,14), V(4,14), V(6,12), V(6,8), V(4,6), V(0,6) },
|
|
/* E */ { M(6,6), V(0,6), V(0,10), V(4,10), V(0,10), V(0,14), V(6,14) },
|
|
/* F */ { V(0,10), V(4,10), V(0,10), V(0,14), V(6,14) },
|
|
/* G */ { M(6,13), V(5,14), V(2,14), V(0,12), V(0,8), V(2,6), V(4,6), V(6,8),
|
|
V(6,10), V(4,10) },
|
|
/* H */ { V(0,14), V(0,10), V(6,10), V(6,14), V(6,6) },
|
|
/* I */ { M(1,6), V(5,6), V(3,6), V(3,14), V(1,14), V(5,14) },
|
|
/* J */ { M(1,9), V(1,7), V(2,6), V(3,6), V(4,7), V(4,14), V(2,14), V(6,14) },
|
|
/* K */ { V(0,14), V(0,8), V(6,14), V(2,10), V(6,6) },
|
|
/* L */ { M(0,14), V(0,6), V(6,6) },
|
|
/* M */ { V(0,14), V(3,11), V(6,14), V(6,6) },
|
|
/* N */ { V(0,14), V(0,13), V(6,7), V(6,6), V(6,14) },
|
|
/* O */ { M(0,8), V(0,12), V(2,14), V(4,14), V(6,12), V(6,8), V(4,6), V(2,6),
|
|
V(0,8) },
|
|
/* P */ { V(0,14), V(5,14), V(6,13), V(6,11), V(5,10), V(0,10) },
|
|
/* Q */ { M(0,8), V(0,12), V(2,14), V(4,14), V(6,12), V(6,8), V(4,6), V(2,6),
|
|
V(0,8), M(3,9), V(6,6) },
|
|
/* R */ { V(0,14), V(5,14), V(6,13), V(6,11), V(5,10), V(0,10), V(2,10),
|
|
V(6,6) },
|
|
/* S */ { M(0,8), V(2,6), V(4,6), V(6,8), V(4,10), V(2,10), V(0,12), V(2,14),
|
|
V(4,14), V(6,12) },
|
|
/* T */ { M(3,6), V(3,14), V(0,14), V(6,14) },
|
|
/* U */ { M(0,14), V(0,7), V(1,6), V(5,6), V(6,7), V(6,14) },
|
|
/* V */ { M(0,14), V(0,9), V(3,6), V(6,9), V(6,14) },
|
|
/* W */ { M(0,14), V(0,6), V(3,9), V(6,6), V(6,14) },
|
|
/* X */ { V(0,7), V(6,13), V(6,14), M(0,14), V(0,13), V(6,7), V(6,6) },
|
|
/* Y */ { M(0,14), V(3,11), V(6,14), V(3,11), V(3,6) },
|
|
/* Z */ { M(0,14), V(6,14), V(6,13), V(0,7), V(0,6), V(6,6) },
|
|
/* [ */ { M(3,5), V(0,5), V(0,15), V(3,15) },
|
|
/* \ */ { M(0,12), V(6,6) },
|
|
/* ] */ { M(0,5), V(3,5), V(3,15), V(0,15) },
|
|
/* up arrow */ { M(0,11), V(3,14), V(6,11), M(3,14), V(3,6) },
|
|
/* left arrow*/{ M(3,7), V(0,10), V(3,13), M(0,10), V(6,10) },
|
|
/* ` */ { M(2,14), V(4,12) },
|
|
/* a */ { M(0,9), V(1,10), V(3,10), V(4,9), V(4,6), M(4,8), V(3,9), V(1,9),
|
|
V(0,8), V(0,7), V(1,6), V(3,6), V(4,7) },
|
|
/* b */ { V(0,13), M(0,9), V(1,10), V(3,10), V(4,9), V(4,7), V(3,6), V(1,6),
|
|
V(0,7) },
|
|
/* c */ { M(4,9), V(3,10), V(1,10), V(0,9), V(0,7), V(1,6), V(3,6), V(4,7) },
|
|
/* d */ { M(0,7), V(0,9), V(1,10), V(3,10), V(4,9), V(4,7), V(3,6), V(1,6),
|
|
V(0,7), M(4,6), V(4,13) },
|
|
/* e */ { M(4,7), V(3,6), V(1,6), V(0,7), V(0,9), V(1,10), V(3,10), V(4,9),
|
|
V(4,8), V(0,8) },
|
|
/* f */ { M(2,6), V(2,12), V(3,13), V(4,13), V(5,12), M(0,11), V(4,11) },
|
|
/* g */ { M(4,9), V(3,10), V(1,10), V(0,9), V(0,7), V(1,6), V(3,6), V(4,7),
|
|
M(4,10), V(4,5), V(3,4), V(1,4), V(0,5) },
|
|
/* h */ { V(0,13), M(0,9), V(1,10), V(3,10), V(4,9), V(4,6) },
|
|
/* i */ { M(3,12), V(3,11), M(3,10), V(3,7), V(4,6), V(5,6) },
|
|
/* k */ { M(3,12), V(3,11), M(3,10), V(3,5), V(2,4), V(1,3) },
|
|
/* j */ { V(0,13), M(0,8), V(2,10), M(0,8), V(2,6) },
|
|
/* l */ { M(2,6), V(2,13) },
|
|
/* m */ { V(0,10), M(0,9), V(1,10), V(2,10), V(3,9), V(3,6), M(3,9), V(4,10),
|
|
V(5,10), V(6,9), V(6,6) },
|
|
/* n */ { V(0,10), M(0,9), V(1,10), V(2,10), V(3,9), V(3,6) },
|
|
/* o */ { M(0,7), V(0,9), V(1,10), V(3,10), V(4,9), V(4,7), V(3,6), V(1,6),
|
|
V(0,7) },
|
|
/* p */ { M(0,4), V(0,10), M(0,9), V(1,10), V(3,10), V(4,9), V(4,7), V(3,6),
|
|
V(1,6), V(0,7) },
|
|
/* q */ { M(4,9), V(3,10), V(1,10), V(0,9), V(0,7), V(1,6), V(3,6), V(4,7),
|
|
M(4,10), V(4,4) },
|
|
/* r */ { V(0,10), M(0,9), V(1,10), V(3,10), V(4,9) },
|
|
/* s */ { M(0,7), V(1,6), V(3,6), V(4,7), V(3,8), V(1,8), V(0,9), V(1,10),
|
|
V(3,10), V(4,9) },
|
|
/* t */ { M(2,13), V(2,7), V(3,6), V(4,6), V(5,7), M(1,11), V(3,11) },
|
|
/* u */ { M(0,10), V(0,7), V(1,6), V(3,6), V(4,7), V(4,10), V(4,6) },
|
|
/* v */ { M(0,9), V(3,6), V(6,9) },
|
|
/* w */ { M(0,10), V(0,6), V(2,8), V(4,6), V(4,10) },
|
|
/* x */ { V(4,10), M(0,10), V(4,6) },
|
|
/* y */ { M(0,9), V(3,6), M(6,9), V(1,4), V(0,4) },
|
|
/* z */ { M(0,10), V(4,10), V(0,6), V(4,6) },
|
|
/* { */ { M(3,15), V(2,14), V(2,12), V(0,10), V(2,8), V(2,6), V(3,5) },
|
|
/* | */ { M(2,4), V(2,14) },
|
|
/* diamon */ { M(3,6), V(0,9), V(3,12), V(6,9), V(3,6) },
|
|
/* } */ { M(0,15), V(1,14), V(1,12), V(3,10), V(1,8), V(1,6), V(0,5) },
|
|
/* \ */ { M(0,12), V(6,6) },
|
|
};
|
|
|
|
float scale[] = { 1.0F,
|
|
1.0F, /* 128 chars per line */
|
|
1.3F, /* 96 chars per line */
|
|
2.0F, /* 64 chars per line */
|
|
2.5F, /* 48 chars per line */
|
|
4.0F, /* 32 chars per line */
|
|
5.3F, /* 24 chars per line */
|
|
8.0F /* 16 chars per line */
|
|
};
|
|
|
|
|
|
uint64 iii_instr; /* Currently executing instruction */
|
|
int iii_sel; /* Select mask */
|
|
|
|
t_stat iii_devio(uint32 dev, uint64 *data);
|
|
t_stat iii_svc(UNIT *uptr);
|
|
t_stat iii_reset(DEVICE *dptr);
|
|
static void draw_point(int x, int y, int b, UNIT *uptr);
|
|
static void draw_line(int x1, int y1, int x2, int y2, int b, UNIT *uptr);
|
|
t_stat iii_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr);
|
|
const char *iii_description (DEVICE *dptr);
|
|
|
|
DIB iii_dib = { III_DEVNUM, 1, iii_devio, NULL};
|
|
|
|
UNIT iii_unit[] = {
|
|
{UDATA (&iii_svc, UNIT_IDLE, 0) },
|
|
{ 0 }
|
|
};
|
|
|
|
|
|
MTAB iii_mod[] = {
|
|
{ 0 }
|
|
};
|
|
|
|
DEVICE iii_dev = {
|
|
"III", iii_unit, NULL, iii_mod,
|
|
2, 10, 31, 1, 8, 8,
|
|
NULL, NULL, iii_reset,
|
|
NULL, NULL, NULL, &iii_dib, DEV_DEBUG | DEV_DISABLE | DEV_DIS | DEV_DISPLAY, 0, dev_debug,
|
|
NULL, NULL, &iii_help, NULL, NULL, &iii_description
|
|
};
|
|
|
|
t_stat iii_devio(uint32 dev, uint64 *data) {
|
|
UNIT *uptr = &iii_unit[0];
|
|
switch(dev & 3) {
|
|
case CONI:
|
|
*data = (((uint64)iii_sel) << 18) | (uint64)(uptr->PIA);
|
|
if ((iii_instr & 037) == 0)
|
|
*data |= INST_HLT;
|
|
*data |= (uptr->STATUS & 07) << 4;
|
|
if (uptr->STATUS & NXM_FLG)
|
|
*data |= NXM_BIT;
|
|
if (uptr->STATUS & DATA_FLG)
|
|
*data |= DATAO_LK;
|
|
if ((uptr->STATUS & RUN_FLG) == 0)
|
|
*data |= HLT_FLG;
|
|
if (uptr->STATUS & CTL_FBIT)
|
|
*data |= CONT_BIT;
|
|
if (uptr->STATUS & WRP_FBIT)
|
|
*data |= WRAP_FLG;
|
|
if (uptr->STATUS & EDG_FBIT)
|
|
*data |= EDGE_FLG;
|
|
if (uptr->STATUS & LIT_FBIT)
|
|
*data |= LIGHT_FLG;
|
|
sim_debug(DEBUG_CONI, &iii_dev, "III %03o CONI %06o %06o\n", dev, (uint32)*data,
|
|
PC);
|
|
break;
|
|
case CONO:
|
|
clr_interrupt(III_DEVNUM);
|
|
if (*data & SET_PIA)
|
|
uptr->PIA = (int)(*data&PIA_MSK);
|
|
if (*data & F)
|
|
uptr->STATUS &= ~(WRP_FBIT|EDG_FBIT|LIT_FBIT|DATA_FLG|NXM_FLG);
|
|
uptr->STATUS &= ~(017 & ((*data >> 14) ^ (*data >> 10)));
|
|
uptr->STATUS ^= (017 & (*data >> 10));
|
|
if (*data & STOP)
|
|
uptr->STATUS &= ~RUN_FLG;
|
|
if (*data & CONT) {
|
|
uptr->STATUS |= RUN_FLG;
|
|
iii_instr = M[uptr->MAR];
|
|
sim_activate(uptr, 10);
|
|
}
|
|
if (((uptr->STATUS >> 3) & (uptr->STATUS & (WRAP_MSK|EDGE_MSK|LIGH_MSK))) != 0)
|
|
set_interrupt(III_DEVNUM, uptr->PIA);
|
|
if (uptr->STATUS & HLT_MSK)
|
|
set_interrupt(III_DEVNUM, uptr->PIA);
|
|
sim_debug(DEBUG_CONO, &iii_dev, "III %03o CONO %06o %06o\n", dev,
|
|
(uint32)*data, PC);
|
|
break;
|
|
case DATAI:
|
|
sim_debug(DEBUG_DATAIO, &iii_dev, "III %03o DATAI %06o\n", dev, (uint32)*data);
|
|
break;
|
|
case DATAO:
|
|
if (uptr->STATUS & RUN_FLG)
|
|
uptr->STATUS |= DATA_FLG;
|
|
else {
|
|
iii_instr = *data;
|
|
sim_activate(uptr, 10);
|
|
}
|
|
sim_debug(DEBUG_DATAIO, &iii_dev, "III %03o DATAO %06o\n", dev, (uint32)*data);
|
|
break;
|
|
}
|
|
return SCPE_OK;
|
|
}
|
|
|
|
t_stat
|
|
iii_svc (UNIT *uptr)
|
|
{
|
|
uint64 temp;
|
|
int A;
|
|
int ox, oy, nx, ny, br, sz;
|
|
int i, j, ch;
|
|
float ch_sz;
|
|
|
|
iii_cycle(10, 0);
|
|
|
|
/* Extract X,Y,Bright and Size */
|
|
sz = (uptr->POS & CSIZE) >> CSIZE_V;
|
|
br = (uptr->POS & CBRT) >> CBRT_V;
|
|
ox = (uptr->POS & POS_X) >> POS_X_V;
|
|
oy = (uptr->POS & POS_Y) >> POS_Y_V;
|
|
nx = ox = (ox ^ 02000) - 02000;
|
|
ny = oy = (oy ^ 02000) - 02000;
|
|
ch_sz = scale[sz];
|
|
|
|
sim_debug(DEBUG_DETAIL, &iii_dev, "III: pos %d %d %d %d %o\n", ox, oy, br, sz,
|
|
uptr->STATUS );
|
|
switch(iii_instr & 017) {
|
|
case 000: /* JMP and HLT */
|
|
if (iii_instr & 020) {
|
|
uptr->MAR = (iii_instr >> 18) & RMASK;
|
|
} else {
|
|
uptr->STATUS &= ~RUN_FLG;
|
|
if (uptr->STATUS & HLT_MSK)
|
|
set_interrupt(III_DEVNUM, uptr->PIA);
|
|
return SCPE_OK;
|
|
}
|
|
goto skip_up;
|
|
case 001:
|
|
case 003:
|
|
case 005:
|
|
case 007:
|
|
case 011:
|
|
case 013:
|
|
case 015:
|
|
case 017: /* Draw 4 characters */
|
|
for (i = 29; i >= 1; i -= 7) {
|
|
/* Extract character and compute initial point */
|
|
int cx, cy;
|
|
int lx, ly;
|
|
ch = (iii_instr >> i) & 0177;
|
|
cx = 0;
|
|
cy = (int)(6.0 * ch_sz);
|
|
lx = ox;
|
|
ly = oy + cy;
|
|
sim_debug(DEBUG_DETAIL, &iii_dev, "III: ch %d %d %o '%c' %o %o\n",
|
|
lx, ly, ch, (ch < ' ')? '.' : ch, sz, br);
|
|
if (ch == '\t' || ch == 0)
|
|
continue;
|
|
if (ch == '\r') {
|
|
ox = -512;
|
|
continue;
|
|
}
|
|
if (ch == '\n') {
|
|
oy -= (int)(16.0 * ch_sz);
|
|
continue;
|
|
}
|
|
/* Scan map and draw lines as needed */
|
|
if ((iii_sel & 04000) != 0) {
|
|
for(j = 0; j < 18; j++) {
|
|
uint8 v = map[ch][j];
|
|
if (v == 0)
|
|
break;
|
|
cx = (int)((float)((v >> 4) & 07) * ch_sz);
|
|
cy = (int)((float)(v & 017) * ch_sz);
|
|
nx = ox + cx;
|
|
ny = oy + cy;
|
|
sim_debug(DEBUG_DATA, &iii_dev, "III: map %d %d %d %d %02x\n",
|
|
lx, ly, nx, ny, v);
|
|
if (v & 0200)
|
|
draw_line(lx, ly, nx, ny, br, uptr);
|
|
lx = nx;
|
|
ly = ny;
|
|
}
|
|
}
|
|
ox += (int)(8.0 * ch_sz);
|
|
}
|
|
nx = ox;
|
|
ny = oy;
|
|
break;
|
|
|
|
case 002: /* Short Vector */
|
|
if ((iii_sel & 04000) == 0)
|
|
break;
|
|
/* Do first point */
|
|
nx = (iii_instr >> 26) & 077;
|
|
ny = (iii_instr >> 20) & 077;
|
|
/* Sign extend */
|
|
nx = (nx ^ 040) - 040;
|
|
ny = (ny ^ 040) - 040;
|
|
/* Compute relative position. */
|
|
sim_debug(DEBUG_DETAIL, &iii_dev, "III: short %d %d %o %d\n",
|
|
nx, ny, sz, br);
|
|
nx += ox;
|
|
ny += oy;
|
|
if (nx < -512 || nx > 512 || ny < -512 || ny > 512)
|
|
uptr->STATUS |= EDG_FBIT;
|
|
i = (int)((iii_instr >> 18) & 3);
|
|
if ((i & 02) == 0 && (iii_sel & 04000) != 0) { /* Check if visible */
|
|
if ((i & 01) == 0) { /* Draw a line */
|
|
draw_line(ox, oy, nx, ny, br, uptr);
|
|
} else {
|
|
draw_point(nx, ny, br, uptr);
|
|
}
|
|
}
|
|
ox = nx;
|
|
oy = ny;
|
|
/* Do second point */
|
|
nx = (iii_instr >> 12) & 0177;
|
|
ny = (iii_instr >> 6) & 0177;
|
|
/* Sign extend */
|
|
nx = (nx ^ 040) - 040;
|
|
ny = (ny ^ 040) - 040;
|
|
sim_debug(DEBUG_DETAIL, &iii_dev, "III: short2 %d %d %o %d\n",
|
|
nx, ny, sz, br);
|
|
/* Compute relative position. */
|
|
nx += ox;
|
|
ny += oy;
|
|
if (nx < -512 || nx > 512 || ny < -512 || ny > 512)
|
|
uptr->STATUS |= EDG_FBIT;
|
|
/* Check if visible */
|
|
if ((iii_instr & 040) == 0 && (iii_sel & 04000) != 0) {
|
|
if ((iii_instr & 020) == 0) { /* Draw a line */
|
|
draw_line(ox, oy, nx, ny, br, uptr);
|
|
} else {
|
|
draw_point(nx, ny, br, uptr);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 004: /* JSR, JMS, SAVE */
|
|
temp = (((uint64)uptr->MAR) << 18) | 020 /* | CPC */;
|
|
A = (iii_instr >> 18) & RMASK;
|
|
if ((iii_instr & 030) != 030) {
|
|
M[A] = temp;
|
|
A++;
|
|
}
|
|
if ((iii_instr & 020) != 020) {
|
|
temp = uptr->STATUS & 0377;
|
|
temp |= ((uint64)uptr->POS) << 8;
|
|
M[A] = temp;
|
|
A++;
|
|
}
|
|
if ((iii_instr & 030) != 030) {
|
|
uptr->MAR = A;
|
|
}
|
|
goto skip_up;
|
|
|
|
case 006: /* Long Vector */
|
|
/* Update sizes if needed */
|
|
if (((iii_instr >> 8) & CSIZE) != 0)
|
|
sz = (iii_instr >> 8) & CSIZE;
|
|
if (((iii_instr >> 11) & 7) != 0)
|
|
br = (iii_instr > 11) & 7;
|
|
nx = (iii_instr >> 25) & 03777;
|
|
ny = (iii_instr >> 14) & 03777;
|
|
nx = (nx ^ 02000) - 02000;
|
|
ny = (ny ^ 02000) - 02000;
|
|
sim_debug(DEBUG_DETAIL, &iii_dev, "III: long %d %d %o %o\n",
|
|
nx, ny, sz, br);
|
|
if ((iii_instr & 0100) == 0) { /* Relative mode */
|
|
nx += ox;
|
|
ny += oy;
|
|
if (nx < -512 || nx > 512 || ny < -512 || ny > 512)
|
|
uptr->STATUS |= EDG_FBIT;
|
|
}
|
|
/* Check if visible */
|
|
if ((iii_instr & 040) == 0 && (iii_sel & 04000) != 0) {
|
|
if ((iii_instr & 020) == 0) /* Draw a line */
|
|
draw_line(ox, oy, nx, ny, br, uptr);
|
|
else
|
|
draw_point(nx, ny, br, uptr);
|
|
}
|
|
break;
|
|
|
|
case 010: /* Select instruction */
|
|
i = (iii_instr >> 24) & 07777; /* Set mask */
|
|
j = (iii_instr >> 12) & 07777; /* Reset mask */
|
|
ch = i & j; /* Compliment mask */
|
|
i &= ~ch;
|
|
j &= ~ch;
|
|
iii_sel = ((iii_sel | i) & ~j) ^ ch;
|
|
goto skip_up;
|
|
|
|
case 012: /* Test instruction */
|
|
A = (uptr->STATUS & (int32)(iii_instr >> 12) & 0377) != 0;
|
|
j = (int)((iii_instr >> 20) & 0377); /* set mask */
|
|
i = (int)((iii_instr >> 28) & 0377); /* Reset */
|
|
uptr->STATUS &= ~(i ^ j);
|
|
uptr->STATUS ^= j;
|
|
if (A ^ ((iii_instr & 020) != 0))
|
|
uptr->MAR++;
|
|
goto skip_up;
|
|
|
|
case 014: /* Restore */
|
|
A = (iii_instr >> 18) & RMASK;
|
|
temp = M[A];
|
|
if ((iii_instr & 020) != 0) {
|
|
uptr->STATUS &= ~0377;
|
|
uptr->STATUS |= temp & 0377;
|
|
}
|
|
if ((iii_instr & 040) != 0) {
|
|
uptr->POS = (temp >> 8) & (POS_X|POS_Y|CBRT|CSIZE);
|
|
}
|
|
goto skip_up;
|
|
|
|
case 016: /* Nop */
|
|
break;
|
|
}
|
|
/* Repack to new position. */
|
|
sim_debug(DEBUG_DATA, &iii_dev, "III: update %d %d %8o ", nx, ny, uptr->POS);
|
|
uptr->POS = (POS_X & ((nx & 03777) << POS_X_V)) |
|
|
(POS_Y & ((ny & 03777) << POS_Y_V)) |
|
|
(CBRT & (br << CBRT_V)) |
|
|
(CSIZE & (sz << CSIZE_V));
|
|
sim_debug(DEBUG_DATA, &iii_dev, "-> %8o\n", uptr->POS);
|
|
skip_up:
|
|
if (uptr->STATUS & RUN_FLG) {
|
|
iii_instr = M[uptr->MAR];
|
|
sim_debug(DEBUG_DETAIL, &iii_dev, "III: fetch %06o %012llo\n",
|
|
uptr->MAR, iii_instr);
|
|
uptr->MAR++;
|
|
uptr->MAR &= RMASK;
|
|
sim_activate(uptr, 50);
|
|
}
|
|
|
|
if (((uptr->STATUS >> 3) & (uptr->STATUS & (WRAP_MSK|EDGE_MSK|LIGH_MSK))) != 0)
|
|
set_interrupt(III_DEVNUM, uptr->PIA);
|
|
|
|
return SCPE_OK;
|
|
}
|
|
|
|
t_stat iii_reset (DEVICE *dptr)
|
|
{
|
|
if (dptr->flags & DEV_DIS) {
|
|
display_close(dptr);
|
|
} else {
|
|
display_reset();
|
|
dptr->units[0].POS = 0;
|
|
iii_init(dptr, 1);
|
|
}
|
|
return SCPE_OK;
|
|
}
|
|
|
|
/* Draw a point at x,y with intensity b. */
|
|
/* X and Y runs from -512 to 512. */
|
|
static void
|
|
draw_point(int x, int y, int b, UNIT *uptr)
|
|
{
|
|
if (x < -512 || x > 512 || y < -512 || y > 512)
|
|
uptr->STATUS |= WRP_FBIT;
|
|
iii_point(x, y, b);
|
|
}
|
|
|
|
/* Draw a line between two points */
|
|
static void
|
|
draw_line(int x1, int y1, int x2, int y2, int b, UNIT *uptr)
|
|
{
|
|
if (x1 < -512 || x1 > 512 || y1 < -512 || y1 > 512)
|
|
uptr->STATUS |= WRP_FBIT;
|
|
if (x2 < -512 || x2 > 512 || y2 < -512 || y2 > 512)
|
|
uptr->STATUS |= WRP_FBIT;
|
|
iii_draw_line(x1, y1, x2, y2, b);
|
|
}
|
|
|
|
t_stat iii_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr)
|
|
{
|
|
return SCPE_OK;
|
|
}
|
|
|
|
const char *iii_description (DEVICE *dptr)
|
|
{
|
|
return "Triple III Display";
|
|
}
|
|
#endif
|