576 lines
21 KiB
C
576 lines
21 KiB
C
/* vax4xx_vc.c: Monochrome video simulator
|
|
|
|
Copyright (c) 2019, Matt Burke
|
|
|
|
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 AUTHOR 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 author.
|
|
|
|
vc Monochrome video
|
|
*/
|
|
|
|
#include "vax_defs.h"
|
|
#include "sim_video.h"
|
|
#include "vax_lk.h"
|
|
#include "vax_vs.h"
|
|
|
|
#define VC_XSIZE 1024 /* visible width */
|
|
#define VC_YSIZE 864 /* visible height */
|
|
|
|
#define VC_BXSIZE 1024 /* buffer width */
|
|
#define VC_BUFMASK (VC_BUFSIZE - 1)
|
|
|
|
#define CUR_X_OF 216
|
|
#define CUR_Y_OF 33
|
|
|
|
#define CMD_TEST 0x8000
|
|
#define CMD_HSHI 0x4000
|
|
#define CMD_VBHI 0x2000
|
|
#define CMD_LODSA 0x1000
|
|
#define CMD_FORG2 0x0800
|
|
#define CMD_ENRG2 0x0400
|
|
#define CMD_FORG1 0x0200
|
|
#define CMD_ENRG1 0x0100
|
|
#define CMD_XHWID 0x0080
|
|
#define CMD_XHCL1 0x0040
|
|
#define CMD_XHCLP 0x0020
|
|
#define CMD_XHAIR 0x0010
|
|
#define CMD_FOPB 0x0008
|
|
#define CMD_ENPB 0x0004
|
|
#define CMD_FOPA 0x0002
|
|
#define CMD_ENPA 0x0001
|
|
|
|
#define CUR_X ((vc_xpos < CUR_X_OF) ? 0 : (vc_xpos - CUR_X_OF))
|
|
#define CUR_Y ((vc_ypos < CUR_Y_OF) ? 0 : (vc_ypos - CUR_Y_OF))
|
|
#define CUR_V ((vc_cmd & CMD_LODSA) == 0)
|
|
#define CUR_F (0)
|
|
|
|
#define CUR_PLNA 0
|
|
#define CUR_PLNB 16
|
|
|
|
/* Debugging Bitmaps */
|
|
|
|
#define DBG_REG 0x0001 /* registers */
|
|
#define DBG_CURSOR 0x0002 /* Cursor content, function and visibility activity */
|
|
#define DBG_TCURSOR 0x0800 /* Cursor content, function and visibility activity */
|
|
|
|
extern int32 tmxr_poll;
|
|
extern int32 ka_cfgtst;
|
|
|
|
uint32 vc_cmd = 0; /* cursor command reg */
|
|
uint32 vc_xpos = 0; /* cursor x position */
|
|
uint32 vc_ypos = 0; /* cursor y position */
|
|
uint32 vc_xmin1 = 0; /* region 1 left edge */
|
|
uint32 vc_xmax1 = 0; /* region 1 right edge */
|
|
uint32 vc_ymin1 = 0; /* region 1 top edge */
|
|
uint32 vc_ymax1 = 0; /* region 1 bottom edge */
|
|
uint32 vc_xmin2 = 0; /* region 2 left edge */
|
|
uint32 vc_xmax2 = 0; /* region 2 right edge */
|
|
uint32 vc_ymin2 = 0; /* region 2 top edge */
|
|
uint32 vc_ymax2 = 0; /* region 2 bottom edge */
|
|
uint16 vc_cur[32]; /* cursor image data */
|
|
uint32 vc_cur_p = 0; /* cursor image pointer */
|
|
t_bool vc_updated[VC_YSIZE];
|
|
t_bool vc_cur_new_data = FALSE; /* New Cursor image data */
|
|
t_bool vc_input_captured = FALSE; /* Mouse and Keyboard input captured in video window */
|
|
uint32 vc_cur_x = 0; /* Last cursor X-position */
|
|
uint32 vc_cur_y = 0; /* Last cursor Y-position */
|
|
uint32 vc_cur_f = 0; /* Last cursor function */
|
|
t_bool vc_cur_v = FALSE; /* Last cursor visible */
|
|
uint32 vc_org = 0; /* display origin */
|
|
uint32 vc_last_org = 0; /* display last origin */
|
|
uint32 vc_sel = 0; /* interrupt select */
|
|
uint32 *vc_buf = NULL; /* Video memory */
|
|
uint32 *vc_lines = NULL; /* Video Display Lines */
|
|
uint32 vc_palette[2]; /* Monochrome palette */
|
|
t_bool vc_active = FALSE;
|
|
|
|
t_stat vc_svc (UNIT *uptr);
|
|
t_stat vc_reset (DEVICE *dptr);
|
|
t_stat vc_detach (UNIT *dptr);
|
|
t_stat vc_set_enable (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
|
|
t_stat vc_set_capture (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
|
|
t_stat vc_show_capture (FILE* st, UNIT* uptr, int32 val, CONST void* desc);
|
|
t_stat vc_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr);
|
|
const char *vc_description (DEVICE *dptr);
|
|
|
|
/* VC data structures
|
|
|
|
vc_dev VC device descriptor
|
|
vc_unit VC unit descriptor
|
|
vc_reg VC register list
|
|
*/
|
|
|
|
UNIT vc_unit = {
|
|
UDATA ( &vc_svc, UNIT_IDLE, 0 )
|
|
};
|
|
|
|
REG vc_reg[] = {
|
|
{ HRDATAD (CMD, vc_cmd, 16, "Cursor command register") },
|
|
{ DRDATAD (XPOS, vc_xpos, 16, "Cursor X position") },
|
|
{ DRDATAD (YPOS, vc_ypos, 16, "Cursor Y position") },
|
|
{ DRDATAD (XMIN1, vc_xmin1, 16, "Region 1 left edge") },
|
|
{ DRDATAD (XMAX1, vc_xmax1, 16, "Region 1 right edge") },
|
|
{ DRDATAD (YMIN1, vc_ymin1, 16, "Region 1 top edge") },
|
|
{ DRDATAD (YMAX1, vc_ymax1, 16, "Region 1 bottom edge") },
|
|
{ DRDATAD (XMIN2, vc_xmin2, 16, "Region 2 left edge") },
|
|
{ DRDATAD (XMAX2, vc_xmax2, 16, "Region 2 right edge") },
|
|
{ DRDATAD (YMIN2, vc_ymin2, 16, "Region 2 top edge") },
|
|
{ DRDATAD (YMAX2, vc_ymax2, 16, "Region 2 bottom edge") },
|
|
{ DRDATAD (ORG, vc_org, 8, "Display origin") },
|
|
{ DRDATAD (ISEL, vc_sel, 1, "Interrupt select") },
|
|
{ HRDATA (CURP, vc_cur_p, 5), REG_HRO },
|
|
{ NULL }
|
|
};
|
|
|
|
DEBTAB vc_debug[] = {
|
|
{ "REG", DBG_REG, "Register activity" },
|
|
{ "CURSOR", DBG_CURSOR, "Cursor content, function and visibility activity" },
|
|
{ "TCURSOR", DBG_TCURSOR, "Cursor content, function and visibility activity" },
|
|
{ 0 }
|
|
};
|
|
|
|
MTAB vc_mod[] = {
|
|
{ MTAB_XTD|MTAB_VDV, 1, NULL, "ENABLE",
|
|
&vc_set_enable, NULL, NULL, "Enable Monochrome Video" },
|
|
{ MTAB_XTD|MTAB_VDV, 0, NULL, "DISABLE",
|
|
&vc_set_enable, NULL, NULL, "Disable Monochrome Video" },
|
|
{ MTAB_XTD|MTAB_VDV, TRUE, NULL, "CAPTURE",
|
|
&vc_set_capture, &vc_show_capture, NULL, "Enable Captured Input Mode" },
|
|
{ MTAB_XTD|MTAB_VDV, FALSE, NULL, "NOCAPTURE",
|
|
&vc_set_capture, NULL, NULL, "Disable Captured Input Mode" },
|
|
{ MTAB_XTD|MTAB_VDV, TRUE, "OSCURSOR", NULL,
|
|
NULL, &vc_show_capture, NULL, "Display Input Capture mode" },
|
|
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "VIDEO", NULL,
|
|
NULL, &vid_show_video, NULL, "Display the host system video capabilities" },
|
|
{ 0 }
|
|
};
|
|
|
|
DEVICE vc_dev = {
|
|
"VC", &vc_unit, vc_reg, vc_mod,
|
|
1, 10, 31, 1, DEV_RDX, 8,
|
|
NULL, NULL, &vc_reset,
|
|
NULL, NULL, &vc_detach,
|
|
NULL, DEV_DEBUG | DEV_DIS, 0,
|
|
vc_debug, NULL, NULL, &vc_help, NULL, NULL,
|
|
&vc_description
|
|
};
|
|
|
|
/* VC routines
|
|
|
|
vc_wr I/O page write
|
|
vc_svc process event
|
|
vc_reset process reset
|
|
*/
|
|
|
|
void vc_wr (int32 pa, int32 data, int32 access)
|
|
{
|
|
int32 rg = (pa >> 2) & 0x1F;
|
|
|
|
if (vc_dev.flags & DEV_DIS) /* disabled? */
|
|
return;
|
|
|
|
switch (rg) {
|
|
|
|
case 0: /* CUR_CMD */
|
|
if ((data & CMD_TEST) == 0) {
|
|
if (data & (CMD_ENRG2|CMD_FORG2|CMD_ENRG1|CMD_FORG1|CMD_FOPB|CMD_FOPA))
|
|
ka_cfgtst = ka_cfgtst & ~(1 << 4);
|
|
else ka_cfgtst = ka_cfgtst | (1 << 4);
|
|
}
|
|
else ka_cfgtst = ka_cfgtst | (1 << 4);
|
|
if ((vc_cmd ^ data) & CMD_LODSA) /* toggle sprite display? */
|
|
vc_cur_p = 0; /* reset array ptr */
|
|
vc_cmd = data;
|
|
break;
|
|
|
|
case 1: /* CUR_XPOS */
|
|
vc_xpos = data;
|
|
vid_set_cursor_position (CUR_X, CUR_Y);
|
|
break;
|
|
|
|
case 2: /* CUR_YPOS */
|
|
vc_ypos = data;
|
|
vid_set_cursor_position (CUR_X, CUR_Y);
|
|
break;
|
|
|
|
case 3: /* CUR_XMIN_1 */
|
|
vc_xmin1 = data;
|
|
break;
|
|
|
|
case 4: /* CUR_XMAX_1 */
|
|
vc_xmax1 = data;
|
|
break;
|
|
|
|
case 5: /* CUR_YMIN_1 */
|
|
vc_ymin1 = data;
|
|
break;
|
|
|
|
case 6: /* CUR_YMAX_1 */
|
|
vc_ymax1 = data;
|
|
break;
|
|
|
|
case 11: /* CUR_XMIN_2 */
|
|
vc_xmin2 = data;
|
|
break;
|
|
|
|
case 12: /* CUR_XMAX_2 */
|
|
vc_xmax2 = data;
|
|
break;
|
|
|
|
case 13: /* CUR_YMIN_2 */
|
|
vc_ymin2 = data;
|
|
break;
|
|
|
|
case 14: /* CUR_YMAX_2 */
|
|
vc_ymax2 = data;
|
|
break;
|
|
|
|
case 15: /* CUR_LOAD */
|
|
vc_cur[vc_cur_p++] = data;
|
|
if (vc_cur_p == 32)
|
|
vc_cur_p--;
|
|
vc_cur_new_data = TRUE;
|
|
break;
|
|
}
|
|
|
|
sim_debug (DBG_REG, &vc_dev, "reg %d write, value = %X\n", rg, data);
|
|
return;
|
|
}
|
|
|
|
int32 vc_mem_rd (int32 pa)
|
|
{
|
|
int32 rg = ((pa - 0x30000000) >> 2);
|
|
|
|
if (!vc_buf) /* MONO disabled? */
|
|
return 0; /* Invalid memory reference */
|
|
|
|
return vc_buf[rg];
|
|
}
|
|
|
|
void vc_mem_wr (int32 pa, int32 val, int32 lnt)
|
|
{
|
|
int32 nval;
|
|
int32 rg = ((pa - 0x30000000) >> 2);
|
|
uint32 scrln;
|
|
|
|
if (!vc_buf) /* MONO disabled? */
|
|
return; /* Invalid memory reference */
|
|
|
|
if (lnt < L_LONG) { /* byte or word? */
|
|
int32 sc = (pa & 3) << 3; /* merge */
|
|
int32 mask = (lnt == L_WORD)? 0xFFFF: 0xFF;
|
|
int32 t = vc_buf[rg];
|
|
nval = ((val & mask) << sc) | (t & ~(mask << sc));
|
|
}
|
|
else nval = val;
|
|
vc_buf[rg] = nval; /* update buffer */
|
|
scrln = ((rg >> 5) + VC_BYSIZE - (vc_org << VC_ORSC)) & (VC_BYSIZE - 1);
|
|
if (scrln < VC_YSIZE)
|
|
vc_updated[scrln] = TRUE; /* flag as updated */
|
|
return;
|
|
}
|
|
|
|
static void vc_set_vid_cursor (t_bool visible)
|
|
{
|
|
uint8 data[2*16];
|
|
uint8 mask[2*16];
|
|
uint32 ln, col;
|
|
uint16 *plna, *plnb;
|
|
uint16 bita, bitb;
|
|
int i, d, m;
|
|
|
|
sim_debug (DBG_CURSOR, &vc_dev, "vc_set_vid_cursor(%s)\n", visible ? "Visible" : "Invisible");
|
|
memset (data, 0, sizeof(data));
|
|
memset (mask, 0, sizeof(mask));
|
|
for (ln = 0; ln < 16; ln++) {
|
|
plna = &vc_cur[(CUR_PLNA + ln)]; /* get plane A base */
|
|
plnb = &vc_cur[(CUR_PLNB + ln)]; /* get plane B base */
|
|
for (col = 0; col < 16; col++) {
|
|
if (vc_cmd & CMD_FOPA) /* force plane A to 1? */
|
|
bita = 1;
|
|
else if (vc_cmd & CMD_ENPA) /* plane A enabled? */
|
|
bita = (*plna >> col) & 1;
|
|
else bita = 0;
|
|
if (vc_cmd & CMD_FOPB) /* force plane B to 1? */
|
|
bitb = 1;
|
|
else if (vc_cmd & CMD_ENPB) /* plane B enabled? */
|
|
bitb = (*plnb >> col) & 1;
|
|
else bitb = 0;
|
|
|
|
if (bita) {
|
|
if (bitb) {
|
|
d = 0; m = 1; /* white */
|
|
}
|
|
else {
|
|
d = 1; m = 0; /* inverted */
|
|
}
|
|
}
|
|
else {
|
|
if (bitb) {
|
|
d = 1; m = 1; /* black */
|
|
}
|
|
else {
|
|
d = 0; m = 0; /* transparent */
|
|
}
|
|
}
|
|
i = (ln * 16) + col;
|
|
data[i>>3] |= d<<(7-(i&7));
|
|
mask[i>>3] |= m<<(7-(i&7));
|
|
}
|
|
}
|
|
if ((vc_dev.dctrl & DBG_CURSOR) && (vc_dev.dctrl & DBG_TCURSOR)) {
|
|
/* box the cursor image */
|
|
for (i=0; i<16*16; i++) {
|
|
if ((0 == i>>4) || (0xF == i>>4) || (0 == (i&0xF)) || (0xF == (i&0xF))) {
|
|
data[i>>3] |= 1<<(7-(i&7));
|
|
mask[i>>3] |= 1<<(7-(i&7));
|
|
}
|
|
if ((1 == i>>4) || (0xE == i>>4) || (1 == (i&0xF)) || (0xE == (i&0xF))) {
|
|
data[i>>3] &= ~(1<<(7-(i&7)));
|
|
mask[i>>3] |= 1<<(7-(i&7));
|
|
}
|
|
}
|
|
}
|
|
vid_set_cursor (visible, 16, 16, data, mask, 0, 0);
|
|
}
|
|
|
|
static SIM_INLINE void vc_invalidate (uint32 y1, uint32 y2)
|
|
{
|
|
uint32 ln;
|
|
|
|
for (ln = y1; ln < y2; ln++)
|
|
vc_updated[ln] = TRUE; /* flag as updated */
|
|
}
|
|
|
|
t_stat vc_svc (UNIT *uptr)
|
|
{
|
|
SIM_MOUSE_EVENT mev;
|
|
SIM_KEY_EVENT kev;
|
|
t_bool updated = FALSE; /* flag for refresh */
|
|
uint32 lines;
|
|
uint32 ln, col, off;
|
|
uint16 *plna, *plnb;
|
|
uint16 bita, bitb;
|
|
uint32 c;
|
|
|
|
if (vc_cur_v != CUR_V) { /* visibility changed? */
|
|
if (CUR_V) /* visible? */
|
|
vc_invalidate (CUR_Y, (CUR_Y + 16)); /* invalidate new pos */
|
|
else
|
|
vc_invalidate (vc_cur_y, (vc_cur_y + 16)); /* invalidate old pos */
|
|
}
|
|
else if (vc_cur_y != CUR_Y) { /* moved (Y)? */
|
|
vc_invalidate (CUR_Y, (CUR_Y + 16)); /* invalidate new pos */
|
|
vc_invalidate (vc_cur_y, (vc_cur_y + 16)); /* invalidate old pos */
|
|
}
|
|
else if ((vc_cur_x != CUR_X) || /* moved (X)? */
|
|
(vc_cur_new_data)) { /* cursor image changed? */
|
|
vc_invalidate (CUR_Y, (CUR_Y + 16)); /* invalidate new pos */
|
|
}
|
|
|
|
if ((!vc_input_captured) && /* OS cursor? AND */
|
|
((vc_cur_new_data) || /* cursor image changed? OR */
|
|
(vc_cur_v != CUR_V))) { /* visibility changed? */
|
|
vc_set_vid_cursor (CUR_V);
|
|
}
|
|
|
|
vc_cur_x = CUR_X; /* store cursor data */
|
|
vc_cur_y = CUR_Y;
|
|
vid_set_cursor_position (vc_cur_x, vc_cur_y);
|
|
vc_cur_v = CUR_V;
|
|
vc_cur_f = CUR_F;
|
|
vc_cur_new_data = FALSE;
|
|
|
|
if (vid_poll_kb (&kev) == SCPE_OK) /* poll keyboard */
|
|
lk_event (&kev); /* push event */
|
|
if (vid_poll_mouse (&mev) == SCPE_OK) /* poll mouse */
|
|
vs_event (&mev); /* push event */
|
|
|
|
if (vc_org != vc_last_org) /* origin moved? */
|
|
vc_invalidate (0, (VC_YSIZE - 1)); /* redraw whole screen */
|
|
|
|
vc_last_org = vc_org; /* store video origin */
|
|
|
|
lines = 0;
|
|
for (ln = 0; ln < VC_YSIZE; ln++) {
|
|
if (vc_updated[ln]) { /* line invalid? */
|
|
off = ((ln + (vc_org << VC_ORSC)) << 5) & VC_BUFMASK; /* get video buf offet */
|
|
for (col = 0; col < VC_XSIZE; col++)
|
|
vc_lines[ln*VC_XSIZE + col] = vc_palette[(vc_buf[off + (col >> 5)] >> (col & 0x1F)) & 1];
|
|
/* 1bpp to 32bpp */
|
|
if (CUR_V && /* cursor visible && need to draw cursor? */
|
|
(vc_input_captured || (vc_dev.dctrl & DBG_CURSOR))) {
|
|
if ((ln >= CUR_Y) && (ln < (CUR_Y + 16))) { /* cursor on this line? */
|
|
plna = &vc_cur[(CUR_PLNA + ln - CUR_Y)];/* get plane A base */
|
|
plnb = &vc_cur[(CUR_PLNB + ln - CUR_Y)];/* get plane B base */
|
|
for (col = 0; col < 16; col++) {
|
|
if ((CUR_X + col) >= VC_XSIZE) /* Part of cursor off screen? */
|
|
continue; /* Skip */
|
|
if (vc_cmd & CMD_FOPA) /* force plane A to 1? */
|
|
bita = 1;
|
|
else if (vc_cmd & CMD_ENPA) /* plane A enabled? */
|
|
bita = (*plna >> col) & 1;
|
|
else bita = 0;
|
|
if (vc_cmd & CMD_FOPB) /* force plane B to 1? */
|
|
bitb = 1;
|
|
else if (vc_cmd & CMD_ENPB) /* plane B enabled? */
|
|
bitb = (*plnb >> col) & 1;
|
|
else bitb = 0;
|
|
vc_lines[ln*VC_XSIZE + CUR_X + col] = vc_palette[((vc_lines[ln*VC_XSIZE + CUR_X + col] == vc_palette[1]) & ~bitb) ^ bita];
|
|
}
|
|
}
|
|
}
|
|
vc_updated[ln] = FALSE; /* set valid */
|
|
if ((ln == (VC_YSIZE-1)) || /* if end of window OR */
|
|
(vc_updated[ln+1] == FALSE)) { /* next is already valid? */
|
|
vid_draw (0, ln-lines, VC_XSIZE, lines+1, vc_lines+(ln-lines)*VC_XSIZE); /* update region */
|
|
lines = 0;
|
|
}
|
|
else
|
|
lines++;
|
|
updated = TRUE;
|
|
}
|
|
}
|
|
|
|
if (updated) /* video updated? */
|
|
vid_refresh (); /* put to screen */
|
|
|
|
SET_INT (VC1); /* VSYNC int */
|
|
sim_activate (uptr, tmxr_poll);
|
|
if ((c = sim_poll_kbd ()) < SCPE_KFLAG) /* no char or error? */
|
|
return c;
|
|
return SCPE_OK;
|
|
}
|
|
|
|
t_stat vc_reset (DEVICE *dptr)
|
|
{
|
|
t_stat r;
|
|
uint32 i;
|
|
|
|
CLR_INT (VC1);
|
|
sim_cancel (&vc_unit); /* deactivate unit */
|
|
|
|
vc_cmd = 0;
|
|
vc_xpos = 0;
|
|
vc_ypos = 0;
|
|
vc_xmin1 = 0;
|
|
vc_xmax1 = 0;
|
|
vc_ymin1 = 0;
|
|
vc_ymax1 = 0;
|
|
vc_xmin2 = 0;
|
|
vc_xmax2 = 0;
|
|
vc_ymin2 = 0;
|
|
vc_ymax2 = 0;
|
|
vc_cur_p = 0;
|
|
|
|
for (i = 0; i < VC_YSIZE; i++)
|
|
vc_updated[i] = FALSE;
|
|
|
|
if (dptr->flags & DEV_DIS) {
|
|
if (vc_active) {
|
|
free (vc_buf);
|
|
vc_buf = NULL;
|
|
free (vc_lines);
|
|
vc_lines = NULL;
|
|
vc_active = FALSE;
|
|
return vid_close ();
|
|
}
|
|
else
|
|
return SCPE_OK;
|
|
}
|
|
|
|
if (!vid_active && !vc_active) {
|
|
r = vid_open (dptr, NULL, VC_XSIZE, VC_YSIZE, vc_input_captured ? SIM_VID_INPUTCAPTURED : 0); /* display size */
|
|
if (r != SCPE_OK)
|
|
return r;
|
|
vc_buf = (uint32 *) calloc (VC_BUFSIZE, sizeof (uint32));
|
|
if (vc_buf == NULL) {
|
|
vid_close ();
|
|
return SCPE_MEM;
|
|
}
|
|
vc_lines = (uint32 *) calloc (VC_XSIZE * VC_YSIZE, sizeof (uint32));
|
|
if (vc_lines == NULL) {
|
|
free (vc_buf);
|
|
vc_buf = NULL;
|
|
vid_close ();
|
|
return SCPE_MEM;
|
|
}
|
|
vc_palette[0] = vid_map_rgb (0x00, 0x00, 0x00); /* black */
|
|
vc_palette[1] = vid_map_rgb (0xFF, 0xFF, 0xFF); /* white */
|
|
sim_printf ("Monochrome Video Display Created. ");
|
|
vc_show_capture (stdout, NULL, 0, NULL);
|
|
if (sim_log)
|
|
vc_show_capture (sim_log, NULL, 0, NULL);
|
|
sim_printf ("\n");
|
|
vc_active = TRUE;
|
|
}
|
|
sim_activate_abs (&vc_unit, tmxr_poll);
|
|
return SCPE_OK;
|
|
}
|
|
|
|
t_stat vc_detach (UNIT *uptr)
|
|
{
|
|
if ((vc_dev.flags & DEV_DIS) == 0) {
|
|
vc_dev.flags |= DEV_DIS;
|
|
vc_reset(&vc_dev);
|
|
}
|
|
return SCPE_OK;
|
|
}
|
|
|
|
t_stat vc_set_enable (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
|
|
{
|
|
return cpu_set_model (NULL, 0, (val ? "VAXSTATION" : "MICROVAX"), NULL);
|
|
}
|
|
|
|
t_stat vc_set_capture (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
|
|
{
|
|
if (vid_active)
|
|
return sim_messagef (SCPE_ALATT, "Capture Mode Can't be changed with device enabled\n");
|
|
vc_input_captured = val;
|
|
return SCPE_OK;
|
|
}
|
|
|
|
t_stat vc_show_capture (FILE* st, UNIT* uptr, int32 val, CONST void* desc)
|
|
{
|
|
if (vc_input_captured) {
|
|
fprintf (st, "Captured Input Mode, ");
|
|
vid_show_release_key (st, uptr, val, desc);
|
|
}
|
|
else
|
|
fprintf (st, "Uncaptured Input Mode");
|
|
return SCPE_OK;
|
|
}
|
|
|
|
t_stat vc_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr)
|
|
{
|
|
fprintf (st, "Monochrome Video Subsystem (%s)\n\n", dptr->name);
|
|
fprintf (st, "Use the Control-Right-Shift key combination to regain focus from the simulated\n");
|
|
fprintf (st, "video display\n");
|
|
fprint_set_help (st, dptr);
|
|
fprint_show_help (st, dptr);
|
|
fprint_reg_help (st, dptr);
|
|
return SCPE_OK;
|
|
}
|
|
|
|
const char *vc_description (DEVICE *dptr)
|
|
{
|
|
return "Monochrome Graphics Adapter";
|
|
}
|