211 lines
6.8 KiB
C
211 lines
6.8 KiB
C
/* pdp1_dpy.c: PDP-1 display simulator
|
||
|
||
Copyright (c) 2004, Philip L. Budne
|
||
Copyright (c) 1993-2003, Robert M. Supnik
|
||
|
||
Permission is hereby granted, free of charge, to any person obtaining a
|
||
copy of this software and associated documentation files (the "Software"),
|
||
to deal in the Software without restriction, including without limitation
|
||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||
and/or sell copies of the Software, and to permit persons to whom the
|
||
Software is furnished to do so, subject to the following conditions:
|
||
|
||
The above copyright notice and this permission notice shall be included in
|
||
all copies or substantial portions of the Software.
|
||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||
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.
|
||
|
||
dpy Type 30 Display for the PDP-1
|
||
02-Feb-04 PLB Revamp intensity levels
|
||
02-Jan-04 DAG Provide dummy global when display not supported
|
||
16-Sep-03 PLB Update for SIMH 3.0-2
|
||
12-Sep-03 PLB Add spacewar switch support
|
||
04-Sep-03 PLB Start from pdp1_lp.c
|
||
*/
|
||
|
||
#ifdef USE_DISPLAY
|
||
#include "pdp1_defs.h"
|
||
#include "display/display.h"
|
||
#include "sim_video.h"
|
||
|
||
extern int32 ios, cpls, iosta, PF;
|
||
extern int32 stop_inst;
|
||
|
||
t_stat dpy_svc (UNIT *uptr);
|
||
t_stat dpy_reset (DEVICE *dptr);
|
||
|
||
/* DPY data structures
|
||
|
||
dpy_dev DPY device descriptor
|
||
dpy_unit DPY unit
|
||
dpy_reg DPY register list
|
||
*/
|
||
|
||
#define CYCLE_TIME 5 /* 5us memory cycle */
|
||
#define DPY_WAIT (50/CYCLE_TIME) /* 50us */
|
||
|
||
UNIT dpy_unit = {
|
||
UDATA (&dpy_svc, UNIT_ATTABLE, 0), DPY_WAIT };
|
||
|
||
static t_bool dpy_stop_flag = FALSE;
|
||
|
||
static void dpy_quit_callback (void)
|
||
{
|
||
dpy_stop_flag = TRUE;
|
||
}
|
||
|
||
#define DEB_VMOU SIM_VID_DBG_MOUSE /* Video mouse */
|
||
#define DEB_VKEY SIM_VID_DBG_KEY /* Video key */
|
||
#define DEB_VCUR SIM_VID_DBG_CURSOR /* Video cursor */
|
||
#define DEB_VVID SIM_VID_DBG_VIDEO /* Video */
|
||
|
||
DEBTAB dpy_deb[] = {
|
||
{ "VMOU", DEB_VMOU, "Video Mouse" },
|
||
{ "VKEY", DEB_VKEY, "Video Key" },
|
||
{ "VCUR", DEB_VCUR, "Video Cursor" },
|
||
{ "VVID", DEB_VVID, "Video Video" },
|
||
{ NULL, 0 }
|
||
};
|
||
|
||
DEVICE dpy_dev = {
|
||
"DPY", &dpy_unit, NULL, NULL,
|
||
1, 10, 31, 1, 8, 8,
|
||
NULL, NULL, &dpy_reset,
|
||
NULL, NULL, NULL,
|
||
NULL, DEV_DIS | DEV_DISABLE | DEV_DEBUG,
|
||
0, dpy_deb};
|
||
|
||
/* Display IOT routine */
|
||
|
||
int32 dpy (int32 inst, int32 dev, int32 io, int32 ac)
|
||
{
|
||
int32 x, y;
|
||
int level;
|
||
|
||
if (dpy_dev.flags & DEV_DIS) /* disabled? */
|
||
return (stop_inst << IOT_V_REASON) | io; /* stop if requested */
|
||
if (GEN_CPLS (inst)) { /* comp pulse? */
|
||
ios = 0; /* clear flop */
|
||
cpls = cpls | CPLS_DPY; } /* request completion */
|
||
else cpls = cpls & ~CPLS_DPY;
|
||
|
||
x = (ac >> 8) & 01777; /* high ten bits of ac */
|
||
y = (io >> 8) & 01777; /* high ten bits of io */
|
||
/*
|
||
* convert one's complement -511..+511 center origin
|
||
* to 0..1022 (lower left origin)
|
||
*/
|
||
if (x & 01000)
|
||
x ^= 01000;
|
||
else
|
||
x += 511;
|
||
if (y & 01000)
|
||
y ^= 01000;
|
||
else
|
||
y += 511;
|
||
|
||
/* intensity, from values seen in spacewar (40,00,01,02,03) */
|
||
switch ((inst >> 6) & 077) {
|
||
case 01: level = DISPLAY_INT_MAX-5; break;
|
||
case 02: level = DISPLAY_INT_MAX-4; break;
|
||
case 03: level = DISPLAY_INT_MAX-2; break;
|
||
case 040: /* super bright? */
|
||
default: level = DISPLAY_INT_MAX; break;
|
||
}
|
||
|
||
if (display_point(x,y,level,0)) {
|
||
/* here with light pen hit */
|
||
PF = PF | 010; /* set prog flag 3 */
|
||
iosta |= IOS_TTI; /* set io status flag */
|
||
}
|
||
else
|
||
iosta &= ~IOS_TTI; /* clear io status flag */
|
||
sim_activate (&dpy_unit, dpy_unit.wait); /* activate */
|
||
|
||
return io;
|
||
}
|
||
|
||
/*
|
||
* Unit service routine
|
||
*
|
||
*/
|
||
t_stat dpy_svc (UNIT *uptr)
|
||
{
|
||
if (cpls & CPLS_DPY) { /* completion pulse? */
|
||
ios = 1; /* restart */
|
||
cpls = cpls & ~CPLS_DPY; } /* clr pulse pending */
|
||
|
||
display_age(dpy_unit.wait*CYCLE_TIME, 0);
|
||
sim_activate_after (&dpy_unit, dpy_unit.wait*CYCLE_TIME); /* requeue! */
|
||
if (dpy_stop_flag) {
|
||
dpy_stop_flag = FALSE; /* reset flag after we notice it */
|
||
return SCPE_STOP;
|
||
}
|
||
return SCPE_OK;
|
||
}
|
||
|
||
static void dpy_joy_motion (int device, int axis, int value)
|
||
{
|
||
if (device < 2 && axis < 1) {
|
||
int mask = 0;
|
||
int shift = 14 * device;
|
||
if (value < -10000)
|
||
mask = 010;
|
||
else if (value > 1000)
|
||
mask = 004;
|
||
spacewar_switches &= ~(014 << shift);
|
||
spacewar_switches |= mask << shift;
|
||
}
|
||
}
|
||
|
||
static void dpy_joy_button (int device, int button, int state)
|
||
{
|
||
if (device < 2 && button < 2) {
|
||
/* Button 0 is fire, 1 is thrust. */
|
||
int mask = 1 << button;
|
||
mask <<= 14 * device;
|
||
if (state)
|
||
spacewar_switches |= mask;
|
||
else
|
||
spacewar_switches &= ~mask;
|
||
}
|
||
}
|
||
|
||
/* Reset routine */
|
||
|
||
t_stat dpy_reset (DEVICE *dptr)
|
||
{
|
||
if (dptr->flags & DEV_DIS) {
|
||
display_close(dptr);
|
||
}
|
||
else {
|
||
display_init(DISPLAY_TYPE, PIX_SCALE, dptr);
|
||
display_reset();
|
||
vid_register_quit_callback (&dpy_quit_callback);
|
||
vid_register_gamepad_motion_callback (dpy_joy_motion);
|
||
vid_register_gamepad_button_callback (dpy_joy_button);
|
||
cpls = cpls & ~CPLS_DPY;
|
||
iosta = iosta & ~(IOS_PNT | IOS_SPC); /* clear flags */
|
||
}
|
||
sim_cancel (&dpy_unit); /* deactivate unit */
|
||
return SCPE_OK;
|
||
}
|
||
|
||
int32 spacewar (int32 inst, int32 dev, int32 io)
|
||
{
|
||
if (dpy_dev.flags & DEV_DIS) /* disabled? */
|
||
return (stop_inst << IOT_V_REASON) | io; /* stop if requested */
|
||
return spacewar_switches;
|
||
}
|
||
#else /* USE_DISPLAY not defined */
|
||
char pdp1_dpy_unused; /* sometimes empty object modules cause problems */
|
||
#endif /* USE_DISPLAY not defined */
|